summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
committerkan <kan@FreeBSD.org>2007-05-19 01:19:51 +0000
commitd0339348709ba83b91c11c0ea103e72b2e1fb308 (patch)
tree055ffd4e8cac61cc1c826f3d608d5986074f04bf /contrib/gcc/config
parente2c9edc61a77626a22487b87a0f00d67df51c4b7 (diff)
parent1f9ea4d0a40cca64d60cf4dab152349da7b9dddf (diff)
downloadFreeBSD-src-d0339348709ba83b91c11c0ea103e72b2e1fb308.zip
FreeBSD-src-d0339348709ba83b91c11c0ea103e72b2e1fb308.tar.gz
This commit was generated by cvs2svn to compensate for changes in r169689,
which included commits to RCS files with non-trunk default branches.
Diffstat (limited to 'contrib/gcc/config')
-rw-r--r--contrib/gcc/config/arm/README-interworking2
-rw-r--r--contrib/gcc/config/arm/aof.h81
-rw-r--r--contrib/gcc/config/arm/aout.h48
-rw-r--r--contrib/gcc/config/arm/arm-cores.def117
-rw-r--r--contrib/gcc/config/arm/arm-generic.md152
-rw-r--r--contrib/gcc/config/arm/arm-modes.def14
-rw-r--r--contrib/gcc/config/arm/arm-protos.h113
-rw-r--r--contrib/gcc/config/arm/arm-tune.md5
-rw-r--r--contrib/gcc/config/arm/arm.c8969
-rw-r--r--contrib/gcc/config/arm/arm.h1509
-rw-r--r--contrib/gcc/config/arm/arm.md3383
-rw-r--r--contrib/gcc/config/arm/arm.opt155
-rw-r--r--contrib/gcc/config/arm/arm1020e.md388
-rw-r--r--contrib/gcc/config/arm/arm1026ejs.md241
-rw-r--r--contrib/gcc/config/arm/arm1136jfs.md377
-rw-r--r--contrib/gcc/config/arm/arm926ejs.md188
-rw-r--r--contrib/gcc/config/arm/bpabi.S95
-rw-r--r--contrib/gcc/config/arm/bpabi.c61
-rw-r--r--contrib/gcc/config/arm/bpabi.h118
-rw-r--r--contrib/gcc/config/arm/cirrus.md122
-rw-r--r--contrib/gcc/config/arm/coff.h13
-rw-r--r--contrib/gcc/config/arm/constraints.md186
-rw-r--r--contrib/gcc/config/arm/crti.asm16
-rw-r--r--contrib/gcc/config/arm/crtn.asm16
-rw-r--r--contrib/gcc/config/arm/ecos-elf.h4
-rw-r--r--contrib/gcc/config/arm/elf.h26
-rw-r--r--contrib/gcc/config/arm/fpa.md214
-rw-r--r--contrib/gcc/config/arm/freebsd.h5
-rwxr-xr-xcontrib/gcc/config/arm/gentune.sh12
-rw-r--r--contrib/gcc/config/arm/ieee754-df.S1133
-rw-r--r--contrib/gcc/config/arm/ieee754-sf.S932
-rw-r--r--contrib/gcc/config/arm/iwmmxt.md46
-rw-r--r--contrib/gcc/config/arm/kaos-arm.h4
-rw-r--r--contrib/gcc/config/arm/kaos-strongarm.h4
-rw-r--r--contrib/gcc/config/arm/lib1funcs.asm474
-rw-r--r--contrib/gcc/config/arm/libgcc-bpabi.ver83
-rw-r--r--contrib/gcc/config/arm/libunwind.S120
-rw-r--r--contrib/gcc/config/arm/linux-eabi.h85
-rw-r--r--contrib/gcc/config/arm/linux-elf.h78
-rw-r--r--contrib/gcc/config/arm/linux-gas.h22
-rw-r--r--contrib/gcc/config/arm/mmintrin.h34
-rw-r--r--contrib/gcc/config/arm/netbsd-elf.h47
-rw-r--r--contrib/gcc/config/arm/netbsd.h31
-rw-r--r--contrib/gcc/config/arm/pe.c54
-rw-r--r--contrib/gcc/config/arm/pe.h108
-rw-r--r--contrib/gcc/config/arm/pe.opt24
-rw-r--r--contrib/gcc/config/arm/pr-support.c381
-rw-r--r--contrib/gcc/config/arm/predicates.md458
-rw-r--r--contrib/gcc/config/arm/rtems-elf.h21
-rw-r--r--contrib/gcc/config/arm/semi.h19
-rw-r--r--contrib/gcc/config/arm/semiaof.h16
-rw-r--r--contrib/gcc/config/arm/strongarm-coff.h4
-rw-r--r--contrib/gcc/config/arm/strongarm-elf.h4
-rw-r--r--contrib/gcc/config/arm/strongarm-pe.h4
-rw-r--r--contrib/gcc/config/arm/symbian.h101
-rw-r--r--contrib/gcc/config/arm/t-arm22
-rw-r--r--contrib/gcc/config/arm/t-arm-coff2
-rw-r--r--contrib/gcc/config/arm/t-arm-elf12
-rw-r--r--contrib/gcc/config/arm/t-bpabi16
-rw-r--r--contrib/gcc/config/arm/t-linux5
-rw-r--r--contrib/gcc/config/arm/t-linux-eabi14
-rw-r--r--contrib/gcc/config/arm/t-netbsd5
-rw-r--r--contrib/gcc/config/arm/t-pe6
-rw-r--r--contrib/gcc/config/arm/t-semi6
-rw-r--r--contrib/gcc/config/arm/t-strongarm-elf2
-rw-r--r--contrib/gcc/config/arm/t-strongarm-pe2
-rw-r--r--contrib/gcc/config/arm/t-symbian32
-rw-r--r--contrib/gcc/config/arm/t-wince-pe8
-rw-r--r--contrib/gcc/config/arm/t-xscale-coff15
-rw-r--r--contrib/gcc/config/arm/t-xscale-elf27
-rw-r--r--contrib/gcc/config/arm/uclinux-elf.h52
-rw-r--r--contrib/gcc/config/arm/unaligned-funcs.c62
-rw-r--r--contrib/gcc/config/arm/unknown-elf.h28
-rw-r--r--contrib/gcc/config/arm/unwind-arm.c1016
-rw-r--r--contrib/gcc/config/arm/unwind-arm.h271
-rw-r--r--contrib/gcc/config/arm/vfp.md841
-rw-r--r--contrib/gcc/config/arm/vxworks.h18
-rw-r--r--contrib/gcc/config/arm/wince-pe.h12
-rw-r--r--contrib/gcc/config/arm/xscale-coff.h4
-rw-r--r--contrib/gcc/config/arm/xscale-elf.h4
-rw-r--r--contrib/gcc/config/darwin-64.c77
-rw-r--r--contrib/gcc/config/darwin-c.c505
-rw-r--r--contrib/gcc/config/darwin-crt2.c13
-rw-r--r--contrib/gcc/config/darwin-crt3.c537
-rw-r--r--contrib/gcc/config/darwin-protos.h103
-rw-r--r--contrib/gcc/config/darwin-sections.def63
-rw-r--r--contrib/gcc/config/darwin.c1503
-rw-r--r--contrib/gcc/config/darwin.h718
-rw-r--r--contrib/gcc/config/darwin.opt40
-rw-r--r--contrib/gcc/config/darwin9.h13
-rw-r--r--contrib/gcc/config/dbx.h4
-rw-r--r--contrib/gcc/config/dbxcoff.h31
-rw-r--r--contrib/gcc/config/dbxelf.h30
-rw-r--r--contrib/gcc/config/dfp-bit.c541
-rw-r--r--contrib/gcc/config/dfp-bit.h513
-rw-r--r--contrib/gcc/config/elfos.h31
-rw-r--r--contrib/gcc/config/floatunsidf.c15
-rw-r--r--contrib/gcc/config/floatunsisf.c18
-rw-r--r--contrib/gcc/config/floatunsitf.c15
-rw-r--r--contrib/gcc/config/floatunsixf.c15
-rw-r--r--contrib/gcc/config/fp-bit.c175
-rw-r--r--contrib/gcc/config/fp-bit.h54
-rw-r--r--contrib/gcc/config/freebsd-nthr.h4
-rw-r--r--contrib/gcc/config/gnu.h4
-rw-r--r--contrib/gcc/config/gofast.h7
-rw-r--r--contrib/gcc/config/host-darwin.c79
-rw-r--r--contrib/gcc/config/host-darwin.h28
-rw-r--r--contrib/gcc/config/host-hpux.c136
-rw-r--r--contrib/gcc/config/host-linux.c4
-rw-r--r--contrib/gcc/config/host-solaris.c4
-rw-r--r--contrib/gcc/config/i386/athlon.md209
-rw-r--r--contrib/gcc/config/i386/att.h4
-rw-r--r--contrib/gcc/config/i386/beos-elf.h22
-rw-r--r--contrib/gcc/config/i386/biarch64.h4
-rw-r--r--contrib/gcc/config/i386/bsd.h4
-rw-r--r--contrib/gcc/config/i386/constraints.md152
-rw-r--r--contrib/gcc/config/i386/crtdll.h4
-rw-r--r--contrib/gcc/config/i386/crtfastmath.c116
-rw-r--r--contrib/gcc/config/i386/cygming.h174
-rw-r--r--contrib/gcc/config/i386/cygming.opt48
-rw-r--r--contrib/gcc/config/i386/cygwin.asm4
-rw-r--r--contrib/gcc/config/i386/cygwin.h18
-rw-r--r--contrib/gcc/config/i386/cygwin1.c6
-rw-r--r--contrib/gcc/config/i386/cygwin2.c4
-rw-r--r--contrib/gcc/config/i386/darwin-libgcc.10.4.ver81
-rw-r--r--contrib/gcc/config/i386/darwin-libgcc.10.5.ver85
-rw-r--r--contrib/gcc/config/i386/darwin.h164
-rw-r--r--contrib/gcc/config/i386/darwin64.h35
-rw-r--r--contrib/gcc/config/i386/djgpp.h20
-rw-r--r--contrib/gcc/config/i386/djgpp.opt26
-rw-r--r--contrib/gcc/config/i386/driver-i386.c300
-rw-r--r--contrib/gcc/config/i386/emmintrin.h1087
-rw-r--r--contrib/gcc/config/i386/gas.h15
-rw-r--r--contrib/gcc/config/i386/gmm_malloc.h77
-rw-r--r--contrib/gcc/config/i386/gmon-sol2.c54
-rw-r--r--contrib/gcc/config/i386/gnu.h7
-rw-r--r--contrib/gcc/config/i386/gthr-win32.c74
-rwxr-xr-xcontrib/gcc/config/i386/host-cygwin.c81
-rw-r--r--contrib/gcc/config/i386/host-i386-darwin.c31
-rw-r--r--contrib/gcc/config/i386/host-mingw32.c148
-rw-r--r--contrib/gcc/config/i386/i386-aout.h4
-rw-r--r--contrib/gcc/config/i386/i386-coff.h13
-rw-r--r--contrib/gcc/config/i386/i386-interix.h18
-rw-r--r--contrib/gcc/config/i386/i386-interix3.h4
-rw-r--r--contrib/gcc/config/i386/i386-modes.def35
-rw-r--r--contrib/gcc/config/i386/i386-protos.h164
-rw-r--r--contrib/gcc/config/i386/i386.opt229
-rw-r--r--contrib/gcc/config/i386/i386elf.h4
-rw-r--r--contrib/gcc/config/i386/k6.md360
-rw-r--r--contrib/gcc/config/i386/kaos-i386.h4
-rw-r--r--contrib/gcc/config/i386/kfreebsd-gnu.h26
-rw-r--r--contrib/gcc/config/i386/knetbsd-gnu.h24
-rw-r--r--contrib/gcc/config/i386/linux-unwind.h181
-rw-r--r--contrib/gcc/config/i386/linux.h136
-rw-r--r--contrib/gcc/config/i386/linux64.h155
-rw-r--r--contrib/gcc/config/i386/lynx.h94
-rw-r--r--contrib/gcc/config/i386/mingw32.h20
-rw-r--r--contrib/gcc/config/i386/mm3dnow.h220
-rw-r--r--contrib/gcc/config/i386/mmintrin.h363
-rw-r--r--contrib/gcc/config/i386/mmx.md1433
-rw-r--r--contrib/gcc/config/i386/netbsd-elf.h6
-rw-r--r--contrib/gcc/config/i386/netbsd64.h6
-rw-r--r--contrib/gcc/config/i386/netware-crt0.c80
-rw-r--r--contrib/gcc/config/i386/netware-libgcc.c59
-rw-r--r--contrib/gcc/config/i386/netware-libgcc.def2
-rw-r--r--contrib/gcc/config/i386/netware-libgcc.exp74
-rw-r--r--contrib/gcc/config/i386/netware.c194
-rw-r--r--contrib/gcc/config/i386/nto.h9
-rw-r--r--contrib/gcc/config/i386/nwld.c74
-rw-r--r--contrib/gcc/config/i386/nwld.h63
-rw-r--r--contrib/gcc/config/i386/openbsd.h4
-rw-r--r--contrib/gcc/config/i386/openbsdelf.h132
-rw-r--r--contrib/gcc/config/i386/pentium.md4
-rw-r--r--contrib/gcc/config/i386/pmm_malloc.h60
-rw-r--r--contrib/gcc/config/i386/pmmintrin.h43
-rw-r--r--contrib/gcc/config/i386/ppro.md884
-rw-r--r--contrib/gcc/config/i386/predicates.md990
-rw-r--r--contrib/gcc/config/i386/ptx4-i.h4
-rw-r--r--contrib/gcc/config/i386/rtemself.h4
-rw-r--r--contrib/gcc/config/i386/sco5.h23
-rw-r--r--contrib/gcc/config/i386/sco5.opt25
-rw-r--r--contrib/gcc/config/i386/sol2-10.h114
-rw-r--r--contrib/gcc/config/i386/sol2-c1.asm4
-rw-r--r--contrib/gcc/config/i386/sol2-ci.asm4
-rw-r--r--contrib/gcc/config/i386/sol2-cn.asm4
-rw-r--r--contrib/gcc/config/i386/sol2-gc1.asm4
-rw-r--r--contrib/gcc/config/i386/sol2.h48
-rw-r--r--contrib/gcc/config/i386/sse.md3950
-rw-r--r--contrib/gcc/config/i386/sync.md291
-rw-r--r--contrib/gcc/config/i386/sysv4-cpp.h4
-rw-r--r--contrib/gcc/config/i386/sysv4.h4
-rw-r--r--contrib/gcc/config/i386/sysv5.h4
-rw-r--r--contrib/gcc/config/i386/t-crtfm6
-rw-r--r--contrib/gcc/config/i386/t-cygming13
-rw-r--r--contrib/gcc/config/i386/t-darwin5
-rw-r--r--contrib/gcc/config/i386/t-darwin643
-rw-r--r--contrib/gcc/config/i386/t-gmm_malloc6
-rw-r--r--contrib/gcc/config/i386/t-gthr-win323
-rw-r--r--contrib/gcc/config/i386/t-linux643
-rw-r--r--contrib/gcc/config/i386/t-mingw329
-rw-r--r--contrib/gcc/config/i386/t-nwld61
-rw-r--r--contrib/gcc/config/i386/t-pmm_malloc6
-rw-r--r--contrib/gcc/config/i386/t-rtems-i38615
-rw-r--r--contrib/gcc/config/i386/t-sol222
-rw-r--r--contrib/gcc/config/i386/t-sol2-1011
-rw-r--r--contrib/gcc/config/i386/t-vxworks10
-rw-r--r--contrib/gcc/config/i386/t-vxworksae5
-rw-r--r--contrib/gcc/config/i386/unix.h4
-rw-r--r--contrib/gcc/config/i386/uwin.h9
-rw-r--r--contrib/gcc/config/i386/vxworks.h109
-rw-r--r--contrib/gcc/config/i386/vxworksae.h27
-rwxr-xr-xcontrib/gcc/config/i386/winnt-cxx.c167
-rwxr-xr-xcontrib/gcc/config/i386/winnt-stubs.c53
-rw-r--r--contrib/gcc/config/i386/winnt.c574
-rw-r--r--contrib/gcc/config/i386/x-darwin4
-rw-r--r--contrib/gcc/config/i386/x-i3863
-rw-r--r--contrib/gcc/config/i386/x-mingw329
-rw-r--r--contrib/gcc/config/i386/xm-cygwin.h4
-rw-r--r--contrib/gcc/config/i386/xm-djgpp.h7
-rw-r--r--contrib/gcc/config/i386/xm-mingw32.h11
-rw-r--r--contrib/gcc/config/i386/xmmintrin.h496
-rw-r--r--contrib/gcc/config/ia64/crtbegin.asm35
-rw-r--r--contrib/gcc/config/ia64/crtend.asm35
-rw-r--r--contrib/gcc/config/ia64/crtfastmath.c40
-rw-r--r--contrib/gcc/config/ia64/crti.asm4
-rw-r--r--contrib/gcc/config/ia64/crtn.asm4
-rw-r--r--contrib/gcc/config/ia64/fde-glibc.c4
-rw-r--r--contrib/gcc/config/ia64/freebsd.h4
-rw-r--r--contrib/gcc/config/ia64/hpux.h80
-rw-r--r--contrib/gcc/config/ia64/ia64-c.c16
-rw-r--r--contrib/gcc/config/ia64/ia64-modes.def43
-rw-r--r--contrib/gcc/config/ia64/ia64-protos.h84
-rw-r--r--contrib/gcc/config/ia64/ia64.c4934
-rw-r--r--contrib/gcc/config/ia64/ia64.h594
-rw-r--r--contrib/gcc/config/ia64/ia64.md1524
-rw-r--r--contrib/gcc/config/ia64/ia64.opt147
-rw-r--r--contrib/gcc/config/ia64/ia64intrin.h132
-rw-r--r--contrib/gcc/config/ia64/ilp32.opt7
-rw-r--r--contrib/gcc/config/ia64/itanium1.md144
-rw-r--r--contrib/gcc/config/ia64/itanium2.md179
-rw-r--r--contrib/gcc/config/ia64/lib1funcs.asm61
-rw-r--r--contrib/gcc/config/ia64/linux-unwind.h193
-rw-r--r--contrib/gcc/config/ia64/linux.h164
-rw-r--r--contrib/gcc/config/ia64/predicates.md591
-rw-r--r--contrib/gcc/config/ia64/quadlib.c4
-rw-r--r--contrib/gcc/config/ia64/sync.md178
-rw-r--r--contrib/gcc/config/ia64/sysv4.h40
-rw-r--r--contrib/gcc/config/ia64/t-hpux27
-rw-r--r--contrib/gcc/config/ia64/t-ia647
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.c42
-rw-r--r--contrib/gcc/config/ia64/unwind-ia64.h4
-rw-r--r--contrib/gcc/config/ia64/vect.md1304
-rw-r--r--contrib/gcc/config/interix.h10
-rw-r--r--contrib/gcc/config/interix3.h4
-rw-r--r--contrib/gcc/config/kaos.h4
-rw-r--r--contrib/gcc/config/kfreebsd-gnu.h38
-rw-r--r--contrib/gcc/config/knetbsd-gnu.h39
-rw-r--r--contrib/gcc/config/libgloss.h8
-rw-r--r--contrib/gcc/config/linux.h69
-rw-r--r--contrib/gcc/config/linux.opt29
-rw-r--r--contrib/gcc/config/lynx.h289
-rw-r--r--contrib/gcc/config/lynx.opt32
-rw-r--r--contrib/gcc/config/memcmp.c16
-rw-r--r--contrib/gcc/config/memcpy.c12
-rw-r--r--contrib/gcc/config/memmove.c20
-rw-r--r--contrib/gcc/config/memset.c11
-rw-r--r--contrib/gcc/config/mips/24k.md455
-rw-r--r--contrib/gcc/config/mips/3000.md72
-rw-r--r--contrib/gcc/config/mips/4000.md33
-rw-r--r--contrib/gcc/config/mips/4100.md52
-rw-r--r--contrib/gcc/config/mips/4130.md136
-rw-r--r--contrib/gcc/config/mips/4300.md86
-rw-r--r--contrib/gcc/config/mips/4600.md88
-rw-r--r--contrib/gcc/config/mips/4k.md154
-rw-r--r--contrib/gcc/config/mips/5000.md81
-rw-r--r--contrib/gcc/config/mips/5400.md166
-rw-r--r--contrib/gcc/config/mips/5500.md209
-rw-r--r--contrib/gcc/config/mips/5k.md230
-rw-r--r--contrib/gcc/config/mips/6000.md57
-rw-r--r--contrib/gcc/config/mips/7000.md215
-rw-r--r--contrib/gcc/config/mips/9000.md152
-rw-r--r--contrib/gcc/config/mips/constraints.md195
-rw-r--r--contrib/gcc/config/mips/crti.asm26
-rw-r--r--contrib/gcc/config/mips/crtn.asm29
-rw-r--r--contrib/gcc/config/mips/dbxmdebug.h6
-rw-r--r--contrib/gcc/config/mips/elf.h54
-rw-r--r--contrib/gcc/config/mips/elforion.h22
-rw-r--r--contrib/gcc/config/mips/generic.md106
-rw-r--r--contrib/gcc/config/mips/iris.h222
-rw-r--r--contrib/gcc/config/mips/iris5.h45
-rw-r--r--contrib/gcc/config/mips/iris6.h118
-rw-r--r--contrib/gcc/config/mips/irix-crti.asm51
-rw-r--r--contrib/gcc/config/mips/irix-crtn.asm27
-rw-r--r--contrib/gcc/config/mips/linux-unwind.h112
-rw-r--r--contrib/gcc/config/mips/linux.h181
-rw-r--r--contrib/gcc/config/mips/linux64.h72
-rw-r--r--contrib/gcc/config/mips/mips-dsp.md1057
-rw-r--r--contrib/gcc/config/mips/mips-modes.def43
-rw-r--r--contrib/gcc/config/mips/mips-protos.h255
-rw-r--r--contrib/gcc/config/mips/mips-ps-3d.md618
-rw-r--r--contrib/gcc/config/mips/mips.c10840
-rw-r--r--contrib/gcc/config/mips/mips.h2711
-rw-r--r--contrib/gcc/config/mips/mips.md5485
-rw-r--r--contrib/gcc/config/mips/mips.opt222
-rw-r--r--contrib/gcc/config/mips/mips16.S739
-rw-r--r--contrib/gcc/config/mips/netbsd.h203
-rw-r--r--contrib/gcc/config/mips/openbsd.h98
-rw-r--r--contrib/gcc/config/mips/predicates.md286
-rw-r--r--contrib/gcc/config/mips/r3900.h37
-rw-r--r--contrib/gcc/config/mips/rtems.h36
-rw-r--r--contrib/gcc/config/mips/sb1.md564
-rw-r--r--contrib/gcc/config/mips/sdb.h88
-rw-r--r--contrib/gcc/config/mips/sr71k.md321
-rw-r--r--contrib/gcc/config/mips/t-elf40
-rw-r--r--contrib/gcc/config/mips/t-gofast19
-rw-r--r--contrib/gcc/config/mips/t-iris12
-rw-r--r--contrib/gcc/config/mips/t-iris619
-rw-r--r--contrib/gcc/config/mips/t-isa326440
-rw-r--r--contrib/gcc/config/mips/t-linux6417
-rw-r--r--contrib/gcc/config/mips/t-mips23
-rw-r--r--contrib/gcc/config/mips/t-r390031
-rw-r--r--contrib/gcc/config/mips/t-rtems16
-rw-r--r--contrib/gcc/config/mips/t-sb144
-rw-r--r--contrib/gcc/config/mips/t-slibgcc-irix34
-rw-r--r--contrib/gcc/config/mips/t-sr71k51
-rw-r--r--contrib/gcc/config/mips/t-vr112
-rw-r--r--contrib/gcc/config/mips/t-vxworks16
-rw-r--r--contrib/gcc/config/mips/vr.h53
-rw-r--r--contrib/gcc/config/mips/vr4120-div.S75
-rw-r--r--contrib/gcc/config/mips/vxworks.h68
-rw-r--r--contrib/gcc/config/mips/windiss.h101
-rw-r--r--contrib/gcc/config/netbsd-aout.h4
-rw-r--r--contrib/gcc/config/netbsd-elf.h4
-rw-r--r--contrib/gcc/config/netbsd.h20
-rw-r--r--contrib/gcc/config/openbsd-oldgas.h4
-rw-r--r--contrib/gcc/config/openbsd.h67
-rw-r--r--contrib/gcc/config/ptx4.h26
-rw-r--r--contrib/gcc/config/rs6000/40x.md32
-rw-r--r--contrib/gcc/config/rs6000/440.md25
-rw-r--r--contrib/gcc/config/rs6000/603.md29
-rw-r--r--contrib/gcc/config/rs6000/6xx.md48
-rw-r--r--contrib/gcc/config/rs6000/7450.md36
-rw-r--r--contrib/gcc/config/rs6000/7xx.md34
-rw-r--r--contrib/gcc/config/rs6000/8540.md30
-rw-r--r--contrib/gcc/config/rs6000/aix.h102
-rw-r--r--contrib/gcc/config/rs6000/aix.opt25
-rw-r--r--contrib/gcc/config/rs6000/aix41.h32
-rw-r--r--contrib/gcc/config/rs6000/aix41.opt25
-rw-r--r--contrib/gcc/config/rs6000/aix43.h54
-rw-r--r--contrib/gcc/config/rs6000/aix51.h53
-rw-r--r--contrib/gcc/config/rs6000/aix52.h68
-rw-r--r--contrib/gcc/config/rs6000/aix64.opt33
-rw-r--r--contrib/gcc/config/rs6000/altivec.h11760
-rw-r--r--contrib/gcc/config/rs6000/altivec.md2337
-rw-r--r--contrib/gcc/config/rs6000/beos.h7
-rw-r--r--contrib/gcc/config/rs6000/biarch64.h4
-rw-r--r--contrib/gcc/config/rs6000/constraints.md162
-rw-r--r--contrib/gcc/config/rs6000/crtsavres.asm4
-rw-r--r--contrib/gcc/config/rs6000/darwin-asm.h61
-rw-r--r--contrib/gcc/config/rs6000/darwin-fallback.c471
-rw-r--r--contrib/gcc/config/rs6000/darwin-fpsave.asm102
-rw-r--r--contrib/gcc/config/rs6000/darwin-ldouble-format84
-rw-r--r--contrib/gcc/config/rs6000/darwin-ldouble.c396
-rw-r--r--contrib/gcc/config/rs6000/darwin-libgcc.10.4.ver76
-rw-r--r--contrib/gcc/config/rs6000/darwin-libgcc.10.5.ver89
-rw-r--r--contrib/gcc/config/rs6000/darwin-tramp.asm48
-rw-r--r--contrib/gcc/config/rs6000/darwin-unwind.h35
-rw-r--r--contrib/gcc/config/rs6000/darwin-vecsave.asm165
-rw-r--r--contrib/gcc/config/rs6000/darwin-world.asm269
-rw-r--r--contrib/gcc/config/rs6000/darwin.h308
-rw-r--r--contrib/gcc/config/rs6000/darwin.md440
-rw-r--r--contrib/gcc/config/rs6000/darwin.opt33
-rw-r--r--contrib/gcc/config/rs6000/darwin64.h36
-rw-r--r--contrib/gcc/config/rs6000/darwin7.h31
-rw-r--r--contrib/gcc/config/rs6000/darwin8.h33
-rw-r--r--contrib/gcc/config/rs6000/default64.h9
-rw-r--r--contrib/gcc/config/rs6000/e500-double.h25
-rw-r--r--contrib/gcc/config/rs6000/eabi-ci.asm4
-rw-r--r--contrib/gcc/config/rs6000/eabi-cn.asm4
-rw-r--r--contrib/gcc/config/rs6000/eabi.asm4
-rw-r--r--contrib/gcc/config/rs6000/eabi.h12
-rw-r--r--contrib/gcc/config/rs6000/eabialtivec.h4
-rw-r--r--contrib/gcc/config/rs6000/eabisim.h4
-rw-r--r--contrib/gcc/config/rs6000/eabispe.h23
-rw-r--r--contrib/gcc/config/rs6000/gnu.h4
-rw-r--r--contrib/gcc/config/rs6000/host-darwin.c93
-rw-r--r--contrib/gcc/config/rs6000/host-ppc64-darwin.c31
-rw-r--r--contrib/gcc/config/rs6000/kaos-ppc.h4
-rw-r--r--contrib/gcc/config/rs6000/libgcc-ppc-glibc.ver52
-rw-r--r--contrib/gcc/config/rs6000/linux-unwind.h466
-rw-r--r--contrib/gcc/config/rs6000/linux.h52
-rw-r--r--contrib/gcc/config/rs6000/linux64.h196
-rw-r--r--contrib/gcc/config/rs6000/linux64.opt25
-rw-r--r--contrib/gcc/config/rs6000/linuxaltivec.h4
-rw-r--r--contrib/gcc/config/rs6000/linuxspe.h28
-rw-r--r--contrib/gcc/config/rs6000/lynx.h166
-rw-r--r--contrib/gcc/config/rs6000/mpc.md23
-rw-r--r--contrib/gcc/config/rs6000/netbsd.h4
-rw-r--r--contrib/gcc/config/rs6000/power4.md100
-rw-r--r--contrib/gcc/config/rs6000/power5.md78
-rw-r--r--contrib/gcc/config/rs6000/ppc64-fp.c60
-rw-r--r--contrib/gcc/config/rs6000/predicates.md1307
-rw-r--r--contrib/gcc/config/rs6000/rios1.md25
-rw-r--r--contrib/gcc/config/rs6000/rios2.md23
-rw-r--r--contrib/gcc/config/rs6000/rs6000-c.c2476
-rw-r--r--contrib/gcc/config/rs6000/rs6000-modes.def13
-rw-r--r--contrib/gcc/config/rs6000/rs6000-protos.h152
-rw-r--r--contrib/gcc/config/rs6000/rs6000.c10891
-rw-r--r--contrib/gcc/config/rs6000/rs6000.h1325
-rw-r--r--contrib/gcc/config/rs6000/rs6000.md5558
-rw-r--r--contrib/gcc/config/rs6000/rs6000.opt247
-rw-r--r--contrib/gcc/config/rs6000/rs64.md33
-rw-r--r--contrib/gcc/config/rs6000/rtems.h6
-rw-r--r--contrib/gcc/config/rs6000/secureplt.h21
-rw-r--r--contrib/gcc/config/rs6000/sfp-machine.h63
-rw-r--r--contrib/gcc/config/rs6000/sol-ci.asm4
-rw-r--r--contrib/gcc/config/rs6000/sol-cn.asm4
-rw-r--r--contrib/gcc/config/rs6000/spe.h6
-rw-r--r--contrib/gcc/config/rs6000/spe.md352
-rw-r--r--contrib/gcc/config/rs6000/sync.md625
-rw-r--r--contrib/gcc/config/rs6000/sysv4.h383
-rw-r--r--contrib/gcc/config/rs6000/sysv4.opt149
-rw-r--r--contrib/gcc/config/rs6000/sysv4le.h4
-rw-r--r--contrib/gcc/config/rs6000/t-aix4326
-rw-r--r--contrib/gcc/config/rs6000/t-aix5226
-rw-r--r--contrib/gcc/config/rs6000/t-beos3
-rw-r--r--contrib/gcc/config/rs6000/t-darwin40
-rw-r--r--contrib/gcc/config/rs6000/t-darwin83
-rw-r--r--contrib/gcc/config/rs6000/t-fprules13
-rw-r--r--contrib/gcc/config/rs6000/t-fprules-fpbit11
-rw-r--r--contrib/gcc/config/rs6000/t-fprules-softfp6
-rw-r--r--contrib/gcc/config/rs6000/t-linux6438
-rw-r--r--contrib/gcc/config/rs6000/t-lynx38
-rw-r--r--contrib/gcc/config/rs6000/t-ppccomm10
-rw-r--r--contrib/gcc/config/rs6000/t-rtems89
-rw-r--r--contrib/gcc/config/rs6000/t-vxworks15
-rw-r--r--contrib/gcc/config/rs6000/t-vxworksae5
-rw-r--r--contrib/gcc/config/rs6000/tramp.asm14
-rw-r--r--contrib/gcc/config/rs6000/vxworks.h181
-rw-r--r--contrib/gcc/config/rs6000/vxworksae.h24
-rw-r--r--contrib/gcc/config/rs6000/windiss.h4
-rw-r--r--contrib/gcc/config/rs6000/x-darwin8
-rw-r--r--contrib/gcc/config/rs6000/x-darwin644
-rw-r--r--contrib/gcc/config/rs6000/xcoff.h113
-rw-r--r--contrib/gcc/config/rtems.h13
-rw-r--r--contrib/gcc/config/s390/2064.md55
-rw-r--r--contrib/gcc/config/s390/2084.md214
-rw-r--r--contrib/gcc/config/s390/constraints.md438
-rw-r--r--contrib/gcc/config/s390/fixdfdi.h159
-rw-r--r--contrib/gcc/config/s390/libgcc-glibc.ver33
-rw-r--r--contrib/gcc/config/s390/linux-unwind.h134
-rw-r--r--contrib/gcc/config/s390/linux.h107
-rw-r--r--contrib/gcc/config/s390/predicates.md379
-rw-r--r--contrib/gcc/config/s390/s390-modes.def139
-rw-r--r--contrib/gcc/config/s390/s390-protos.h96
-rw-r--r--contrib/gcc/config/s390/s390.c6915
-rw-r--r--contrib/gcc/config/s390/s390.h469
-rw-r--r--contrib/gcc/config/s390/s390.md8094
-rw-r--r--contrib/gcc/config/s390/s390.opt100
-rw-r--r--contrib/gcc/config/s390/s390x.h4
-rw-r--r--contrib/gcc/config/s390/t-crtstuff1
-rw-r--r--contrib/gcc/config/s390/t-linux3
-rw-r--r--contrib/gcc/config/s390/t-linux644
-rw-r--r--contrib/gcc/config/s390/t-tpf8
-rw-r--r--contrib/gcc/config/s390/tpf-unwind.h257
-rw-r--r--contrib/gcc/config/s390/tpf.h85
-rw-r--r--contrib/gcc/config/s390/tpf.md34
-rw-r--r--contrib/gcc/config/s390/tpf.opt28
-rw-r--r--contrib/gcc/config/soft-fp/README4
-rw-r--r--contrib/gcc/config/soft-fp/adddf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/addsf3.c50
-rw-r--r--contrib/gcc/config/soft-fp/addtf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/divdf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/divsf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/divtf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/double.h264
-rw-r--r--contrib/gcc/config/soft-fp/eqdf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/eqsf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/eqtf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/extenddftf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/extended.h453
-rw-r--r--contrib/gcc/config/soft-fp/extendsfdf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/extendsftf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/fixdfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixdfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixsfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixsfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixtfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixtfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunsdfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunsdfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunssfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunssfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunstfdi.c46
-rw-r--r--contrib/gcc/config/soft-fp/fixunstfsi.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatdidf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatdisf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatditf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatsidf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatsisf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatsitf.c46
-rw-r--r--contrib/gcc/config/soft-fp/floatundidf.c47
-rw-r--r--contrib/gcc/config/soft-fp/floatundisf.c47
-rw-r--r--contrib/gcc/config/soft-fp/floatunditf.c47
-rw-r--r--contrib/gcc/config/soft-fp/floatunsidf.c47
-rw-r--r--contrib/gcc/config/soft-fp/floatunsisf.c47
-rw-r--r--contrib/gcc/config/soft-fp/floatunsitf.c47
-rw-r--r--contrib/gcc/config/soft-fp/gedf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/gesf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/getf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/ledf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/lesf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/letf2.c51
-rw-r--r--contrib/gcc/config/soft-fp/muldf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/mulsf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/multf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/negdf2.c48
-rw-r--r--contrib/gcc/config/soft-fp/negsf2.c48
-rw-r--r--contrib/gcc/config/soft-fp/negtf2.c48
-rw-r--r--contrib/gcc/config/soft-fp/op-1.h302
-rw-r--r--contrib/gcc/config/soft-fp/op-2.h615
-rw-r--r--contrib/gcc/config/soft-fp/op-4.h686
-rw-r--r--contrib/gcc/config/soft-fp/op-8.h111
-rw-r--r--contrib/gcc/config/soft-fp/op-common.h1333
-rw-r--r--contrib/gcc/config/soft-fp/quad.h271
-rw-r--r--contrib/gcc/config/soft-fp/single.h151
-rw-r--r--contrib/gcc/config/soft-fp/soft-fp.h209
-rw-r--r--contrib/gcc/config/soft-fp/subdf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/subsf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/subtf3.c49
-rw-r--r--contrib/gcc/config/soft-fp/t-softfp108
-rw-r--r--contrib/gcc/config/soft-fp/truncdfsf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/trunctfdf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/trunctfsf2.c54
-rw-r--r--contrib/gcc/config/soft-fp/unorddf2.c45
-rw-r--r--contrib/gcc/config/soft-fp/unordsf2.c46
-rw-r--r--contrib/gcc/config/soft-fp/unordtf2.c46
-rw-r--r--contrib/gcc/config/sol2-10.h24
-rw-r--r--contrib/gcc/config/sol2-6.h27
-rw-r--r--contrib/gcc/config/sol2-c.c272
-rw-r--r--contrib/gcc/config/sol2-protos.h24
-rw-r--r--contrib/gcc/config/sol2.c120
-rw-r--r--contrib/gcc/config/sol2.h59
-rw-r--r--contrib/gcc/config/sparc/biarch64.h4
-rw-r--r--contrib/gcc/config/sparc/crtfastmath.c4
-rw-r--r--contrib/gcc/config/sparc/cypress.md4
-rw-r--r--contrib/gcc/config/sparc/hypersparc.md4
-rw-r--r--contrib/gcc/config/sparc/libgcc-sparc-glibc.ver33
-rw-r--r--contrib/gcc/config/sparc/linux-unwind.h158
-rw-r--r--contrib/gcc/config/sparc/linux.h186
-rw-r--r--contrib/gcc/config/sparc/linux64.h232
-rw-r--r--contrib/gcc/config/sparc/little-endian.opt28
-rw-r--r--contrib/gcc/config/sparc/long-double-switch.opt28
-rw-r--r--contrib/gcc/config/sparc/netbsd-elf.h38
-rw-r--r--contrib/gcc/config/sparc/niagara.md119
-rw-r--r--contrib/gcc/config/sparc/openbsd1-64.h4
-rw-r--r--contrib/gcc/config/sparc/openbsd64.h9
-rw-r--r--contrib/gcc/config/sparc/predicates.md478
-rw-r--r--contrib/gcc/config/sparc/rtemself.h13
-rw-r--r--contrib/gcc/config/sparc/sol2-64.h11
-rw-r--r--contrib/gcc/config/sparc/sol2-bi.h27
-rw-r--r--contrib/gcc/config/sparc/sol2-c1.asm4
-rw-r--r--contrib/gcc/config/sparc/sol2-ci.asm4
-rw-r--r--contrib/gcc/config/sparc/sol2-cn.asm4
-rw-r--r--contrib/gcc/config/sparc/sol2-gas-bi.h6
-rw-r--r--contrib/gcc/config/sparc/sol2-gas.h13
-rw-r--r--contrib/gcc/config/sparc/sol2.h60
-rw-r--r--contrib/gcc/config/sparc/sp-elf.h80
-rw-r--r--contrib/gcc/config/sparc/sp64-elf.h58
-rw-r--r--contrib/gcc/config/sparc/sparc-modes.def10
-rw-r--r--contrib/gcc/config/sparc/sparc-protos.h43
-rw-r--r--contrib/gcc/config/sparc/sparc.c6072
-rw-r--r--contrib/gcc/config/sparc/sparc.h805
-rw-r--r--contrib/gcc/config/sparc/sparc.md3155
-rw-r--r--contrib/gcc/config/sparc/sparc.opt126
-rw-r--r--contrib/gcc/config/sparc/sparclet.md4
-rw-r--r--contrib/gcc/config/sparc/supersparc.md4
-rw-r--r--contrib/gcc/config/sparc/sync.md208
-rw-r--r--contrib/gcc/config/sparc/sysv4-only.h7
-rw-r--r--contrib/gcc/config/sparc/sysv4.h4
-rw-r--r--contrib/gcc/config/sparc/t-linux5
-rw-r--r--contrib/gcc/config/sparc/t-linux646
-rw-r--r--contrib/gcc/config/sparc/ultra1_2.md8
-rw-r--r--contrib/gcc/config/sparc/ultra3.md8
-rw-r--r--contrib/gcc/config/svr3.h42
-rw-r--r--contrib/gcc/config/svr4.h6
-rw-r--r--contrib/gcc/config/t-darwin23
-rw-r--r--contrib/gcc/config/t-dfprules10
-rw-r--r--contrib/gcc/config/t-libunwind-elf19
-rw-r--r--contrib/gcc/config/t-linux2
-rw-r--r--contrib/gcc/config/t-lynx15
-rw-r--r--contrib/gcc/config/t-slibgcc-darwin115
-rw-r--r--contrib/gcc/config/t-slibgcc-elf-ver22
-rw-r--r--contrib/gcc/config/t-slibgcc-sld21
-rw-r--r--contrib/gcc/config/t-sol212
-rw-r--r--contrib/gcc/config/t-vxworks11
-rw-r--r--contrib/gcc/config/usegas.h4
-rw-r--r--contrib/gcc/config/vx-common.h88
-rw-r--r--contrib/gcc/config/vxlib.c197
-rw-r--r--contrib/gcc/config/vxworks.h131
-rw-r--r--contrib/gcc/config/vxworks.opt32
-rw-r--r--contrib/gcc/config/vxworksae.h58
-rw-r--r--contrib/gcc/config/windiss.h4
-rw-r--r--contrib/gcc/config/x-darwin3
-rw-r--r--contrib/gcc/config/x-hpux4
-rw-r--r--contrib/gcc/config/x-solaris2
606 files changed, 115001 insertions, 50052 deletions
diff --git a/contrib/gcc/config/arm/README-interworking b/contrib/gcc/config/arm/README-interworking
index 0a03cdc..d221e15 100644
--- a/contrib/gcc/config/arm/README-interworking
+++ b/contrib/gcc/config/arm/README-interworking
@@ -78,7 +78,7 @@ then the following rules must be obeyed:
* All externally visible functions which should be entered in
Thumb mode must have the .thumb_func pseudo op specified just
- before their entry point. eg:
+ before their entry point. e.g.:
.code 16
.global function
diff --git a/contrib/gcc/config/arm/aof.h b/contrib/gcc/config/arm/aof.h
index 5a6ab2c..8a1223c 100644
--- a/contrib/gcc/config/arm/aof.h
+++ b/contrib/gcc/config/arm/aof.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler, for Advanced RISC Machines
ARM compilation, AOF Assembler.
- Copyright (C) 1995, 1996, 1997, 2000, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 2000, 2003, 2004
+ Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk)
This file is part of GCC.
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
@@ -34,8 +35,7 @@
#define ENDFILE_SPEC "crtend.o%s"
#ifndef ASM_SPEC
-#define ASM_SPEC "%{g -g} -arch 4 \
--apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/26bit}}"
+#define ASM_SPEC "%{g -g} -arch 4 -apcs 3/32bit"
#endif
#ifndef LIB_SPEC
@@ -44,48 +44,6 @@
#define LIBGCC_SPEC "libgcc.a%s"
-/* Dividing the Output into Sections (Text, Data, ...) */
-/* AOF Assembler syntax is a nightmare when it comes to areas, since once
- we change from one area to another, we can't go back again. Instead,
- we must create a new area with the same attributes and add the new output
- to that. Unfortunately, there is nothing we can do here to guarantee that
- two areas with the same attributes will be linked adjacently in the
- resulting executable, so we have to be careful not to do pc-relative
- addressing across such boundaries. */
-#define TEXT_SECTION_ASM_OP aof_text_section ()
-
-#define DATA_SECTION_ASM_OP aof_data_section ()
-
-#define EXTRA_SECTIONS in_zero_init, in_common
-
-#define EXTRA_SECTION_FUNCTIONS \
- ZERO_INIT_SECTION \
- COMMON_SECTION
-
-#define ZERO_INIT_SECTION \
- void \
- zero_init_section () \
- { \
- static int zero_init_count = 1; \
- \
- if (in_section != in_zero_init) \
- { \
- fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", \
- zero_init_count++); \
- in_section = in_zero_init; \
- } \
- }
-
-/* Used by ASM_OUTPUT_COMMON (below) to tell varasm.c that we've
- changed areas. */
-#define COMMON_SECTION \
- void \
- common_section () \
- { \
- if (in_section != in_common) \
- in_section = in_common; \
- }
-
#define CTOR_LIST_BEGIN \
asm (CTORS_SECTION_ASM_OP); \
extern func_ptr __CTOR_END__[1]; \
@@ -130,6 +88,8 @@
whole table generation until the end of the function. */
#define JUMP_TABLES_IN_TEXT_SECTION 1
+#define TARGET_ASM_INIT_SECTIONS aof_asm_init_sections
+
/* Some systems use __main in a way incompatible with its use in gcc, in these
cases use the macros NAME__MAIN to give a quoted symbol and SYMBOL__MAIN to
give the same symbol without quotes for an alternative entry point. You
@@ -159,7 +119,7 @@
/* Output of Uninitialized Variables. */
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
- (common_section (), \
+ (in_section = NULL, \
fprintf ((STREAM), "\tAREA "), \
assemble_name ((STREAM), (NAME)), \
fprintf ((STREAM), ", DATA, COMMON\n\t%% %d\t%s size=%d\n", \
@@ -246,7 +206,12 @@ do { \
"wr0", "wr1", "wr2", "wr3", \
"wr4", "wr5", "wr6", "wr7", \
"wr8", "wr9", "wr10", "wr11", \
- "wr12", "wr13", "wr14", "wr15" \
+ "wr12", "wr13", "wr14", "wr15", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
+ "vfpcc" \
}
#define ADDITIONAL_REGISTER_NAMES \
@@ -266,7 +231,23 @@ do { \
{"r12", 12}, {"ip", 12}, \
{"r13", 13}, {"sp", 13}, \
{"r14", 14}, {"lr", 14}, \
- {"r15", 15}, {"pc", 15} \
+ {"r15", 15}, {"pc", 15}, \
+ {"d0", 63}, \
+ {"d1", 65}, \
+ {"d2", 67}, \
+ {"d3", 69}, \
+ {"d4", 71}, \
+ {"d5", 73}, \
+ {"d6", 75}, \
+ {"d7", 77}, \
+ {"d8", 79}, \
+ {"d9", 81}, \
+ {"d10", 83}, \
+ {"d11", 85}, \
+ {"d12", 87}, \
+ {"d13", 89}, \
+ {"d14", 91}, \
+ {"d15", 93} \
}
#define REGISTER_PREFIX "__"
diff --git a/contrib/gcc/config/arm/aout.h b/contrib/gcc/config/arm/aout.h
index 1f060fa..903afa7 100644
--- a/contrib/gcc/config/arm/aout.h
+++ b/contrib/gcc/config/arm/aout.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM with a.out
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2004
Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@armltd.co.uk).
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#ifndef ASM_APP_ON
#define ASM_APP_ON ""
@@ -49,7 +49,7 @@
/* The assembler's names for the registers. */
#ifndef REGISTER_NAMES
-#define REGISTER_NAMES \
+#define REGISTER_NAMES \
{ \
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
"r8", "r9", "sl", "fp", "ip", "sp", "lr", "pc", \
@@ -63,7 +63,12 @@
"wr0", "wr1", "wr2", "wr3", \
"wr4", "wr5", "wr6", "wr7", \
"wr8", "wr9", "wr10", "wr11", \
- "wr12", "wr13", "wr14", "wr15" \
+ "wr12", "wr13", "wr14", "wr15", \
+ "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", \
+ "s8", "s9", "s10", "s11", "s12", "s13", "s14", "s15", \
+ "s16", "s17", "s18", "s19", "s20", "s21", "s22", "s23", \
+ "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31", \
+ "vfpcc" \
}
#endif
@@ -152,7 +157,23 @@
{"mvdx12", 39}, \
{"mvdx13", 40}, \
{"mvdx14", 41}, \
- {"mvdx15", 42} \
+ {"mvdx15", 42}, \
+ {"d0", 63}, \
+ {"d1", 65}, \
+ {"d2", 67}, \
+ {"d3", 69}, \
+ {"d4", 71}, \
+ {"d5", 73}, \
+ {"d6", 75}, \
+ {"d7", 77}, \
+ {"d8", 79}, \
+ {"d9", 81}, \
+ {"d10", 83}, \
+ {"d11", 85}, \
+ {"d12", 87}, \
+ {"d13", 89}, \
+ {"d14", 91}, \
+ {"d15", 93}, \
}
#endif
@@ -172,19 +193,6 @@
#define DBX_CONTIN_LENGTH 0
#endif
-/* Output a source filename for the debugger. RISCiX dbx insists that the
- ``desc'' field is set to compiler version number >= 315 (sic). */
-#define DBX_OUTPUT_MAIN_SOURCE_FILENAME(STREAM, NAME) \
- do \
- { \
- fprintf (STREAM, ".stabs "); \
- output_quoted_string (STREAM, NAME); \
- fprintf (STREAM, ",%d,0,315,%s\n", N_SO, &ltext_label_name[1]); \
- text_section (); \
- (*targetm.asm_out.internal_label) (STREAM, "Ltext", 0); \
- } \
- while (0)
-
/* Output a function label definition. */
#ifndef ASM_DECLARE_FUNCTION_NAME
#define ASM_DECLARE_FUNCTION_NAME(STREAM, NAME, DECL) \
@@ -265,7 +273,7 @@
#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
do \
{ \
- bss_section (); \
+ switch_to_section (bss_section); \
ASM_OUTPUT_ALIGN (STREAM, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (STREAM, NAME); \
fprintf (STREAM, "\t.space\t%d\n", (int)(SIZE)); \
diff --git a/contrib/gcc/config/arm/arm-cores.def b/contrib/gcc/config/arm/arm-cores.def
new file mode 100644
index 0000000..3f9b7ba
--- /dev/null
+++ b/contrib/gcc/config/arm/arm-cores.def
@@ -0,0 +1,117 @@
+/* ARM CPU Cores
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+ Written by CodeSourcery, LLC
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+/* Before using #include to read this file, define a macro:
+
+ ARM_CORE(CORE_NAME, CORE_IDENT, ARCH, FLAGS, COSTS)
+
+ The CORE_NAME is the name of the core, represented as a string constant.
+ The CORE_IDENT is the name of the core, represented as an identifier.
+ ARCH is the architecture revision implemented by the chip.
+ FLAGS are the bitwise-or of the traits that apply to that core.
+ This need not include flags implied by the architecture.
+ COSTS is the name of the rtx_costs routine to use.
+
+ If you update this table, you must update the "tune" attribute in
+ arm.md.
+
+ Some tools assume no whitespace up to the first "," in each entry. */
+
+/* V2/V2A Architecture Processors */
+ARM_CORE("arm2", arm2, 2, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm250", arm250, 2, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm3", arm3, 2, FL_CO_PROC | FL_MODE26, slowmul)
+
+/* V3 Architecture Processors */
+ARM_CORE("arm6", arm6, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm60", arm60, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm600", arm600, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm610", arm610, 3, FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm620", arm620, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm7", arm7, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm7d", arm7d, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm7di", arm7di, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm70", arm70, 3, FL_CO_PROC | FL_MODE26, slowmul)
+ARM_CORE("arm700", arm700, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm700i", arm700i, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm710", arm710, 3, FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm720", arm720, 3, FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm710c", arm710c, 3, FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm7100", arm7100, 3, FL_MODE26 | FL_WBUF, slowmul)
+ARM_CORE("arm7500", arm7500, 3, FL_MODE26 | FL_WBUF, slowmul)
+/* Doesn't have an external co-proc, but does have embedded fpa. */
+ARM_CORE("arm7500fe", arm7500fe, 3, FL_CO_PROC | FL_MODE26 | FL_WBUF, slowmul)
+
+/* V3M Architecture Processors */
+/* arm7m doesn't exist on its own, but only with D, ("and", and I), but
+ those don't alter the code, so arm7m is sometimes used. */
+ARM_CORE("arm7m", arm7m, 3M, FL_CO_PROC | FL_MODE26, fastmul)
+ARM_CORE("arm7dm", arm7dm, 3M, FL_CO_PROC | FL_MODE26, fastmul)
+ARM_CORE("arm7dmi", arm7dmi, 3M, FL_CO_PROC | FL_MODE26, fastmul)
+
+/* V4 Architecture Processors */
+ARM_CORE("arm8", arm8, 4, FL_MODE26 | FL_LDSCHED, fastmul)
+ARM_CORE("arm810", arm810, 4, FL_MODE26 | FL_LDSCHED, fastmul)
+ARM_CORE("strongarm", strongarm, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
+ARM_CORE("strongarm110", strongarm110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
+ARM_CORE("strongarm1100", strongarm1100, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
+ARM_CORE("strongarm1110", strongarm1110, 4, FL_MODE26 | FL_LDSCHED | FL_STRONG, fastmul)
+
+/* V4T Architecture Processors */
+ARM_CORE("arm7tdmi", arm7tdmi, 4T, FL_CO_PROC , fastmul)
+ARM_CORE("arm7tdmi-s", arm7tdmis, 4T, FL_CO_PROC , fastmul)
+ARM_CORE("arm710t", arm710t, 4T, FL_WBUF, fastmul)
+ARM_CORE("arm720t", arm720t, 4T, FL_WBUF, fastmul)
+ARM_CORE("arm740t", arm740t, 4T, FL_WBUF, fastmul)
+ARM_CORE("arm9", arm9, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("arm9tdmi", arm9tdmi, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("arm920", arm920, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("arm920t", arm920t, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("arm922t", arm922t, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("arm940t", arm940t, 4T, FL_LDSCHED, fastmul)
+ARM_CORE("ep9312", ep9312, 4T, FL_LDSCHED | FL_CIRRUS, fastmul)
+
+/* V5T Architecture Processors */
+ARM_CORE("arm10tdmi", arm10tdmi, 5T, FL_LDSCHED, fastmul)
+ARM_CORE("arm1020t", arm1020t, 5T, FL_LDSCHED, fastmul)
+
+/* V5TE Architecture Processors */
+ARM_CORE("arm9e", arm9e, 5TE, FL_LDSCHED, 9e)
+ARM_CORE("arm946e-s", arm946es, 5TE, FL_LDSCHED, 9e)
+ARM_CORE("arm966e-s", arm966es, 5TE, FL_LDSCHED, 9e)
+ARM_CORE("arm968e-s", arm968es, 5TE, FL_LDSCHED, 9e)
+ARM_CORE("arm10e", arm10e, 5TE, FL_LDSCHED, fastmul)
+ARM_CORE("arm1020e", arm1020e, 5TE, FL_LDSCHED, fastmul)
+ARM_CORE("arm1022e", arm1022e, 5TE, FL_LDSCHED, fastmul)
+ARM_CORE("xscale", xscale, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE, xscale)
+ARM_CORE("iwmmxt", iwmmxt, 5TE, FL_LDSCHED | FL_STRONG | FL_XSCALE | FL_IWMMXT, xscale)
+
+/* V5TEJ Architecture Processors */
+ARM_CORE("arm926ej-s", arm926ejs, 5TEJ, FL_LDSCHED, 9e)
+ARM_CORE("arm1026ej-s", arm1026ejs, 5TEJ, FL_LDSCHED, 9e)
+
+/* V6 Architecture Processors */
+ARM_CORE("arm1136j-s", arm1136js, 6J, FL_LDSCHED, 9e)
+ARM_CORE("arm1136jf-s", arm1136jfs, 6J, FL_LDSCHED | FL_VFPV2, 9e)
+ARM_CORE("arm1176jz-s", arm1176jzs, 6ZK, FL_LDSCHED, 9e)
+ARM_CORE("arm1176jzf-s", arm1176jzfs, 6ZK, FL_LDSCHED | FL_VFPV2, 9e)
+ARM_CORE("mpcorenovfp", mpcorenovfp, 6K, FL_LDSCHED, 9e)
+ARM_CORE("mpcore", mpcore, 6K, FL_LDSCHED | FL_VFPV2, 9e)
diff --git a/contrib/gcc/config/arm/arm-generic.md b/contrib/gcc/config/arm/arm-generic.md
new file mode 100644
index 0000000..6116486
--- /dev/null
+++ b/contrib/gcc/config/arm/arm-generic.md
@@ -0,0 +1,152 @@
+;; Generic ARM Pipeline Description
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+(define_automaton "arm")
+
+;; Write buffer
+;
+; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
+;
+; The write buffer on some of the arm6 processors is hard to model exactly.
+; There is room in the buffer for up to two addresses and up to eight words
+; of memory, but the two needn't be split evenly. When writing the two
+; addresses are fully pipelined. However, a read from memory that is not
+; currently in the cache will block until the writes have completed.
+; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
+; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
+; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
+; cycle to add as well.
+(define_cpu_unit "write_buf" "arm")
+
+;; Write blockage unit
+;
+; The write_blockage unit models (partially), the fact that reads will stall
+; until the write buffer empties.
+; The f_mem_r and r_mem_f could also block, but they are to the stack,
+; so we don't model them here
+(define_cpu_unit "write_blockage" "arm")
+
+;; Core
+;
+(define_cpu_unit "core" "arm")
+
+(define_insn_reservation "r_mem_f_wbuf" 5
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "yes")
+ (eq_attr "type" "r_mem_f")))
+ "core+write_buf*3")
+
+(define_insn_reservation "store_wbuf" 5
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "yes")
+ (eq_attr "type" "store1")))
+ "core+write_buf*3+write_blockage*5")
+
+(define_insn_reservation "store2_wbuf" 7
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "yes")
+ (eq_attr "type" "store2")))
+ "core+write_buf*4+write_blockage*7")
+
+(define_insn_reservation "store3_wbuf" 9
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "yes")
+ (eq_attr "type" "store3")))
+ "core+write_buf*5+write_blockage*9")
+
+(define_insn_reservation "store4_wbuf" 11
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "yes")
+ (eq_attr "type" "store4")))
+ "core+write_buf*6+write_blockage*11")
+
+(define_insn_reservation "store2" 3
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "no")
+ (eq_attr "type" "store2")))
+ "core*3")
+
+(define_insn_reservation "store3" 4
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "no")
+ (eq_attr "type" "store3")))
+ "core*4")
+
+(define_insn_reservation "store4" 5
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "model_wbuf" "no")
+ (eq_attr "type" "store4")))
+ "core*5")
+
+(define_insn_reservation "store_ldsched" 1
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "yes")
+ (eq_attr "type" "store1")))
+ "core")
+
+(define_insn_reservation "load_ldsched_xscale" 3
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "yes")
+ (and (eq_attr "type" "load_byte,load1")
+ (eq_attr "is_xscale" "yes"))))
+ "core")
+
+(define_insn_reservation "load_ldsched" 2
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "yes")
+ (and (eq_attr "type" "load_byte,load1")
+ (eq_attr "is_xscale" "no"))))
+ "core")
+
+(define_insn_reservation "load_or_store" 2
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "!yes")
+ (eq_attr "type" "load_byte,load1,load2,load3,load4,store1")))
+ "core*2")
+
+(define_insn_reservation "mult" 16
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")))
+ "core*16")
+
+(define_insn_reservation "mult_ldsched_strongarm" 3
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "yes")
+ (and (eq_attr "is_strongarm" "yes")
+ (eq_attr "type" "mult"))))
+ "core*2")
+
+(define_insn_reservation "mult_ldsched" 4
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "ldsched" "yes")
+ (and (eq_attr "is_strongarm" "no")
+ (eq_attr "type" "mult"))))
+ "core*4")
+
+(define_insn_reservation "multi_cycle" 32
+ (and (eq_attr "generic_sched" "yes")
+ (and (eq_attr "core_cycles" "multi")
+ (eq_attr "type" "!mult,load_byte,load1,load2,load3,load4,store1,store2,store3,store4")))
+ "core*32")
+
+(define_insn_reservation "single_cycle" 1
+ (and (eq_attr "generic_sched" "yes")
+ (eq_attr "core_cycles" "single"))
+ "core")
diff --git a/contrib/gcc/config/arm/arm-modes.def b/contrib/gcc/config/arm/arm-modes.def
index b853551..10ba025 100644
--- a/contrib/gcc/config/arm/arm-modes.def
+++ b/contrib/gcc/config/arm/arm-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com)
@@ -19,8 +19,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Extended precision floating point.
FIXME What format is this? */
@@ -50,3 +50,11 @@ CC_MODE (CC_DGEU);
CC_MODE (CC_DGTU);
CC_MODE (CC_C);
CC_MODE (CC_N);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
+
diff --git a/contrib/gcc/config/arm/arm-protos.h b/contrib/gcc/config/arm/arm-protos.h
index 0b28e74..c8c119e 100644
--- a/contrib/gcc/config/arm/arm-protos.h
+++ b/contrib/gcc/config/arm/arm-protos.h
@@ -1,5 +1,5 @@
/* Prototypes for exported functions defined in arm.c and pe.c
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Richard Earnshaw (rearnsha@arm.com)
Minor hacks by Nick Clifton (nickc@cygnus.com)
@@ -18,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#ifndef GCC_ARM_PROTOS_H
#define GCC_ARM_PROTOS_H
@@ -27,76 +27,57 @@
extern void arm_override_options (void);
extern int use_return_insn (int, rtx);
extern int arm_regno_class (int);
-extern void arm_finalize_pic (int);
+extern void arm_load_pic_register (unsigned long);
extern int arm_volatile_func (void);
extern const char *arm_output_epilogue (rtx);
extern void arm_expand_prologue (void);
-extern HOST_WIDE_INT arm_get_frame_size (void);
extern const char *arm_strip_name_encoding (const char *);
extern void arm_asm_output_labelref (FILE *, const char *);
extern unsigned long arm_current_func_type (void);
-extern unsigned int arm_compute_initial_elimination_offset (unsigned int,
- unsigned int);
+extern HOST_WIDE_INT arm_compute_initial_elimination_offset (unsigned int,
+ unsigned int);
+extern HOST_WIDE_INT thumb_compute_initial_elimination_offset (unsigned int,
+ unsigned int);
+extern unsigned int arm_dbx_register_number (unsigned int);
+extern void arm_output_fn_unwind (FILE *, bool);
+
#ifdef TREE_CODE
extern int arm_return_in_memory (tree);
extern void arm_encode_call_attribute (tree, int);
#endif
#ifdef RTX_CODE
+extern bool arm_vector_mode_supported_p (enum machine_mode);
extern int arm_hard_regno_mode_ok (unsigned int, enum machine_mode);
extern int const_ok_for_arm (HOST_WIDE_INT);
-extern int arm_split_constant (RTX_CODE, enum machine_mode, HOST_WIDE_INT, rtx,
- rtx, int);
-extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, rtx *);
+extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx,
+ HOST_WIDE_INT, rtx, rtx, int);
+extern RTX_CODE arm_canonicalize_comparison (RTX_CODE, enum machine_mode,
+ rtx *);
extern int legitimate_pic_operand_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
-extern int arm_legitimate_address_p (enum machine_mode, rtx, int);
+extern rtx legitimize_tls_address (rtx, rtx);
+extern int arm_legitimate_address_p (enum machine_mode, rtx, RTX_CODE, int);
extern int thumb_legitimate_address_p (enum machine_mode, rtx, int);
extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT);
extern rtx arm_legitimize_address (rtx, rtx, enum machine_mode);
-extern int const_double_rtx_ok_for_fpa (rtx);
+extern rtx thumb_legitimize_address (rtx, rtx, enum machine_mode);
+extern rtx thumb_legitimize_reload_address (rtx *, enum machine_mode, int, int,
+ int);
+extern int arm_const_double_rtx (rtx);
extern int neg_const_double_rtx_ok_for_fpa (rtx);
+extern enum reg_class coproc_secondary_reload_class (enum machine_mode, rtx,
+ bool);
+extern bool arm_tls_referenced_p (rtx);
-/* Predicates. */
-extern int s_register_operand (rtx, enum machine_mode);
-extern int arm_hard_register_operand (rtx, enum machine_mode);
-extern int f_register_operand (rtx, enum machine_mode);
-extern int reg_or_int_operand (rtx, enum machine_mode);
-extern int arm_reload_memory_operand (rtx, enum machine_mode);
-extern int arm_rhs_operand (rtx, enum machine_mode);
-extern int arm_rhsm_operand (rtx, enum machine_mode);
-extern int arm_add_operand (rtx, enum machine_mode);
-extern int arm_addimm_operand (rtx, enum machine_mode);
-extern int arm_not_operand (rtx, enum machine_mode);
-extern int offsettable_memory_operand (rtx, enum machine_mode);
-extern int alignable_memory_operand (rtx, enum machine_mode);
-extern int bad_signed_byte_operand (rtx, enum machine_mode);
-extern int fpa_rhs_operand (rtx, enum machine_mode);
-extern int fpa_add_operand (rtx, enum machine_mode);
-extern int power_of_two_operand (rtx, enum machine_mode);
-extern int nonimmediate_di_operand (rtx, enum machine_mode);
-extern int di_operand (rtx, enum machine_mode);
-extern int nonimmediate_soft_df_operand (rtx, enum machine_mode);
-extern int soft_df_operand (rtx, enum machine_mode);
-extern int index_operand (rtx, enum machine_mode);
-extern int const_shift_operand (rtx, enum machine_mode);
-extern int arm_comparison_operator (rtx, enum machine_mode);
-extern int shiftable_operator (rtx, enum machine_mode);
-extern int shift_operator (rtx, enum machine_mode);
-extern int equality_operator (rtx, enum machine_mode);
-extern int minmax_operator (rtx, enum machine_mode);
-extern int cc_register (rtx, enum machine_mode);
-extern int dominant_cc_register (rtx, enum machine_mode);
-extern int logical_binary_operator (rtx, enum machine_mode);
-extern int multi_register_push (rtx, enum machine_mode);
-extern int load_multiple_operation (rtx, enum machine_mode);
-extern int store_multiple_operation (rtx, enum machine_mode);
-extern int cirrus_fp_register (rtx, enum machine_mode);
-extern int cirrus_general_operand (rtx, enum machine_mode);
-extern int cirrus_register_operand (rtx, enum machine_mode);
-extern int cirrus_shift_const (rtx, enum machine_mode);
extern int cirrus_memory_offset (rtx);
+extern int arm_coproc_mem_operand (rtx, bool);
+extern int arm_no_early_store_addr_dep (rtx, rtx);
+extern int arm_no_early_alu_shift_dep (rtx, rtx);
+extern int arm_no_early_alu_shift_value_dep (rtx, rtx);
+extern int arm_no_early_mul_dep (rtx, rtx);
+extern int tls_mentioned_p (rtx);
extern int symbol_mentioned_p (rtx);
extern int label_mentioned_p (rtx);
extern RTX_CODE minmax_code (rtx);
@@ -109,8 +90,7 @@ extern rtx arm_gen_load_multiple (int, int, rtx, int, int,
rtx, HOST_WIDE_INT *);
extern rtx arm_gen_store_multiple (int, int, rtx, int, int,
rtx, HOST_WIDE_INT *);
-extern int arm_gen_movstrqi (rtx *);
-extern rtx arm_gen_rotated_half_load (rtx);
+extern int arm_gen_movmemqi (rtx *);
extern enum machine_mode arm_select_cc_mode (RTX_CODE, rtx, rtx);
extern enum machine_mode arm_select_dominance_cc_mode (rtx, rtx,
HOST_WIDE_INT);
@@ -118,6 +98,8 @@ extern rtx arm_gen_compare_reg (RTX_CODE, rtx, rtx);
extern rtx arm_gen_return_addr_mask (void);
extern void arm_reload_in_hi (rtx *);
extern void arm_reload_out_hi (rtx *);
+extern int arm_const_double_inline_cost (rtx);
+extern bool arm_const_double_by_parts (rtx);
extern const char *fp_immediate_constant (rtx);
extern const char *output_call (rtx *);
extern const char *output_call_mem (rtx *);
@@ -127,7 +109,6 @@ extern const char *output_mov_long_double_arm_from_arm (rtx *);
extern const char *output_mov_double_fpa_from_arm (rtx *);
extern const char *output_mov_double_arm_from_fpa (rtx *);
extern const char *output_move_double (rtx *);
-extern const char *output_mov_immediate (rtx *);
extern const char *output_add_immediate (rtx *);
extern const char *arithmetic_instr (rtx, int);
extern void output_ascii_pseudo_op (FILE *, const unsigned char *, int);
@@ -141,24 +122,27 @@ extern int arm_debugger_arg_offset (int, rtx);
extern int arm_is_longcall_p (rtx, int, int);
extern int arm_emit_vector_const (FILE *, rtx);
extern const char * arm_output_load_gr (rtx *);
+extern const char *vfp_output_fstmx (rtx *);
+extern void arm_set_return_address (rtx, rtx);
extern int arm_eliminable_register (rtx);
+extern bool arm_output_addr_const_extra (FILE *, rtx);
+
#if defined TREE_CODE
extern rtx arm_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
extern void arm_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
-extern rtx arm_va_arg (tree, tree);
-extern int arm_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
+extern bool arm_pad_arg_upward (enum machine_mode, tree);
+extern bool arm_pad_reg_upward (enum machine_mode, tree, int);
+extern bool arm_needs_doubleword_align (enum machine_mode, tree);
+extern rtx arm_function_value(tree, tree);
#endif
+extern int arm_apply_result_size (void);
-#if defined AOF_ASSEMBLER
+#if defined AOF_ASSEMBLER
extern rtx aof_pic_entry (rtx);
-extern char *aof_text_section (void);
-extern char *aof_data_section (void);
extern void aof_add_import (const char *);
extern void aof_delete_import (const char *);
extern void zero_init_section (void);
-extern void common_section (void);
#endif /* AOF_ASSEMBLER */
#endif /* RTX_CODE */
@@ -167,9 +151,7 @@ extern int arm_float_words_big_endian (void);
/* Thumb functions. */
extern void arm_init_expanders (void);
-extern int thumb_far_jump_used_p (int);
extern const char *thumb_unexpanded_epilogue (void);
-extern HOST_WIDE_INT thumb_get_frame_size (void);
extern void thumb_expand_prologue (void);
extern void thumb_expand_epilogue (void);
#ifdef TREE_CODE
@@ -180,14 +162,13 @@ extern int thumb_shiftable_const (unsigned HOST_WIDE_INT);
extern void thumb_final_prescan_insn (rtx);
extern const char *thumb_load_double_from_address (rtx *);
extern const char *thumb_output_move_mem_multiple (int, rtx *);
-extern void thumb_expand_movstrqi (rtx *);
-extern int thumb_cmp_operand (rtx, enum machine_mode);
-extern int thumb_cbrch_target_operand (rtx, enum machine_mode);
-extern rtx *thumb_legitimize_pic_address (rtx, enum machine_mode, rtx);
+extern const char *thumb_call_via_reg (rtx);
+extern void thumb_expand_movmemqi (rtx *);
extern int thumb_go_if_legitimate_address (enum machine_mode, rtx);
extern rtx arm_return_addr (int, rtx);
extern void thumb_reload_out_hi (rtx *);
extern void thumb_reload_in_hi (rtx *);
+extern void thumb_set_return_address (rtx, rtx);
#endif
/* Defined in pe.c. */
diff --git a/contrib/gcc/config/arm/arm-tune.md b/contrib/gcc/config/arm/arm-tune.md
new file mode 100644
index 0000000..950cd91
--- /dev/null
+++ b/contrib/gcc/config/arm/arm-tune.md
@@ -0,0 +1,5 @@
+;; -*- buffer-read-only: t -*-
+;; Generated automatically by gentune.sh from arm-cores.def
+(define_attr "tune"
+ "arm2,arm250,arm3,arm6,arm60,arm600,arm610,arm620,arm7,arm7d,arm7di,arm70,arm700,arm700i,arm710,arm720,arm710c,arm7100,arm7500,arm7500fe,arm7m,arm7dm,arm7dmi,arm8,arm810,strongarm,strongarm110,strongarm1100,strongarm1110,arm7tdmi,arm7tdmis,arm710t,arm720t,arm740t,arm9,arm9tdmi,arm920,arm920t,arm922t,arm940t,ep9312,arm10tdmi,arm1020t,arm9e,arm946es,arm966es,arm968es,arm10e,arm1020e,arm1022e,xscale,iwmmxt,arm926ejs,arm1026ejs,arm1136js,arm1136jfs,arm1176jzs,arm1176jzfs,mpcorenovfp,mpcore"
+ (const (symbol_ref "arm_tune")))
diff --git a/contrib/gcc/config/arm/arm.c b/contrib/gcc/config/arm/arm.c
index 2f0eaed..dc7aa77 100644
--- a/contrib/gcc/config/arm/arm.c
+++ b/contrib/gcc/config/arm/arm.c
@@ -1,6 +1,6 @@
/* Output routines for GCC for ARM.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -19,9 +19,9 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -51,6 +51,7 @@
#include "target.h"
#include "target-def.h"
#include "debug.h"
+#include "langhooks.h"
/* Forward definitions of types. */
typedef struct minipool_node Mnode;
@@ -59,34 +60,32 @@ typedef struct minipool_fixup Mfix;
const struct attribute_spec arm_attribute_table[];
/* Forward function declarations. */
+static arm_stack_offsets *arm_get_frame_offsets (void);
static void arm_add_gc_roots (void);
-static int arm_gen_constant (enum rtx_code, enum machine_mode, HOST_WIDE_INT,
- rtx, rtx, int, int);
+static int arm_gen_constant (enum rtx_code, enum machine_mode, rtx,
+ HOST_WIDE_INT, rtx, rtx, int, int);
static unsigned bit_count (unsigned long);
static int arm_address_register_rtx_p (rtx, int);
-static int arm_legitimate_index_p (enum machine_mode, rtx, int);
+static int arm_legitimate_index_p (enum machine_mode, rtx, RTX_CODE, int);
static int thumb_base_register_rtx_p (rtx, enum machine_mode, int);
inline static int thumb_index_register_rtx_p (rtx, int);
+static int thumb_far_jump_used_p (void);
+static bool thumb_force_lr_save (void);
static int const_ok_for_op (HOST_WIDE_INT, enum rtx_code);
-static rtx emit_multi_reg_push (int);
static rtx emit_sfm (int, int);
+static int arm_size_return_regs (void);
#ifndef AOF_ASSEMBLER
static bool arm_assemble_integer (rtx, unsigned int, int);
#endif
static const char *fp_const_from_val (REAL_VALUE_TYPE *);
static arm_cc get_arm_condition_code (rtx);
-static void init_fpa_table (void);
static HOST_WIDE_INT int_log2 (HOST_WIDE_INT);
static rtx is_jump_table (rtx);
static const char *output_multi_immediate (rtx *, const char *, const char *,
int, HOST_WIDE_INT);
-static void print_multi_reg (FILE *, const char *, int, int);
static const char *shift_op (rtx, HOST_WIDE_INT *);
static struct machine_function *arm_init_machine_status (void);
-static int number_of_first_bit_set (int);
-static void replace_symbols_in_block (tree, rtx, rtx);
-static void thumb_exit (FILE *, int, rtx);
-static void thumb_pushpop (FILE *, int, int, int *, int);
+static void thumb_exit (FILE *, int);
static rtx is_jump_table (rtx);
static HOST_WIDE_INT get_jump_table_size (rtx);
static Mnode *move_minipool_fix_forward_ref (Mnode *, Mnode *, HOST_WIDE_INT);
@@ -110,13 +109,15 @@ static unsigned long arm_isr_value (tree);
static unsigned long arm_compute_func_type (void);
static tree arm_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
static tree arm_handle_isr_attribute (tree *, tree, tree, int, bool *);
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+static tree arm_handle_notshared_attribute (tree *, tree, tree, int, bool *);
+#endif
static void arm_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void arm_output_function_prologue (FILE *, HOST_WIDE_INT);
static void thumb_output_function_prologue (FILE *, HOST_WIDE_INT);
static int arm_comp_type_attributes (tree, tree);
static void arm_set_default_type_attributes (tree);
static int arm_adjust_cost (rtx, rtx, rtx, int);
-static int arm_use_dfa_pipeline_interface (void);
static int count_insns_for_constant (HOST_WIDE_INT, int);
static int arm_get_strip_length (int);
static bool arm_function_ok_for_sibcall (tree, tree);
@@ -124,7 +125,11 @@ static void arm_internal_label (FILE *, const char *, unsigned long);
static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
tree);
static int arm_rtx_costs_1 (rtx, enum rtx_code, enum rtx_code);
-static bool arm_rtx_costs (rtx, int, int, int *);
+static bool arm_size_rtx_costs (rtx, int, int, int *);
+static bool arm_slowmul_rtx_costs (rtx, int, int, int *);
+static bool arm_fastmul_rtx_costs (rtx, int, int, int *);
+static bool arm_xscale_rtx_costs (rtx, int, int, int *);
+static bool arm_9e_rtx_costs (rtx, int, int, int *);
static int arm_address_cost (rtx);
static bool arm_memory_load_p (rtx);
static bool arm_cirrus_insn_p (rtx);
@@ -136,24 +141,60 @@ static rtx safe_vector_operand (rtx, enum machine_mode);
static rtx arm_expand_binop_builtin (enum insn_code, tree, rtx);
static rtx arm_expand_unop_builtin (enum insn_code, tree, rtx, int);
static rtx arm_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static void emit_constant_insn (rtx cond, rtx pattern);
+static rtx emit_set_insn (rtx, rtx);
+static int arm_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
#ifdef OBJECT_FORMAT_ELF
-static void arm_elf_asm_named_section (const char *, unsigned int);
+static void arm_elf_asm_constructor (rtx, int);
#endif
#ifndef ARM_PE
static void arm_encode_section_info (tree, rtx, int);
#endif
+
+static void arm_file_end (void);
+
#ifdef AOF_ASSEMBLER
static void aof_globalize_label (FILE *, const char *);
static void aof_dump_imports (FILE *);
static void aof_dump_pic_table (FILE *);
static void aof_file_start (void);
static void aof_file_end (void);
+static void aof_asm_init_sections (void);
#endif
+static void arm_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int *, int);
+static bool arm_pass_by_reference (CUMULATIVE_ARGS *,
+ enum machine_mode, tree, bool);
+static bool arm_promote_prototypes (tree);
+static bool arm_default_short_enums (void);
+static bool arm_align_anon_bitfield (void);
+static bool arm_return_in_msb (tree);
+static bool arm_must_pass_in_stack (enum machine_mode, tree);
+#ifdef TARGET_UNWIND_INFO
+static void arm_unwind_emit (FILE *, rtx);
+static bool arm_output_ttype (rtx);
+#endif
+
+static tree arm_cxx_guard_type (void);
+static bool arm_cxx_guard_mask_bit (void);
+static tree arm_get_cookie_size (tree);
+static bool arm_cookie_has_size (void);
+static bool arm_cxx_cdtor_returns_this (void);
+static bool arm_cxx_key_method_may_be_inline (void);
+static void arm_cxx_determine_class_data_visibility (tree);
+static bool arm_cxx_class_data_always_comdat (void);
+static bool arm_cxx_use_aeabi_atexit (void);
+static void arm_init_libfuncs (void);
+static bool arm_handle_option (size_t, const char *, int);
+static unsigned HOST_WIDE_INT arm_shift_truncation_mask (enum machine_mode);
+static bool arm_cannot_copy_insn_p (rtx);
+static bool arm_tls_symbol_p (rtx x);
/* Initialize the GCC target structure. */
-#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
#undef TARGET_MERGE_DECL_ATTRIBUTES
#define TARGET_MERGE_DECL_ATTRIBUTES merge_dllimport_decl_attributes
#endif
@@ -161,6 +202,9 @@ static void aof_file_end (void);
#undef TARGET_ATTRIBUTE_TABLE
#define TARGET_ATTRIBUTE_TABLE arm_attribute_table
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END arm_file_end
+
#ifdef AOF_ASSEMBLER
#undef TARGET_ASM_BYTE_OP
#define TARGET_ASM_BYTE_OP "\tDCB\t"
@@ -187,6 +231,11 @@ static void aof_file_end (void);
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE arm_output_function_epilogue
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_SCHED_PROLOG)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION arm_handle_option
+
#undef TARGET_COMP_TYPE_ATTRIBUTES
#define TARGET_COMP_TYPE_ATTRIBUTES arm_comp_type_attributes
@@ -196,9 +245,6 @@ static void aof_file_end (void);
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST arm_adjust_cost
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE arm_use_dfa_pipeline_interface
-
#undef TARGET_ENCODE_SECTION_INFO
#ifdef ARM_PE
#define TARGET_ENCODE_SECTION_INFO arm_pe_encode_section_info
@@ -220,11 +266,17 @@ static void aof_file_end (void);
#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
#define TARGET_ASM_CAN_OUTPUT_MI_THUNK default_can_output_mi_thunk_no_vcall
+/* This will be overridden in arm_override_options. */
#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS arm_rtx_costs
+#define TARGET_RTX_COSTS arm_slowmul_rtx_costs
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST arm_address_cost
+#undef TARGET_SHIFT_TRUNCATION_MASK
+#define TARGET_SHIFT_TRUNCATION_MASK arm_shift_truncation_mask
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P arm_vector_mode_supported_p
+
#undef TARGET_MACHINE_DEPENDENT_REORG
#define TARGET_MACHINE_DEPENDENT_REORG arm_reorg
@@ -233,6 +285,89 @@ static void aof_file_end (void);
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN arm_expand_builtin
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS arm_init_libfuncs
+
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES arm_promote_prototypes
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE arm_pass_by_reference
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES arm_arg_partial_bytes
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS arm_setup_incoming_varargs
+
+#undef TARGET_DEFAULT_SHORT_ENUMS
+#define TARGET_DEFAULT_SHORT_ENUMS arm_default_short_enums
+
+#undef TARGET_ALIGN_ANON_BITFIELD
+#define TARGET_ALIGN_ANON_BITFIELD arm_align_anon_bitfield
+
+#undef TARGET_NARROW_VOLATILE_BITFIELD
+#define TARGET_NARROW_VOLATILE_BITFIELD hook_bool_void_false
+
+#undef TARGET_CXX_GUARD_TYPE
+#define TARGET_CXX_GUARD_TYPE arm_cxx_guard_type
+
+#undef TARGET_CXX_GUARD_MASK_BIT
+#define TARGET_CXX_GUARD_MASK_BIT arm_cxx_guard_mask_bit
+
+#undef TARGET_CXX_GET_COOKIE_SIZE
+#define TARGET_CXX_GET_COOKIE_SIZE arm_get_cookie_size
+
+#undef TARGET_CXX_COOKIE_HAS_SIZE
+#define TARGET_CXX_COOKIE_HAS_SIZE arm_cookie_has_size
+
+#undef TARGET_CXX_CDTOR_RETURNS_THIS
+#define TARGET_CXX_CDTOR_RETURNS_THIS arm_cxx_cdtor_returns_this
+
+#undef TARGET_CXX_KEY_METHOD_MAY_BE_INLINE
+#define TARGET_CXX_KEY_METHOD_MAY_BE_INLINE arm_cxx_key_method_may_be_inline
+
+#undef TARGET_CXX_USE_AEABI_ATEXIT
+#define TARGET_CXX_USE_AEABI_ATEXIT arm_cxx_use_aeabi_atexit
+
+#undef TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY
+#define TARGET_CXX_DETERMINE_CLASS_DATA_VISIBILITY \
+ arm_cxx_determine_class_data_visibility
+
+#undef TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT
+#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT arm_cxx_class_data_always_comdat
+
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB arm_return_in_msb
+
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK arm_must_pass_in_stack
+
+#ifdef TARGET_UNWIND_INFO
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT arm_unwind_emit
+
+/* EABI unwinding tables use a different format for the typeinfo tables. */
+#undef TARGET_ASM_TTYPE
+#define TARGET_ASM_TTYPE arm_output_ttype
+
+#undef TARGET_ARM_EABI_UNWINDER
+#define TARGET_ARM_EABI_UNWINDER true
+#endif /* TARGET_UNWIND_INFO */
+
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P arm_cannot_copy_insn_p
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM arm_tls_referenced_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
@@ -252,25 +387,37 @@ int making_const_table;
stored from the compare operation. */
rtx arm_compare_op0, arm_compare_op1;
-/* What type of floating point are we tuning for? */
-enum fputype arm_fpu_tune;
+/* The processor for which instructions should be scheduled. */
+enum processor_type arm_tune = arm_none;
+
+/* Which floating point model to use. */
+enum arm_fp_model arm_fp_model;
-/* What type of floating point instructions are available? */
+/* Which floating point hardware is available. */
enum fputype arm_fpu_arch;
-/* What program mode is the cpu running in? 26-bit mode or 32-bit mode. */
-enum prog_mode_type arm_prgmode;
+/* Which floating point hardware to schedule for. */
+enum fputype arm_fpu_tune;
+
+/* Whether to use floating point hardware. */
+enum float_abi_type arm_float_abi;
+
+/* Which ABI to use. */
+enum arm_abi_type arm_abi;
-/* Set by the -mfp=... option. */
-const char * target_fp_name = NULL;
+/* Which thread pointer model to use. */
+enum arm_tp_type target_thread_pointer = TP_AUTO;
/* Used to parse -mstructure_size_boundary command line option. */
-const char * structure_size_string = NULL;
int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
+/* Used for Thumb call_via trampolines. */
+rtx thumb_call_via_label[14];
+static int thumb_call_reg_needed;
+
/* Bit values used to identify processor capabilities. */
#define FL_CO_PROC (1 << 0) /* Has external co-processor bus */
-#define FL_FAST_MULT (1 << 1) /* Fast multiply */
+#define FL_ARCH3M (1 << 1) /* Extended multiply */
#define FL_MODE26 (1 << 2) /* 26-bit mode support */
#define FL_MODE32 (1 << 3) /* 32-bit mode support */
#define FL_ARCH4 (1 << 4) /* Architecture rel 4 */
@@ -281,41 +428,71 @@ int arm_structure_size_boundary = DEFAULT_STRUCTURE_SIZE_BOUNDARY;
#define FL_ARCH5E (1 << 9) /* DSP extensions to v5 */
#define FL_XSCALE (1 << 10) /* XScale */
#define FL_CIRRUS (1 << 11) /* Cirrus/DSP. */
-#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
-#define FL_ARCH6J (1 << 12) /* Architecture rel 6. Adds
+#define FL_ARCH6 (1 << 12) /* Architecture rel 6. Adds
media instructions. */
#define FL_VFPV2 (1 << 13) /* Vector Floating Point V2. */
+#define FL_WBUF (1 << 14) /* Schedule for write buffer ops.
+ Note: ARM6 & 7 derivatives only. */
+#define FL_ARCH6K (1 << 15) /* Architecture rel 6 K extensions. */
+
+#define FL_IWMMXT (1 << 29) /* XScale v2 or "Intel Wireless MMX technology". */
+
+#define FL_FOR_ARCH2 0
+#define FL_FOR_ARCH3 FL_MODE32
+#define FL_FOR_ARCH3M (FL_FOR_ARCH3 | FL_ARCH3M)
+#define FL_FOR_ARCH4 (FL_FOR_ARCH3M | FL_ARCH4)
+#define FL_FOR_ARCH4T (FL_FOR_ARCH4 | FL_THUMB)
+#define FL_FOR_ARCH5 (FL_FOR_ARCH4 | FL_ARCH5)
+#define FL_FOR_ARCH5T (FL_FOR_ARCH5 | FL_THUMB)
+#define FL_FOR_ARCH5E (FL_FOR_ARCH5 | FL_ARCH5E)
+#define FL_FOR_ARCH5TE (FL_FOR_ARCH5E | FL_THUMB)
+#define FL_FOR_ARCH5TEJ FL_FOR_ARCH5TE
+#define FL_FOR_ARCH6 (FL_FOR_ARCH5TE | FL_ARCH6)
+#define FL_FOR_ARCH6J FL_FOR_ARCH6
+#define FL_FOR_ARCH6K (FL_FOR_ARCH6 | FL_ARCH6K)
+#define FL_FOR_ARCH6Z FL_FOR_ARCH6
+#define FL_FOR_ARCH6ZK FL_FOR_ARCH6K
/* The bits in this mask specify which
instructions we are allowed to generate. */
static unsigned long insn_flags = 0;
/* The bits in this mask specify which instruction scheduling options should
- be used. Note - there is an overlap with the FL_FAST_MULT. For some
- hardware we want to be able to generate the multiply instructions, but to
- tune as if they were not present in the architecture. */
+ be used. */
static unsigned long tune_flags = 0;
/* The following are used in the arm.md file as equivalents to bits
in the above two flag variables. */
-/* Nonzero if this is an "M" variant of the processor. */
-int arm_fast_multiply = 0;
+/* Nonzero if this chip supports the ARM Architecture 3M extensions. */
+int arm_arch3m = 0;
/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
int arm_arch4 = 0;
+/* Nonzero if this chip supports the ARM Architecture 4t extensions. */
+int arm_arch4t = 0;
+
/* Nonzero if this chip supports the ARM Architecture 5 extensions. */
int arm_arch5 = 0;
/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
int arm_arch5e = 0;
+/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
+int arm_arch6 = 0;
+
+/* Nonzero if this chip supports the ARM 6K extensions. */
+int arm_arch6k = 0;
+
/* Nonzero if this chip can benefit from load scheduling. */
int arm_ld_sched = 0;
/* Nonzero if this chip is a StrongARM. */
-int arm_is_strong = 0;
+int arm_tune_strongarm = 0;
+
+/* Nonzero if this chip is a Cirrus variant. */
+int arm_arch_cirrus = 0;
/* Nonzero if this chip supports Intel Wireless MMX technology. */
int arm_arch_iwmmxt = 0;
@@ -326,23 +503,27 @@ int arm_arch_xscale = 0;
/* Nonzero if tuning for XScale */
int arm_tune_xscale = 0;
-/* Nonzero if this chip is an ARM6 or an ARM7. */
-int arm_is_6_or_7 = 0;
-
-/* Nonzero if this chip is a Cirrus/DSP. */
-int arm_is_cirrus = 0;
+/* Nonzero if we want to tune for stores that access the write-buffer.
+ This typically means an ARM6 or ARM7 with MMU or MPU. */
+int arm_tune_wbuf = 0;
/* Nonzero if generating Thumb instructions. */
int thumb_code = 0;
+/* Nonzero if we should define __THUMB_INTERWORK__ in the
+ preprocessor.
+ XXX This is a bit of a hack, it's intended to help work around
+ problems in GLD which doesn't understand that armv5t code is
+ interworking clean. */
+int arm_cpp_interwork = 0;
+
/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
must report the mode of the memory reference from PRINT_OPERAND to
PRINT_OPERAND_ADDRESS. */
enum machine_mode output_memory_reference_mode;
/* The register number to be used for the PIC offset register. */
-const char * arm_pic_register_string = NULL;
-int arm_pic_register = INVALID_REGNUM;
+unsigned arm_pic_register = INVALID_REGNUM;
/* Set to 1 when a return insn is output, this means that the epilogue
is not needed. */
@@ -375,7 +556,10 @@ static const char * const arm_condition_codes[] =
struct processors
{
const char *const name;
+ enum processor_type core;
+ const char *arch;
const unsigned long flags;
+ bool (* rtx_costs) (rtx, int, int, int *);
};
/* Not all of these give usefully different compilation alternatives,
@@ -383,103 +567,162 @@ struct processors
static const struct processors all_cores[] =
{
/* ARM Cores */
-
- {"arm2", FL_CO_PROC | FL_MODE26 },
- {"arm250", FL_CO_PROC | FL_MODE26 },
- {"arm3", FL_CO_PROC | FL_MODE26 },
- {"arm6", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm60", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm600", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm610", FL_MODE26 | FL_MODE32 },
- {"arm620", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm7", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- /* arm7m doesn't exist on its own, but only with D, (and I), but
- those don't alter the code, so arm7m is sometimes used. */
- {"arm7m", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
- {"arm7d", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm7dm", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
- {"arm7di", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm7dmi", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
- {"arm70", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm700", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm700i", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- {"arm710", FL_MODE26 | FL_MODE32 },
- {"arm720", FL_MODE26 | FL_MODE32 },
- {"arm710c", FL_MODE26 | FL_MODE32 },
- {"arm7100", FL_MODE26 | FL_MODE32 },
- {"arm7500", FL_MODE26 | FL_MODE32 },
- /* Doesn't have an external co-proc, but does have embedded fpa. */
- {"arm7500fe", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- /* V4 Architecture Processors */
- {"arm7tdmi", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- {"arm710t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- {"arm720t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- {"arm740t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- {"arm8", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED },
- {"arm810", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED },
- {"arm9", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
- {"arm920", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED },
- {"arm920t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
- {"arm940t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
- {"arm9tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED },
- {"arm9e", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED },
- {"ep9312", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_CIRRUS },
- {"strongarm", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
- {"strongarm110", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
- {"strongarm1100", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
- {"strongarm1110", FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_STRONG },
- /* V5 Architecture Processors */
- {"arm10tdmi", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
- {"arm1020t", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_ARCH5 },
- {"arm926ejs", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
- {"arm1026ejs", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
- {"xscale", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE },
- {"iwmmxt", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE | FL_IWMMXT },
- /* V6 Architecture Processors */
- {"arm1136js", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E | FL_ARCH6J },
- {"arm1136jfs", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E | FL_ARCH6J | FL_VFPV2 },
- {NULL, 0}
+#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
+ {NAME, arm_none, #ARCH, FLAGS | FL_FOR_ARCH##ARCH, arm_##COSTS##_rtx_costs},
+#include "arm-cores.def"
+#undef ARM_CORE
+ {NULL, arm_none, NULL, 0, NULL}
};
static const struct processors all_architectures[] =
{
/* ARM Architectures */
-
- { "armv2", FL_CO_PROC | FL_MODE26 },
- { "armv2a", FL_CO_PROC | FL_MODE26 },
- { "armv3", FL_CO_PROC | FL_MODE26 | FL_MODE32 },
- { "armv3m", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT },
- { "armv4", FL_CO_PROC | FL_MODE26 | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 },
+ /* We don't specify rtx_costs here as it will be figured out
+ from the core. */
+
+ {"armv2", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL},
+ {"armv2a", arm2, "2", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH2, NULL},
+ {"armv3", arm6, "3", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3, NULL},
+ {"armv3m", arm7m, "3M", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH3M, NULL},
+ {"armv4", arm7tdmi, "4", FL_CO_PROC | FL_MODE26 | FL_FOR_ARCH4, NULL},
/* Strictly, FL_MODE26 is a permitted option for v4t, but there are no
implementations that support it, so we will leave it out for now. */
- { "armv4t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB },
- { "armv5", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
- { "armv5t", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 },
- { "armv5te", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E },
- { "armv6j", FL_CO_PROC | FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_ARCH5 | FL_ARCH5E | FL_ARCH6J },
- { "ep9312", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_LDSCHED | FL_CIRRUS },
- {"iwmmxt", FL_MODE32 | FL_FAST_MULT | FL_ARCH4 | FL_THUMB | FL_LDSCHED | FL_STRONG | FL_ARCH5 | FL_ARCH5E | FL_XSCALE | FL_IWMMXT },
- { NULL, 0 }
+ {"armv4t", arm7tdmi, "4T", FL_CO_PROC | FL_FOR_ARCH4T, NULL},
+ {"armv5", arm10tdmi, "5", FL_CO_PROC | FL_FOR_ARCH5, NULL},
+ {"armv5t", arm10tdmi, "5T", FL_CO_PROC | FL_FOR_ARCH5T, NULL},
+ {"armv5e", arm1026ejs, "5E", FL_CO_PROC | FL_FOR_ARCH5E, NULL},
+ {"armv5te", arm1026ejs, "5TE", FL_CO_PROC | FL_FOR_ARCH5TE, NULL},
+ {"armv6", arm1136js, "6", FL_CO_PROC | FL_FOR_ARCH6, NULL},
+ {"armv6j", arm1136js, "6J", FL_CO_PROC | FL_FOR_ARCH6J, NULL},
+ {"armv6k", mpcore, "6K", FL_CO_PROC | FL_FOR_ARCH6K, NULL},
+ {"armv6z", arm1176jzs, "6Z", FL_CO_PROC | FL_FOR_ARCH6Z, NULL},
+ {"armv6zk", arm1176jzs, "6ZK", FL_CO_PROC | FL_FOR_ARCH6ZK, NULL},
+ {"ep9312", ep9312, "4T", FL_LDSCHED | FL_CIRRUS | FL_FOR_ARCH4, NULL},
+ {"iwmmxt", iwmmxt, "5TE", FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT , NULL},
+ {NULL, arm_none, NULL, 0 , NULL}
+};
+
+struct arm_cpu_select
+{
+ const char * string;
+ const char * name;
+ const struct processors * processors;
};
/* This is a magic structure. The 'string' field is magically filled in
with a pointer to the value specified by the user on the command line
assuming that the user has specified such a value. */
-struct arm_cpu_select arm_select[] =
+static struct arm_cpu_select arm_select[] =
{
- /* string name processors */
+ /* string name processors */
{ NULL, "-mcpu=", all_cores },
{ NULL, "-march=", all_architectures },
{ NULL, "-mtune=", all_cores }
};
+/* Defines representing the indexes into the above table. */
+#define ARM_OPT_SET_CPU 0
+#define ARM_OPT_SET_ARCH 1
+#define ARM_OPT_SET_TUNE 2
+
+/* The name of the preprocessor macro to define for this architecture. */
+
+char arm_arch_name[] = "__ARM_ARCH_0UNK__";
+
+struct fpu_desc
+{
+ const char * name;
+ enum fputype fpu;
+};
+
+
+/* Available values for -mfpu=. */
+
+static const struct fpu_desc all_fpus[] =
+{
+ {"fpa", FPUTYPE_FPA},
+ {"fpe2", FPUTYPE_FPA_EMU2},
+ {"fpe3", FPUTYPE_FPA_EMU2},
+ {"maverick", FPUTYPE_MAVERICK},
+ {"vfp", FPUTYPE_VFP}
+};
+
+
+/* Floating point models used by the different hardware.
+ See fputype in arm.h. */
+
+static const enum fputype fp_model_for_fpu[] =
+{
+ /* No FP hardware. */
+ ARM_FP_MODEL_UNKNOWN, /* FPUTYPE_NONE */
+ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA */
+ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU2 */
+ ARM_FP_MODEL_FPA, /* FPUTYPE_FPA_EMU3 */
+ ARM_FP_MODEL_MAVERICK, /* FPUTYPE_MAVERICK */
+ ARM_FP_MODEL_VFP /* FPUTYPE_VFP */
+};
+
+
+struct float_abi
+{
+ const char * name;
+ enum float_abi_type abi_type;
+};
+
+
+/* Available values for -mfloat-abi=. */
+
+static const struct float_abi all_float_abis[] =
+{
+ {"soft", ARM_FLOAT_ABI_SOFT},
+ {"softfp", ARM_FLOAT_ABI_SOFTFP},
+ {"hard", ARM_FLOAT_ABI_HARD}
+};
+
+
+struct abi_name
+{
+ const char *name;
+ enum arm_abi_type abi_type;
+};
+
+
+/* Available values for -mabi=. */
+
+static const struct abi_name arm_all_abis[] =
+{
+ {"apcs-gnu", ARM_ABI_APCS},
+ {"atpcs", ARM_ABI_ATPCS},
+ {"aapcs", ARM_ABI_AAPCS},
+ {"iwmmxt", ARM_ABI_IWMMXT},
+ {"aapcs-linux", ARM_ABI_AAPCS_LINUX}
+};
+
+/* Supported TLS relocations. */
+
+enum tls_reloc {
+ TLS_GD32,
+ TLS_LDM32,
+ TLS_LDO32,
+ TLS_IE32,
+ TLS_LE32
+};
+
+/* Emit an insn that's a simple single-set. Both the operands must be known
+ to be valid. */
+inline static rtx
+emit_set_insn (rtx x, rtx y)
+{
+ return emit_insn (gen_rtx_SET (VOIDmode, x, y));
+}
+
/* Return the number of bits set in VALUE. */
static unsigned
bit_count (unsigned long value)
{
unsigned long count = 0;
-
+
while (value)
{
count++;
@@ -489,18 +732,159 @@ bit_count (unsigned long value)
return count;
}
+/* Set up library functions unique to ARM. */
+
+static void
+arm_init_libfuncs (void)
+{
+ /* There are no special library functions unless we are using the
+ ARM BPABI. */
+ if (!TARGET_BPABI)
+ return;
+
+ /* The functions below are described in Section 4 of the "Run-Time
+ ABI for the ARM architecture", Version 1.0. */
+
+ /* Double-precision floating-point arithmetic. Table 2. */
+ set_optab_libfunc (add_optab, DFmode, "__aeabi_dadd");
+ set_optab_libfunc (sdiv_optab, DFmode, "__aeabi_ddiv");
+ set_optab_libfunc (smul_optab, DFmode, "__aeabi_dmul");
+ set_optab_libfunc (neg_optab, DFmode, "__aeabi_dneg");
+ set_optab_libfunc (sub_optab, DFmode, "__aeabi_dsub");
+
+ /* Double-precision comparisons. Table 3. */
+ set_optab_libfunc (eq_optab, DFmode, "__aeabi_dcmpeq");
+ set_optab_libfunc (ne_optab, DFmode, NULL);
+ set_optab_libfunc (lt_optab, DFmode, "__aeabi_dcmplt");
+ set_optab_libfunc (le_optab, DFmode, "__aeabi_dcmple");
+ set_optab_libfunc (ge_optab, DFmode, "__aeabi_dcmpge");
+ set_optab_libfunc (gt_optab, DFmode, "__aeabi_dcmpgt");
+ set_optab_libfunc (unord_optab, DFmode, "__aeabi_dcmpun");
+
+ /* Single-precision floating-point arithmetic. Table 4. */
+ set_optab_libfunc (add_optab, SFmode, "__aeabi_fadd");
+ set_optab_libfunc (sdiv_optab, SFmode, "__aeabi_fdiv");
+ set_optab_libfunc (smul_optab, SFmode, "__aeabi_fmul");
+ set_optab_libfunc (neg_optab, SFmode, "__aeabi_fneg");
+ set_optab_libfunc (sub_optab, SFmode, "__aeabi_fsub");
+
+ /* Single-precision comparisons. Table 5. */
+ set_optab_libfunc (eq_optab, SFmode, "__aeabi_fcmpeq");
+ set_optab_libfunc (ne_optab, SFmode, NULL);
+ set_optab_libfunc (lt_optab, SFmode, "__aeabi_fcmplt");
+ set_optab_libfunc (le_optab, SFmode, "__aeabi_fcmple");
+ set_optab_libfunc (ge_optab, SFmode, "__aeabi_fcmpge");
+ set_optab_libfunc (gt_optab, SFmode, "__aeabi_fcmpgt");
+ set_optab_libfunc (unord_optab, SFmode, "__aeabi_fcmpun");
+
+ /* Floating-point to integer conversions. Table 6. */
+ set_conv_libfunc (sfix_optab, SImode, DFmode, "__aeabi_d2iz");
+ set_conv_libfunc (ufix_optab, SImode, DFmode, "__aeabi_d2uiz");
+ set_conv_libfunc (sfix_optab, DImode, DFmode, "__aeabi_d2lz");
+ set_conv_libfunc (ufix_optab, DImode, DFmode, "__aeabi_d2ulz");
+ set_conv_libfunc (sfix_optab, SImode, SFmode, "__aeabi_f2iz");
+ set_conv_libfunc (ufix_optab, SImode, SFmode, "__aeabi_f2uiz");
+ set_conv_libfunc (sfix_optab, DImode, SFmode, "__aeabi_f2lz");
+ set_conv_libfunc (ufix_optab, DImode, SFmode, "__aeabi_f2ulz");
+
+ /* Conversions between floating types. Table 7. */
+ set_conv_libfunc (trunc_optab, SFmode, DFmode, "__aeabi_d2f");
+ set_conv_libfunc (sext_optab, DFmode, SFmode, "__aeabi_f2d");
+
+ /* Integer to floating-point conversions. Table 8. */
+ set_conv_libfunc (sfloat_optab, DFmode, SImode, "__aeabi_i2d");
+ set_conv_libfunc (ufloat_optab, DFmode, SImode, "__aeabi_ui2d");
+ set_conv_libfunc (sfloat_optab, DFmode, DImode, "__aeabi_l2d");
+ set_conv_libfunc (ufloat_optab, DFmode, DImode, "__aeabi_ul2d");
+ set_conv_libfunc (sfloat_optab, SFmode, SImode, "__aeabi_i2f");
+ set_conv_libfunc (ufloat_optab, SFmode, SImode, "__aeabi_ui2f");
+ set_conv_libfunc (sfloat_optab, SFmode, DImode, "__aeabi_l2f");
+ set_conv_libfunc (ufloat_optab, SFmode, DImode, "__aeabi_ul2f");
+
+ /* Long long. Table 9. */
+ set_optab_libfunc (smul_optab, DImode, "__aeabi_lmul");
+ set_optab_libfunc (sdivmod_optab, DImode, "__aeabi_ldivmod");
+ set_optab_libfunc (udivmod_optab, DImode, "__aeabi_uldivmod");
+ set_optab_libfunc (ashl_optab, DImode, "__aeabi_llsl");
+ set_optab_libfunc (lshr_optab, DImode, "__aeabi_llsr");
+ set_optab_libfunc (ashr_optab, DImode, "__aeabi_lasr");
+ set_optab_libfunc (cmp_optab, DImode, "__aeabi_lcmp");
+ set_optab_libfunc (ucmp_optab, DImode, "__aeabi_ulcmp");
+
+ /* Integer (32/32->32) division. \S 4.3.1. */
+ set_optab_libfunc (sdivmod_optab, SImode, "__aeabi_idivmod");
+ set_optab_libfunc (udivmod_optab, SImode, "__aeabi_uidivmod");
+
+ /* The divmod functions are designed so that they can be used for
+ plain division, even though they return both the quotient and the
+ remainder. The quotient is returned in the usual location (i.e.,
+ r0 for SImode, {r0, r1} for DImode), just as would be expected
+ for an ordinary division routine. Because the AAPCS calling
+ conventions specify that all of { r0, r1, r2, r3 } are
+ callee-saved registers, there is no need to tell the compiler
+ explicitly that those registers are clobbered by these
+ routines. */
+ set_optab_libfunc (sdiv_optab, DImode, "__aeabi_ldivmod");
+ set_optab_libfunc (udiv_optab, DImode, "__aeabi_uldivmod");
+
+ /* For SImode division the ABI provides div-without-mod routines,
+ which are faster. */
+ set_optab_libfunc (sdiv_optab, SImode, "__aeabi_idiv");
+ set_optab_libfunc (udiv_optab, SImode, "__aeabi_uidiv");
+
+ /* We don't have mod libcalls. Fortunately gcc knows how to use the
+ divmod libcalls instead. */
+ set_optab_libfunc (smod_optab, DImode, NULL);
+ set_optab_libfunc (umod_optab, DImode, NULL);
+ set_optab_libfunc (smod_optab, SImode, NULL);
+ set_optab_libfunc (umod_optab, SImode, NULL);
+}
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+arm_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_march_:
+ arm_select[1].string = arg;
+ return true;
+
+ case OPT_mcpu_:
+ arm_select[0].string = arg;
+ return true;
+
+ case OPT_mhard_float:
+ target_float_abi_name = "hard";
+ return true;
+
+ case OPT_msoft_float:
+ target_float_abi_name = "soft";
+ return true;
+
+ case OPT_mtune_:
+ arm_select[2].string = arg;
+ return true;
+
+ default:
+ return true;
+ }
+}
+
/* Fix up any incompatible options that the user has specified.
This has now turned into a maze. */
void
arm_override_options (void)
{
unsigned i;
-
+ enum processor_type target_arch_cpu = arm_none;
+
/* Set up the flags based on the cpu/architecture selected by the user. */
for (i = ARRAY_SIZE (arm_select); i--;)
{
struct arm_cpu_select * ptr = arm_select + i;
-
+
if (ptr->string != NULL && ptr->string[0] != '\0')
{
const struct processors * sel;
@@ -508,21 +892,38 @@ arm_override_options (void)
for (sel = ptr->processors; sel->name != NULL; sel++)
if (streq (ptr->string, sel->name))
{
- if (i == 2)
- tune_flags = sel->flags;
- else
+ /* Set the architecture define. */
+ if (i != ARM_OPT_SET_TUNE)
+ sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
+
+ /* Determine the processor core for which we should
+ tune code-generation. */
+ if (/* -mcpu= is a sensible default. */
+ i == ARM_OPT_SET_CPU
+ /* -mtune= overrides -mcpu= and -march=. */
+ || i == ARM_OPT_SET_TUNE)
+ arm_tune = (enum processor_type) (sel - ptr->processors);
+
+ /* Remember the CPU associated with this architecture.
+ If no other option is used to set the CPU type,
+ we'll use this to guess the most suitable tuning
+ options. */
+ if (i == ARM_OPT_SET_ARCH)
+ target_arch_cpu = sel->core;
+
+ if (i != ARM_OPT_SET_TUNE)
{
/* If we have been given an architecture and a processor
make sure that they are compatible. We only generate
a warning though, and we prefer the CPU over the
architecture. */
if (insn_flags != 0 && (insn_flags ^ sel->flags))
- warning ("switch -mcpu=%s conflicts with -march= switch",
+ warning (0, "switch -mcpu=%s conflicts with -march= switch",
ptr->string);
-
+
insn_flags = sel->flags;
}
-
+
break;
}
@@ -530,71 +931,41 @@ arm_override_options (void)
error ("bad value (%s) for %s switch", ptr->string, ptr->name);
}
}
-
+
+ /* Guess the tuning options from the architecture if necessary. */
+ if (arm_tune == arm_none)
+ arm_tune = target_arch_cpu;
+
/* If the user did not specify a processor, choose one for them. */
if (insn_flags == 0)
{
const struct processors * sel;
unsigned int sought;
- static const struct cpu_default
- {
- const int cpu;
- const char *const name;
- }
- cpu_defaults[] =
- {
- { TARGET_CPU_arm2, "arm2" },
- { TARGET_CPU_arm6, "arm6" },
- { TARGET_CPU_arm610, "arm610" },
- { TARGET_CPU_arm710, "arm710" },
- { TARGET_CPU_arm7m, "arm7m" },
- { TARGET_CPU_arm7500fe, "arm7500fe" },
- { TARGET_CPU_arm7tdmi, "arm7tdmi" },
- { TARGET_CPU_arm8, "arm8" },
- { TARGET_CPU_arm810, "arm810" },
- { TARGET_CPU_arm9, "arm9" },
- { TARGET_CPU_strongarm, "strongarm" },
- { TARGET_CPU_xscale, "xscale" },
- { TARGET_CPU_ep9312, "ep9312" },
- { TARGET_CPU_iwmmxt, "iwmmxt" },
- { TARGET_CPU_arm926ej_s, "arm926ej-s" },
- { TARGET_CPU_arm1026ej_s, "arm1026ej-s" },
- { TARGET_CPU_arm1136j_s, "arm1136j_s" },
- { TARGET_CPU_arm1136jf_s, "arm1136jf_s" },
- { TARGET_CPU_generic, "arm" },
- { 0, 0 }
- };
- const struct cpu_default * def;
-
- /* Find the default. */
- for (def = cpu_defaults; def->name; def++)
- if (def->cpu == TARGET_CPU_DEFAULT)
- break;
+ enum processor_type cpu;
- /* Make sure we found the default CPU. */
- if (def->name == NULL)
- abort ();
-
- /* Find the default CPU's flags. */
- for (sel = all_cores; sel->name != NULL; sel++)
- if (streq (def->name, sel->name))
- break;
-
- if (sel->name == NULL)
- abort ();
+ cpu = TARGET_CPU_DEFAULT;
+ if (cpu == arm_none)
+ {
+#ifdef SUBTARGET_CPU_DEFAULT
+ /* Use the subtarget default CPU if none was specified by
+ configure. */
+ cpu = SUBTARGET_CPU_DEFAULT;
+#endif
+ /* Default to ARM6. */
+ if (cpu == arm_none)
+ cpu = arm6;
+ }
+ sel = &all_cores[cpu];
insn_flags = sel->flags;
-
+
/* Now check to see if the user has specified some command line
switch that require certain abilities from the cpu. */
sought = 0;
-
+
if (TARGET_INTERWORK || TARGET_THUMB)
{
sought |= (FL_THUMB | FL_MODE32);
-
- /* Force apcs-32 to be used for interworking. */
- target_flags |= ARM_FLAG_APCS_32;
/* There are no ARM processors that support both APCS-26 and
interworking. Therefore we force FL_MODE26 to be removed
@@ -602,9 +973,7 @@ arm_override_options (void)
below will always be able to find a compatible processor. */
insn_flags &= ~FL_MODE26;
}
- else if (!TARGET_APCS_32)
- sought |= FL_MODE26;
-
+
if (sought != 0 && ((sought & insn_flags) != sought))
{
/* Try to locate a CPU type that supports all of the abilities
@@ -618,7 +987,7 @@ arm_override_options (void)
{
unsigned current_bit_count = 0;
const struct processors * best_fit = NULL;
-
+
/* Ideally we would like to issue an error message here
saying that it was not possible to find a CPU compatible
with the default CPU, but which also supports the command
@@ -626,12 +995,10 @@ arm_override_options (void)
ought to use the -mcpu=<name> command line option to
override the default CPU type.
- Unfortunately this does not work with multilibing. We
- need to be able to support multilibs for -mapcs-26 and for
- -mthumb-interwork and there is no CPU that can support both
- options. Instead if we cannot find a cpu that has both the
- characteristics of the default cpu and the given command line
- options we scan the array again looking for a best match. */
+ If we cannot find a cpu that has both the
+ characteristics of the default cpu and the given
+ command line options we scan the array again looking
+ for a best match. */
for (sel = all_cores; sel->name != NULL; sel++)
if ((sel->flags & sought) == sought)
{
@@ -646,184 +1013,275 @@ arm_override_options (void)
}
}
- if (best_fit == NULL)
- abort ();
- else
- sel = best_fit;
+ gcc_assert (best_fit);
+ sel = best_fit;
}
insn_flags = sel->flags;
}
+ sprintf (arm_arch_name, "__ARM_ARCH_%s__", sel->arch);
+ if (arm_tune == arm_none)
+ arm_tune = (enum processor_type) (sel - all_cores);
}
-
- /* If tuning has not been specified, tune for whichever processor or
- architecture has been selected. */
- if (tune_flags == 0)
- tune_flags = insn_flags;
+
+ /* The processor for which we should tune should now have been
+ chosen. */
+ gcc_assert (arm_tune != arm_none);
+
+ tune_flags = all_cores[(int)arm_tune].flags;
+ if (optimize_size)
+ targetm.rtx_costs = arm_size_rtx_costs;
+ else
+ targetm.rtx_costs = all_cores[(int)arm_tune].rtx_costs;
/* Make sure that the processor choice does not conflict with any of the
other command line choices. */
- if (TARGET_APCS_32 && !(insn_flags & FL_MODE32))
- {
- /* If APCS-32 was not the default then it must have been set by the
- user, so issue a warning message. If the user has specified
- "-mapcs-32 -mcpu=arm2" then we loose here. */
- if ((TARGET_DEFAULT & ARM_FLAG_APCS_32) == 0)
- warning ("target CPU does not support APCS-32" );
- target_flags &= ~ARM_FLAG_APCS_32;
- }
- else if (!TARGET_APCS_32 && !(insn_flags & FL_MODE26))
- {
- warning ("target CPU does not support APCS-26" );
- target_flags |= ARM_FLAG_APCS_32;
- }
-
if (TARGET_INTERWORK && !(insn_flags & FL_THUMB))
{
- warning ("target CPU does not support interworking" );
- target_flags &= ~ARM_FLAG_INTERWORK;
+ warning (0, "target CPU does not support interworking" );
+ target_flags &= ~MASK_INTERWORK;
}
-
+
if (TARGET_THUMB && !(insn_flags & FL_THUMB))
{
- warning ("target CPU does not support THUMB instructions");
- target_flags &= ~ARM_FLAG_THUMB;
+ warning (0, "target CPU does not support THUMB instructions");
+ target_flags &= ~MASK_THUMB;
}
- if (!TARGET_APCS_32)
- inform ("future releases of GCC will not support -mapcs-26");
-
if (TARGET_APCS_FRAME && TARGET_THUMB)
{
- /* warning ("ignoring -mapcs-frame because -mthumb was used"); */
- target_flags &= ~ARM_FLAG_APCS_FRAME;
+ /* warning (0, "ignoring -mapcs-frame because -mthumb was used"); */
+ target_flags &= ~MASK_APCS_FRAME;
}
+ /* Callee super interworking implies thumb interworking. Adding
+ this to the flags here simplifies the logic elsewhere. */
+ if (TARGET_THUMB && TARGET_CALLEE_INTERWORKING)
+ target_flags |= MASK_INTERWORK;
+
/* TARGET_BACKTRACE calls leaf_function_p, which causes a crash if done
from here where no function is being compiled currently. */
- if ((target_flags & (THUMB_FLAG_LEAF_BACKTRACE | THUMB_FLAG_BACKTRACE))
- && TARGET_ARM)
- warning ("enabling backtrace support is only meaningful when compiling for the Thumb");
+ if ((TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) && TARGET_ARM)
+ warning (0, "enabling backtrace support is only meaningful when compiling for the Thumb");
if (TARGET_ARM && TARGET_CALLEE_INTERWORKING)
- warning ("enabling callee interworking support is only meaningful when compiling for the Thumb");
+ warning (0, "enabling callee interworking support is only meaningful when compiling for the Thumb");
if (TARGET_ARM && TARGET_CALLER_INTERWORKING)
- warning ("enabling caller interworking support is only meaningful when compiling for the Thumb");
+ warning (0, "enabling caller interworking support is only meaningful when compiling for the Thumb");
- /* If interworking is enabled then APCS-32 must be selected as well. */
- if (TARGET_INTERWORK)
- {
- if (!TARGET_APCS_32)
- warning ("interworking forces APCS-32 to be used" );
- target_flags |= ARM_FLAG_APCS_32;
- }
-
if (TARGET_APCS_STACK && !TARGET_APCS_FRAME)
{
- warning ("-mapcs-stack-check incompatible with -mno-apcs-frame");
- target_flags |= ARM_FLAG_APCS_FRAME;
+ warning (0, "-mapcs-stack-check incompatible with -mno-apcs-frame");
+ target_flags |= MASK_APCS_FRAME;
}
-
+
if (TARGET_POKE_FUNCTION_NAME)
- target_flags |= ARM_FLAG_APCS_FRAME;
-
+ target_flags |= MASK_APCS_FRAME;
+
if (TARGET_APCS_REENT && flag_pic)
error ("-fpic and -mapcs-reent are incompatible");
-
+
if (TARGET_APCS_REENT)
- warning ("APCS reentrant code not supported. Ignored");
-
+ warning (0, "APCS reentrant code not supported. Ignored");
+
/* If this target is normally configured to use APCS frames, warn if they
are turned off and debugging is turned on. */
if (TARGET_ARM
&& write_symbols != NO_DEBUG
&& !TARGET_APCS_FRAME
- && (TARGET_DEFAULT & ARM_FLAG_APCS_FRAME))
- warning ("-g with -mno-apcs-frame may not give sensible debugging");
-
+ && (TARGET_DEFAULT & MASK_APCS_FRAME))
+ warning (0, "-g with -mno-apcs-frame may not give sensible debugging");
+
/* If stack checking is disabled, we can use r10 as the PIC register,
which keeps r9 available. */
- if (flag_pic)
+ if (flag_pic && TARGET_SINGLE_PIC_BASE)
arm_pic_register = TARGET_APCS_STACK ? 9 : 10;
-
+
if (TARGET_APCS_FLOAT)
- warning ("passing floating point arguments in fp regs not yet supported");
-
- /* Initialize boolean versions of the flags, for use in the arm.md file. */
- arm_fast_multiply = (insn_flags & FL_FAST_MULT) != 0;
- arm_arch4 = (insn_flags & FL_ARCH4) != 0;
- arm_arch5 = (insn_flags & FL_ARCH5) != 0;
- arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
- arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
+ warning (0, "passing floating point arguments in fp regs not yet supported");
- arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
- arm_is_strong = (tune_flags & FL_STRONG) != 0;
- thumb_code = (TARGET_ARM == 0);
- arm_is_6_or_7 = (((tune_flags & (FL_MODE26 | FL_MODE32))
- && !(tune_flags & FL_ARCH4))) != 0;
- arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
- arm_is_cirrus = (tune_flags & FL_CIRRUS) != 0;
- arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0;
+ /* Initialize boolean versions of the flags, for use in the arm.md file. */
+ arm_arch3m = (insn_flags & FL_ARCH3M) != 0;
+ arm_arch4 = (insn_flags & FL_ARCH4) != 0;
+ arm_arch4t = arm_arch4 & ((insn_flags & FL_THUMB) != 0);
+ arm_arch5 = (insn_flags & FL_ARCH5) != 0;
+ arm_arch5e = (insn_flags & FL_ARCH5E) != 0;
+ arm_arch6 = (insn_flags & FL_ARCH6) != 0;
+ arm_arch6k = (insn_flags & FL_ARCH6K) != 0;
+ arm_arch_xscale = (insn_flags & FL_XSCALE) != 0;
+ arm_arch_cirrus = (insn_flags & FL_CIRRUS) != 0;
+
+ arm_ld_sched = (tune_flags & FL_LDSCHED) != 0;
+ arm_tune_strongarm = (tune_flags & FL_STRONG) != 0;
+ thumb_code = (TARGET_ARM == 0);
+ arm_tune_wbuf = (tune_flags & FL_WBUF) != 0;
+ arm_tune_xscale = (tune_flags & FL_XSCALE) != 0;
+ arm_arch_iwmmxt = (insn_flags & FL_IWMMXT) != 0;
+
+ /* V5 code we generate is completely interworking capable, so we turn off
+ TARGET_INTERWORK here to avoid many tests later on. */
+
+ /* XXX However, we must pass the right pre-processor defines to CPP
+ or GLD can get confused. This is a hack. */
+ if (TARGET_INTERWORK)
+ arm_cpp_interwork = 1;
- if (TARGET_IWMMXT && (! TARGET_ATPCS))
- target_flags |= ARM_FLAG_ATPCS;
+ if (arm_arch5)
+ target_flags &= ~MASK_INTERWORK;
- if (arm_is_cirrus)
+ if (target_abi_name)
{
- arm_fpu_tune = FPUTYPE_MAVERICK;
+ for (i = 0; i < ARRAY_SIZE (arm_all_abis); i++)
+ {
+ if (streq (arm_all_abis[i].name, target_abi_name))
+ {
+ arm_abi = arm_all_abis[i].abi_type;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE (arm_all_abis))
+ error ("invalid ABI option: -mabi=%s", target_abi_name);
+ }
+ else
+ arm_abi = ARM_DEFAULT_ABI;
+
+ if (TARGET_IWMMXT && !ARM_DOUBLEWORD_ALIGN)
+ error ("iwmmxt requires an AAPCS compatible ABI for proper operation");
- /* Ignore -mhard-float if -mcpu=ep9312. */
- if (TARGET_HARD_FLOAT)
- target_flags ^= ARM_FLAG_SOFT_FLOAT;
+ if (TARGET_IWMMXT_ABI && !TARGET_IWMMXT)
+ error ("iwmmxt abi requires an iwmmxt capable cpu");
+
+ arm_fp_model = ARM_FP_MODEL_UNKNOWN;
+ if (target_fpu_name == NULL && target_fpe_name != NULL)
+ {
+ if (streq (target_fpe_name, "2"))
+ target_fpu_name = "fpe2";
+ else if (streq (target_fpe_name, "3"))
+ target_fpu_name = "fpe3";
+ else
+ error ("invalid floating point emulation option: -mfpe=%s",
+ target_fpe_name);
+ }
+ if (target_fpu_name != NULL)
+ {
+ /* The user specified a FPU. */
+ for (i = 0; i < ARRAY_SIZE (all_fpus); i++)
+ {
+ if (streq (all_fpus[i].name, target_fpu_name))
+ {
+ arm_fpu_arch = all_fpus[i].fpu;
+ arm_fpu_tune = arm_fpu_arch;
+ arm_fp_model = fp_model_for_fpu[arm_fpu_arch];
+ break;
+ }
+ }
+ if (arm_fp_model == ARM_FP_MODEL_UNKNOWN)
+ error ("invalid floating point option: -mfpu=%s", target_fpu_name);
}
else
- /* Default value for floating point code... if no co-processor
- bus, then schedule for emulated floating point. Otherwise,
- assume the user has an FPA.
- Note: this does not prevent use of floating point instructions,
- -msoft-float does that. */
- arm_fpu_tune = (tune_flags & FL_CO_PROC) ? FPUTYPE_FPA : FPUTYPE_FPA_EMU3;
-
- if (target_fp_name)
{
- if (streq (target_fp_name, "2"))
+#ifdef FPUTYPE_DEFAULT
+ /* Use the default if it is specified for this platform. */
+ arm_fpu_arch = FPUTYPE_DEFAULT;
+ arm_fpu_tune = FPUTYPE_DEFAULT;
+#else
+ /* Pick one based on CPU type. */
+ /* ??? Some targets assume FPA is the default.
+ if ((insn_flags & FL_VFP) != 0)
+ arm_fpu_arch = FPUTYPE_VFP;
+ else
+ */
+ if (arm_arch_cirrus)
+ arm_fpu_arch = FPUTYPE_MAVERICK;
+ else
arm_fpu_arch = FPUTYPE_FPA_EMU2;
- else if (streq (target_fp_name, "3"))
- arm_fpu_arch = FPUTYPE_FPA_EMU3;
+#endif
+ if (tune_flags & FL_CO_PROC && arm_fpu_arch == FPUTYPE_FPA_EMU2)
+ arm_fpu_tune = FPUTYPE_FPA;
else
- error ("invalid floating point emulation option: -mfpe-%s",
- target_fp_name);
+ arm_fpu_tune = arm_fpu_arch;
+ arm_fp_model = fp_model_for_fpu[arm_fpu_arch];
+ gcc_assert (arm_fp_model != ARM_FP_MODEL_UNKNOWN);
}
- else
- arm_fpu_arch = FPUTYPE_DEFAULT;
-
- if (TARGET_FPE)
+
+ if (target_float_abi_name != NULL)
{
- if (arm_fpu_tune == FPUTYPE_FPA_EMU3)
- arm_fpu_tune = FPUTYPE_FPA_EMU2;
- else if (arm_fpu_tune == FPUTYPE_MAVERICK)
- warning ("-mfpe switch not supported by ep9312 target cpu - ignored.");
- else if (arm_fpu_tune != FPUTYPE_FPA)
- arm_fpu_tune = FPUTYPE_FPA_EMU2;
+ /* The user specified a FP ABI. */
+ for (i = 0; i < ARRAY_SIZE (all_float_abis); i++)
+ {
+ if (streq (all_float_abis[i].name, target_float_abi_name))
+ {
+ arm_float_abi = all_float_abis[i].abi_type;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE (all_float_abis))
+ error ("invalid floating point abi: -mfloat-abi=%s",
+ target_float_abi_name);
}
-
+ else
+ arm_float_abi = TARGET_DEFAULT_FLOAT_ABI;
+
+ if (arm_float_abi == ARM_FLOAT_ABI_HARD && TARGET_VFP)
+ sorry ("-mfloat-abi=hard and VFP");
+
+ /* FPA and iWMMXt are incompatible because the insn encodings overlap.
+ VFP and iWMMXt can theoretically coexist, but it's unlikely such silicon
+ will ever exist. GCC makes no attempt to support this combination. */
+ if (TARGET_IWMMXT && !TARGET_SOFT_FLOAT)
+ sorry ("iWMMXt and hardware floating point");
+
+ /* If soft-float is specified then don't use FPU. */
+ if (TARGET_SOFT_FLOAT)
+ arm_fpu_arch = FPUTYPE_NONE;
+
/* For arm2/3 there is no need to do any scheduling if there is only
a floating point emulator, or we are doing software floating-point. */
- if ((TARGET_SOFT_FLOAT || arm_fpu_tune != FPUTYPE_FPA)
+ if ((TARGET_SOFT_FLOAT
+ || arm_fpu_tune == FPUTYPE_FPA_EMU2
+ || arm_fpu_tune == FPUTYPE_FPA_EMU3)
&& (tune_flags & FL_MODE32) == 0)
flag_schedule_insns = flag_schedule_insns_after_reload = 0;
-
- arm_prgmode = TARGET_APCS_32 ? PROG_MODE_PROG32 : PROG_MODE_PROG26;
-
+
+ if (target_thread_switch)
+ {
+ if (strcmp (target_thread_switch, "soft") == 0)
+ target_thread_pointer = TP_SOFT;
+ else if (strcmp (target_thread_switch, "auto") == 0)
+ target_thread_pointer = TP_AUTO;
+ else if (strcmp (target_thread_switch, "cp15") == 0)
+ target_thread_pointer = TP_CP15;
+ else
+ error ("invalid thread pointer option: -mtp=%s", target_thread_switch);
+ }
+
+ /* Use the cp15 method if it is available. */
+ if (target_thread_pointer == TP_AUTO)
+ {
+ if (arm_arch6k && !TARGET_THUMB)
+ target_thread_pointer = TP_CP15;
+ else
+ target_thread_pointer = TP_SOFT;
+ }
+
+ if (TARGET_HARD_TP && TARGET_THUMB)
+ error ("can not use -mtp=cp15 with -mthumb");
+
+ /* Override the default structure alignment for AAPCS ABI. */
+ if (TARGET_AAPCS_BASED)
+ arm_structure_size_boundary = 8;
+
if (structure_size_string != NULL)
{
int size = strtol (structure_size_string, NULL, 0);
-
- if (size == 8 || size == 32)
+
+ if (size == 8 || size == 32
+ || (ARM_DOUBLEWORD_ALIGN && size == 64))
arm_structure_size_boundary = size;
else
- warning ("structure size boundary can only be set to 8 or 32");
+ warning (0, "structure size boundary can only be set to %s",
+ ARM_DOUBLEWORD_ALIGN ? "8, 32 or 64": "8 or 32");
}
if (arm_pic_register_string != NULL)
@@ -831,7 +1289,7 @@ arm_override_options (void)
int pic_register = decode_reg_name (arm_pic_register_string);
if (!flag_pic)
- warning ("-mpic-register= is useless without -fpic");
+ warning (0, "-mpic-register= is useless without -fpic");
/* Prevent the user from choosing an obviously stupid PIC register. */
else if (pic_register < 0 || call_used_regs[pic_register]
@@ -851,10 +1309,6 @@ arm_override_options (void)
if (optimize_size)
{
- /* There's some dispute as to whether this should be 1 or 2. However,
- experiments seem to show that in pathological cases a setting of
- 1 degrades less severely than a setting of 2. This could change if
- other parts of the compiler change their behavior. */
arm_constant_limit = 1;
/* If optimizing for size, bump the number of instructions that we
@@ -866,7 +1320,7 @@ arm_override_options (void)
/* For processors with load scheduling, it never costs more than
2 cycles to load a constant, and the load scheduler may well
reduce that to 1. */
- if (tune_flags & FL_LDSCHED)
+ if (arm_ld_sched)
arm_constant_limit = 1;
/* On XScale the longer latency of a load makes it more difficult
@@ -877,7 +1331,7 @@ arm_override_options (void)
/* StrongARM has early execution of branches, so a sequence
that is worth skipping is shorter. */
- if (arm_is_strong)
+ if (arm_tune_strongarm)
max_insns_skipped = 3;
}
@@ -956,42 +1410,38 @@ arm_compute_func_type (void)
unsigned long type = ARM_FT_UNKNOWN;
tree a;
tree attr;
-
- if (TREE_CODE (current_function_decl) != FUNCTION_DECL)
- abort ();
+
+ gcc_assert (TREE_CODE (current_function_decl) == FUNCTION_DECL);
/* Decide if the current function is volatile. Such functions
never return, and many memory cycles can be saved by not storing
register values that will never be needed again. This optimization
was added to speed up context switching in a kernel application. */
if (optimize > 0
- && current_function_nothrow
+ && (TREE_NOTHROW (current_function_decl)
+ || !(flag_unwind_tables
+ || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
&& TREE_THIS_VOLATILE (current_function_decl))
type |= ARM_FT_VOLATILE;
-
- if (current_function_needs_context)
+
+ if (cfun->static_chain_decl != NULL)
type |= ARM_FT_NESTED;
attr = DECL_ATTRIBUTES (current_function_decl);
-
+
a = lookup_attribute ("naked", attr);
if (a != NULL_TREE)
type |= ARM_FT_NAKED;
- if (cfun->machine->eh_epilogue_sp_ofs != NULL_RTX)
- type |= ARM_FT_EXCEPTION_HANDLER;
+ a = lookup_attribute ("isr", attr);
+ if (a == NULL_TREE)
+ a = lookup_attribute ("interrupt", attr);
+
+ if (a == NULL_TREE)
+ type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
else
- {
- a = lookup_attribute ("isr", attr);
- if (a == NULL_TREE)
- a = lookup_attribute ("interrupt", attr);
-
- if (a == NULL_TREE)
- type |= TARGET_INTERWORK ? ARM_FT_INTERWORKED : ARM_FT_NORMAL;
- else
- type |= arm_isr_value (TREE_VALUE (a));
- }
-
+ type |= arm_isr_value (TREE_VALUE (a));
+
return type;
}
@@ -1006,7 +1456,7 @@ arm_current_func_type (void)
return cfun->machine->func_type;
}
-/* Return 1 if it is possible to return using a single instruction.
+/* Return 1 if it is possible to return using a single instruction.
If SIBLING is non-null, this is a test for a return before a sibling
call. SIBLING is the call insn, so we can examine its register usage. */
@@ -1017,6 +1467,7 @@ use_return_insn (int iscond, rtx sibling)
unsigned int func_type;
unsigned long saved_int_regs;
unsigned HOST_WIDE_INT stack_adjust;
+ arm_stack_offsets *offsets;
/* Never use a return instruction before reload has run. */
if (!reload_completed)
@@ -1033,13 +1484,14 @@ use_return_insn (int iscond, rtx sibling)
if (IS_INTERRUPT (func_type) && frame_pointer_needed)
return 0;
- stack_adjust = arm_get_frame_size () + current_function_outgoing_args_size;
+ offsets = arm_get_frame_offsets ();
+ stack_adjust = offsets->outgoing_args - offsets->saved_regs;
/* As do variadic functions. */
if (current_function_pretend_args_size
|| cfun->machine->uses_anonymous_args
/* Or if the function calls __builtin_eh_return () */
- || ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
+ || current_function_calls_eh_return
/* Or if the function calls alloca */
|| current_function_calls_alloca
/* Or if there is a stack adjustment. However, if the stack pointer
@@ -1057,7 +1509,7 @@ use_return_insn (int iscond, rtx sibling)
pointer won't be correctly restored if the instruction takes a
page fault. We work around this problem by popping r3 along with
the other registers, since that is never slower than executing
- another instruction.
+ another instruction.
We test for !arm_arch5 here, because code for any architecture
less than this could potentially be run on one of the buggy
@@ -1069,13 +1521,14 @@ use_return_insn (int iscond, rtx sibling)
if (!call_used_regs[3])
return 0;
- /* ... that it isn't being used for a return value (always true
- until we implement return-in-regs), or for a tail-call
- argument ... */
+ /* ... that it isn't being used for a return value ... */
+ if (arm_size_return_regs () >= (4 * UNITS_PER_WORD))
+ return 0;
+
+ /* ... or for a tail-call argument ... */
if (sibling)
{
- if (GET_CODE (sibling) != CALL_INSN)
- abort ();
+ gcc_assert (GET_CODE (sibling) == CALL_INSN);
if (find_regno_fusage (sibling, USE, 3))
return 0;
@@ -1094,14 +1547,16 @@ use_return_insn (int iscond, rtx sibling)
/* On StrongARM, conditional returns are expensive if they aren't
taken and multiple registers have been stacked. */
- if (iscond && arm_is_strong)
+ if (iscond && arm_tune_strongarm)
{
- /* Conditional return when just the LR is stored is a simple
+ /* Conditional return when just the LR is stored is a simple
conditional-load instruction, that's not expensive. */
if (saved_int_regs != 0 && saved_int_regs != (1 << LR_REGNUM))
return 0;
- if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ if (flag_pic
+ && arm_pic_register != INVALID_REGNUM
+ && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
return 0;
}
@@ -1112,8 +1567,14 @@ use_return_insn (int iscond, rtx sibling)
/* Can't be done if any of the FPA regs are pushed,
since this also requires an insn. */
- if (TARGET_HARD_FLOAT)
- for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
+ if (TARGET_HARD_FLOAT && TARGET_FPA)
+ for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++)
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ return 0;
+
+ /* Likewise VFP regs. */
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ for (regno = FIRST_VFP_REGNUM; regno <= LAST_VFP_REGNUM; regno++)
if (regs_ever_live[regno] && !call_used_regs[regno])
return 0;
@@ -1130,29 +1591,34 @@ use_return_insn (int iscond, rtx sibling)
int
const_ok_for_arm (HOST_WIDE_INT i)
{
- unsigned HOST_WIDE_INT mask = ~(unsigned HOST_WIDE_INT)0xFF;
+ int lowbit;
- /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
+ /* For machines with >32 bit HOST_WIDE_INT, the bits above bit 31 must
be all zero, or all one. */
if ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0
&& ((i & ~(unsigned HOST_WIDE_INT) 0xffffffff)
!= ((~(unsigned HOST_WIDE_INT) 0)
& ~(unsigned HOST_WIDE_INT) 0xffffffff)))
return FALSE;
-
- /* Fast return for 0 and powers of 2 */
- if ((i & (i - 1)) == 0)
+
+ i &= (unsigned HOST_WIDE_INT) 0xffffffff;
+
+ /* Fast return for 0 and small values. We must do this for zero, since
+ the code below can't handle that one case. */
+ if ((i & ~(unsigned HOST_WIDE_INT) 0xff) == 0)
return TRUE;
- do
- {
- if ((i & mask & (unsigned HOST_WIDE_INT) 0xffffffff) == 0)
- return TRUE;
- mask =
- (mask << 2) | ((mask & (unsigned HOST_WIDE_INT) 0xffffffff)
- >> (32 - 2)) | ~(unsigned HOST_WIDE_INT) 0xffffffff;
- }
- while (mask != ~(unsigned HOST_WIDE_INT) 0xFF);
+ /* Get the number of trailing zeros, rounded down to the nearest even
+ number. */
+ lowbit = (ffs ((int) i) - 1) & ~1;
+
+ if ((i & ~(((unsigned HOST_WIDE_INT) 0xff) << lowbit)) == 0)
+ return TRUE;
+ else if (lowbit <= 4
+ && ((i & ~0xc000003f) == 0
+ || (i & ~0xf000000f) == 0
+ || (i & ~0xfc000003) == 0))
+ return TRUE;
return FALSE;
}
@@ -1178,7 +1644,7 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -1193,9 +1659,16 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
Return value is the number of insns emitted. */
int
-arm_split_constant (enum rtx_code code, enum machine_mode mode,
+arm_split_constant (enum rtx_code code, enum machine_mode mode, rtx insn,
HOST_WIDE_INT val, rtx target, rtx source, int subtargets)
{
+ rtx cond;
+
+ if (insn && GET_CODE (PATTERN (insn)) == COND_EXEC)
+ cond = COND_EXEC_TEST (PATTERN (insn));
+ else
+ cond = NULL_RTX;
+
if (subtargets || code == SET
|| (GET_CODE (target) == REG && GET_CODE (source) == REG
&& REGNO (target) != REGNO (source)))
@@ -1210,35 +1683,37 @@ arm_split_constant (enum rtx_code code, enum machine_mode mode,
Ref: gcc -O1 -mcpu=strongarm gcc.c-torture/compile/980506-2.c
*/
if (!after_arm_reorg
- && (arm_gen_constant (code, mode, val, target, source, 1, 0)
+ && !cond
+ && (arm_gen_constant (code, mode, NULL_RTX, val, target, source,
+ 1, 0)
> arm_constant_limit + (code != SET)))
{
if (code == SET)
{
/* Currently SET is the only monadic value for CODE, all
the rest are diadic. */
- emit_insn (gen_rtx_SET (VOIDmode, target, GEN_INT (val)));
+ emit_set_insn (target, GEN_INT (val));
return 1;
}
else
{
rtx temp = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx_SET (VOIDmode, temp, GEN_INT (val)));
+ emit_set_insn (temp, GEN_INT (val));
/* For MINUS, the value is subtracted from, since we never
have subtraction of a constant. */
if (code == MINUS)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_MINUS (mode, temp, source)));
+ emit_set_insn (target, gen_rtx_MINUS (mode, temp, source));
else
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx (code, mode, source, temp)));
+ emit_set_insn (target,
+ gen_rtx_fmt_ee (code, mode, source, temp));
return 2;
}
}
}
- return arm_gen_constant (code, mode, val, target, source, subtargets, 1);
+ return arm_gen_constant (code, mode, cond, val, target, source, subtargets,
+ 1);
}
static int
@@ -1249,7 +1724,7 @@ count_insns_for_constant (HOST_WIDE_INT remainder, int i)
do
{
int end;
-
+
if (i <= 0)
i += 32;
if (remainder & (3 << (i - 2)))
@@ -1268,11 +1743,23 @@ count_insns_for_constant (HOST_WIDE_INT remainder, int i)
return num_insns;
}
+/* Emit an instruction with the indicated PATTERN. If COND is
+ non-NULL, conditionalize the execution of the instruction on COND
+ being true. */
+
+static void
+emit_constant_insn (rtx cond, rtx pattern)
+{
+ if (cond)
+ pattern = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (cond), pattern);
+ emit_insn (pattern);
+}
+
/* As above, but extra parameter GENERATE which, if clear, suppresses
RTL generation. */
static int
-arm_gen_constant (enum rtx_code code, enum machine_mode mode,
+arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
HOST_WIDE_INT val, rtx target, rtx source, int subtargets,
int generate)
{
@@ -1310,8 +1797,9 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (remainder == 0xffffffff)
{
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- GEN_INT (ARM_SIGN_EXTEND (val))));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ GEN_INT (ARM_SIGN_EXTEND (val))));
return 1;
}
if (remainder == 0)
@@ -1319,7 +1807,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (reload_completed && rtx_equal_p (target, source))
return 0;
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target, source));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target, source));
return 1;
}
break;
@@ -1328,7 +1817,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (remainder == 0)
{
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target, const0_rtx));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target, const0_rtx));
return 1;
}
if (remainder == 0xffffffff)
@@ -1336,7 +1826,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (reload_completed && rtx_equal_p (target, source))
return 0;
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target, source));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target, source));
return 1;
}
can_invert = 1;
@@ -1348,19 +1839,19 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (reload_completed && rtx_equal_p (target, source))
return 0;
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target, source));
- return 1;
- }
- if (remainder == 0xffffffff)
- {
- if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode, source)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target, source));
return 1;
}
- /* We don't know how to handle this yet below. */
- abort ();
+ /* We don't know how to handle other cases yet. */
+ gcc_assert (remainder == 0xffffffff);
+
+ if (generate)
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_NOT (mode, source)));
+ return 1;
case MINUS:
/* We treat MINUS as (val - source), since (source - val) is always
@@ -1368,16 +1859,18 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (remainder == 0)
{
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_NEG (mode, source)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_NEG (mode, source)));
return 1;
}
if (const_ok_for_arm (val))
{
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_MINUS (mode, GEN_INT (val),
- source)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_MINUS (mode, GEN_INT (val),
+ source)));
return 1;
}
can_negate = 1;
@@ -1385,7 +1878,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* If we can do it in one insn get out quickly. */
@@ -1394,10 +1887,12 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
|| (can_invert && const_ok_for_arm (~val)))
{
if (generate)
- emit_insn (gen_rtx_SET (VOIDmode, target,
- (source ? gen_rtx (code, mode, source,
- GEN_INT (val))
- : GEN_INT (val))));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ (source
+ ? gen_rtx_fmt_ee (code, mode, source,
+ GEN_INT (val))
+ : GEN_INT (val))));
return 1;
}
@@ -1444,16 +1939,18 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (set_sign_bit_copies > 1)
{
if (const_ok_for_arm
- (temp1 = ARM_SIGN_EXTEND (remainder
+ (temp1 = ARM_SIGN_EXTEND (remainder
<< (set_sign_bit_copies - 1))))
{
if (generate)
{
rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx_SET (VOIDmode, new_src,
- GEN_INT (temp1)));
- emit_insn (gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_constant_insn (cond,
+ gen_ashrsi3 (target, new_src,
+ GEN_INT (set_sign_bit_copies - 1)));
}
return 2;
}
@@ -1465,11 +1962,48 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (generate)
{
rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx_SET (VOIDmode, new_src,
- GEN_INT (temp1)));
- emit_insn (gen_ashrsi3 (target, new_src,
- GEN_INT (set_sign_bit_copies - 1)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_constant_insn (cond,
+ gen_ashrsi3 (target, new_src,
+ GEN_INT (set_sign_bit_copies - 1)));
+ }
+ return 2;
+ }
+ }
+
+ /* See if we can calculate the value as the difference between two
+ valid immediates. */
+ if (clear_sign_bit_copies + clear_zero_bit_copies <= 16)
+ {
+ int topshift = clear_sign_bit_copies & ~1;
+
+ temp1 = ARM_SIGN_EXTEND ((remainder + (0x00800000 >> topshift))
+ & (0xff000000 >> topshift));
+
+ /* If temp1 is zero, then that means the 9 most significant
+ bits of remainder were 1 and we've caused it to overflow.
+ When topshift is 0 we don't need to do anything since we
+ can borrow from 'bit 32'. */
+ if (temp1 == 0 && topshift != 0)
+ temp1 = 0x80000000 >> (topshift - 1);
+
+ temp2 = ARM_SIGN_EXTEND (temp1 - remainder);
+
+ if (const_ok_for_arm (temp2))
+ {
+ if (generate)
+ {
+ rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ GEN_INT (temp1)));
+ emit_constant_insn (cond,
+ gen_addsi3 (target, new_src,
+ GEN_INT (-temp2)));
}
+
return 2;
}
}
@@ -1493,16 +2027,18 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
rtx new_src = (subtargets
? (generate ? gen_reg_rtx (mode) : NULL_RTX)
: target);
- insns = arm_gen_constant (code, mode, temp2, new_src,
+ insns = arm_gen_constant (code, mode, cond, temp2, new_src,
source, subtargets, generate);
source = new_src;
if (generate)
- emit_insn (gen_rtx_SET
- (VOIDmode, target,
- gen_rtx_IOR (mode,
- gen_rtx_ASHIFT (mode, source,
- GEN_INT (i)),
- source)));
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET
+ (VOIDmode, target,
+ gen_rtx_IOR (mode,
+ gen_rtx_ASHIFT (mode, source,
+ GEN_INT (i)),
+ source)));
return insns + 1;
}
}
@@ -1516,12 +2052,13 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
rtx new_src = (subtargets
? (generate ? gen_reg_rtx (mode) : NULL_RTX)
: target);
- insns = arm_gen_constant (code, mode, temp1, new_src,
+ insns = arm_gen_constant (code, mode, cond, temp1, new_src,
source, subtargets, generate);
source = new_src;
if (generate)
- emit_insn
- (gen_rtx_SET (VOIDmode, target,
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET (VOIDmode, target,
gen_rtx_IOR
(mode,
gen_rtx_LSHIFTRT (mode, source,
@@ -1548,9 +2085,13 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
{
rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx_SET (VOIDmode, sub, GEN_INT (val)));
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx (code, mode, source, sub)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, sub,
+ GEN_INT (val)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_fmt_ee (code, mode,
+ source, sub)));
}
return 2;
}
@@ -1567,15 +2108,19 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
rtx sub = subtargets ? gen_reg_rtx (mode) : target;
rtx shift = GEN_INT (set_sign_bit_copies);
- emit_insn (gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode,
- gen_rtx_ASHIFT (mode,
- source,
- shift))));
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode,
- gen_rtx_LSHIFTRT (mode, sub,
- shift))));
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET (VOIDmode, sub,
+ gen_rtx_NOT (mode,
+ gen_rtx_ASHIFT (mode,
+ source,
+ shift))));
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_NOT (mode,
+ gen_rtx_LSHIFTRT (mode, sub,
+ shift))));
}
return 2;
}
@@ -1588,15 +2133,19 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
rtx sub = subtargets ? gen_reg_rtx (mode) : target;
rtx shift = GEN_INT (set_zero_bit_copies);
- emit_insn (gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode,
- gen_rtx_LSHIFTRT (mode,
- source,
- shift))));
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode,
- gen_rtx_ASHIFT (mode, sub,
- shift))));
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET (VOIDmode, sub,
+ gen_rtx_NOT (mode,
+ gen_rtx_LSHIFTRT (mode,
+ source,
+ shift))));
+ emit_constant_insn
+ (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_NOT (mode,
+ gen_rtx_ASHIFT (mode, sub,
+ shift))));
}
return 2;
}
@@ -1606,16 +2155,19 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (generate)
{
rtx sub = subtargets ? gen_reg_rtx (mode) : target;
- emit_insn (gen_rtx_SET (VOIDmode, sub,
- gen_rtx_NOT (mode, source)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, sub,
+ gen_rtx_NOT (mode, source)));
source = sub;
if (subtargets)
sub = gen_reg_rtx (mode);
- emit_insn (gen_rtx_SET (VOIDmode, sub,
- gen_rtx_AND (mode, source,
- GEN_INT (temp1))));
- emit_insn (gen_rtx_SET (VOIDmode, target,
- gen_rtx_NOT (mode, sub)));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, sub,
+ gen_rtx_AND (mode, source,
+ GEN_INT (temp1))));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, target,
+ gen_rtx_NOT (mode, sub)));
}
return 3;
}
@@ -1634,14 +2186,16 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (generate)
{
rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ insns = arm_gen_constant (AND, mode, cond,
+ remainder | shift_mask,
new_src, source, subtargets, 1);
source = new_src;
}
else
{
rtx targ = subtargets ? NULL_RTX : target;
- insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ insns = arm_gen_constant (AND, mode, cond,
+ remainder | shift_mask,
targ, source, subtargets, 0);
}
}
@@ -1661,14 +2215,15 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
if (clear_zero_bit_copies >= 16 && clear_zero_bit_copies < 24)
{
HOST_WIDE_INT shift_mask = (1 << clear_zero_bit_copies) - 1;
-
+
if ((remainder | shift_mask) != 0xffffffff)
{
if (generate)
{
rtx new_src = subtargets ? gen_reg_rtx (mode) : target;
- insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ insns = arm_gen_constant (AND, mode, cond,
+ remainder | shift_mask,
new_src, source, subtargets, 1);
source = new_src;
}
@@ -1676,7 +2231,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
{
rtx targ = subtargets ? NULL_RTX : target;
- insns = arm_gen_constant (AND, mode, remainder | shift_mask,
+ insns = arm_gen_constant (AND, mode, cond,
+ remainder | shift_mask,
targ, source, subtargets, 0);
}
}
@@ -1763,12 +2319,12 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
rather than having to synthesize both large constants from scratch.
Therefore, we calculate how many insns would be required to emit
- the constant starting from `best_start', and also starting from
- zero (ie with bit 31 first to be output). If `best_start' doesn't
+ the constant starting from `best_start', and also starting from
+ zero (i.e. with bit 31 first to be output). If `best_start' doesn't
yield a shorter sequence, we may as well use zero. */
if (best_start != 0
&& ((((unsigned HOST_WIDE_INT) 1) << best_start) < remainder)
- && (count_insns_for_constant (remainder, 0) <=
+ && (count_insns_for_constant (remainder, 0) <=
count_insns_for_constant (remainder, best_start)))
best_start = 0;
@@ -1821,7 +2377,9 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
else
temp1_rtx = gen_rtx_fmt_ee (code, mode, source, temp1_rtx);
- emit_insn (gen_rtx_SET (VOIDmode, new_src, temp1_rtx));
+ emit_constant_insn (cond,
+ gen_rtx_SET (VOIDmode, new_src,
+ temp1_rtx));
source = new_src;
}
@@ -1849,9 +2407,12 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode,
immediate value easier to load. */
enum rtx_code
-arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
+arm_canonicalize_comparison (enum rtx_code code, enum machine_mode mode,
+ rtx * op1)
{
unsigned HOST_WIDE_INT i = INTVAL (*op1);
+ unsigned HOST_WIDE_INT maxval;
+ maxval = (((unsigned HOST_WIDE_INT) 1) << (GET_MODE_BITSIZE(mode) - 1)) - 1;
switch (code)
{
@@ -1861,7 +2422,7 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
case GT:
case LE:
- if (i != ((((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1)) - 1)
+ if (i != maxval
&& (const_ok_for_arm (i + 1) || const_ok_for_arm (-(i + 1))))
{
*op1 = GEN_INT (i + 1);
@@ -1871,7 +2432,7 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
case GE:
case LT:
- if (i != (((unsigned HOST_WIDE_INT) 1) << (HOST_BITS_PER_WIDE_INT - 1))
+ if (i != ~maxval
&& (const_ok_for_arm (i - 1) || const_ok_for_arm (-(i - 1))))
{
*op1 = GEN_INT (i - 1);
@@ -1900,12 +2461,65 @@ arm_canonicalize_comparison (enum rtx_code code, rtx * op1)
break;
default:
- abort ();
+ gcc_unreachable ();
}
return code;
}
+
+/* Define how to find the value returned by a function. */
+
+rtx
+arm_function_value(tree type, tree func ATTRIBUTE_UNUSED)
+{
+ enum machine_mode mode;
+ int unsignedp ATTRIBUTE_UNUSED;
+ rtx r ATTRIBUTE_UNUSED;
+
+ mode = TYPE_MODE (type);
+ /* Promote integer types. */
+ if (INTEGRAL_TYPE_P (type))
+ PROMOTE_FUNCTION_MODE (mode, unsignedp, type);
+
+ /* Promotes small structs returned in a register to full-word size
+ for big-endian AAPCS. */
+ if (arm_return_in_msb (type))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ if (size % UNITS_PER_WORD != 0)
+ {
+ size += UNITS_PER_WORD - size % UNITS_PER_WORD;
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+ }
+ }
+
+ return LIBCALL_VALUE(mode);
+}
+
+/* Determine the amount of memory needed to store the possible return
+ registers of an untyped call. */
+int
+arm_apply_result_size (void)
+{
+ int size = 16;
+
+ if (TARGET_ARM)
+ {
+ if (TARGET_HARD_FLOAT_ABI)
+ {
+ if (TARGET_FPA)
+ size += 12;
+ if (TARGET_MAVERICK)
+ size += 8;
+ }
+ if (TARGET_IWMMXT_ABI)
+ size += 8;
+ }
+
+ return size;
+}
+
/* Decide whether a type should be returned in memory (true)
or in a register (false). This is called by the macro
RETURN_IN_MEMORY. */
@@ -1914,19 +2528,27 @@ arm_return_in_memory (tree type)
{
HOST_WIDE_INT size;
- if (!AGGREGATE_TYPE_P (type))
- /* All simple types are returned in registers. */
+ if (!AGGREGATE_TYPE_P (type) &&
+ (TREE_CODE (type) != VECTOR_TYPE) &&
+ !(TARGET_AAPCS_BASED && TREE_CODE (type) == COMPLEX_TYPE))
+ /* All simple types are returned in registers.
+ For AAPCS, complex types are treated the same as aggregates. */
return 0;
size = int_size_in_bytes (type);
- if (TARGET_ATPCS)
+ if (arm_abi != ARM_ABI_APCS)
{
- /* ATPCS returns aggregate types in memory only if they are
+ /* ATPCS and later return aggregate types in memory only if they are
larger than a word (or are variable size). */
return (size < 0 || size > UNITS_PER_WORD);
}
-
+
+ /* To maximize backwards compatibility with previous versions of gcc,
+ return vectors up to 4 words in registers. */
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ return (size < 0 || size > (4 * UNITS_PER_WORD));
+
/* For the arm-wince targets we choose to be compatible with Microsoft's
ARM and Thumb compilers, which always return aggregates in memory. */
#ifndef ARM_WINCE
@@ -1936,7 +2558,7 @@ arm_return_in_memory (tree type)
we will want to return it via memory and not in a register. */
if (size < 0 || size > UNITS_PER_WORD)
return 1;
-
+
if (TREE_CODE (type) == RECORD_TYPE)
{
tree field;
@@ -1946,14 +2568,14 @@ arm_return_in_memory (tree type)
has an offset of zero. For practical purposes this means
that the structure can have at most one non bit-field element
and that this element must be the first one in the structure. */
-
+
/* Find the first field, ignoring non FIELD_DECL things which will
have been created by C++. */
for (field = TYPE_FIELDS (type);
field && TREE_CODE (field) != FIELD_DECL;
field = TREE_CHAIN (field))
continue;
-
+
if (field == NULL)
return 0; /* An empty structure. Allowed by an extension to ANSI C. */
@@ -1976,14 +2598,14 @@ arm_return_in_memory (tree type)
{
if (TREE_CODE (field) != FIELD_DECL)
continue;
-
+
if (!DECL_BIT_FIELD_TYPE (field))
return 1;
}
return 0;
}
-
+
if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
@@ -1999,15 +2621,15 @@ arm_return_in_memory (tree type)
if (FLOAT_TYPE_P (TREE_TYPE (field)))
return 1;
-
+
if (RETURN_IN_MEMORY (TREE_TYPE (field)))
return 1;
}
-
+
return 0;
}
-#endif /* not ARM_WINCE */
-
+#endif /* not ARM_WINCE */
+
/* Return all other types in memory. */
return 1;
}
@@ -2017,15 +2639,14 @@ arm_return_in_memory (tree type)
int
arm_float_words_big_endian (void)
{
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
return 0;
/* For FPA, float words are always big-endian. For VFP, floats words
follow the memory system mode. */
- if (TARGET_HARD_FLOAT)
+ if (TARGET_FPA)
{
- /* FIXME: TARGET_HARD_FLOAT currently implies FPA. */
return 1;
}
@@ -2039,19 +2660,20 @@ arm_float_words_big_endian (void)
for a call to a function whose data type is FNTYPE.
For a library call, FNTYPE is NULL. */
void
-arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
+arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
rtx libname ATTRIBUTE_UNUSED,
tree fndecl ATTRIBUTE_UNUSED)
{
/* On the ARM, the offset starts at 0. */
- pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) ? 1 : 0);
+ pcum->nregs = 0;
pcum->iwmmxt_nregs = 0;
-
+ pcum->can_split = true;
+
pcum->call_cookie = CALL_NORMAL;
if (TARGET_LONG_CALLS)
pcum->call_cookie = CALL_LONG;
-
+
/* Check for long call/short call attributes. The attributes
override any command line option. */
if (fntype)
@@ -2081,6 +2703,16 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
}
}
+
+/* Return true if mode/type need doubleword alignment. */
+bool
+arm_needs_doubleword_align (enum machine_mode mode, tree type)
+{
+ return (GET_MODE_ALIGNMENT (mode) > PARM_BOUNDARY
+ || (type && TYPE_ALIGN (type) > PARM_BOUNDARY));
+}
+
+
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -2096,92 +2728,81 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
rtx
arm_function_arg (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
- tree type ATTRIBUTE_UNUSED, int named)
+ tree type, int named)
{
- if (TARGET_REALLY_IWMMXT)
+ int nregs;
+
+ /* Varargs vectors are treated the same as long long.
+ named_count avoids having to change the way arm handles 'named' */
+ if (TARGET_IWMMXT_ABI
+ && arm_vector_mode_supported_p (mode)
+ && pcum->named_count > pcum->nargs + 1)
{
- if (VECTOR_MODE_SUPPORTED_P (mode))
+ if (pcum->iwmmxt_nregs <= 9)
+ return gen_rtx_REG (mode, pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM);
+ else
{
- /* varargs vectors are treated the same as long long.
- named_count avoids having to change the way arm handles 'named' */
- if (pcum->named_count <= pcum->nargs + 1)
- {
- if (pcum->nregs == 1)
- pcum->nregs += 1;
- if (pcum->nregs <= 2)
- return gen_rtx_REG (mode, pcum->nregs);
- else
- return NULL_RTX;
- }
- else if (pcum->iwmmxt_nregs <= 9)
- return gen_rtx_REG (mode, pcum->iwmmxt_nregs + FIRST_IWMMXT_REGNUM);
- else
- return NULL_RTX;
+ pcum->can_split = false;
+ return NULL_RTX;
}
- else if ((mode == DImode || mode == DFmode) && pcum->nregs & 1)
- pcum->nregs += 1;
}
+ /* Put doubleword aligned quantities in even register pairs. */
+ if (pcum->nregs & 1
+ && ARM_DOUBLEWORD_ALIGN
+ && arm_needs_doubleword_align (mode, type))
+ pcum->nregs++;
+
if (mode == VOIDmode)
/* Compute operand 2 of the call insn. */
return GEN_INT (pcum->call_cookie);
-
- if (!named || pcum->nregs >= NUM_ARG_REGS)
+
+ /* Only allow splitting an arg between regs and memory if all preceding
+ args were allocated to regs. For args passed by reference we only count
+ the reference pointer. */
+ if (pcum->can_split)
+ nregs = 1;
+ else
+ nregs = ARM_NUM_REGS2 (mode, type);
+
+ if (!named || pcum->nregs + nregs > NUM_ARG_REGS)
return NULL_RTX;
-
+
return gen_rtx_REG (mode, pcum->nregs);
}
-/* Variable sized types are passed by reference. This is a GCC
- extension to the ARM ABI. */
-
-int
-arm_function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int named ATTRIBUTE_UNUSED)
+static int
+arm_arg_partial_bytes (CUMULATIVE_ARGS *pcum, enum machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
{
- return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
-}
-
-/* Implement va_arg. */
+ int nregs = pcum->nregs;
-rtx
-arm_va_arg (tree valist, tree type)
-{
- /* Variable sized types are passed by reference. */
- if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- {
- rtx addr = std_expand_builtin_va_arg (valist, build_pointer_type (type));
- return gen_rtx_MEM (ptr_mode, force_reg (Pmode, addr));
- }
+ if (arm_vector_mode_supported_p (mode))
+ return 0;
- if (FUNCTION_ARG_BOUNDARY (TYPE_MODE (type), NULL) == IWMMXT_ALIGNMENT)
- {
- tree minus_eight;
- tree t;
+ if (NUM_ARG_REGS > nregs
+ && (NUM_ARG_REGS < nregs + ARM_NUM_REGS2 (mode, type))
+ && pcum->can_split)
+ return (NUM_ARG_REGS - nregs) * UNITS_PER_WORD;
- /* Maintain 64-bit alignment of the valist pointer by
- constructing: valist = ((valist + (8 - 1)) & -8). */
- minus_eight = build_int_2 (- (IWMMXT_ALIGNMENT / BITS_PER_UNIT), -1);
- t = build_int_2 ((IWMMXT_ALIGNMENT / BITS_PER_UNIT) - 1, 0);
- t = build (PLUS_EXPR, TREE_TYPE (valist), valist, t);
- t = build (BIT_AND_EXPR, TREE_TYPE (t), t, minus_eight);
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ return 0;
+}
- /* This is to stop the combine pass optimizing
- away the alignment adjustment. */
- mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY);
- }
+/* Variable sized types are passed by reference. This is a GCC
+ extension to the ARM ABI. */
- return std_expand_builtin_va_arg (valist, type);
+static bool
+arm_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type, bool named ATTRIBUTE_UNUSED)
+{
+ return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
}
/* Encode the current state of the #pragma [no_]long_calls. */
typedef enum
{
- OFF, /* No #pramgma [no_]long_calls is in effect. */
+ OFF, /* No #pragma [no_]long_calls is in effect. */
LONG, /* #pragma long_calls is in effect. */
SHORT /* #pragma no_long_calls is in effect. */
} arm_pragma_enum;
@@ -2217,7 +2838,7 @@ const struct attribute_spec arm_attribute_table[] =
/* Whereas these functions are always known to reside within the 26 bit
addressing range. */
{ "short_call", 0, 0, false, true, true, NULL },
- /* Interrupt Service Routines have special prologue and epilogue requirements. */
+ /* Interrupt Service Routines have special prologue and epilogue requirements. */
{ "isr", 0, 1, false, false, false, arm_handle_isr_attribute },
{ "interrupt", 0, 1, false, false, false, arm_handle_isr_attribute },
{ "naked", 0, 0, true, false, false, arm_handle_fndecl_attribute },
@@ -2234,6 +2855,10 @@ const struct attribute_spec arm_attribute_table[] =
{ "dllimport", 0, 0, true, false, false, NULL },
{ "dllexport", 0, 0, true, false, false, NULL },
{ "interfacearm", 0, 0, true, false, false, arm_handle_fndecl_attribute },
+#elif TARGET_DLLIMPORT_DECL_ATTRIBUTES
+ { "dllimport", 0, 0, false, false, false, handle_dll_attribute },
+ { "dllexport", 0, 0, false, false, false, handle_dll_attribute },
+ { "notshared", 0, 0, false, true, false, arm_handle_notshared_attribute },
#endif
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -2246,7 +2871,7 @@ arm_handle_fndecl_attribute (tree *node, tree name, tree args ATTRIBUTE_UNUSED,
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
- warning ("`%s' attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
@@ -2264,7 +2889,7 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
{
if (TREE_CODE (*node) != FUNCTION_DECL)
{
- warning ("`%s' attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
@@ -2278,7 +2903,8 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
{
if (arm_isr_value (args) == ARM_FT_UNKNOWN)
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
}
@@ -2287,7 +2913,7 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
|| TREE_CODE (TREE_TYPE (*node)) == METHOD_TYPE)
&& arm_isr_value (args) != ARM_FT_UNKNOWN)
{
- *node = build_type_copy (*node);
+ *node = build_variant_type_copy (*node);
TREE_TYPE (*node) = build_type_attribute_variant
(TREE_TYPE (*node),
tree_cons (name, args, TYPE_ATTRIBUTES (TREE_TYPE (*node))));
@@ -2305,7 +2931,8 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
}
else
{
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
}
}
}
@@ -2313,6 +2940,31 @@ arm_handle_isr_attribute (tree *node, tree name, tree args, int flags,
return NULL_TREE;
}
+#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
+/* Handle the "notshared" attribute. This attribute is another way of
+ requesting hidden visibility. ARM's compiler supports
+ "__declspec(notshared)"; we support the same thing via an
+ attribute. */
+
+static tree
+arm_handle_notshared_attribute (tree *node,
+ tree name ATTRIBUTE_UNUSED,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
+{
+ tree decl = TYPE_NAME (*node);
+
+ if (decl)
+ {
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+ *no_add_attrs = false;
+ }
+ return NULL_TREE;
+}
+#endif
+
/* Return 0 if the attributes for two types are incompatible, 1 if they
are compatible, and 2 if they are nearly compatible (which causes a
warning to be generated). */
@@ -2320,7 +2972,7 @@ static int
arm_comp_type_attributes (tree type1, tree type2)
{
int l1, l2, s1, s2;
-
+
/* Check for mismatch of non-default calling convention. */
if (TREE_CODE (type1) != FUNCTION_TYPE)
return 1;
@@ -2342,7 +2994,7 @@ arm_comp_type_attributes (tree type1, tree type2)
if ((l1 & s2) || (l2 & s1))
return 0;
}
-
+
/* Check for mismatched ISR attribute. */
l1 = lookup_attribute ("isr", TYPE_ATTRIBUTES (type1)) != NULL;
if (! l1)
@@ -2416,7 +3068,7 @@ current_file_function_operand (rtx sym_ref)
return 1;
/* The current function is always defined within the current compilation
- unit. if it s a weak definition however, then this may not be the real
+ unit. If it s a weak definition however, then this may not be the real
definition of the function, and so we have to say no. */
if (sym_ref == XEXP (DECL_RTL (current_function_decl), 0)
&& !DECL_WEAK (current_function_decl))
@@ -2432,16 +3084,19 @@ current_file_function_operand (rtx sym_ref)
a. has an __attribute__((long call))
or b. is within the scope of a #pragma long_calls
or c. the -mlong-calls command line switch has been specified
+ . and either:
+ 1. -ffunction-sections is in effect
+ or 2. the current function has __attribute__ ((section))
+ or 3. the target function has __attribute__ ((section))
However we do not generate a long call if the function:
-
+
d. has an __attribute__ ((short_call))
or e. is inside the scope of a #pragma no_long_calls
- or f. has an __attribute__ ((section))
- or g. is defined within the current compilation unit.
-
+ or f. is defined within the current compilation unit.
+
This function will be called by C fragments contained in the machine
- description file. CALL_REF and CALL_COOKIE correspond to the matched
+ description file. SYM_REF and CALL_COOKIE correspond to the matched
rtl operands. CALL_SYMBOL is used to distinguish between
two different callers of the function. It is set to 1 in the
"call_symbol" and "call_symbol_value" patterns and to 0 in the "call"
@@ -2464,12 +3119,18 @@ arm_is_longcall_p (rtx sym_ref, int call_cookie, int call_symbol)
if (call_cookie & CALL_SHORT)
return 0;
- if (TARGET_LONG_CALLS && flag_function_sections)
- return 1;
-
+ if (TARGET_LONG_CALLS)
+ {
+ if (flag_function_sections
+ || DECL_SECTION_NAME (current_function_decl))
+ /* c.3 is handled by the definition of the
+ ARM_DECLARE_FUNCTION_SIZE macro. */
+ return 1;
+ }
+
if (current_file_function_operand (sym_ref))
return 0;
-
+
return (call_cookie & CALL_LONG)
|| ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref, 0))
|| TARGET_LONG_CALLS;
@@ -2502,7 +3163,7 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
return false;
/* If we are interworking and the function is not declared static
- then we can't tail-call it unless we know that it exists in this
+ then we can't tail-call it unless we know that it exists in this
compilation unit (since it might be a Thumb routine). */
if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl))
return false;
@@ -2519,16 +3180,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* Addressing mode support functions. */
/* Return nonzero if X is a legitimate immediate operand when compiling
- for PIC. */
+ for PIC. We know that X satisfies CONSTANT_P and flag_pic is true. */
int
legitimate_pic_operand_p (rtx x)
{
- if (CONSTANT_P (x)
- && flag_pic
- && (GET_CODE (x) == SYMBOL_REF
- || (GET_CODE (x) == CONST
- && GET_CODE (XEXP (x, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)))
+ if (GET_CODE (x) == SYMBOL_REF
+ || (GET_CODE (x) == CONST
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
return 0;
return 1;
@@ -2546,12 +3205,53 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
rtx insn;
int subregs = 0;
+ /* If this function doesn't have a pic register, create one now.
+ A lot of the logic here is made obscure by the fact that this
+ routine gets called as part of the rtx cost estimation
+ process. We don't want those calls to affect any assumptions
+ about the real function; and further, we can't call
+ entry_of_function() until we start the real expansion
+ process. */
+ if (!current_function_uses_pic_offset_table)
+ {
+ gcc_assert (!no_new_pseudos);
+ if (arm_pic_register != INVALID_REGNUM)
+ {
+ cfun->machine->pic_reg = gen_rtx_REG (Pmode, arm_pic_register);
+
+ /* Play games to avoid marking the function as needing pic
+ if we are being called as part of the cost-estimation
+ process. */
+ if (!ir_type())
+ current_function_uses_pic_offset_table = 1;
+ }
+ else
+ {
+ rtx seq;
+
+ cfun->machine->pic_reg = gen_reg_rtx (Pmode);
+
+ /* Play games to avoid marking the function as needing pic
+ if we are being called as part of the cost-estimation
+ process. */
+ if (!ir_type())
+ {
+ current_function_uses_pic_offset_table = 1;
+ start_sequence ();
+
+ arm_load_pic_register (0UL);
+
+ seq = get_insns ();
+ end_sequence ();
+ emit_insn_after (seq, entry_of_function ());
+ }
+ }
+ }
+
if (reg == 0)
{
- if (no_new_pseudos)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (!no_new_pseudos);
+ reg = gen_reg_rtx (Pmode);
subregs = 1;
}
@@ -2572,21 +3272,19 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
emit_insn (gen_pic_load_addr_thumb (address, orig));
if ((GET_CODE (orig) == LABEL_REF
- || (GET_CODE (orig) == SYMBOL_REF &&
+ || (GET_CODE (orig) == SYMBOL_REF &&
SYMBOL_REF_LOCAL_P (orig)))
&& NEED_GOT_RELOC)
- pic_ref = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, address);
+ pic_ref = gen_rtx_PLUS (Pmode, cfun->machine->pic_reg, address);
else
{
- pic_ref = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
- address));
- RTX_UNCHANGING_P (pic_ref) = 1;
+ pic_ref = gen_const_mem (Pmode,
+ gen_rtx_PLUS (Pmode, cfun->machine->pic_reg,
+ address));
}
insn = emit_move_insn (reg, pic_ref);
#endif
- current_function_uses_pic_offset_table = 1;
/* Put a REG_EQUAL note on this insn, so that it can be optimized
by loop. */
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, orig,
@@ -2598,36 +3296,33 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
rtx base, offset;
if (GET_CODE (XEXP (orig, 0)) == PLUS
- && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+ && XEXP (XEXP (orig, 0), 0) == cfun->machine->pic_reg)
+ return orig;
+
+ if (GET_CODE (XEXP (orig, 0)) == UNSPEC
+ && XINT (XEXP (orig, 0), 1) == UNSPEC_TLS)
return orig;
if (reg == 0)
{
- if (no_new_pseudos)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (!no_new_pseudos);
+ reg = gen_reg_rtx (Pmode);
}
- if (GET_CODE (XEXP (orig, 0)) == PLUS)
- {
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
- }
- else
- abort ();
+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+ base == reg ? 0 : reg);
if (GET_CODE (offset) == CONST_INT)
{
/* The base register doesn't really matter, we only want to
test the index for the appropriate mode. */
- if (!arm_legitimate_index_p (mode, offset, 0))
+ if (!arm_legitimate_index_p (mode, offset, SET, 0))
{
- if (!no_new_pseudos)
- offset = force_reg (Pmode, offset);
- else
- abort ();
+ gcc_assert (!no_new_pseudos);
+ offset = force_reg (Pmode, offset);
}
if (GET_CODE (offset) == CONST_INT)
@@ -2648,31 +3343,89 @@ legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
return orig;
}
-/* Generate code to load the PIC register. PROLOGUE is true if
- called from arm_expand_prologue (in which case we want the
- generated insns at the start of the function); false if called
- by an exception receiver that needs the PIC register reloaded
- (in which case the insns are just dumped at the current location). */
+
+/* Find a spare low register to use during the prolog of a function. */
+
+static int
+thumb_find_work_register (unsigned long pushed_regs_mask)
+{
+ int reg;
+
+ /* Check the argument registers first as these are call-used. The
+ register allocation order means that sometimes r3 might be used
+ but earlier argument registers might not, so check them all. */
+ for (reg = LAST_ARG_REGNUM; reg >= 0; reg --)
+ if (!regs_ever_live[reg])
+ return reg;
+
+ /* Before going on to check the call-saved registers we can try a couple
+ more ways of deducing that r3 is available. The first is when we are
+ pushing anonymous arguments onto the stack and we have less than 4
+ registers worth of fixed arguments(*). In this case r3 will be part of
+ the variable argument list and so we can be sure that it will be
+ pushed right at the start of the function. Hence it will be available
+ for the rest of the prologue.
+ (*): ie current_function_pretend_args_size is greater than 0. */
+ if (cfun->machine->uses_anonymous_args
+ && current_function_pretend_args_size > 0)
+ return LAST_ARG_REGNUM;
+
+ /* The other case is when we have fixed arguments but less than 4 registers
+ worth. In this case r3 might be used in the body of the function, but
+ it is not being used to convey an argument into the function. In theory
+ we could just check current_function_args_size to see how many bytes are
+ being passed in argument registers, but it seems that it is unreliable.
+ Sometimes it will have the value 0 when in fact arguments are being
+ passed. (See testcase execute/20021111-1.c for an example). So we also
+ check the args_info.nregs field as well. The problem with this field is
+ that it makes no allowances for arguments that are passed to the
+ function but which are not used. Hence we could miss an opportunity
+ when a function has an unused argument in r3. But it is better to be
+ safe than to be sorry. */
+ if (! cfun->machine->uses_anonymous_args
+ && current_function_args_size >= 0
+ && current_function_args_size <= (LAST_ARG_REGNUM * UNITS_PER_WORD)
+ && cfun->args_info.nregs < 4)
+ return LAST_ARG_REGNUM;
+
+ /* Otherwise look for a call-saved register that is going to be pushed. */
+ for (reg = LAST_LO_REGNUM; reg > LAST_ARG_REGNUM; reg --)
+ if (pushed_regs_mask & (1 << reg))
+ return reg;
+
+ /* Something went wrong - thumb_compute_save_reg_mask()
+ should have arranged for a suitable register to be pushed. */
+ gcc_unreachable ();
+}
+
+static GTY(()) int pic_labelno;
+
+/* Generate code to load the PIC register. In thumb mode SCRATCH is a
+ low register. */
+
void
-arm_finalize_pic (int prologue ATTRIBUTE_UNUSED)
+arm_load_pic_register (unsigned long saved_regs ATTRIBUTE_UNUSED)
{
#ifndef AOF_ASSEMBLER
- rtx l1, pic_tmp, pic_tmp2, seq, pic_rtx;
+ rtx l1, labelno, pic_tmp, pic_tmp2, pic_rtx;
rtx global_offset_table;
if (current_function_uses_pic_offset_table == 0 || TARGET_SINGLE_PIC_BASE)
return;
- if (!flag_pic)
- abort ();
+ gcc_assert (flag_pic);
- start_sequence ();
- l1 = gen_label_rtx ();
+ /* We use an UNSPEC rather than a LABEL_REF because this label never appears
+ in the code stream. */
+
+ labelno = GEN_INT (pic_labelno++);
+ l1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
+ l1 = gen_rtx_CONST (VOIDmode, l1);
global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
/* On the ARM the PC register contains 'dot + 8' at the time of the
addition, on the Thumb it is 'dot + 4'. */
- pic_tmp = plus_constant (gen_rtx_LABEL_REF (Pmode, l1), TARGET_ARM ? 8 : 4);
+ pic_tmp = plus_constant (l1, TARGET_ARM ? 8 : 4);
if (GOT_PCREL)
pic_tmp2 = gen_rtx_CONST (VOIDmode,
gen_rtx_PLUS (Pmode, global_offset_table, pc_rtx));
@@ -2680,31 +3433,38 @@ arm_finalize_pic (int prologue ATTRIBUTE_UNUSED)
pic_tmp2 = gen_rtx_CONST (VOIDmode, global_offset_table);
pic_rtx = gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, pic_tmp2, pic_tmp));
-
+
if (TARGET_ARM)
{
- emit_insn (gen_pic_load_addr_arm (pic_offset_table_rtx, pic_rtx));
- emit_insn (gen_pic_add_dot_plus_eight (pic_offset_table_rtx, l1));
+ emit_insn (gen_pic_load_addr_arm (cfun->machine->pic_reg, pic_rtx));
+ emit_insn (gen_pic_add_dot_plus_eight (cfun->machine->pic_reg,
+ cfun->machine->pic_reg, labelno));
}
else
{
- emit_insn (gen_pic_load_addr_thumb (pic_offset_table_rtx, pic_rtx));
- emit_insn (gen_pic_add_dot_plus_four (pic_offset_table_rtx, l1));
+ if (arm_pic_register != INVALID_REGNUM
+ && REGNO (cfun->machine->pic_reg) > LAST_LO_REGNUM)
+ {
+ /* We will have pushed the pic register, so we should always be
+ able to find a work register. */
+ pic_tmp = gen_rtx_REG (SImode,
+ thumb_find_work_register (saved_regs));
+ emit_insn (gen_pic_load_addr_thumb (pic_tmp, pic_rtx));
+ emit_insn (gen_movsi (pic_offset_table_rtx, pic_tmp));
+ }
+ else
+ emit_insn (gen_pic_load_addr_thumb (cfun->machine->pic_reg, pic_rtx));
+ emit_insn (gen_pic_add_dot_plus_four (cfun->machine->pic_reg,
+ cfun->machine->pic_reg, labelno));
}
- seq = get_insns ();
- end_sequence ();
- if (prologue)
- emit_insn_after (seq, get_insns ());
- else
- emit_insn (seq);
-
/* Need to emit this whether or not we obey regdecls,
since setjmp/longjmp can cause life info to screw up. */
- emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
+ emit_insn (gen_rtx_USE (VOIDmode, cfun->machine->pic_reg));
#endif /* AOF_ASSEMBLER */
}
+
/* Return nonzero if X is valid as an ARM state addressing register. */
static int
arm_address_register_rtx_p (rtx x, int strict_p)
@@ -2725,28 +3485,62 @@ arm_address_register_rtx_p (rtx x, int strict_p)
|| regno == ARG_POINTER_REGNUM);
}
+/* Return TRUE if this rtx is the difference of a symbol and a label,
+ and will reduce to a PC-relative relocation in the object file.
+ Expressions like this can be left alone when generating PIC, rather
+ than forced through the GOT. */
+static int
+pcrel_constant_p (rtx x)
+{
+ if (GET_CODE (x) == MINUS)
+ return symbol_mentioned_p (XEXP (x, 0)) && label_mentioned_p (XEXP (x, 1));
+
+ return FALSE;
+}
+
/* Return nonzero if X is a valid ARM state address operand. */
int
-arm_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
+arm_legitimate_address_p (enum machine_mode mode, rtx x, RTX_CODE outer,
+ int strict_p)
{
+ bool use_ldrd;
+ enum rtx_code code = GET_CODE (x);
+
if (arm_address_register_rtx_p (x, strict_p))
return 1;
- else if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC)
+ use_ldrd = (TARGET_LDRD
+ && (mode == DImode
+ || (mode == DFmode && (TARGET_SOFT_FLOAT || TARGET_VFP))));
+
+ if (code == POST_INC || code == PRE_DEC
+ || ((code == PRE_INC || code == POST_DEC)
+ && (use_ldrd || GET_MODE_SIZE (mode) <= 4)))
return arm_address_register_rtx_p (XEXP (x, 0), strict_p);
- else if ((GET_CODE (x) == POST_MODIFY || GET_CODE (x) == PRE_MODIFY)
- && GET_MODE_SIZE (mode) <= 4
+ else if ((code == POST_MODIFY || code == PRE_MODIFY)
&& arm_address_register_rtx_p (XEXP (x, 0), strict_p)
&& GET_CODE (XEXP (x, 1)) == PLUS
&& rtx_equal_p (XEXP (XEXP (x, 1), 0), XEXP (x, 0)))
- return arm_legitimate_index_p (mode, XEXP (XEXP (x, 1), 1), strict_p);
+ {
+ rtx addend = XEXP (XEXP (x, 1), 1);
+
+ /* Don't allow ldrd post increment by register because it's hard
+ to fixup invalid register choices. */
+ if (use_ldrd
+ && GET_CODE (x) == POST_MODIFY
+ && GET_CODE (addend) == REG)
+ return 0;
+
+ return ((use_ldrd || GET_MODE_SIZE (mode) <= 4)
+ && arm_legitimate_index_p (mode, addend, outer, strict_p));
+ }
/* After reload constants split into minipools will have addresses
from a LABEL_REF. */
else if (reload_completed
- && (GET_CODE (x) == LABEL_REF
- || (GET_CODE (x) == CONST
+ && (code == LABEL_REF
+ || (code == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF
&& GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)))
@@ -2755,28 +3549,15 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
else if (mode == TImode)
return 0;
- else if (mode == DImode || (TARGET_SOFT_FLOAT && mode == DFmode))
- {
- if (GET_CODE (x) == PLUS
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p)
- && GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
-
- if (val == 4 || val == -4 || val == -8)
- return 1;
- }
- }
-
- else if (GET_CODE (x) == PLUS)
+ else if (code == PLUS)
{
rtx xop0 = XEXP (x, 0);
rtx xop1 = XEXP (x, 1);
return ((arm_address_register_rtx_p (xop0, strict_p)
- && arm_legitimate_index_p (mode, xop1, strict_p))
+ && arm_legitimate_index_p (mode, xop1, outer, strict_p))
|| (arm_address_register_rtx_p (xop1, strict_p)
- && arm_legitimate_index_p (mode, xop0, strict_p)));
+ && arm_legitimate_index_p (mode, xop0, outer, strict_p)));
}
#if 0
@@ -2787,20 +3568,16 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
rtx xop1 = XEXP (x, 1);
return (arm_address_register_rtx_p (xop0, strict_p)
- && arm_legitimate_index_p (mode, xop1, strict_p));
+ && arm_legitimate_index_p (mode, xop1, outer, strict_p));
}
#endif
else if (GET_MODE_CLASS (mode) != MODE_FLOAT
- && GET_CODE (x) == SYMBOL_REF
+ && code == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x)
&& ! (flag_pic
- && symbol_mentioned_p (get_pool_constant (x))))
- return 1;
-
- else if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == POST_DEC)
- && (GET_MODE_SIZE (mode) <= 4)
- && arm_address_register_rtx_p (XEXP (x, 0), strict_p))
+ && symbol_mentioned_p (get_pool_constant (x))
+ && ! pcrel_constant_p (get_pool_constant (x))))
return 1;
return 0;
@@ -2809,63 +3586,87 @@ arm_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
/* Return nonzero if INDEX is valid for an address index operand in
ARM state. */
static int
-arm_legitimate_index_p (enum machine_mode mode, rtx index, int strict_p)
+arm_legitimate_index_p (enum machine_mode mode, rtx index, RTX_CODE outer,
+ int strict_p)
{
HOST_WIDE_INT range;
enum rtx_code code = GET_CODE (index);
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ /* Standard coprocessor addressing modes. */
+ if (TARGET_HARD_FLOAT
+ && (TARGET_FPA || TARGET_MAVERICK)
+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || (TARGET_MAVERICK && mode == DImode)))
return (code == CONST_INT && INTVAL (index) < 1024
&& INTVAL (index) > -1024
&& (INTVAL (index) & 3) == 0);
- if (TARGET_CIRRUS
- && (GET_MODE_CLASS (mode) == MODE_FLOAT || mode == DImode))
- return (code == CONST_INT
- && INTVAL (index) < 255
- && INTVAL (index) > -255);
+ if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
+ {
+ /* For DImode assume values will usually live in core regs
+ and only allow LDRD addressing modes. */
+ if (!TARGET_LDRD || mode != DImode)
+ return (code == CONST_INT
+ && INTVAL (index) < 1024
+ && INTVAL (index) > -1024
+ && (INTVAL (index) & 3) == 0);
+ }
if (arm_address_register_rtx_p (index, strict_p)
- && GET_MODE_SIZE (mode) <= 4)
+ && (GET_MODE_SIZE (mode) <= 4))
return 1;
- if (TARGET_REALLY_IWMMXT && VALID_IWMMXT_REG_MODE (mode))
- return (code == CONST_INT
- && INTVAL (index) < 256
- && INTVAL (index) > -256);
-
- /* XXX What about ldrsb? */
- if (GET_MODE_SIZE (mode) <= 4 && code == MULT
- && (!arm_arch4 || (mode) != HImode))
+ if (mode == DImode || mode == DFmode)
{
- rtx xiop0 = XEXP (index, 0);
- rtx xiop1 = XEXP (index, 1);
+ if (code == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL (index);
+
+ if (TARGET_LDRD)
+ return val > -256 && val < 256;
+ else
+ return val > -4096 && val < 4092;
+ }
- return ((arm_address_register_rtx_p (xiop0, strict_p)
- && power_of_two_operand (xiop1, SImode))
- || (arm_address_register_rtx_p (xiop1, strict_p)
- && power_of_two_operand (xiop0, SImode)));
+ return TARGET_LDRD && arm_address_register_rtx_p (index, strict_p);
}
if (GET_MODE_SIZE (mode) <= 4
- && (code == LSHIFTRT || code == ASHIFTRT
- || code == ASHIFT || code == ROTATERT)
- && (!arm_arch4 || (mode) != HImode))
+ && ! (arm_arch4
+ && (mode == HImode
+ || (mode == QImode && outer == SIGN_EXTEND))))
{
- rtx op = XEXP (index, 1);
+ if (code == MULT)
+ {
+ rtx xiop0 = XEXP (index, 0);
+ rtx xiop1 = XEXP (index, 1);
- return (arm_address_register_rtx_p (XEXP (index, 0), strict_p)
- && GET_CODE (op) == CONST_INT
- && INTVAL (op) > 0
- && INTVAL (op) <= 31);
+ return ((arm_address_register_rtx_p (xiop0, strict_p)
+ && power_of_two_operand (xiop1, SImode))
+ || (arm_address_register_rtx_p (xiop1, strict_p)
+ && power_of_two_operand (xiop0, SImode)));
+ }
+ else if (code == LSHIFTRT || code == ASHIFTRT
+ || code == ASHIFT || code == ROTATERT)
+ {
+ rtx op = XEXP (index, 1);
+
+ return (arm_address_register_rtx_p (XEXP (index, 0), strict_p)
+ && GET_CODE (op) == CONST_INT
+ && INTVAL (op) > 0
+ && INTVAL (op) <= 31);
+ }
}
- /* XXX For ARM v4 we may be doing a sign-extend operation during the
- load, but that has a restricted addressing range and we are unable
- to tell here whether that is the case. To be safe we restrict all
- loads to that range. */
+ /* For ARM v4 we may be doing a sign-extend operation during the
+ load. */
if (arm_arch4)
- range = (mode == HImode || mode == QImode) ? 256 : 4096;
+ {
+ if (mode == HImode || (outer == SIGN_EXTEND && mode == QImode))
+ range = 256;
+ else
+ range = 4096;
+ }
else
range = (mode == HImode) ? 4095 : 4096;
@@ -2907,7 +3708,7 @@ thumb_index_register_rtx_p (rtx x, int strict_p)
}
/* Return nonzero if x is a legitimate Thumb-state address.
-
+
The AP may be eliminated to either the SP or the FP, so we use the
least common denominator, e.g. SImode, and offsets from 0 to 64.
@@ -2944,7 +3745,7 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
/* This is PC relative data before arm_reorg runs. */
else if (GET_MODE_SIZE (mode) >= 4 && CONSTANT_P (x)
&& GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x) && ! flag_pic)
+ && CONSTANT_POOL_ADDRESS_P (x) && !flag_pic)
return 1;
/* This is PC relative data after arm_reorg runs. */
@@ -3006,8 +3807,9 @@ thumb_legitimate_address_p (enum machine_mode mode, rtx x, int strict_p)
&& GET_MODE_SIZE (mode) == 4
&& GET_CODE (x) == SYMBOL_REF
&& CONSTANT_POOL_ADDRESS_P (x)
- && !(flag_pic
- && symbol_mentioned_p (get_pool_constant (x))))
+ && ! (flag_pic
+ && symbol_mentioned_p (get_pool_constant (x))
+ && ! pcrel_constant_p (get_pool_constant (x))))
return 1;
return 0;
@@ -3033,11 +3835,166 @@ thumb_legitimate_offset_p (enum machine_mode mode, HOST_WIDE_INT val)
}
}
+/* Build the SYMBOL_REF for __tls_get_addr. */
+
+static GTY(()) rtx tls_get_addr_libfunc;
+
+static rtx
+get_tls_get_addr (void)
+{
+ if (!tls_get_addr_libfunc)
+ tls_get_addr_libfunc = init_one_libfunc ("__tls_get_addr");
+ return tls_get_addr_libfunc;
+}
+
+static rtx
+arm_load_tp (rtx target)
+{
+ if (!target)
+ target = gen_reg_rtx (SImode);
+
+ if (TARGET_HARD_TP)
+ {
+ /* Can return in any reg. */
+ emit_insn (gen_load_tp_hard (target));
+ }
+ else
+ {
+ /* Always returned in r0. Immediately copy the result into a pseudo,
+ otherwise other uses of r0 (e.g. setting up function arguments) may
+ clobber the value. */
+
+ rtx tmp;
+
+ emit_insn (gen_load_tp_soft ());
+
+ tmp = gen_rtx_REG (SImode, 0);
+ emit_move_insn (target, tmp);
+ }
+ return target;
+}
+
+static rtx
+load_tls_operand (rtx x, rtx reg)
+{
+ rtx tmp;
+
+ if (reg == NULL_RTX)
+ reg = gen_reg_rtx (SImode);
+
+ tmp = gen_rtx_CONST (SImode, x);
+
+ emit_move_insn (reg, tmp);
+
+ return reg;
+}
+
+static rtx
+arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
+{
+ rtx insns, label, labelno, sum;
+
+ start_sequence ();
+
+ labelno = GEN_INT (pic_labelno++);
+ label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
+ label = gen_rtx_CONST (VOIDmode, label);
+
+ sum = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (4, x, GEN_INT (reloc), label,
+ GEN_INT (TARGET_ARM ? 8 : 4)),
+ UNSPEC_TLS);
+ reg = load_tls_operand (sum, reg);
+
+ if (TARGET_ARM)
+ emit_insn (gen_pic_add_dot_plus_eight (reg, reg, labelno));
+ else
+ emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
+
+ *valuep = emit_library_call_value (get_tls_get_addr (), NULL_RTX, LCT_PURE, /* LCT_CONST? */
+ Pmode, 1, reg, Pmode);
+
+ insns = get_insns ();
+ end_sequence ();
+
+ return insns;
+}
+
+rtx
+legitimize_tls_address (rtx x, rtx reg)
+{
+ rtx dest, tp, label, labelno, sum, insns, ret, eqv, addend;
+ unsigned int model = SYMBOL_REF_TLS_MODEL (x);
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ insns = arm_call_tls_get_addr (x, reg, &ret, TLS_GD32);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, dest, ret, x);
+ return dest;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ insns = arm_call_tls_get_addr (x, reg, &ret, TLS_LDM32);
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LDM result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx),
+ UNSPEC_TLS);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, dest, ret, eqv);
+
+ /* Load the addend. */
+ addend = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (TLS_LDO32)),
+ UNSPEC_TLS);
+ addend = force_reg (SImode, gen_rtx_CONST (SImode, addend));
+ return gen_rtx_PLUS (Pmode, dest, addend);
+
+ case TLS_MODEL_INITIAL_EXEC:
+ labelno = GEN_INT (pic_labelno++);
+ label = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, labelno), UNSPEC_PIC_LABEL);
+ label = gen_rtx_CONST (VOIDmode, label);
+ sum = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (4, x, GEN_INT (TLS_IE32), label,
+ GEN_INT (TARGET_ARM ? 8 : 4)),
+ UNSPEC_TLS);
+ reg = load_tls_operand (sum, reg);
+
+ if (TARGET_ARM)
+ emit_insn (gen_tls_load_dot_plus_eight (reg, reg, labelno));
+ else
+ {
+ emit_insn (gen_pic_add_dot_plus_four (reg, reg, labelno));
+ emit_move_insn (reg, gen_const_mem (SImode, reg));
+ }
+
+ tp = arm_load_tp (NULL_RTX);
+
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ case TLS_MODEL_LOCAL_EXEC:
+ tp = arm_load_tp (NULL_RTX);
+
+ reg = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (2, x, GEN_INT (TLS_LE32)),
+ UNSPEC_TLS);
+ reg = force_reg (SImode, gen_rtx_CONST (SImode, reg));
+
+ return gen_rtx_PLUS (Pmode, tp, reg);
+
+ default:
+ abort ();
+ }
+}
+
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address. */
rtx
arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
{
+ if (arm_tls_symbol_p (x))
+ return legitimize_tls_address (x, NULL_RTX);
+
if (GET_CODE (x) == PLUS)
{
rtx xop0 = XEXP (x, 0);
@@ -3056,7 +4013,10 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
rtx base_reg, val;
n = INTVAL (xop1);
- if (mode == DImode || (TARGET_SOFT_FLOAT && mode == DFmode))
+ /* VFP addressing modes actually allow greater offsets, but for
+ now we just stick with the lowest common denominator. */
+ if (mode == DImode
+ || ((TARGET_SOFT_FLOAT || TARGET_VFP) && mode == DFmode))
{
low_n = n & 0x0f;
n &= ~0x0f;
@@ -3074,11 +4034,9 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
}
base_reg = gen_reg_rtx (SImode);
- val = force_operand (gen_rtx_PLUS (SImode, xop0,
- GEN_INT (n)), NULL_RTX);
+ val = force_operand (plus_constant (xop0, n), NULL_RTX);
emit_move_insn (base_reg, val);
- x = (low_n == 0 ? base_reg
- : gen_rtx_PLUS (SImode, base_reg, GEN_INT (low_n)));
+ x = plus_constant (base_reg, low_n);
}
else if (xop0 != XEXP (x, 0) || xop1 != XEXP (x, 1))
x = gen_rtx_PLUS (SImode, xop0, xop1);
@@ -3101,6 +4059,34 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
x = gen_rtx_MINUS (SImode, xop0, xop1);
}
+ /* Make sure to take full advantage of the pre-indexed addressing mode
+ with absolute addresses which often allows for the base register to
+ be factorized for multiple adjacent memory references, and it might
+ even allows for the mini pool to be avoided entirely. */
+ else if (GET_CODE (x) == CONST_INT && optimize > 0)
+ {
+ unsigned int bits;
+ HOST_WIDE_INT mask, base, index;
+ rtx base_reg;
+
+ /* ldr and ldrb can use a 12 bit index, ldrsb and the rest can only
+ use a 8 bit index. So let's use a 12 bit index for SImode only and
+ hope that arm_gen_constant will enable ldrb to use more bits. */
+ bits = (mode == SImode) ? 12 : 8;
+ mask = (1 << bits) - 1;
+ base = INTVAL (x) & ~mask;
+ index = INTVAL (x) & mask;
+ if (bit_count (base & 0xffffffff) > (32 - bits)/2)
+ {
+ /* It'll most probably be more efficient to generate the base
+ with more bits set and use a negative index instead. */
+ base |= mask;
+ index -= mask;
+ }
+ base_reg = force_reg (SImode, GEN_INT (base));
+ x = plus_constant (base_reg, index);
+ }
+
if (flag_pic)
{
/* We need to find and carefully transform any SYMBOL and LABEL
@@ -3114,8 +4100,164 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
return x;
}
-
+/* Try machine-dependent ways of modifying an illegitimate Thumb address
+ to be legitimate. If we find one, return the new, valid address. */
+rtx
+thumb_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
+{
+ if (arm_tls_symbol_p (x))
+ return legitimize_tls_address (x, NULL_RTX);
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && (INTVAL (XEXP (x, 1)) >= 32 * GET_MODE_SIZE (mode)
+ || INTVAL (XEXP (x, 1)) < 0))
+ {
+ rtx xop0 = XEXP (x, 0);
+ rtx xop1 = XEXP (x, 1);
+ HOST_WIDE_INT offset = INTVAL (xop1);
+
+ /* Try and fold the offset into a biasing of the base register and
+ then offsetting that. Don't do this when optimizing for space
+ since it can cause too many CSEs. */
+ if (optimize_size && offset >= 0
+ && offset < 256 + 31 * GET_MODE_SIZE (mode))
+ {
+ HOST_WIDE_INT delta;
+
+ if (offset >= 256)
+ delta = offset - (256 - GET_MODE_SIZE (mode));
+ else if (offset < 32 * GET_MODE_SIZE (mode) + 8)
+ delta = 31 * GET_MODE_SIZE (mode);
+ else
+ delta = offset & (~31 * GET_MODE_SIZE (mode));
+
+ xop0 = force_operand (plus_constant (xop0, offset - delta),
+ NULL_RTX);
+ x = plus_constant (xop0, delta);
+ }
+ else if (offset < 0 && offset > -256)
+ /* Small negative offsets are best done with a subtract before the
+ dereference, forcing these into a register normally takes two
+ instructions. */
+ x = force_operand (x, NULL_RTX);
+ else
+ {
+ /* For the remaining cases, force the constant into a register. */
+ xop1 = force_reg (SImode, xop1);
+ x = gen_rtx_PLUS (SImode, xop0, xop1);
+ }
+ }
+ else if (GET_CODE (x) == PLUS
+ && s_register_operand (XEXP (x, 1), SImode)
+ && !s_register_operand (XEXP (x, 0), SImode))
+ {
+ rtx xop0 = force_operand (XEXP (x, 0), NULL_RTX);
+
+ x = gen_rtx_PLUS (SImode, xop0, XEXP (x, 1));
+ }
+
+ if (flag_pic)
+ {
+ /* We need to find and carefully transform any SYMBOL and LABEL
+ references; so go back to the original address expression. */
+ rtx new_x = legitimize_pic_address (orig_x, mode, NULL_RTX);
+
+ if (new_x != orig_x)
+ x = new_x;
+ }
+
+ return x;
+}
+
+rtx
+thumb_legitimize_reload_address (rtx *x_p,
+ enum machine_mode mode,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED)
+{
+ rtx x = *x_p;
+
+ if (GET_CODE (x) == PLUS
+ && GET_MODE_SIZE (mode) < 4
+ && REG_P (XEXP (x, 0))
+ && XEXP (x, 0) == stack_pointer_rtx
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && !thumb_legitimate_offset_p (mode, INTVAL (XEXP (x, 1))))
+ {
+ rtx orig_x = x;
+
+ x = copy_rtx (x);
+ push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
+ Pmode, VOIDmode, 0, 0, opnum, type);
+ return x;
+ }
+
+ /* If both registers are hi-regs, then it's better to reload the
+ entire expression rather than each register individually. That
+ only requires one reload register rather than two. */
+ if (GET_CODE (x) == PLUS
+ && REG_P (XEXP (x, 0))
+ && REG_P (XEXP (x, 1))
+ && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 0), mode)
+ && !REG_MODE_OK_FOR_REG_BASE_P (XEXP (x, 1), mode))
+ {
+ rtx orig_x = x;
+
+ x = copy_rtx (x);
+ push_reload (orig_x, NULL_RTX, x_p, NULL, MODE_BASE_REG_CLASS (mode),
+ Pmode, VOIDmode, 0, 0, opnum, type);
+ return x;
+ }
+
+ return NULL;
+}
+
+/* Test for various thread-local symbols. */
+
+/* Return TRUE if X is a thread-local symbol. */
+
+static bool
+arm_tls_symbol_p (rtx x)
+{
+ if (! TARGET_HAVE_TLS)
+ return false;
+
+ if (GET_CODE (x) != SYMBOL_REF)
+ return false;
+
+ return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+/* Helper for arm_tls_referenced_p. */
+
+static int
+arm_tls_operand_p_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ if (GET_CODE (*x) == SYMBOL_REF)
+ return SYMBOL_REF_TLS_MODEL (*x) != 0;
+
+ /* Don't recurse into UNSPEC_TLS looking for TLS symbols; these are
+ TLS offsets, not real symbol references. */
+ if (GET_CODE (*x) == UNSPEC
+ && XINT (*x, 1) == UNSPEC_TLS)
+ return -1;
+
+ return 0;
+}
+
+/* Return TRUE if X contains any TLS symbol references. */
+
+bool
+arm_tls_referenced_p (rtx x)
+{
+ if (! TARGET_HAVE_TLS)
+ return false;
+
+ return for_each_rtx (&x, arm_tls_operand_p_1, NULL);
+}
+
#define REG_OR_SUBREG_REG(X) \
(GET_CODE (X) == REG \
|| (GET_CODE (X) == SUBREG && GET_CODE (SUBREG_REG (X)) == REG))
@@ -3126,129 +4268,132 @@ arm_legitimize_address (rtx x, rtx orig_x, enum machine_mode mode)
#ifndef COSTS_N_INSNS
#define COSTS_N_INSNS(N) ((N) * 4 - 2)
#endif
-/* Worker routine for arm_rtx_costs. */
static inline int
-arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
+thumb_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
{
enum machine_mode mode = GET_MODE (x);
- enum rtx_code subcode;
- int extra_cost;
- if (TARGET_THUMB)
+ switch (code)
{
- switch (code)
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ROTATERT:
+ case PLUS:
+ case MINUS:
+ case COMPARE:
+ case NEG:
+ case NOT:
+ return COSTS_N_INSNS (1);
+
+ case MULT:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
{
- case ASHIFT:
- case ASHIFTRT:
- case LSHIFTRT:
- case ROTATERT:
- case PLUS:
- case MINUS:
- case COMPARE:
- case NEG:
- case NOT:
- return COSTS_N_INSNS (1);
-
- case MULT:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- int cycles = 0;
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
-
- while (i)
- {
- i >>= 2;
- cycles++;
- }
- return COSTS_N_INSNS (2) + cycles;
+ int cycles = 0;
+ unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
+
+ while (i)
+ {
+ i >>= 2;
+ cycles++;
}
- return COSTS_N_INSNS (1) + 16;
-
- case SET:
- return (COSTS_N_INSNS (1)
- + 4 * ((GET_CODE (SET_SRC (x)) == MEM)
- + GET_CODE (SET_DEST (x)) == MEM));
-
- case CONST_INT:
- if (outer == SET)
- {
- if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)
- return 0;
- if (thumb_shiftable_const (INTVAL (x)))
- return COSTS_N_INSNS (2);
- return COSTS_N_INSNS (3);
- }
- else if ((outer == PLUS || outer == COMPARE)
- && INTVAL (x) < 256 && INTVAL (x) > -256)
+ return COSTS_N_INSNS (2) + cycles;
+ }
+ return COSTS_N_INSNS (1) + 16;
+
+ case SET:
+ return (COSTS_N_INSNS (1)
+ + 4 * ((GET_CODE (SET_SRC (x)) == MEM)
+ + GET_CODE (SET_DEST (x)) == MEM));
+
+ case CONST_INT:
+ if (outer == SET)
+ {
+ if ((unsigned HOST_WIDE_INT) INTVAL (x) < 256)
return 0;
- else if (outer == AND
- && INTVAL (x) < 256 && INTVAL (x) >= -256)
- return COSTS_N_INSNS (1);
- else if (outer == ASHIFT || outer == ASHIFTRT
- || outer == LSHIFTRT)
- return 0;
- return COSTS_N_INSNS (2);
-
- case CONST:
- case CONST_DOUBLE:
- case LABEL_REF:
- case SYMBOL_REF:
+ if (thumb_shiftable_const (INTVAL (x)))
+ return COSTS_N_INSNS (2);
return COSTS_N_INSNS (3);
-
- case UDIV:
- case UMOD:
- case DIV:
- case MOD:
- return 100;
-
- case TRUNCATE:
- return 99;
+ }
+ else if ((outer == PLUS || outer == COMPARE)
+ && INTVAL (x) < 256 && INTVAL (x) > -256)
+ return 0;
+ else if (outer == AND
+ && INTVAL (x) < 256 && INTVAL (x) >= -256)
+ return COSTS_N_INSNS (1);
+ else if (outer == ASHIFT || outer == ASHIFTRT
+ || outer == LSHIFTRT)
+ return 0;
+ return COSTS_N_INSNS (2);
- case AND:
- case XOR:
- case IOR:
- /* XXX guess. */
- return 8;
+ case CONST:
+ case CONST_DOUBLE:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ return COSTS_N_INSNS (3);
- case ADDRESSOF:
- case MEM:
- /* XXX another guess. */
- /* Memory costs quite a lot for the first word, but subsequent words
- load at the equivalent of a single insn each. */
- return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
- + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
- ? 4 : 0));
-
- case IF_THEN_ELSE:
- /* XXX a guess. */
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- return 14;
- return 2;
+ case UDIV:
+ case UMOD:
+ case DIV:
+ case MOD:
+ return 100;
+
+ case TRUNCATE:
+ return 99;
+
+ case AND:
+ case XOR:
+ case IOR:
+ /* XXX guess. */
+ return 8;
+
+ case MEM:
+ /* XXX another guess. */
+ /* Memory costs quite a lot for the first word, but subsequent words
+ load at the equivalent of a single insn each. */
+ return (10 + 4 * ((GET_MODE_SIZE (mode) - 1) / UNITS_PER_WORD)
+ + ((GET_CODE (x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (x))
+ ? 4 : 0));
+
+ case IF_THEN_ELSE:
+ /* XXX a guess. */
+ if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
+ return 14;
+ return 2;
+
+ case ZERO_EXTEND:
+ /* XXX still guessing. */
+ switch (GET_MODE (XEXP (x, 0)))
+ {
+ case QImode:
+ return (1 + (mode == DImode ? 4 : 0)
+ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
+
+ case HImode:
+ return (4 + (mode == DImode ? 4 : 0)
+ + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
+
+ case SImode:
+ return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
- case ZERO_EXTEND:
- /* XXX still guessing. */
- switch (GET_MODE (XEXP (x, 0)))
- {
- case QImode:
- return (1 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case HImode:
- return (4 + (mode == DImode ? 4 : 0)
- + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- case SImode:
- return (1 + (GET_CODE (XEXP (x, 0)) == MEM ? 10 : 0));
-
- default:
- return 99;
- }
-
default:
return 99;
}
+
+ default:
+ return 99;
}
-
+}
+
+
+/* Worker routine for arm_rtx_costs. */
+static inline int
+arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
+{
+ enum machine_mode mode = GET_MODE (x);
+ enum rtx_code subcode;
+ int extra_cost;
+
switch (code)
{
case MEM:
@@ -3275,7 +4420,7 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
case ASHIFT: case LSHIFTRT: case ASHIFTRT:
if (mode == DImode)
return (8 + (GET_CODE (XEXP (x, 1)) == CONST_INT ? 0 : 8)
- + ((GET_CODE (XEXP (x, 0)) == REG
+ + ((GET_CODE (XEXP (x, 0)) == REG
|| (GET_CODE (XEXP (x, 0)) == SUBREG
&& GET_CODE (SUBREG_REG (XEXP (x, 0))) == REG))
? 0 : 8));
@@ -3300,11 +4445,11 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
return (2 + ((REG_OR_SUBREG_REG (XEXP (x, 1))
|| (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
- && const_double_rtx_ok_for_fpa (XEXP (x, 1))))
+ && arm_const_double_rtx (XEXP (x, 1))))
? 0 : 8)
+ ((REG_OR_SUBREG_REG (XEXP (x, 0))
|| (GET_CODE (XEXP (x, 0)) == CONST_DOUBLE
- && const_double_rtx_ok_for_fpa (XEXP (x, 0))))
+ && arm_const_double_rtx (XEXP (x, 0))))
? 0 : 8));
if (((GET_CODE (XEXP (x, 0)) == CONST_INT
@@ -3324,16 +4469,24 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
return 1;
/* Fall through */
- case PLUS:
+ case PLUS:
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ extra_cost = rtx_cost (XEXP (x, 0), code);
+ if (!REG_OR_SUBREG_REG (XEXP (x, 1)))
+ extra_cost += 4 * ARM_NUM_REGS (mode);
+ return extra_cost;
+ }
+
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
return (2 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 8)
+ ((REG_OR_SUBREG_REG (XEXP (x, 1))
|| (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
- && const_double_rtx_ok_for_fpa (XEXP (x, 1))))
+ && arm_const_double_rtx (XEXP (x, 1))))
? 0 : 8));
/* Fall through */
- case AND: case XOR: case IOR:
+ case AND: case XOR: case IOR:
extra_cost = 0;
/* Normally the frame registers will be spilt into reg+const during
@@ -3379,65 +4532,11 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
return 8;
case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (arm_fast_multiply && mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- return 8;
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || mode == DImode)
- return 30;
-
- if (GET_CODE (XEXP (x, 1)) == CONST_INT)
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- int j, booth_unit_size;
-
- if (arm_tune_xscale)
- {
- unsigned HOST_WIDE_INT masked_const;
-
- /* The cost will be related to two insns.
- First a load of the constant (MOV or LDR), then a multiply. */
- cost = 2;
- if (! const_ok)
- cost += 1; /* LDR is probably more expensive because
- of longer result latency. */
- masked_const = i & 0xffff8000;
- if (masked_const != 0 && masked_const != 0xffff8000)
- {
- masked_const = i & 0xf8000000;
- if (masked_const == 0 || masked_const == 0xf8000000)
- cost += 1;
- else
- cost += 2;
- }
- return cost;
- }
-
- /* Tune as appropriate. */
- cost = const_ok ? 4 : 8;
- booth_unit_size = ((tune_flags & FL_FAST_MULT) ? 8 : 2);
- for (j = 0; i && j < 32; j += booth_unit_size)
- {
- i >>= booth_unit_size;
- cost += 2;
- }
-
- return cost;
- }
-
- return (((tune_flags & FL_FAST_MULT) ? 8 : 30)
- + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
- + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4));
+ /* This should have been handled by the CPU specific routines. */
+ gcc_unreachable ();
case TRUNCATE:
- if (arm_fast_multiply && mode == SImode
+ if (arm_arch3m && mode == SImode
&& GET_CODE (XEXP (x, 0)) == LSHIFTRT
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
&& (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
@@ -3495,48 +4594,527 @@ arm_rtx_costs_1 (rtx x, enum rtx_code code, enum rtx_code outer)
return 1;
default:
- break;
+ gcc_unreachable ();
}
- abort ();
+ gcc_unreachable ();
- case CONST_INT:
- if (const_ok_for_arm (INTVAL (x)))
- return outer == SET ? 2 : -1;
- else if (outer == AND
- && const_ok_for_arm (~INTVAL (x)))
- return -1;
- else if ((outer == COMPARE
- || outer == PLUS || outer == MINUS)
- && const_ok_for_arm (-INTVAL (x)))
- return -1;
- else
+ case CONST_INT:
+ if (const_ok_for_arm (INTVAL (x)))
+ return outer == SET ? 2 : -1;
+ else if (outer == AND
+ && const_ok_for_arm (~INTVAL (x)))
+ return -1;
+ else if ((outer == COMPARE
+ || outer == PLUS || outer == MINUS)
+ && const_ok_for_arm (-INTVAL (x)))
+ return -1;
+ else
return 5;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
return 6;
-
- case CONST_DOUBLE:
- if (const_double_rtx_ok_for_fpa (x))
- return outer == SET ? 2 : -1;
- else if ((outer == COMPARE || outer == PLUS)
- && neg_const_double_rtx_ok_for_fpa (x))
- return -1;
+
+ case CONST_DOUBLE:
+ if (arm_const_double_rtx (x))
+ return outer == SET ? 2 : -1;
+ else if ((outer == COMPARE || outer == PLUS)
+ && neg_const_double_rtx_ok_for_fpa (x))
+ return -1;
return 7;
-
+
default:
return 99;
}
}
+/* RTX costs when optimizing for size. */
static bool
-arm_rtx_costs (rtx x, int code, int outer_code, int *total)
+arm_size_rtx_costs (rtx x, int code, int outer_code, int *total)
{
- *total = arm_rtx_costs_1 (x, code, outer_code);
- return true;
+ enum machine_mode mode = GET_MODE (x);
+
+ if (TARGET_THUMB)
+ {
+ /* XXX TBD. For now, use the standard costs. */
+ *total = thumb_rtx_costs (x, code, outer_code);
+ return true;
+ }
+
+ switch (code)
+ {
+ case MEM:
+ /* A memory access costs 1 insn if the mode is small, or the address is
+ a single register, otherwise it costs one insn per word. */
+ if (REG_P (XEXP (x, 0)))
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ return true;
+
+ case DIV:
+ case MOD:
+ case UDIV:
+ case UMOD:
+ /* Needs a libcall, so it costs about this. */
+ *total = COSTS_N_INSNS (2);
+ return false;
+
+ case ROTATE:
+ if (mode == SImode && GET_CODE (XEXP (x, 1)) == REG)
+ {
+ *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), code);
+ return true;
+ }
+ /* Fall through */
+ case ROTATERT:
+ case ASHIFT:
+ case LSHIFTRT:
+ case ASHIFTRT:
+ if (mode == DImode && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), code);
+ return true;
+ }
+ else if (mode == SImode)
+ {
+ *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), code);
+ /* Slightly disparage register shifts, but not by much. */
+ if (GET_CODE (XEXP (x, 1)) != CONST_INT)
+ *total += 1 + rtx_cost (XEXP (x, 1), code);
+ return true;
+ }
+
+ /* Needs a libcall. */
+ *total = COSTS_N_INSNS (2);
+ return false;
+
+ case MINUS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+
+ if (mode == SImode)
+ {
+ enum rtx_code subcode0 = GET_CODE (XEXP (x, 0));
+ enum rtx_code subcode1 = GET_CODE (XEXP (x, 1));
+
+ if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT
+ || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT
+ || subcode1 == ROTATE || subcode1 == ROTATERT
+ || subcode1 == ASHIFT || subcode1 == LSHIFTRT
+ || subcode1 == ASHIFTRT)
+ {
+ /* It's just the cost of the two operands. */
+ *total = 0;
+ return false;
+ }
+
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ return false;
+
+ case PLUS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+
+ /* Fall through */
+ case AND: case XOR: case IOR:
+ if (mode == SImode)
+ {
+ enum rtx_code subcode = GET_CODE (XEXP (x, 0));
+
+ if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT
+ || subcode == LSHIFTRT || subcode == ASHIFTRT
+ || (code == AND && subcode == NOT))
+ {
+ /* It's just the cost of the two operands. */
+ *total = 0;
+ return false;
+ }
+ }
+
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ return false;
+
+ case MULT:
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ return false;
+
+ case NEG:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ *total = COSTS_N_INSNS (1);
+ /* Fall through */
+ case NOT:
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+
+ return false;
+
+ case IF_THEN_ELSE:
+ *total = 0;
+ return false;
+
+ case COMPARE:
+ if (cc_register (XEXP (x, 0), VOIDmode))
+ * total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
+
+ case ABS:
+ if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
+ return false;
+
+ case SIGN_EXTEND:
+ *total = 0;
+ if (GET_MODE_SIZE (GET_MODE (XEXP (x, 0))) < 4)
+ {
+ if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
+ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
+ }
+ if (mode == DImode)
+ *total += COSTS_N_INSNS (1);
+ return false;
+
+ case ZERO_EXTEND:
+ *total = 0;
+ if (!(arm_arch4 && MEM_P (XEXP (x, 0))))
+ {
+ switch (GET_MODE (XEXP (x, 0)))
+ {
+ case QImode:
+ *total += COSTS_N_INSNS (1);
+ break;
+
+ case HImode:
+ *total += COSTS_N_INSNS (arm_arch6 ? 1 : 2);
+
+ case SImode:
+ break;
+
+ default:
+ *total += COSTS_N_INSNS (2);
+ }
+ }
+
+ if (mode == DImode)
+ *total += COSTS_N_INSNS (1);
+
+ return false;
+
+ case CONST_INT:
+ if (const_ok_for_arm (INTVAL (x)))
+ *total = COSTS_N_INSNS (outer_code == SET ? 1 : 0);
+ else if (const_ok_for_arm (~INTVAL (x)))
+ *total = COSTS_N_INSNS (outer_code == AND ? 0 : 1);
+ else if (const_ok_for_arm (-INTVAL (x)))
+ {
+ if (outer_code == COMPARE || outer_code == PLUS
+ || outer_code == MINUS)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ }
+ else
+ *total = COSTS_N_INSNS (2);
+ return true;
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = COSTS_N_INSNS (2);
+ return true;
+
+ case CONST_DOUBLE:
+ *total = COSTS_N_INSNS (4);
+ return true;
+
+ default:
+ if (mode != VOIDmode)
+ *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
+ else
+ *total = COSTS_N_INSNS (4); /* How knows? */
+ return false;
+ }
+}
+
+/* RTX costs for cores with a slow MUL implementation. */
+
+static bool
+arm_slowmul_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ if (TARGET_THUMB)
+ {
+ *total = thumb_rtx_costs (x, code, outer_code);
+ return true;
+ }
+
+ switch (code)
+ {
+ case MULT:
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || mode == DImode)
+ {
+ *total = 30;
+ return true;
+ }
+
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
+ & (unsigned HOST_WIDE_INT) 0xffffffff);
+ int cost, const_ok = const_ok_for_arm (i);
+ int j, booth_unit_size;
+
+ /* Tune as appropriate. */
+ cost = const_ok ? 4 : 8;
+ booth_unit_size = 2;
+ for (j = 0; i && j < 32; j += booth_unit_size)
+ {
+ i >>= booth_unit_size;
+ cost += 2;
+ }
+
+ *total = cost;
+ return true;
+ }
+
+ *total = 30 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
+ return true;
+
+ default:
+ *total = arm_rtx_costs_1 (x, code, outer_code);
+ return true;
+ }
}
+
+/* RTX cost for cores with a fast multiply unit (M variants). */
+
+static bool
+arm_fastmul_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ if (TARGET_THUMB)
+ {
+ *total = thumb_rtx_costs (x, code, outer_code);
+ return true;
+ }
+
+ switch (code)
+ {
+ case MULT:
+ /* There is no point basing this on the tuning, since it is always the
+ fast variant if it exists at all. */
+ if (mode == DImode
+ && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
+ && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
+ {
+ *total = 8;
+ return true;
+ }
+
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || mode == DImode)
+ {
+ *total = 30;
+ return true;
+ }
+
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
+ & (unsigned HOST_WIDE_INT) 0xffffffff);
+ int cost, const_ok = const_ok_for_arm (i);
+ int j, booth_unit_size;
+
+ /* Tune as appropriate. */
+ cost = const_ok ? 4 : 8;
+ booth_unit_size = 8;
+ for (j = 0; i && j < 32; j += booth_unit_size)
+ {
+ i >>= booth_unit_size;
+ cost += 2;
+ }
+
+ *total = cost;
+ return true;
+ }
+
+ *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
+ return true;
+
+ default:
+ *total = arm_rtx_costs_1 (x, code, outer_code);
+ return true;
+ }
+}
+
+
+/* RTX cost for XScale CPUs. */
+
+static bool
+arm_xscale_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+ enum machine_mode mode = GET_MODE (x);
+
+ if (TARGET_THUMB)
+ {
+ *total = thumb_rtx_costs (x, code, outer_code);
+ return true;
+ }
+
+ switch (code)
+ {
+ case MULT:
+ /* There is no point basing this on the tuning, since it is always the
+ fast variant if it exists at all. */
+ if (mode == DImode
+ && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
+ && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
+ {
+ *total = 8;
+ return true;
+ }
+
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || mode == DImode)
+ {
+ *total = 30;
+ return true;
+ }
+
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
+ & (unsigned HOST_WIDE_INT) 0xffffffff);
+ int cost, const_ok = const_ok_for_arm (i);
+ unsigned HOST_WIDE_INT masked_const;
+
+ /* The cost will be related to two insns.
+ First a load of the constant (MOV or LDR), then a multiply. */
+ cost = 2;
+ if (! const_ok)
+ cost += 1; /* LDR is probably more expensive because
+ of longer result latency. */
+ masked_const = i & 0xffff8000;
+ if (masked_const != 0 && masked_const != 0xffff8000)
+ {
+ masked_const = i & 0xf8000000;
+ if (masked_const == 0 || masked_const == 0xf8000000)
+ cost += 1;
+ else
+ cost += 2;
+ }
+ *total = cost;
+ return true;
+ }
+
+ *total = 8 + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : 4)
+ + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : 4);
+ return true;
+
+ case COMPARE:
+ /* A COMPARE of a MULT is slow on XScale; the muls instruction
+ will stall until the multiplication is complete. */
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ *total = 4 + rtx_cost (XEXP (x, 0), code);
+ else
+ *total = arm_rtx_costs_1 (x, code, outer_code);
+ return true;
+
+ default:
+ *total = arm_rtx_costs_1 (x, code, outer_code);
+ return true;
+ }
+}
+
+
+/* RTX costs for 9e (and later) cores. */
+
+static bool
+arm_9e_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+ enum machine_mode mode = GET_MODE (x);
+ int nonreg_cost;
+ int cost;
+
+ if (TARGET_THUMB)
+ {
+ switch (code)
+ {
+ case MULT:
+ *total = COSTS_N_INSNS (3);
+ return true;
+
+ default:
+ *total = thumb_rtx_costs (x, code, outer_code);
+ return true;
+ }
+ }
+
+ switch (code)
+ {
+ case MULT:
+ /* There is no point basing this on the tuning, since it is always the
+ fast variant if it exists at all. */
+ if (mode == DImode
+ && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
+ && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
+ || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
+ {
+ *total = 3;
+ return true;
+ }
+
+
+ if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ *total = 30;
+ return true;
+ }
+ if (mode == DImode)
+ {
+ cost = 7;
+ nonreg_cost = 8;
+ }
+ else
+ {
+ cost = 2;
+ nonreg_cost = 4;
+ }
+
+
+ *total = cost + (REG_OR_SUBREG_REG (XEXP (x, 0)) ? 0 : nonreg_cost)
+ + (REG_OR_SUBREG_REG (XEXP (x, 1)) ? 0 : nonreg_cost);
+ return true;
+
+ default:
+ *total = arm_rtx_costs_1 (x, code, outer_code);
+ return true;
+ }
+}
/* All address computations that can be done are free, but rtx cost returns
the same for practically all of them. So we weight the different types
of address here in the order (most pref first):
@@ -3553,13 +5131,10 @@ arm_arm_address_cost (rtx x)
if (c == PLUS || c == MINUS)
{
- char cl0 = GET_RTX_CLASS (GET_CODE (XEXP (x, 0)));
- char cl1 = GET_RTX_CLASS (GET_CODE (XEXP (x, 1)));
-
if (GET_CODE (XEXP (x, 0)) == CONST_INT)
return 2;
- if (cl0 == '2' || cl0 == 'c' || cl1 == '2' || cl1 == 'c')
+ if (ARITHMETIC_P (XEXP (x, 0)) || ARITHMETIC_P (XEXP (x, 1)))
return 3;
return 4;
@@ -3590,12 +5165,6 @@ arm_address_cost (rtx x)
}
static int
-arm_use_dfa_pipeline_interface (void)
-{
- return true;
-}
-
-static int
arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
{
rtx i_pat, d_pat;
@@ -3614,11 +5183,12 @@ arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
operand for INSN. If we have a shifted input operand and the
instruction we depend on is another ALU instruction, then we may
have to account for an additional stall. */
- if (shift_opnum != 0 && attr_type == TYPE_NORMAL)
+ if (shift_opnum != 0
+ && (attr_type == TYPE_ALU_SHIFT || attr_type == TYPE_ALU_SHIFT_REG))
{
rtx shifted_operand;
int opno;
-
+
/* Get the shifted operand. */
extract_insn (insn);
shifted_operand = recog_data.operand[shift_opnum];
@@ -3659,9 +5229,9 @@ arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
rtx src_mem = XEXP (SET_SRC (i_pat), 0);
/* This is a load after a store, there is no conflict if the load reads
from a cached area. Assume that loads from the stack, and from the
- constant pool are cached, and that others will miss. This is a
+ constant pool are cached, and that others will miss. This is a
hack. */
-
+
if ((GET_CODE (src_mem) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (src_mem))
|| reg_mentioned_p (stack_pointer_rtx, src_mem)
|| reg_mentioned_p (frame_pointer_rtx, src_mem)
@@ -3672,47 +5242,51 @@ arm_adjust_cost (rtx insn, rtx link, rtx dep, int cost)
return cost;
}
-static int fpa_consts_inited = 0;
+static int fp_consts_inited = 0;
-static const char * const strings_fpa[8] =
+/* Only zero is valid for VFP. Other values are also valid for FPA. */
+static const char * const strings_fp[8] =
{
"0", "1", "2", "3",
"4", "5", "0.5", "10"
};
-static REAL_VALUE_TYPE values_fpa[8];
+static REAL_VALUE_TYPE values_fp[8];
static void
-init_fpa_table (void)
+init_fp_table (void)
{
int i;
REAL_VALUE_TYPE r;
- for (i = 0; i < 8; i++)
+ if (TARGET_VFP)
+ fp_consts_inited = 1;
+ else
+ fp_consts_inited = 8;
+
+ for (i = 0; i < fp_consts_inited; i++)
{
- r = REAL_VALUE_ATOF (strings_fpa[i], DFmode);
- values_fpa[i] = r;
+ r = REAL_VALUE_ATOF (strings_fp[i], DFmode);
+ values_fp[i] = r;
}
-
- fpa_consts_inited = 1;
}
-/* Return TRUE if rtx X is a valid immediate FPA constant. */
+/* Return TRUE if rtx X is a valid immediate FP constant. */
int
-const_double_rtx_ok_for_fpa (rtx x)
+arm_const_double_rtx (rtx x)
{
REAL_VALUE_TYPE r;
int i;
-
- if (!fpa_consts_inited)
- init_fpa_table ();
-
+
+ if (!fp_consts_inited)
+ init_fp_table ();
+
REAL_VALUE_FROM_CONST_DOUBLE (r, x);
if (REAL_VALUE_MINUS_ZERO (r))
return 0;
- for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (r, values_fpa[i]))
+ for (i = 0; i < fp_consts_inited; i++)
+ if (REAL_VALUES_EQUAL (r, values_fp[i]))
return 1;
return 0;
@@ -3724,17 +5298,17 @@ neg_const_double_rtx_ok_for_fpa (rtx x)
{
REAL_VALUE_TYPE r;
int i;
-
- if (!fpa_consts_inited)
- init_fpa_table ();
-
+
+ if (!fp_consts_inited)
+ init_fp_table ();
+
REAL_VALUE_FROM_CONST_DOUBLE (r, x);
r = REAL_VALUE_NEGATE (r);
if (REAL_VALUE_MINUS_ZERO (r))
return 0;
for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (r, values_fpa[i]))
+ if (REAL_VALUES_EQUAL (r, values_fp[i]))
return 1;
return 0;
@@ -3742,244 +5316,6 @@ neg_const_double_rtx_ok_for_fpa (rtx x)
/* Predicates for `match_operand' and `match_operator'. */
-/* s_register_operand is the same as register_operand, but it doesn't accept
- (SUBREG (MEM)...).
-
- This function exists because at the time it was put in it led to better
- code. SUBREG(MEM) always needs a reload in the places where
- s_register_operand is used, and this seemed to lead to excessive
- reloading. */
-int
-s_register_operand (rtx op, enum machine_mode mode)
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- /* XXX might have to check for lo regs only for thumb ??? */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
-
-/* A hard register operand (even before reload. */
-int
-arm_hard_register_operand (rtx op, enum machine_mode mode)
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- return (GET_CODE (op) == REG
- && REGNO (op) < FIRST_PSEUDO_REGISTER);
-}
-
-/* Only accept reg, subreg(reg), const_int. */
-int
-reg_or_int_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- return 1;
-
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
-}
-
-/* Return 1 if OP is an item in memory, given that we are in reload. */
-int
-arm_reload_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int regno = true_regnum (op);
-
- return (!CONSTANT_P (op)
- && (regno == -1
- || (GET_CODE (op) == REG
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return 1 if OP is a valid memory address, but not valid for a signed byte
- memory access (architecture V4).
- MODE is QImode if called when computing constraints, or VOIDmode when
- emitting patterns. In this latter case we cannot use memory_operand()
- because it will fail on badly formed MEMs, which is precisely what we are
- trying to catch. */
-int
-bad_signed_byte_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
-
- /* A sum of anything more complex than reg + reg or reg + const is bad. */
- if ((GET_CODE (op) == PLUS || GET_CODE (op) == MINUS)
- && (!s_register_operand (XEXP (op, 0), VOIDmode)
- || (!s_register_operand (XEXP (op, 1), VOIDmode)
- && GET_CODE (XEXP (op, 1)) != CONST_INT)))
- return 1;
-
- /* Big constants are also bad. */
- if (GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT
- && (INTVAL (XEXP (op, 1)) > 0xff
- || -INTVAL (XEXP (op, 1)) > 0xff))
- return 1;
-
- /* Everything else is good, or can will automatically be made so. */
- return 0;
-}
-
-/* Return TRUE for valid operands for the rhs of an ARM instruction. */
-int
-arm_rhs_operand (rtx op, enum machine_mode mode)
-{
- return (s_register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op))));
-}
-
-/* Return TRUE for valid operands for the
- rhs of an ARM instruction, or a load. */
-int
-arm_rhsm_operand (rtx op, enum machine_mode mode)
-{
- return (s_register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && const_ok_for_arm (INTVAL (op)))
- || memory_operand (op, mode));
-}
-
-/* Return TRUE for valid operands for the rhs of an ARM instruction, or if a
- constant that is valid when negated. */
-int
-arm_add_operand (rtx op, enum machine_mode mode)
-{
- if (TARGET_THUMB)
- return thumb_cmp_operand (op, mode);
-
- return (s_register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
- && (const_ok_for_arm (INTVAL (op))
- || const_ok_for_arm (-INTVAL (op)))));
-}
-
-/* Return TRUE for valid ARM constants (or when valid if negated). */
-int
-arm_addimm_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (const_ok_for_arm (INTVAL (op))
- || const_ok_for_arm (-INTVAL (op))));
-}
-
-int
-arm_not_operand (rtx op, enum machine_mode mode)
-{
- return (s_register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
- && (const_ok_for_arm (INTVAL (op))
- || const_ok_for_arm (~INTVAL (op)))));
-}
-
-/* Return TRUE if the operand is a memory reference which contains an
- offsettable address. */
-int
-offsettable_memory_operand (rtx op, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- return (mode == GET_MODE (op)
- && GET_CODE (op) == MEM
- && offsettable_address_p (reload_completed | reload_in_progress,
- mode, XEXP (op, 0)));
-}
-
-/* Return TRUE if the operand is a memory reference which is, or can be
- made word aligned by adjusting the offset. */
-int
-alignable_memory_operand (rtx op, enum machine_mode mode)
-{
- rtx reg;
-
- if (mode == VOIDmode)
- mode = GET_MODE (op);
-
- if (mode != GET_MODE (op) || GET_CODE (op) != MEM)
- return 0;
-
- op = XEXP (op, 0);
-
- return ((GET_CODE (reg = op) == REG
- || (GET_CODE (op) == SUBREG
- && GET_CODE (reg = SUBREG_REG (op)) == REG)
- || (GET_CODE (op) == PLUS
- && GET_CODE (XEXP (op, 1)) == CONST_INT
- && (GET_CODE (reg = XEXP (op, 0)) == REG
- || (GET_CODE (XEXP (op, 0)) == SUBREG
- && GET_CODE (reg = SUBREG_REG (XEXP (op, 0))) == REG))))
- && REGNO_POINTER_ALIGN (REGNO (reg)) >= 32);
-}
-
-/* Similar to s_register_operand, but does not allow hard integer
- registers. */
-int
-f_register_operand (rtx op, enum machine_mode mode)
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return 0;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- /* We don't consider registers whose class is NO_REGS
- to be a register operand. */
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
-}
-
-/* Return TRUE for valid operands for the rhs of an FPA instruction. */
-int
-fpa_rhs_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return FALSE;
-
- if (GET_CODE (op) == CONST_DOUBLE)
- return const_double_rtx_ok_for_fpa (op);
-
- return FALSE;
-}
-
-int
-fpa_add_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return FALSE;
-
- if (GET_CODE (op) == CONST_DOUBLE)
- return (const_double_rtx_ok_for_fpa (op)
- || neg_const_double_rtx_ok_for_fpa (op));
-
- return FALSE;
-}
-
/* Return nonzero if OP is a valid Cirrus memory address pattern. */
int
cirrus_memory_offset (rtx op)
@@ -4017,43 +5353,70 @@ cirrus_memory_offset (rtx op)
return 0;
}
-/* Return nonzero if OP is a Cirrus or general register. */
+/* Return TRUE if OP is a valid coprocessor memory address pattern.
+ WB if true if writeback address modes are allowed. */
+
int
-cirrus_register_operand (rtx op, enum machine_mode mode)
+arm_coproc_mem_operand (rtx op, bool wb)
{
- if (GET_MODE (op) != mode && mode != VOIDmode)
- return FALSE;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
+ rtx ind;
- return (GET_CODE (op) == REG
- && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
- || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
-}
+ /* Reject eliminable registers. */
+ if (! (reload_in_progress || reload_completed)
+ && ( reg_mentioned_p (frame_pointer_rtx, op)
+ || reg_mentioned_p (arg_pointer_rtx, op)
+ || reg_mentioned_p (virtual_incoming_args_rtx, op)
+ || reg_mentioned_p (virtual_outgoing_args_rtx, op)
+ || reg_mentioned_p (virtual_stack_dynamic_rtx, op)
+ || reg_mentioned_p (virtual_stack_vars_rtx, op)))
+ return FALSE;
-/* Return nonzero if OP is a cirrus FP register. */
-int
-cirrus_fp_register (rtx op, enum machine_mode mode)
-{
- if (GET_MODE (op) != mode && mode != VOIDmode)
+ /* Constants are converted into offsets from labels. */
+ if (GET_CODE (op) != MEM)
return FALSE;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
+ ind = XEXP (op, 0);
- return (GET_CODE (op) == REG
- && (REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
-}
+ if (reload_completed
+ && (GET_CODE (ind) == LABEL_REF
+ || (GET_CODE (ind) == CONST
+ && GET_CODE (XEXP (ind, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (ind, 0), 0)) == LABEL_REF
+ && GET_CODE (XEXP (XEXP (ind, 0), 1)) == CONST_INT)))
+ return TRUE;
-/* Return nonzero if OP is a 6bit constant (0..63). */
-int
-cirrus_shift_const (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) >= 0
- && INTVAL (op) < 64);
+ /* Match: (mem (reg)). */
+ if (GET_CODE (ind) == REG)
+ return arm_address_register_rtx_p (ind, 0);
+
+ /* Autoincremment addressing modes. */
+ if (wb
+ && (GET_CODE (ind) == PRE_INC
+ || GET_CODE (ind) == POST_INC
+ || GET_CODE (ind) == PRE_DEC
+ || GET_CODE (ind) == POST_DEC))
+ return arm_address_register_rtx_p (XEXP (ind, 0), 0);
+
+ if (wb
+ && (GET_CODE (ind) == POST_MODIFY || GET_CODE (ind) == PRE_MODIFY)
+ && arm_address_register_rtx_p (XEXP (ind, 0), 0)
+ && GET_CODE (XEXP (ind, 1)) == PLUS
+ && rtx_equal_p (XEXP (XEXP (ind, 1), 0), XEXP (ind, 0)))
+ ind = XEXP (ind, 1);
+
+ /* Match:
+ (plus (reg)
+ (const)). */
+ if (GET_CODE (ind) == PLUS
+ && GET_CODE (XEXP (ind, 0)) == REG
+ && REG_MODE_OK_FOR_BASE_P (XEXP (ind, 0), VOIDmode)
+ && GET_CODE (XEXP (ind, 1)) == CONST_INT
+ && INTVAL (XEXP (ind, 1)) > -1024
+ && INTVAL (XEXP (ind, 1)) < 1024
+ && (INTVAL (XEXP (ind, 1)) & 3) == 0)
+ return TRUE;
+
+ return FALSE;
}
/* Return true if X is a register that will be eliminated later on. */
@@ -4066,6 +5429,30 @@ arm_eliminable_register (rtx x)
&& REGNO (x) <= LAST_VIRTUAL_REGISTER));
}
+/* Return GENERAL_REGS if a scratch register required to reload x to/from
+ coprocessor registers. Otherwise return NO_REGS. */
+
+enum reg_class
+coproc_secondary_reload_class (enum machine_mode mode, rtx x, bool wb)
+{
+ if (arm_coproc_mem_operand (x, wb) || s_register_operand (x, mode))
+ return NO_REGS;
+
+ return GENERAL_REGS;
+}
+
+/* Values which must be returned in the most-significant end of the return
+ register. */
+
+static bool
+arm_return_in_msb (tree valtype)
+{
+ return (TARGET_AAPCS_BASED
+ && BYTES_BIG_ENDIAN
+ && (AGGREGATE_TYPE_P (valtype)
+ || TREE_CODE (valtype) == COMPLEX_TYPE));
+}
+
/* Returns TRUE if INSN is an "LDR REG, ADDR" instruction.
Use by the Cirrus Maverick code which has to workaround
a hardware bug triggered by such instructions. */
@@ -4107,7 +5494,7 @@ arm_cirrus_insn_p (rtx insn)
{
enum attr_cirrus attr;
- /* get_attr aborts on USE and CLOBBER. */
+ /* get_attr cannot accept USE or CLOBBER. */
if (!insn
|| GET_CODE (insn) != INSN
|| GET_CODE (PATTERN (insn)) == USE
@@ -4179,10 +5566,11 @@ cirrus_reorg (rtx first)
/* Get Arm register number for ldr insn. */
if (GET_CODE (lhs) == REG)
arm_regno = REGNO (lhs);
- else if (GET_CODE (rhs) == REG)
- arm_regno = REGNO (rhs);
else
- abort ();
+ {
+ gcc_assert (GET_CODE (rhs) == REG);
+ arm_regno = REGNO (rhs);
+ }
/* Next insn. */
first = next_nonnote_insn (first);
@@ -4208,7 +5596,7 @@ cirrus_reorg (rtx first)
}
}
- /* get_attr aborts on USE and CLOBBER. */
+ /* get_attr cannot accept USE or CLOBBER. */
if (!first
|| GET_CODE (first) != INSN
|| GET_CODE (PATTERN (first)) == USE
@@ -4238,262 +5626,6 @@ cirrus_reorg (rtx first)
}
}
-/* Return nonzero if OP is a constant power of two. */
-int
-power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- HOST_WIDE_INT value = INTVAL (op);
-
- return value != 0 && (value & (value - 1)) == 0;
- }
-
- return FALSE;
-}
-
-/* Return TRUE for a valid operand of a DImode operation.
- Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
- Note that this disallows MEM(REG+REG), but allows
- MEM(PRE/POST_INC/DEC(REG)). */
-int
-di_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
- return FALSE;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- switch (GET_CODE (op))
- {
- case CONST_DOUBLE:
- case CONST_INT:
- return TRUE;
-
- case MEM:
- return memory_address_p (DImode, XEXP (op, 0));
-
- default:
- return FALSE;
- }
-}
-
-/* Like di_operand, but don't accept constants. */
-int
-nonimmediate_di_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (mode != VOIDmode && GET_MODE (op) != VOIDmode && GET_MODE (op) != DImode)
- return FALSE;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- if (GET_CODE (op) == MEM)
- return memory_address_p (DImode, XEXP (op, 0));
-
- return FALSE;
-}
-
-/* Return TRUE for a valid operand of a DFmode operation when -msoft-float.
- Either: REG, SUBREG, CONST_DOUBLE or MEM(DImode_address).
- Note that this disallows MEM(REG+REG), but allows
- MEM(PRE/POST_INC/DEC(REG)). */
-int
-soft_df_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return FALSE;
-
- if (GET_CODE (op) == SUBREG && CONSTANT_P (SUBREG_REG (op)))
- return FALSE;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- switch (GET_CODE (op))
- {
- case CONST_DOUBLE:
- return TRUE;
-
- case MEM:
- return memory_address_p (DFmode, XEXP (op, 0));
-
- default:
- return FALSE;
- }
-}
-
-/* Like soft_df_operand, but don't accept constants. */
-int
-nonimmediate_soft_df_operand (rtx op, enum machine_mode mode)
-{
- if (s_register_operand (op, mode))
- return TRUE;
-
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return FALSE;
-
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
-
- if (GET_CODE (op) == MEM)
- return memory_address_p (DFmode, XEXP (op, 0));
- return FALSE;
-}
-
-/* Return TRUE for valid index operands. */
-int
-index_operand (rtx op, enum machine_mode mode)
-{
- return (s_register_operand (op, mode)
- || (immediate_operand (op, mode)
- && (GET_CODE (op) != CONST_INT
- || (INTVAL (op) < 4096 && INTVAL (op) > -4096))));
-}
-
-/* Return TRUE for valid shifts by a constant. This also accepts any
- power of two on the (somewhat overly relaxed) assumption that the
- shift operator in this case was a mult. */
-int
-const_shift_operand (rtx op, enum machine_mode mode)
-{
- return (power_of_two_operand (op, mode)
- || (immediate_operand (op, mode)
- && (GET_CODE (op) != CONST_INT
- || (INTVAL (op) < 32 && INTVAL (op) > 0))));
-}
-
-/* Return TRUE for arithmetic operators which can be combined with a multiply
- (shift). */
-int
-shiftable_operator (rtx x, enum machine_mode mode)
-{
- enum rtx_code code;
-
- if (GET_MODE (x) != mode)
- return FALSE;
-
- code = GET_CODE (x);
-
- return (code == PLUS || code == MINUS
- || code == IOR || code == XOR || code == AND);
-}
-
-/* Return TRUE for binary logical operators. */
-int
-logical_binary_operator (rtx x, enum machine_mode mode)
-{
- enum rtx_code code;
-
- if (GET_MODE (x) != mode)
- return FALSE;
-
- code = GET_CODE (x);
-
- return (code == IOR || code == XOR || code == AND);
-}
-
-/* Return TRUE for shift operators. */
-int
-shift_operator (rtx x,enum machine_mode mode)
-{
- enum rtx_code code;
-
- if (GET_MODE (x) != mode)
- return FALSE;
-
- code = GET_CODE (x);
-
- if (code == MULT)
- return power_of_two_operand (XEXP (x, 1), mode);
-
- return (code == ASHIFT || code == ASHIFTRT || code == LSHIFTRT
- || code == ROTATERT);
-}
-
-/* Return TRUE if x is EQ or NE. */
-int
-equality_operator (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (x) == EQ || GET_CODE (x) == NE;
-}
-
-/* Return TRUE if x is a comparison operator other than LTGT or UNEQ. */
-int
-arm_comparison_operator (rtx x, enum machine_mode mode)
-{
- return (comparison_operator (x, mode)
- && GET_CODE (x) != LTGT
- && GET_CODE (x) != UNEQ);
-}
-
-/* Return TRUE for SMIN SMAX UMIN UMAX operators. */
-int
-minmax_operator (rtx x, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (x);
-
- if (GET_MODE (x) != mode)
- return FALSE;
-
- return code == SMIN || code == SMAX || code == UMIN || code == UMAX;
-}
-
-/* Return TRUE if this is the condition code register, if we aren't given
- a mode, accept any class CCmode register. */
-int
-cc_register (rtx x, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- {
- mode = GET_MODE (x);
-
- if (GET_MODE_CLASS (mode) != MODE_CC)
- return FALSE;
- }
-
- if ( GET_MODE (x) == mode
- && GET_CODE (x) == REG
- && REGNO (x) == CC_REGNUM)
- return TRUE;
-
- return FALSE;
-}
-
-/* Return TRUE if this is the condition code register, if we aren't given
- a mode, accept any class CCmode register which indicates a dominance
- expression. */
-int
-dominant_cc_register (rtx x, enum machine_mode mode)
-{
- if (mode == VOIDmode)
- {
- mode = GET_MODE (x);
-
- if (GET_MODE_CLASS (mode) != MODE_CC)
- return FALSE;
- }
-
- if (mode != CC_DNEmode && mode != CC_DEQmode
- && mode != CC_DLEmode && mode != CC_DLTmode
- && mode != CC_DGEmode && mode != CC_DGTmode
- && mode != CC_DLEUmode && mode != CC_DLTUmode
- && mode != CC_DGEUmode && mode != CC_DGTUmode)
- return FALSE;
-
- return cc_register (x, mode);
-}
-
/* Return TRUE if X references a SYMBOL_REF. */
int
symbol_mentioned_p (rtx x)
@@ -4504,8 +5636,13 @@ symbol_mentioned_p (rtx x)
if (GET_CODE (x) == SYMBOL_REF)
return 1;
+ /* UNSPEC_TLS entries for a symbol include the SYMBOL_REF, but they
+ are constant offsets, not symbols. */
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
+ return 0;
+
fmt = GET_RTX_FORMAT (GET_CODE (x));
-
+
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
if (fmt[i] == 'E')
@@ -4533,6 +5670,11 @@ label_mentioned_p (rtx x)
if (GET_CODE (x) == LABEL_REF)
return 1;
+ /* UNSPEC_TLS entries for a symbol include a LABEL_REF for the referencing
+ instruction, but they are constant offsets, not symbols. */
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
+ return 0;
+
fmt = GET_RTX_FORMAT (GET_CODE (x));
for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
{
@@ -4551,27 +5693,76 @@ label_mentioned_p (rtx x)
return 0;
}
+int
+tls_mentioned_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST:
+ return tls_mentioned_p (XEXP (x, 0));
+
+ case UNSPEC:
+ if (XINT (x, 1) == UNSPEC_TLS)
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+/* Must not copy a SET whose source operand is PC-relative. */
+
+static bool
+arm_cannot_copy_insn_p (rtx insn)
+{
+ rtx pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == PARALLEL
+ && GET_CODE (XVECEXP (pat, 0, 0)) == SET)
+ {
+ rtx rhs = SET_SRC (XVECEXP (pat, 0, 0));
+
+ if (GET_CODE (rhs) == UNSPEC
+ && XINT (rhs, 1) == UNSPEC_PIC_BASE)
+ return TRUE;
+
+ if (GET_CODE (rhs) == MEM
+ && GET_CODE (XEXP (rhs, 0)) == UNSPEC
+ && XINT (XEXP (rhs, 0), 1) == UNSPEC_PIC_BASE)
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
enum rtx_code
minmax_code (rtx x)
{
enum rtx_code code = GET_CODE (x);
- if (code == SMAX)
- return GE;
- else if (code == SMIN)
- return LE;
- else if (code == UMIN)
- return LEU;
- else if (code == UMAX)
- return GEU;
-
- abort ();
+ switch (code)
+ {
+ case SMAX:
+ return GE;
+ case SMIN:
+ return LE;
+ case UMIN:
+ return LEU;
+ case UMAX:
+ return GEU;
+ default:
+ gcc_unreachable ();
+ }
}
/* Return 1 if memory locations are adjacent. */
int
adjacent_mem_locations (rtx a, rtx b)
{
+ /* We don't guarantee to preserve the order of these memory refs. */
+ if (volatile_refs_p (a) || volatile_refs_p (b))
+ return 0;
+
if ((GET_CODE (XEXP (a, 0)) == REG
|| (GET_CODE (XEXP (a, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (a, 0), 1)) == CONST_INT))
@@ -4611,6 +5802,17 @@ adjacent_mem_locations (rtx a, rtx b)
return 0;
val_diff = val1 - val0;
+
+ if (arm_ld_sched)
+ {
+ /* If the target has load delay slots, then there's no benefit
+ to using an ldm instruction unless the offset is zero and
+ we are optimizing for size. */
+ return (optimize_size && (REGNO (reg0) == REGNO (reg1))
+ && (val0 == 0 || val1 == 0 || val0 == 4 || val1 == 4)
+ && (val_diff == 4 || val_diff == -4));
+ }
+
return ((REGNO (reg0) == REGNO (reg1))
&& (val_diff == 4 || val_diff == -4));
}
@@ -4618,124 +5820,6 @@ adjacent_mem_locations (rtx a, rtx b)
return 0;
}
-/* Return 1 if OP is a load multiple operation. It is known to be
- parallel and the first section will be tested. */
-int
-load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT count = XVECLEN (op, 0);
- int dest_regno;
- rtx src_addr;
- HOST_WIDE_INT i = 1, base = 0;
- rtx elt;
-
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
- return 0;
-
- /* Check to see if this might be a write-back. */
- if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
- {
- i++;
- base = 1;
-
- /* Now check it more carefully. */
- if (GET_CODE (SET_DEST (elt)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
- || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
- return 0;
- }
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= i
- || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
- || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
-
- for (; i < count; i++)
- {
- elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
- || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode
- || 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 - base) * 4)
- return 0;
- }
-
- return 1;
-}
-
-/* Return 1 if OP is a store multiple operation. It is known to be
- parallel and the first section will be tested. */
-int
-store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT count = XVECLEN (op, 0);
- int src_regno;
- rtx dest_addr;
- HOST_WIDE_INT i = 1, base = 0;
- rtx elt;
-
- if (count <= 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET)
- return 0;
-
- /* Check to see if this might be a write-back. */
- if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
- {
- i++;
- base = 1;
-
- /* Now check it more carefully. */
- if (GET_CODE (SET_DEST (elt)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
- || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
- || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
- return 0;
- }
-
- /* Perform a quick check so we don't blow up below. */
- if (count <= i
- || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
- || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
- || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
- return 0;
-
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
- dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
-
- for (; i < count; i++)
- {
- elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode
- || 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 - base) * 4)
- return 0;
- }
-
- return 1;
-}
-
int
load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
HOST_WIDE_INT *load_offset)
@@ -4748,11 +5832,10 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
/* Can only handle 2, 3, or 4 insns at present,
though could be easily extended if required. */
- if (nops < 2 || nops > 4)
- abort ();
+ gcc_assert (nops >= 2 && nops <= 4);
/* Loop over the operands and check that the memory references are
- suitable (ie immediate offsets from the same base register). At
+ suitable (i.e. immediate offsets from the same base register). At
the same time, extract the target register, and the memory
offsets. */
for (i = 0; i < nops; i++)
@@ -4764,8 +5847,7 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
if (GET_CODE (operands[nops + i]) == SUBREG)
operands[nops + i] = alter_subreg (operands + (nops + i));
- if (GET_CODE (operands[nops + i]) != MEM)
- abort ();
+ gcc_assert (GET_CODE (operands[nops + i]) == MEM);
/* Don't reorder volatile memory references; it doesn't seem worth
looking for the case where the order is ok anyway. */
@@ -4793,7 +5875,7 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
: REGNO (SUBREG_REG (operands[i])));
order[0] = 0;
}
- else
+ else
{
if (base_reg != (int) REGNO (reg))
/* Not addressed from the same base register. */
@@ -4879,15 +5961,15 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
scratch register (one of the result regs) and then doing a load
multiple actually becomes slower (and no smaller in code size).
That is the transformation
-
+
ldr rd1, [rbase + offset]
ldr rd2, [rbase + offset + 4]
-
+
to
-
+
add rd1, rbase, offset
ldmia rd1, {rd1, rd2}
-
+
produces worse code -- '3 cycles + any stalls on rd2' instead of
'2 cycles + any stalls on rd2'. On ARMs with only one cache
access per cycle, the first sequence could never complete in less
@@ -4903,7 +5985,7 @@ load_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
/* Can't do it without setting up the offset, only do this if it takes
no more than one insn. */
- return (const_ok_for_arm (unsorted_offsets[order[0]])
+ return (const_ok_for_arm (unsorted_offsets[order[0]])
|| const_ok_for_arm (-unsorted_offsets[order[0]])) ? 5 : 0;
}
@@ -4949,10 +6031,10 @@ emit_ldm_seq (rtx *operands, int nops)
break;
default:
- abort ();
+ gcc_unreachable ();
}
- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
+ sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
for (i = 1; i < nops; i++)
@@ -4977,11 +6059,10 @@ store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
/* Can only handle 2, 3, or 4 insns at present, though could be easily
extended if required. */
- if (nops < 2 || nops > 4)
- abort ();
+ gcc_assert (nops >= 2 && nops <= 4);
/* Loop over the operands and check that the memory references are
- suitable (ie immediate offsets from the same base register). At
+ suitable (i.e. immediate offsets from the same base register). At
the same time, extract the target register, and the memory
offsets. */
for (i = 0; i < nops; i++)
@@ -4993,8 +6074,7 @@ store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
if (GET_CODE (operands[nops + i]) == SUBREG)
operands[nops + i] = alter_subreg (operands + (nops + i));
- if (GET_CODE (operands[nops + i]) != MEM)
- abort ();
+ gcc_assert (GET_CODE (operands[nops + i]) == MEM);
/* Don't reorder volatile memory references; it doesn't seem worth
looking for the case where the order is ok anyway. */
@@ -5022,7 +6102,7 @@ store_multiple_sequence (rtx *operands, int nops, int *regs, int *base,
: REGNO (SUBREG_REG (operands[i])));
order[0] = 0;
}
- else
+ else
{
if (base_reg != (int) REGNO (reg))
/* Not addressed from the same base register. */
@@ -5126,10 +6206,10 @@ emit_stm_seq (rtx *operands, int nops)
break;
default:
- abort ();
+ gcc_unreachable ();
}
- sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
+ sprintf (buf + strlen (buf), "%s%s, {%s%s", REGISTER_PREFIX,
reg_names[base_reg], REGISTER_PREFIX, reg_names[regs[0]]);
for (i = 1; i < nops; i++)
@@ -5141,18 +6221,6 @@ emit_stm_seq (rtx *operands, int nops)
output_asm_insn (buf, operands);
return "";
}
-
-int
-multi_register_push (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != PARALLEL
- || (GET_CODE (XVECEXP (op, 0, 0)) != SET)
- || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
- || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
- return 0;
-
- return 1;
-}
/* Routines for use in generating RTL. */
@@ -5167,7 +6235,7 @@ arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
rtx mem, addr;
/* XScale has load-store double instructions, but they have stricter
- alignment requirements than load-store multiple, so we can not
+ alignment requirements than load-store multiple, so we cannot
use them.
For XScale ldm requires 2 + NREGS cycles to complete and blocks
@@ -5197,9 +6265,9 @@ arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
if (arm_tune_xscale && count <= 2 && ! optimize_size)
{
rtx seq;
-
+
start_sequence ();
-
+
for (i = 0; i < count; i++)
{
addr = plus_constant (from, i * 4 * sign);
@@ -5216,7 +6284,7 @@ arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
seq = get_insns ();
end_sequence ();
-
+
return seq;
}
@@ -5225,8 +6293,7 @@ arm_gen_load_multiple (int base_regno, int count, rtx from, int up,
if (write_back)
{
XVECEXP (result, 0, 0)
- = gen_rtx_SET (GET_MODE (from), from,
- plus_constant (from, count * 4 * sign));
+ = gen_rtx_SET (VOIDmode, from, plus_constant (from, count * 4 * sign));
i = 1;
count++;
}
@@ -5261,9 +6328,9 @@ arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
if (arm_tune_xscale && count <= 2 && ! optimize_size)
{
rtx seq;
-
+
start_sequence ();
-
+
for (i = 0; i < count; i++)
{
addr = plus_constant (to, i * 4 * sign);
@@ -5280,7 +6347,7 @@ arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
seq = get_insns ();
end_sequence ();
-
+
return seq;
}
@@ -5289,7 +6356,7 @@ arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
if (write_back)
{
XVECEXP (result, 0, 0)
- = gen_rtx_SET (GET_MODE (to), to,
+ = gen_rtx_SET (VOIDmode, to,
plus_constant (to, count * 4 * sign));
i = 1;
count++;
@@ -5311,7 +6378,7 @@ arm_gen_store_multiple (int base_regno, int count, rtx to, int up,
}
int
-arm_gen_movstrqi (rtx *operands)
+arm_gen_movmemqi (rtx *operands)
{
HOST_WIDE_INT in_words_to_go, out_words_to_go, last_bytes;
HOST_WIDE_INT srcoffset, dstoffset;
@@ -5328,7 +6395,7 @@ arm_gen_movstrqi (rtx *operands)
dstbase = operands[0];
srcbase = operands[1];
-
+
dst = copy_to_mode_reg (SImode, XEXP (dstbase, 0));
src = copy_to_mode_reg (SImode, XEXP (srcbase, 0));
@@ -5336,7 +6403,7 @@ arm_gen_movstrqi (rtx *operands)
out_words_to_go = INTVAL (operands[2]) / 4;
last_bytes = INTVAL (operands[2]) & 3;
dstoffset = srcoffset = 0;
-
+
if (out_words_to_go != in_words_to_go && ((in_words_to_go - 1) & 3) != 0)
part_bytes_reg = gen_rtx_REG (SImode, (in_words_to_go - 1) & 3);
@@ -5346,7 +6413,7 @@ arm_gen_movstrqi (rtx *operands)
emit_insn (arm_gen_load_multiple (0, 4, src, TRUE, TRUE,
srcbase, &srcoffset));
else
- emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
+ emit_insn (arm_gen_load_multiple (0, in_words_to_go, src, TRUE,
FALSE, srcbase, &srcoffset));
if (out_words_to_go)
@@ -5354,10 +6421,9 @@ arm_gen_movstrqi (rtx *operands)
if (out_words_to_go > 4)
emit_insn (arm_gen_store_multiple (0, 4, dst, TRUE, TRUE,
dstbase, &dstoffset));
-
else if (out_words_to_go != 1)
emit_insn (arm_gen_store_multiple (0, out_words_to_go,
- dst, TRUE,
+ dst, TRUE,
(last_bytes == 0
? FALSE : TRUE),
dstbase, &dstoffset));
@@ -5388,22 +6454,19 @@ arm_gen_movstrqi (rtx *operands)
mem = adjust_automodify_address (dstbase, SImode, dst, dstoffset);
emit_move_insn (mem, sreg);
in_words_to_go--;
-
- if (in_words_to_go) /* Sanity check */
- abort ();
+
+ gcc_assert (!in_words_to_go); /* Sanity check */
}
if (in_words_to_go)
{
- if (in_words_to_go < 0)
- abort ();
+ gcc_assert (in_words_to_go > 0);
mem = adjust_automodify_address (srcbase, SImode, src, srcoffset);
part_bytes_reg = copy_to_mode_reg (SImode, mem);
}
- if (last_bytes && part_bytes_reg == NULL)
- abort ();
+ gcc_assert (!last_bytes || part_bytes_reg);
if (BYTES_BIG_ENDIAN && last_bytes)
{
@@ -5413,7 +6476,7 @@ arm_gen_movstrqi (rtx *operands)
emit_insn (gen_lshrsi3 (tmp, part_bytes_reg,
GEN_INT (8 * (4 - last_bytes))));
part_bytes_reg = tmp;
-
+
while (last_bytes)
{
mem = adjust_automodify_address (dstbase, QImode,
@@ -5428,7 +6491,7 @@ arm_gen_movstrqi (rtx *operands)
part_bytes_reg = tmp;
}
}
-
+
}
else
{
@@ -5440,14 +6503,13 @@ arm_gen_movstrqi (rtx *operands)
if (last_bytes)
{
rtx tmp = gen_reg_rtx (SImode);
-
- emit_insn (gen_addsi3 (dst, dst, GEN_INT (2)));
+ emit_insn (gen_addsi3 (dst, dst, const2_rtx));
emit_insn (gen_lshrsi3 (tmp, part_bytes_reg, GEN_INT (16)));
part_bytes_reg = tmp;
dstoffset += 2;
}
}
-
+
if (last_bytes)
{
mem = adjust_automodify_address (dstbase, QImode, dst, dstoffset);
@@ -5458,42 +6520,13 @@ arm_gen_movstrqi (rtx *operands)
return 1;
}
-/* Generate a memory reference for a half word, such that it will be loaded
- into the top 16 bits of the word. We can assume that the address is
- known to be alignable and of the form reg, or plus (reg, const). */
-
-rtx
-arm_gen_rotated_half_load (rtx memref)
-{
- HOST_WIDE_INT offset = 0;
- rtx base = XEXP (memref, 0);
-
- if (GET_CODE (base) == PLUS)
- {
- offset = INTVAL (XEXP (base, 1));
- base = XEXP (base, 0);
- }
-
- /* If we aren't allowed to generate unaligned addresses, then fail. */
- if (TARGET_MMU_TRAPS
- && ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 0)))
- return NULL;
-
- base = gen_rtx_MEM (SImode, plus_constant (base, offset & ~2));
-
- if ((BYTES_BIG_ENDIAN ? 1 : 0) ^ ((offset & 2) == 2))
- return base;
-
- return gen_rtx_ROTATE (SImode, base, GEN_INT (16));
-}
-
/* Select a dominance comparison mode if possible for a test of the general
form (OP (COND_OR (X) (Y)) (const_int 0)). We support three forms.
- COND_OR == DOM_CC_X_AND_Y => (X && Y)
+ COND_OR == DOM_CC_X_AND_Y => (X && Y)
COND_OR == DOM_CC_NX_OR_Y => ((! X) || Y)
- COND_OR == DOM_CC_X_OR_Y => (X || Y)
+ COND_OR == DOM_CC_X_OR_Y => (X || Y)
In all cases OP will be either EQ or NE, but we don't need to know which
- here. If we are unable to support a dominance comparison we return
+ here. If we are unable to support a dominance comparison we return
CC mode. This will then fail to match for the RTL expressions that
generate this call. */
enum machine_mode
@@ -5519,7 +6552,7 @@ arm_select_dominance_cc_mode (rtx x, rtx y, HOST_WIDE_INT cond_or)
/* If the comparisons are not equal, and one doesn't dominate the other,
then we can't do this. */
- if (cond1 != cond2
+ if (cond1 != cond2
&& !comparison_dominates_p (cond1, cond2)
&& (swapped = 1, !comparison_dominates_p (cond2, cond1)))
return CCmode;
@@ -5534,78 +6567,108 @@ arm_select_dominance_cc_mode (rtx x, rtx y, HOST_WIDE_INT cond_or)
switch (cond1)
{
case EQ:
- if (cond2 == EQ || cond_or == DOM_CC_X_AND_Y)
+ if (cond_or == DOM_CC_X_AND_Y)
return CC_DEQmode;
switch (cond2)
{
+ case EQ: return CC_DEQmode;
case LE: return CC_DLEmode;
case LEU: return CC_DLEUmode;
case GE: return CC_DGEmode;
case GEU: return CC_DGEUmode;
- default: break;
+ default: gcc_unreachable ();
}
- break;
-
case LT:
- if (cond2 == LT || cond_or == DOM_CC_X_AND_Y)
+ if (cond_or == DOM_CC_X_AND_Y)
return CC_DLTmode;
- if (cond2 == LE)
- return CC_DLEmode;
- if (cond2 == NE)
- return CC_DNEmode;
- break;
+
+ switch (cond2)
+ {
+ case LT:
+ return CC_DLTmode;
+ case LE:
+ return CC_DLEmode;
+ case NE:
+ return CC_DNEmode;
+ default:
+ gcc_unreachable ();
+ }
case GT:
- if (cond2 == GT || cond_or == DOM_CC_X_AND_Y)
+ if (cond_or == DOM_CC_X_AND_Y)
return CC_DGTmode;
- if (cond2 == GE)
- return CC_DGEmode;
- if (cond2 == NE)
- return CC_DNEmode;
- break;
-
+
+ switch (cond2)
+ {
+ case GT:
+ return CC_DGTmode;
+ case GE:
+ return CC_DGEmode;
+ case NE:
+ return CC_DNEmode;
+ default:
+ gcc_unreachable ();
+ }
+
case LTU:
- if (cond2 == LTU || cond_or == DOM_CC_X_AND_Y)
+ if (cond_or == DOM_CC_X_AND_Y)
return CC_DLTUmode;
- if (cond2 == LEU)
- return CC_DLEUmode;
- if (cond2 == NE)
- return CC_DNEmode;
- break;
+
+ switch (cond2)
+ {
+ case LTU:
+ return CC_DLTUmode;
+ case LEU:
+ return CC_DLEUmode;
+ case NE:
+ return CC_DNEmode;
+ default:
+ gcc_unreachable ();
+ }
case GTU:
- if (cond2 == GTU || cond_or == DOM_CC_X_AND_Y)
+ if (cond_or == DOM_CC_X_AND_Y)
return CC_DGTUmode;
- if (cond2 == GEU)
- return CC_DGEUmode;
- if (cond2 == NE)
- return CC_DNEmode;
- break;
+
+ switch (cond2)
+ {
+ case GTU:
+ return CC_DGTUmode;
+ case GEU:
+ return CC_DGEUmode;
+ case NE:
+ return CC_DNEmode;
+ default:
+ gcc_unreachable ();
+ }
/* The remaining cases only occur when both comparisons are the
same. */
case NE:
+ gcc_assert (cond1 == cond2);
return CC_DNEmode;
case LE:
+ gcc_assert (cond1 == cond2);
return CC_DLEmode;
case GE:
+ gcc_assert (cond1 == cond2);
return CC_DGEmode;
case LEU:
+ gcc_assert (cond1 == cond2);
return CC_DLEUmode;
case GEU:
+ gcc_assert (cond1 == cond2);
return CC_DGEUmode;
default:
- break;
+ gcc_unreachable ();
}
-
- abort ();
}
enum machine_mode
@@ -5633,15 +6696,15 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
case LE:
case GT:
case GE:
- if (TARGET_CIRRUS)
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
return CCFPmode;
return CCFPEmode;
default:
- abort ();
+ gcc_unreachable ();
}
}
-
+
/* A compare with a shifted operand. Because of canonicalization, the
comparison will have to be swapped when we emit the assembler. */
if (GET_MODE (y) == SImode && GET_CODE (y) == REG
@@ -5650,7 +6713,14 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
|| GET_CODE (x) == ROTATERT))
return CC_SWPmode;
- /* This is a special case that is used by combine to allow a
+ /* This operation is performed swapped, but since we only rely on the Z
+ flag we don't need an additional mode. */
+ if (GET_MODE (y) == SImode && REG_P (y)
+ && GET_CODE (x) == NEG
+ && (op == EQ || op == NE))
+ return CC_Zmode;
+
+ /* This is a special case that is used by combine to allow a
comparison of a shifted byte load to be split into a zero-extend
followed by a comparison of the shifted integer (only valid for
equalities and unsigned inequalities). */
@@ -5672,21 +6742,21 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
if (GET_CODE (x) == IF_THEN_ELSE
&& (XEXP (x, 2) == const0_rtx
|| XEXP (x, 2) == const1_rtx)
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
- return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
+ && COMPARISON_P (XEXP (x, 0))
+ && COMPARISON_P (XEXP (x, 1)))
+ return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
INTVAL (XEXP (x, 2)));
/* Alternate canonicalizations of the above. These are somewhat cleaner. */
if (GET_CODE (x) == AND
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
+ && COMPARISON_P (XEXP (x, 0))
+ && COMPARISON_P (XEXP (x, 1)))
return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
DOM_CC_X_AND_Y);
if (GET_CODE (x) == IOR
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == '<'
- && GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == '<')
+ && COMPARISON_P (XEXP (x, 0))
+ && COMPARISON_P (XEXP (x, 1)))
return arm_select_dominance_cc_mode (XEXP (x, 0), XEXP (x, 1),
DOM_CC_X_OR_Y);
@@ -5696,7 +6766,8 @@ arm_select_cc_mode (enum rtx_code op, rtx x, rtx y)
if (TARGET_THUMB
&& GET_MODE (x) == SImode
&& (op == EQ || op == NE)
- && (GET_CODE (x) == ZERO_EXTRACT))
+ && GET_CODE (x) == ZERO_EXTRACT
+ && XEXP (x, 1) == const1_rtx)
return CC_Nmode;
/* An operation that sets the condition codes as a side-effect, the
@@ -5736,8 +6807,7 @@ arm_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
enum machine_mode mode = SELECT_CC_MODE (code, x, y);
rtx cc_reg = gen_rtx_REG (mode, CC_REGNUM);
- emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- gen_rtx_COMPARE (mode, x, y)));
+ emit_set_insn (cc_reg, gen_rtx_COMPARE (mode, x, y));
return cc_reg;
}
@@ -5791,7 +6861,7 @@ arm_reload_in_hi (rtx *operands)
{
rtx base_plus = gen_rtx_REG (SImode, REGNO (operands[2]) + 1);
- emit_insn (gen_rtx_SET (VOIDmode, base_plus, base));
+ emit_set_insn (base_plus, base);
base = base_plus;
}
else if (GET_CODE (base) == PLUS)
@@ -5818,8 +6888,7 @@ arm_reload_in_hi (rtx *operands)
^ (HOST_WIDE_INT) 0x80000000)
- (HOST_WIDE_INT) 0x80000000);
- if (hi + lo != offset)
- abort ();
+ gcc_assert (hi + lo == offset);
if (hi != 0)
{
@@ -5846,24 +6915,23 @@ arm_reload_in_hi (rtx *operands)
plus_constant (base,
offset))));
emit_insn (gen_zero_extendqisi2 (gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_MEM (QImode,
+ gen_rtx_MEM (QImode,
plus_constant (base,
offset + 1))));
if (!BYTES_BIG_ENDIAN)
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_IOR (SImode,
- gen_rtx_ASHIFT
- (SImode,
- gen_rtx_SUBREG (SImode, operands[0], 0),
- GEN_INT (8)),
- scratch)));
+ emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
+ gen_rtx_IOR (SImode,
+ gen_rtx_ASHIFT
+ (SImode,
+ gen_rtx_SUBREG (SImode, operands[0], 0),
+ GEN_INT (8)),
+ scratch));
else
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_SUBREG (SImode, operands[0], 0),
- gen_rtx_IOR (SImode,
- gen_rtx_ASHIFT (SImode, scratch,
- GEN_INT (8)),
- gen_rtx_SUBREG (SImode, operands[0],
- 0))));
+ emit_set_insn (gen_rtx_SUBREG (SImode, operands[0], 0),
+ gen_rtx_IOR (SImode,
+ gen_rtx_ASHIFT (SImode, scratch,
+ GEN_INT (8)),
+ gen_rtx_SUBREG (SImode, operands[0], 0)));
}
/* Handle storing a half-word to memory during reload by synthesizing as two
@@ -5938,7 +7006,7 @@ arm_reload_out_hi (rtx *operands)
}
}
- emit_insn (gen_rtx_SET (VOIDmode, base_plus, base));
+ emit_set_insn (base_plus, base);
base = base_plus;
}
else if (GET_CODE (base) == PLUS)
@@ -5965,8 +7033,7 @@ arm_reload_out_hi (rtx *operands)
^ (HOST_WIDE_INT) 0x80000000)
- (HOST_WIDE_INT) 0x80000000);
- if (hi + lo != offset)
- abort ();
+ gcc_assert (hi + lo == offset);
if (hi != 0)
{
@@ -6008,7 +7075,7 @@ arm_reload_out_hi (rtx *operands)
if (BYTES_BIG_ENDIAN)
{
- emit_insn (gen_movqi (gen_rtx_MEM (QImode,
+ emit_insn (gen_movqi (gen_rtx_MEM (QImode,
plus_constant (base, offset + 1)),
gen_lowpart (QImode, outval)));
emit_insn (gen_lshrsi3 (scratch,
@@ -6029,6 +7096,60 @@ arm_reload_out_hi (rtx *operands)
gen_lowpart (QImode, scratch)));
}
}
+
+/* Return true if a type must be passed in memory. For AAPCS, small aggregates
+ (padded to the size of a word) should be passed in a register. */
+
+static bool
+arm_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+ if (TARGET_AAPCS_BASED)
+ return must_pass_in_stack_var_size (mode, type);
+ else
+ return must_pass_in_stack_var_size_or_pad (mode, type);
+}
+
+
+/* For use by FUNCTION_ARG_PADDING (MODE, TYPE).
+ Return true if an argument passed on the stack should be padded upwards,
+ i.e. if the least-significant byte has useful data.
+ For legacy APCS ABIs we use the default. For AAPCS based ABIs small
+ aggregate types are placed in the lowest memory address. */
+
+bool
+arm_pad_arg_upward (enum machine_mode mode, tree type)
+{
+ if (!TARGET_AAPCS_BASED)
+ return DEFAULT_FUNCTION_ARG_PADDING(mode, type) == upward;
+
+ if (type && BYTES_BIG_ENDIAN && INTEGRAL_TYPE_P (type))
+ return false;
+
+ return true;
+}
+
+
+/* Similarly, for use by BLOCK_REG_PADDING (MODE, TYPE, FIRST).
+ For non-AAPCS, return !BYTES_BIG_ENDIAN if the least significant
+ byte of the register has useful data, and return the opposite if the
+ most significant byte does.
+ For AAPCS, small aggregates and small complex types are always padded
+ upwards. */
+
+bool
+arm_pad_reg_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type, int first ATTRIBUTE_UNUSED)
+{
+ if (TARGET_AAPCS_BASED
+ && BYTES_BIG_ENDIAN
+ && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE)
+ && int_size_in_bytes (type) <= 4)
+ return true;
+
+ /* Otherwise, use default padding. */
+ return !BYTES_BIG_ENDIAN;
+}
+
/* Print a symbolic form of X to the debug file, F. */
static void
@@ -6205,6 +7326,7 @@ struct minipool_fixup
static Mnode * minipool_vector_head;
static Mnode * minipool_vector_tail;
static rtx minipool_vector_label;
+static int minipool_pad;
/* The linked list of all minipool fixes required for this function. */
Mfix * minipool_fix_head;
@@ -6218,7 +7340,7 @@ static rtx
is_jump_table (rtx insn)
{
rtx table;
-
+
if (GET_CODE (insn) == JUMP_INSN
&& JUMP_LABEL (insn) != NULL
&& ((table = next_real_insn (JUMP_LABEL (insn)))
@@ -6241,11 +7363,7 @@ get_jump_table_size (rtx insn)
{
/* ADDR_VECs only take room if read-only data does into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
-#if !defined(READONLY_DATA_SECTION) && !defined(READONLY_DATA_SECTION_ASM_OP)
- || 1
-#endif
- )
+ if (JUMP_TABLES_IN_TEXT_SECTION || readonly_data_section == text_section)
{
rtx body = PATTERN (insn);
int elt = GET_CODE (body) == ADDR_DIFF_VEC ? 1 : 0;
@@ -6263,10 +7381,8 @@ static Mnode *
move_minipool_fix_forward_ref (Mnode *mp, Mnode *max_mp,
HOST_WIDE_INT max_address)
{
- /* This should never be true and the code below assumes these are
- different. */
- if (mp == max_mp)
- abort ();
+ /* The code below assumes these are different. */
+ gcc_assert (mp != max_mp);
if (max_mp == NULL)
{
@@ -6292,7 +7408,7 @@ move_minipool_fix_forward_ref (Mnode *mp, Mnode *max_mp,
mp->next = max_mp;
mp->prev = max_mp->prev;
max_mp->prev = mp;
-
+
if (mp->prev != NULL)
mp->prev->next = mp;
else
@@ -6322,16 +7438,16 @@ add_minipool_forward_ref (Mfix *fix)
/* If set, max_mp is the first pool_entry that has a lower
constraint than the one we are trying to add. */
Mnode * max_mp = NULL;
- HOST_WIDE_INT max_address = fix->address + fix->forwards;
+ HOST_WIDE_INT max_address = fix->address + fix->forwards - minipool_pad;
Mnode * mp;
-
- /* If this fix's address is greater than the address of the first
- entry, then we can't put the fix in this pool. We subtract the
- size of the current fix to ensure that if the table is fully
- packed we still have enough room to insert this value by suffling
- the other fixes forwards. */
+
+ /* If the minipool starts before the end of FIX->INSN then this FIX
+ can not be placed into the current pool. Furthermore, adding the
+ new constant pool entry may cause the pool to start FIX_SIZE bytes
+ earlier. */
if (minipool_vector_head &&
- fix->address >= minipool_vector_head->max_address - fix->fix_size)
+ (fix->address + get_attr_length (fix->insn)
+ >= minipool_vector_head->max_address - fix->fix_size))
return NULL;
/* Scan the pool to see if a constant with the same value has
@@ -6361,7 +7477,7 @@ add_minipool_forward_ref (Mfix *fix)
we have not already found an insertion point, then
make sure that all such 8-byte aligned quantities are
placed at the start of the pool. */
- if (TARGET_REALLY_IWMMXT
+ if (ARM_DOUBLEWORD_ALIGN
&& max_mp == NULL
&& fix->fix_size == 8
&& mp->fix_size != 8)
@@ -6377,7 +7493,7 @@ add_minipool_forward_ref (Mfix *fix)
any existing entry. Otherwise, we insert the new fix before
MAX_MP and, if necessary, adjust the constraints on the other
entries. */
- mp = xmalloc (sizeof (* mp));
+ mp = XNEW (Mnode);
mp->fix_size = fix->fix_size;
mp->mode = fix->mode;
mp->value = fix->value;
@@ -6438,10 +7554,8 @@ move_minipool_fix_backward_ref (Mnode *mp, Mnode *min_mp,
{
HOST_WIDE_INT offset;
- /* This should never be true, and the code below assumes these are
- different. */
- if (mp == min_mp)
- abort ();
+ /* The code below assumes these are different. */
+ gcc_assert (mp != min_mp);
if (min_mp == NULL)
{
@@ -6485,10 +7599,10 @@ move_minipool_fix_backward_ref (Mnode *mp, Mnode *min_mp,
}
return min_mp;
-}
+}
/* Add a constant to the minipool for a backward reference. Returns the
- node added or NULL if the constant will not fit in this pool.
+ node added or NULL if the constant will not fit in this pool.
Note that the code for insertion for a backwards reference can be
somewhat confusing because the calculated offsets for each fix do
@@ -6527,8 +7641,8 @@ add_minipool_backward_ref (Mfix *fix)
&& rtx_equal_p (fix->value, mp->value)
/* Check that there is enough slack to move this entry to the
end of the table (this is conservative). */
- && (mp->max_address
- > (minipool_barrier->address
+ && (mp->max_address
+ > (minipool_barrier->address
+ minipool_vector_tail->offset
+ minipool_vector_tail->fix_size)))
{
@@ -6545,7 +7659,8 @@ add_minipool_backward_ref (Mfix *fix)
{
/* For now, we do not allow the insertion of 8-byte alignment
requiring nodes anywhere but at the start of the pool. */
- if (TARGET_REALLY_IWMMXT && fix->fix_size == 8 && mp->fix_size != 8)
+ if (ARM_DOUBLEWORD_ALIGN
+ && fix->fix_size == 8 && mp->fix_size != 8)
return NULL;
else
min_mp = mp;
@@ -6564,7 +7679,7 @@ add_minipool_backward_ref (Mfix *fix)
we have not already found an insertion point, then
make sure that all such 8-byte aligned quantities are
placed at the start of the pool. */
- else if (TARGET_REALLY_IWMMXT
+ else if (ARM_DOUBLEWORD_ALIGN
&& min_mp == NULL
&& fix->fix_size == 8
&& mp->fix_size < 8)
@@ -6576,7 +7691,7 @@ add_minipool_backward_ref (Mfix *fix)
}
/* We need to create a new entry. */
- mp = xmalloc (sizeof (* mp));
+ mp = XNEW (Mnode);
mp->fix_size = fix->fix_size;
mp->mode = fix->mode;
mp->value = fix->value;
@@ -6605,7 +7720,7 @@ add_minipool_backward_ref (Mfix *fix)
mp->next = min_mp->next;
mp->prev = min_mp;
min_mp->next = mp;
-
+
if (mp->next != NULL)
mp->next->prev = mp;
else
@@ -6648,7 +7763,7 @@ assign_minipool_offsets (Mfix *barrier)
for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
{
mp->offset = offset;
-
+
if (mp->refcount > 0)
offset += mp->fix_size;
}
@@ -6662,7 +7777,7 @@ dump_minipool (rtx scan)
Mnode * nmp;
int align64 = 0;
- if (TARGET_REALLY_IWMMXT)
+ if (ARM_DOUBLEWORD_ALIGN)
for (mp = minipool_vector_head; mp != NULL; mp = mp->next)
if (mp->refcount > 0 && mp->fix_size == 8)
{
@@ -6670,8 +7785,8 @@ dump_minipool (rtx scan)
break;
}
- if (rtl_dump_file)
- fprintf (rtl_dump_file,
+ if (dump_file)
+ fprintf (dump_file,
";; Emitting minipool after insn %u; address %ld; align %d (bytes)\n",
INSN_UID (scan), (unsigned long) minipool_barrier->address, align64 ? 8 : 4);
@@ -6683,14 +7798,14 @@ dump_minipool (rtx scan)
{
if (mp->refcount > 0)
{
- if (rtl_dump_file)
+ if (dump_file)
{
- fprintf (rtl_dump_file,
+ fprintf (dump_file,
";; Offset %u, min %ld, max %ld ",
(unsigned) mp->offset, (unsigned long) mp->min_address,
(unsigned long) mp->max_address);
- arm_print_value (rtl_dump_file, mp->value);
- fputc ('\n', rtl_dump_file);
+ arm_print_value (dump_file, mp->value);
+ fputc ('\n', dump_file);
}
switch (mp->fix_size)
@@ -6720,8 +7835,7 @@ dump_minipool (rtx scan)
#endif
default:
- abort ();
- break;
+ gcc_unreachable ();
}
}
@@ -6752,7 +7866,7 @@ arm_barrier_cost (rtx insn)
case CODE_LABEL:
/* It will always be better to place the table before the label, rather
than after it. */
- return 50;
+ return 50;
case INSN:
case CALL_INSN:
@@ -6776,8 +7890,10 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
HOST_WIDE_INT count = 0;
rtx barrier;
rtx from = fix->insn;
- rtx selected = from;
+ /* The instruction after which we will insert the jump. */
+ rtx selected = NULL;
int selected_cost;
+ /* The address at which the jump instruction will be placed. */
HOST_WIDE_INT selected_address;
Mfix * new_fix;
HOST_WIDE_INT max_count = max_address - fix->address;
@@ -6793,8 +7909,7 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
/* This code shouldn't have been called if there was a natural barrier
within range. */
- if (GET_CODE (from) == BARRIER)
- abort ();
+ gcc_assert (GET_CODE (from) != BARRIER);
/* Count the length of this insn. */
count += get_attr_length (from);
@@ -6810,7 +7925,8 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
still put the pool after the table. */
new_cost = arm_barrier_cost (from);
- if (count < max_count && new_cost <= selected_cost)
+ if (count < max_count
+ && (!selected || new_cost <= selected_cost))
{
selected = tmp;
selected_cost = new_cost;
@@ -6823,8 +7939,9 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
}
new_cost = arm_barrier_cost (from);
-
- if (count < max_count && new_cost <= selected_cost)
+
+ if (count < max_count
+ && (!selected || new_cost <= selected_cost))
{
selected = from;
selected_cost = new_cost;
@@ -6834,6 +7951,9 @@ create_fix_barrier (Mfix *fix, HOST_WIDE_INT max_address)
from = NEXT_INSN (from);
}
+ /* Make sure that we found a place to insert the jump. */
+ gcc_assert (selected);
+
/* Create a new JUMP_INSN that branches around a barrier. */
from = emit_jump_insn_after (gen_jump (label), selected);
JUMP_LABEL (from) = label;
@@ -6899,32 +8019,30 @@ push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc,
fix->minipool = NULL;
/* If an insn doesn't have a range defined for it, then it isn't
- expecting to be reworked by this code. Better to abort now than
+ expecting to be reworked by this code. Better to stop now than
to generate duff assembly code. */
- if (fix->forwards == 0 && fix->backwards == 0)
- abort ();
+ gcc_assert (fix->forwards || fix->backwards);
- /* With iWMMXt enabled, the pool is aligned to an 8-byte boundary.
- So there might be an empty word before the start of the pool.
- Hence we reduce the forward range by 4 to allow for this
- possibility. */
- if (TARGET_REALLY_IWMMXT && fix->fix_size == 8)
- fix->forwards -= 4;
+ /* If an entry requires 8-byte alignment then assume all constant pools
+ require 4 bytes of padding. Trying to do this later on a per-pool
+ basis is awkward because existing pool entries have to be modified. */
+ if (ARM_DOUBLEWORD_ALIGN && fix->fix_size == 8)
+ minipool_pad = 4;
- if (rtl_dump_file)
+ if (dump_file)
{
- fprintf (rtl_dump_file,
+ fprintf (dump_file,
";; %smode fixup for i%d; addr %lu, range (%ld,%ld): ",
GET_MODE_NAME (mode),
- INSN_UID (insn), (unsigned long) address,
+ INSN_UID (insn), (unsigned long) address,
-1 * (long)fix->backwards, (long)fix->forwards);
- arm_print_value (rtl_dump_file, fix->value);
- fprintf (rtl_dump_file, "\n");
+ arm_print_value (dump_file, fix->value);
+ fprintf (dump_file, "\n");
}
/* Add it to the chain of fixes. */
fix->next = NULL;
-
+
if (minipool_fix_head != NULL)
minipool_fix_tail->next = fix;
else
@@ -6933,9 +8051,72 @@ push_minipool_fix (rtx insn, HOST_WIDE_INT address, rtx *loc,
minipool_fix_tail = fix;
}
+/* Return the cost of synthesizing a 64-bit constant VAL inline.
+ Returns the number of insns needed, or 99 if we don't know how to
+ do it. */
+int
+arm_const_double_inline_cost (rtx val)
+{
+ rtx lowpart, highpart;
+ enum machine_mode mode;
+
+ mode = GET_MODE (val);
+
+ if (mode == VOIDmode)
+ mode = DImode;
+
+ gcc_assert (GET_MODE_SIZE (mode) == 8);
+
+ lowpart = gen_lowpart (SImode, val);
+ highpart = gen_highpart_mode (SImode, mode, val);
+
+ gcc_assert (GET_CODE (lowpart) == CONST_INT);
+ gcc_assert (GET_CODE (highpart) == CONST_INT);
+
+ return (arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (lowpart),
+ NULL_RTX, NULL_RTX, 0, 0)
+ + arm_gen_constant (SET, SImode, NULL_RTX, INTVAL (highpart),
+ NULL_RTX, NULL_RTX, 0, 0));
+}
+
+/* Return true if it is worthwhile to split a 64-bit constant into two
+ 32-bit operations. This is the case if optimizing for size, or
+ if we have load delay slots, or if one 32-bit part can be done with
+ a single data operation. */
+bool
+arm_const_double_by_parts (rtx val)
+{
+ enum machine_mode mode = GET_MODE (val);
+ rtx part;
+
+ if (optimize_size || arm_ld_sched)
+ return true;
+
+ if (mode == VOIDmode)
+ mode = DImode;
+
+ part = gen_highpart_mode (SImode, mode, val);
+
+ gcc_assert (GET_CODE (part) == CONST_INT);
+
+ if (const_ok_for_arm (INTVAL (part))
+ || const_ok_for_arm (~INTVAL (part)))
+ return true;
+
+ part = gen_lowpart (SImode, val);
+
+ gcc_assert (GET_CODE (part) == CONST_INT);
+
+ if (const_ok_for_arm (INTVAL (part))
+ || const_ok_for_arm (~INTVAL (part)))
+ return true;
+
+ return false;
+}
+
/* Scan INSN and note any of its operands that need fixing.
If DO_PUSHES is false we do not actually push any of the fixups
- needed. The function returns TRUE is any fixups were needed/pushed.
+ needed. The function returns TRUE if any fixups were needed/pushed.
This is used by arm_memory_load_p() which needs to know about loads
of constants that will be converted into minipool loads. */
static bool
@@ -6952,7 +8133,8 @@ note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
if (recog_data.n_alternatives == 0)
return false;
- /* Fill in recog_op_alt with information about the constraints of this insn. */
+ /* Fill in recog_op_alt with information about the constraints of
+ this insn. */
preprocess_constraints ();
for (opno = 0; opno < recog_data.n_operands; opno++)
@@ -6987,7 +8169,7 @@ note_invalid_constants (rtx insn, HOST_WIDE_INT address, int do_pushes)
/* Casting the address of something to a mode narrower
than a word can cause avoid_constant_pool_reference()
to return the pool reference itself. That's no good to
- us here. Lets just hope that we can use the
+ us here. Lets just hope that we can use the
constant pool value directly. */
if (op == cop)
cop = get_pool_constant (XEXP (op, 0));
@@ -7021,8 +8203,8 @@ arm_reorg (void)
/* The first insn must always be a note, or the code below won't
scan it properly. */
insn = get_insns ();
- if (GET_CODE (insn) != NOTE)
- abort ();
+ gcc_assert (GET_CODE (insn) == NOTE);
+ minipool_pad = 0;
/* Scan all the insns and record the operands that will need fixing. */
for (insn = next_nonnote_insn (insn); insn; insn = next_nonnote_insn (insn))
@@ -7053,7 +8235,7 @@ arm_reorg (void)
}
fix = minipool_fix_head;
-
+
/* Now scan the fixups and perform the required changes. */
while (fix)
{
@@ -7093,7 +8275,7 @@ arm_reorg (void)
the next mini-pool. */
if (last_barrier != NULL)
{
- /* Reduce the refcount for those fixes that won't go into this
+ /* Reduce the refcount for those fixes that won't go into this
pool after all. */
for (fdel = last_barrier->next;
fdel && fdel != ftmp;
@@ -7116,16 +8298,17 @@ arm_reorg (void)
/* The last item on the list of fixes must be a barrier, so
we can never run off the end of the list of fixes without
last_barrier being set. */
- if (ftmp == NULL)
- abort ();
+ gcc_assert (ftmp);
max_address = minipool_vector_head->max_address;
/* Check that there isn't another fix that is in range that
we couldn't fit into this pool because the pool was
already too large: we need to put the pool before such an
- instruction. */
+ instruction. The pool itself may come just after the
+ fix because create_fix_barrier also allows space for a
+ jump instruction. */
if (ftmp->address < max_address)
- max_address = ftmp->address;
+ max_address = ftmp->address + 1;
last_barrier = create_fix_barrier (last_added_fix, max_address);
}
@@ -7149,7 +8332,7 @@ arm_reorg (void)
if (GET_CODE (this_fix->insn) != BARRIER)
{
rtx addr
- = plus_constant (gen_rtx_LABEL_REF (VOIDmode,
+ = plus_constant (gen_rtx_LABEL_REF (VOIDmode,
minipool_vector_label),
this_fix->minipool->offset);
*this_fix->loc = gen_rtx_MEM (this_fix->mode, addr);
@@ -7178,16 +8361,16 @@ fp_immediate_constant (rtx x)
{
REAL_VALUE_TYPE r;
int i;
-
- if (!fpa_consts_inited)
- init_fpa_table ();
-
+
+ if (!fp_consts_inited)
+ init_fp_table ();
+
REAL_VALUE_FROM_CONST_DOUBLE (r, x);
for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (r, values_fpa[i]))
- return strings_fpa[i];
+ if (REAL_VALUES_EQUAL (r, values_fp[i]))
+ return strings_fp[i];
- abort ();
+ gcc_unreachable ();
}
/* As for fp_immediate_constant, but value is passed directly, not in rtx. */
@@ -7196,75 +8379,200 @@ fp_const_from_val (REAL_VALUE_TYPE *r)
{
int i;
- if (!fpa_consts_inited)
- init_fpa_table ();
+ if (!fp_consts_inited)
+ init_fp_table ();
for (i = 0; i < 8; i++)
- if (REAL_VALUES_EQUAL (*r, values_fpa[i]))
- return strings_fpa[i];
+ if (REAL_VALUES_EQUAL (*r, values_fp[i]))
+ return strings_fp[i];
- abort ();
+ gcc_unreachable ();
}
/* Output the operands of a LDM/STM instruction to STREAM.
MASK is the ARM register set mask of which only bits 0-15 are important.
REG is the base register, either the frame pointer or the stack pointer,
INSTR is the possibly suffixed load or store instruction. */
+
static void
-print_multi_reg (FILE *stream, const char *instr, int reg, int mask)
+print_multi_reg (FILE *stream, const char *instr, unsigned reg,
+ unsigned long mask)
{
- int i;
- int not_first = FALSE;
+ unsigned i;
+ bool not_first = FALSE;
fputc ('\t', stream);
asm_fprintf (stream, instr, reg);
fputs (", {", stream);
-
+
for (i = 0; i <= LAST_ARM_REGNUM; i++)
if (mask & (1 << i))
{
if (not_first)
fprintf (stream, ", ");
-
+
asm_fprintf (stream, "%r", i);
not_first = TRUE;
}
- fprintf (stream, "}");
-
- /* Add a ^ character for the 26-bit ABI, but only if we were loading
- the PC. Otherwise we would generate an UNPREDICTABLE instruction.
- Strictly speaking the instruction would be unpredicatble only if
- we were writing back the base register as well, but since we never
- want to generate an LDM type 2 instruction (register bank switching)
- which is what you get if the PC is not being loaded, we do not need
- to check for writeback. */
- if (! TARGET_APCS_32
- && ((mask & (1 << PC_REGNUM)) != 0))
- fprintf (stream, "^");
-
- fprintf (stream, "\n");
+ fprintf (stream, "}\n");
}
+
+/* Output a FLDMX instruction to STREAM.
+ BASE if the register containing the address.
+ REG and COUNT specify the register range.
+ Extra registers may be added to avoid hardware bugs. */
+
+static void
+arm_output_fldmx (FILE * stream, unsigned int base, int reg, int count)
+{
+ int i;
+
+ /* Workaround ARM10 VFPr1 bug. */
+ if (count == 2 && !arm_arch6)
+ {
+ if (reg == 15)
+ reg--;
+ count++;
+ }
+
+ fputc ('\t', stream);
+ asm_fprintf (stream, "fldmfdx\t%r!, {", base);
+
+ for (i = reg; i < reg + count; i++)
+ {
+ if (i > reg)
+ fputs (", ", stream);
+ asm_fprintf (stream, "d%d", i);
+ }
+ fputs ("}\n", stream);
+
+}
+
+
+/* Output the assembly for a store multiple. */
+
+const char *
+vfp_output_fstmx (rtx * operands)
+{
+ char pattern[100];
+ int p;
+ int base;
+ int i;
+
+ strcpy (pattern, "fstmfdx\t%m0!, {%P1");
+ p = strlen (pattern);
+
+ gcc_assert (GET_CODE (operands[1]) == REG);
+
+ base = (REGNO (operands[1]) - FIRST_VFP_REGNUM) / 2;
+ for (i = 1; i < XVECLEN (operands[2], 0); i++)
+ {
+ p += sprintf (&pattern[p], ", d%d", base + i);
+ }
+ strcpy (&pattern[p], "}");
+
+ output_asm_insn (pattern, operands);
+ return "";
+}
+
+
+/* Emit RTL to save block of VFP register pairs to the stack. Returns the
+ number of bytes pushed. */
+
+static int
+vfp_emit_fstmx (int base_reg, int count)
+{
+ rtx par;
+ rtx dwarf;
+ rtx tmp, reg;
+ int i;
+
+ /* Workaround ARM10 VFPr1 bug. Data corruption can occur when exactly two
+ register pairs are stored by a store multiple insn. We avoid this
+ by pushing an extra pair. */
+ if (count == 2 && !arm_arch6)
+ {
+ if (base_reg == LAST_VFP_REGNUM - 3)
+ base_reg -= 2;
+ count++;
+ }
+
+ /* ??? The frame layout is implementation defined. We describe
+ standard format 1 (equivalent to a FSTMD insn and unused pad word).
+ We really need some way of representing the whole block so that the
+ unwinder can figure it out at runtime. */
+ par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
+
+ reg = gen_rtx_REG (DFmode, base_reg);
+ base_reg += 2;
+
+ XVECEXP (par, 0, 0)
+ = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (BLKmode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
+ gen_rtx_UNSPEC (BLKmode,
+ gen_rtvec (1, reg),
+ UNSPEC_PUSH_MULT));
+
+ tmp = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx, -(count * 8 + 4)));
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, 0) = tmp;
+
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (DFmode, stack_pointer_rtx),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, 1) = tmp;
+
+ for (i = 1; i < count; i++)
+ {
+ reg = gen_rtx_REG (DFmode, base_reg);
+ base_reg += 2;
+ XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
+
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (DFmode,
+ plus_constant (stack_pointer_rtx,
+ i * 8)),
+ reg);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, i + 1) = tmp;
+ }
+
+ par = emit_insn (par);
+ REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+ REG_NOTES (par));
+ RTX_FRAME_RELATED_P (par) = 1;
+
+ return count * 8 + 4;
+}
+
+
/* Output a 'call' insn. */
const char *
output_call (rtx *operands)
{
- /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
+ gcc_assert (!arm_arch5); /* Patterns should call blx <reg> directly. */
+ /* Handle calls to lr using ip (which may be clobbered in subr anyway). */
if (REGNO (operands[0]) == LR_REGNUM)
{
operands[0] = gen_rtx_REG (SImode, IP_REGNUM);
output_asm_insn ("mov%?\t%0, %|lr", operands);
}
-
+
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
-
- if (TARGET_INTERWORK)
+
+ if (TARGET_INTERWORK || arm_arch4t)
output_asm_insn ("bx%?\t%0", operands);
else
output_asm_insn ("mov%?\t%|pc, %0", operands);
-
+
return "";
}
@@ -7272,7 +8580,7 @@ output_call (rtx *operands)
const char *
output_call_mem (rtx *operands)
{
- if (TARGET_INTERWORK)
+ if (TARGET_INTERWORK && !arm_arch5)
{
output_asm_insn ("ldr%?\t%|ip, %0", operands);
output_asm_insn ("mov%?\t%|lr, %|pc", operands);
@@ -7284,8 +8592,16 @@ output_call_mem (rtx *operands)
first instruction. It's safe to use IP as the target of the
load since the call will kill it anyway. */
output_asm_insn ("ldr%?\t%|ip, %0", operands);
- output_asm_insn ("mov%?\t%|lr, %|pc", operands);
- output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+ if (arm_arch5)
+ output_asm_insn ("blx%?\t%|ip", operands);
+ else
+ {
+ output_asm_insn ("mov%?\t%|lr, %|pc", operands);
+ if (arm_arch4t)
+ output_asm_insn ("bx%?\t%|ip", operands);
+ else
+ output_asm_insn ("mov%?\t%|pc, %|ip", operands);
+ }
}
else
{
@@ -7296,6 +8612,7 @@ output_call_mem (rtx *operands)
return "";
}
+
/* Output a move from arm registers to an fpa registers.
OPERANDS[0] is an fpa register.
OPERANDS[1] is the first registers of an arm register pair. */
@@ -7305,16 +8622,15 @@ output_mov_long_double_fpa_from_arm (rtx *operands)
int arm_reg0 = REGNO (operands[1]);
rtx ops[3];
- if (arm_reg0 == IP_REGNUM)
- abort ();
+ gcc_assert (arm_reg0 != IP_REGNUM);
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
ops[2] = gen_rtx_REG (SImode, 2 + arm_reg0);
-
+
output_asm_insn ("stm%?fd\t%|sp!, {%0, %1, %2}", ops);
output_asm_insn ("ldf%?e\t%0, [%|sp], #12", operands);
-
+
return "";
}
@@ -7327,8 +8643,7 @@ output_mov_long_double_arm_from_fpa (rtx *operands)
int arm_reg0 = REGNO (operands[0]);
rtx ops[3];
- if (arm_reg0 == IP_REGNUM)
- abort ();
+ gcc_assert (arm_reg0 != IP_REGNUM);
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
@@ -7383,9 +8698,8 @@ output_mov_double_fpa_from_arm (rtx *operands)
int arm_reg0 = REGNO (operands[1]);
rtx ops[2];
- if (arm_reg0 == IP_REGNUM)
- abort ();
-
+ gcc_assert (arm_reg0 != IP_REGNUM);
+
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
output_asm_insn ("stm%?fd\t%|sp!, {%0, %1}", ops);
@@ -7402,8 +8716,7 @@ output_mov_double_arm_from_fpa (rtx *operands)
int arm_reg0 = REGNO (operands[0]);
rtx ops[2];
- if (arm_reg0 == IP_REGNUM)
- abort ();
+ gcc_assert (arm_reg0 != IP_REGNUM);
ops[0] = gen_rtx_REG (SImode, arm_reg0);
ops[1] = gen_rtx_REG (SImode, 1 + arm_reg0);
@@ -7427,267 +8740,177 @@ output_move_double (rtx *operands)
int reg0 = REGNO (operands[0]);
otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
-
- if (code1 == REG)
- {
- int reg1 = REGNO (operands[1]);
- if (reg1 == IP_REGNUM)
- abort ();
- /* Ensure the second source is not overwritten. */
- if (reg1 == reg0 + (WORDS_BIG_ENDIAN ? -1 : 1))
- output_asm_insn ("mov%?\t%Q0, %Q1\n\tmov%?\t%R0, %R1", operands);
- else
- output_asm_insn ("mov%?\t%R0, %R1\n\tmov%?\t%Q0, %Q1", operands);
- }
- else if (code1 == CONST_VECTOR)
- {
- HOST_WIDE_INT hint = 0;
+ gcc_assert (code1 == MEM); /* Constraints should ensure this. */
- switch (GET_MODE (operands[1]))
- {
- case V2SImode:
- otherops[1] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 1)));
- operands[1] = GEN_INT (INTVAL (CONST_VECTOR_ELT (operands[1], 0)));
- break;
-
- case V4HImode:
- if (BYTES_BIG_ENDIAN)
- {
- hint = INTVAL (CONST_VECTOR_ELT (operands[1], 2));
- hint <<= 16;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 3));
- }
- else
- {
- hint = INTVAL (CONST_VECTOR_ELT (operands[1], 3));
- hint <<= 16;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 2));
- }
+ switch (GET_CODE (XEXP (operands[1], 0)))
+ {
+ case REG:
+ output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
+ break;
- otherops[1] = GEN_INT (hint);
- hint = 0;
+ case PRE_INC:
+ gcc_assert (TARGET_LDRD);
+ output_asm_insn ("ldr%?d\t%0, [%m1, #8]!", operands);
+ break;
- if (BYTES_BIG_ENDIAN)
- {
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 0));
- hint <<= 16;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 1));
- }
- else
- {
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 1));
- hint <<= 16;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 0));
- }
+ case PRE_DEC:
+ output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
+ break;
- operands[1] = GEN_INT (hint);
- break;
+ case POST_INC:
+ output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
+ break;
- case V8QImode:
- if (BYTES_BIG_ENDIAN)
- {
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 4));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 5));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 6));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 7));
- }
- else
- {
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 7));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 6));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 5));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 4));
- }
+ case POST_DEC:
+ gcc_assert (TARGET_LDRD);
+ output_asm_insn ("ldr%?d\t%0, [%m1], #-8", operands);
+ break;
- otherops[1] = GEN_INT (hint);
- hint = 0;
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ otherops[0] = operands[0];
+ otherops[1] = XEXP (XEXP (XEXP (operands[1], 0), 1), 0);
+ otherops[2] = XEXP (XEXP (XEXP (operands[1], 0), 1), 1);
- if (BYTES_BIG_ENDIAN)
+ if (GET_CODE (XEXP (operands[1], 0)) == PRE_MODIFY)
+ {
+ if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
{
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 0));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 1));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 2));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 3));
+ /* Registers overlap so split out the increment. */
+ output_asm_insn ("add%?\t%1, %1, %2", otherops);
+ output_asm_insn ("ldr%?d\t%0, [%1] @split", otherops);
}
else
{
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 3));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 2));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 1));
- hint <<= 8;
- hint |= INTVAL (CONST_VECTOR_ELT (operands[1], 0));
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+ otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ }
+ else
+ output_asm_insn ("ldr%?d\t%0, [%1, %2]!", otherops);
}
-
- operands[1] = GEN_INT (hint);
- break;
-
- default:
- abort ();
- }
- output_mov_immediate (operands);
- output_mov_immediate (otherops);
- }
- else if (code1 == CONST_DOUBLE)
- {
- if (GET_MODE (operands[1]) == DFmode)
- {
- REAL_VALUE_TYPE r;
- long l[2];
-
- REAL_VALUE_FROM_CONST_DOUBLE (r, operands[1]);
- REAL_VALUE_TO_TARGET_DOUBLE (r, l);
- otherops[1] = GEN_INT (l[1]);
- operands[1] = GEN_INT (l[0]);
- }
- else if (GET_MODE (operands[1]) != VOIDmode)
- abort ();
- else if (WORDS_BIG_ENDIAN)
- {
- otherops[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- operands[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
- }
- else
- {
- otherops[1] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- }
-
- output_mov_immediate (operands);
- output_mov_immediate (otherops);
- }
- else if (code1 == CONST_INT)
- {
-#if HOST_BITS_PER_WIDE_INT > 32
- /* If HOST_WIDE_INT is more than 32 bits, the intval tells us
- what the upper word is. */
- if (WORDS_BIG_ENDIAN)
- {
- otherops[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
- operands[1] = GEN_INT (INTVAL (operands[1]) >> 32);
}
else
{
- otherops[1] = GEN_INT (INTVAL (operands[1]) >> 32);
- operands[1] = GEN_INT (ARM_SIGN_EXTEND (INTVAL (operands[1])));
- }
-#else
- /* Sign extend the intval into the high-order word. */
- if (WORDS_BIG_ENDIAN)
- {
- otherops[1] = operands[1];
- operands[1] = (INTVAL (operands[1]) < 0
- ? constm1_rtx : const0_rtx);
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ otherops[0] = gen_rtx_REG (SImode, 1 + reg0);
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ otherops[0] = operands[0];
+ output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+ }
+ else
+ /* We only allow constant increments, so this is safe. */
+ output_asm_insn ("ldr%?d\t%0, [%1], %2", otherops);
}
- else
- otherops[1] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
-#endif
- output_mov_immediate (otherops);
- output_mov_immediate (operands);
- }
- else if (code1 == MEM)
- {
- switch (GET_CODE (XEXP (operands[1], 0)))
- {
- case REG:
- output_asm_insn ("ldm%?ia\t%m1, %M0", operands);
- break;
-
- case PRE_INC:
- abort (); /* Should never happen now. */
- break;
-
- case PRE_DEC:
- output_asm_insn ("ldm%?db\t%m1!, %M0", operands);
- break;
-
- case POST_INC:
- output_asm_insn ("ldm%?ia\t%m1!, %M0", operands);
- break;
+ break;
- case POST_DEC:
- abort (); /* Should never happen now. */
- break;
+ case LABEL_REF:
+ case CONST:
+ output_asm_insn ("adr%?\t%0, %1", operands);
+ output_asm_insn ("ldm%?ia\t%0, %M0", operands);
+ break;
- case LABEL_REF:
- case CONST:
- output_asm_insn ("adr%?\t%0, %1", operands);
- output_asm_insn ("ldm%?ia\t%0, %M0", operands);
- break;
+ default:
+ if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1),
+ GET_MODE (XEXP (XEXP (operands[1], 0), 1))))
+ {
+ otherops[0] = operands[0];
+ otherops[1] = XEXP (XEXP (operands[1], 0), 0);
+ otherops[2] = XEXP (XEXP (operands[1], 0), 1);
- default:
- if (arm_add_operand (XEXP (XEXP (operands[1], 0), 1),
- GET_MODE (XEXP (XEXP (operands[1], 0), 1))))
+ if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
{
- otherops[0] = operands[0];
- otherops[1] = XEXP (XEXP (operands[1], 0), 0);
- otherops[2] = XEXP (XEXP (operands[1], 0), 1);
-
- if (GET_CODE (XEXP (operands[1], 0)) == PLUS)
+ if (GET_CODE (otherops[2]) == CONST_INT)
{
- if (GET_CODE (otherops[2]) == CONST_INT)
+ switch ((int) INTVAL (otherops[2]))
{
- switch ((int) INTVAL (otherops[2]))
- {
- case -8:
- output_asm_insn ("ldm%?db\t%1, %M0", otherops);
- return "";
- case -4:
- output_asm_insn ("ldm%?da\t%1, %M0", otherops);
- return "";
- case 4:
- output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
- return "";
- }
-
- if (!(const_ok_for_arm (INTVAL (otherops[2]))))
- output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
- else
- output_asm_insn ("add%?\t%0, %1, %2", otherops);
+ case -8:
+ output_asm_insn ("ldm%?db\t%1, %M0", otherops);
+ return "";
+ case -4:
+ output_asm_insn ("ldm%?da\t%1, %M0", otherops);
+ return "";
+ case 4:
+ output_asm_insn ("ldm%?ib\t%1, %M0", otherops);
+ return "";
}
- else
- output_asm_insn ("add%?\t%0, %1, %2", otherops);
}
- else
- output_asm_insn ("sub%?\t%0, %1, %2", otherops);
-
- return "ldm%?ia\t%0, %M0";
- }
- else
- {
- otherops[1] = adjust_address (operands[1], SImode, 4);
- /* Take care of overlapping base/data reg. */
- if (reg_mentioned_p (operands[0], operands[1]))
+ if (TARGET_LDRD
+ && (GET_CODE (otherops[2]) == REG
+ || (GET_CODE (otherops[2]) == CONST_INT
+ && INTVAL (otherops[2]) > -256
+ && INTVAL (otherops[2]) < 256)))
{
- output_asm_insn ("ldr%?\t%0, %1", otherops);
- output_asm_insn ("ldr%?\t%0, %1", operands);
+ if (reg_overlap_mentioned_p (otherops[0],
+ otherops[2]))
+ {
+ /* Swap base and index registers over to
+ avoid a conflict. */
+ otherops[1] = XEXP (XEXP (operands[1], 0), 1);
+ otherops[2] = XEXP (XEXP (operands[1], 0), 0);
+ }
+ /* If both registers conflict, it will usually
+ have been fixed by a splitter. */
+ if (reg_overlap_mentioned_p (otherops[0], otherops[2]))
+ {
+ output_asm_insn ("add%?\t%1, %1, %2", otherops);
+ output_asm_insn ("ldr%?d\t%0, [%1]",
+ otherops);
+ }
+ else
+ output_asm_insn ("ldr%?d\t%0, [%1, %2]", otherops);
+ return "";
}
- else
+
+ if (GET_CODE (otherops[2]) == CONST_INT)
{
- output_asm_insn ("ldr%?\t%0, %1", operands);
- output_asm_insn ("ldr%?\t%0, %1", otherops);
+ if (!(const_ok_for_arm (INTVAL (otherops[2]))))
+ output_asm_insn ("sub%?\t%0, %1, #%n2", otherops);
+ else
+ output_asm_insn ("add%?\t%0, %1, %2", otherops);
}
+ else
+ output_asm_insn ("add%?\t%0, %1, %2", otherops);
+ }
+ else
+ output_asm_insn ("sub%?\t%0, %1, %2", otherops);
+
+ return "ldm%?ia\t%0, %M0";
+ }
+ else
+ {
+ otherops[1] = adjust_address (operands[1], SImode, 4);
+ /* Take care of overlapping base/data reg. */
+ if (reg_mentioned_p (operands[0], operands[1]))
+ {
+ output_asm_insn ("ldr%?\t%0, %1", otherops);
+ output_asm_insn ("ldr%?\t%0, %1", operands);
+ }
+ else
+ {
+ output_asm_insn ("ldr%?\t%0, %1", operands);
+ output_asm_insn ("ldr%?\t%0, %1", otherops);
}
}
}
- else
- abort (); /* Constraints should prevent this. */
}
- else if (code0 == MEM && code1 == REG)
+ else
{
- if (REGNO (operands[1]) == IP_REGNUM)
- abort ();
+ /* Constraints should ensure this. */
+ gcc_assert (code0 == MEM && code1 == REG);
+ gcc_assert (REGNO (operands[1]) != IP_REGNUM);
switch (GET_CODE (XEXP (operands[0], 0)))
{
@@ -7696,7 +8919,8 @@ output_move_double (rtx *operands)
break;
case PRE_INC:
- abort (); /* Should never happen now. */
+ gcc_assert (TARGET_LDRD);
+ output_asm_insn ("str%?d\t%1, [%m0, #8]!", operands);
break;
case PRE_DEC:
@@ -7708,11 +8932,47 @@ output_move_double (rtx *operands)
break;
case POST_DEC:
- abort (); /* Should never happen now. */
+ gcc_assert (TARGET_LDRD);
+ output_asm_insn ("str%?d\t%1, [%m0], #-8", operands);
+ break;
+
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ otherops[0] = operands[1];
+ otherops[1] = XEXP (XEXP (XEXP (operands[0], 0), 1), 0);
+ otherops[2] = XEXP (XEXP (XEXP (operands[0], 0), 1), 1);
+
+ /* IWMMXT allows offsets larger than ldrd can handle,
+ fix these up with a pair of ldr. */
+ if (GET_CODE (otherops[2]) == CONST_INT
+ && (INTVAL(otherops[2]) <= -256
+ || INTVAL(otherops[2]) >= 256))
+ {
+ rtx reg1;
+ reg1 = gen_rtx_REG (SImode, 1 + REGNO (operands[1]));
+ if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+ {
+ output_asm_insn ("ldr%?\t%0, [%1, %2]!", otherops);
+ otherops[0] = reg1;
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ }
+ else
+ {
+ otherops[0] = reg1;
+ output_asm_insn ("ldr%?\t%0, [%1, #4]", otherops);
+ otherops[0] = operands[1];
+ output_asm_insn ("ldr%?\t%0, [%1], %2", otherops);
+ }
+ }
+ else if (GET_CODE (XEXP (operands[0], 0)) == PRE_MODIFY)
+ output_asm_insn ("str%?d\t%0, [%1, %2]!", otherops);
+ else
+ output_asm_insn ("str%?d\t%0, [%1], %2", otherops);
break;
case PLUS:
- if (GET_CODE (XEXP (XEXP (operands[0], 0), 1)) == CONST_INT)
+ otherops[2] = XEXP (XEXP (operands[0], 0), 1);
+ if (GET_CODE (otherops[2]) == CONST_INT)
{
switch ((int) INTVAL (XEXP (XEXP (operands[0], 0), 1)))
{
@@ -7729,6 +8989,17 @@ output_move_double (rtx *operands)
return "";
}
}
+ if (TARGET_LDRD
+ && (GET_CODE (otherops[2]) == REG
+ || (GET_CODE (otherops[2]) == CONST_INT
+ && INTVAL (otherops[2]) > -256
+ && INTVAL (otherops[2]) < 256)))
+ {
+ otherops[0] = operands[1];
+ otherops[1] = XEXP (XEXP (operands[0], 0), 0);
+ output_asm_insn ("str%?d\t%0, [%1, %2]", otherops);
+ return "";
+ }
/* Fall through */
default:
@@ -7738,46 +9009,6 @@ output_move_double (rtx *operands)
output_asm_insn ("str%?\t%1, %0", otherops);
}
}
- else
- /* Constraints should prevent this. */
- abort ();
-
- return "";
-}
-
-
-/* Output an arbitrary MOV reg, #n.
- OPERANDS[0] is a register. OPERANDS[1] is a const_int. */
-const char *
-output_mov_immediate (rtx *operands)
-{
- HOST_WIDE_INT n = INTVAL (operands[1]);
-
- /* Try to use one MOV. */
- if (const_ok_for_arm (n))
- output_asm_insn ("mov%?\t%0, %1", operands);
-
- /* Try to use one MVN. */
- else if (const_ok_for_arm (~n))
- {
- operands[1] = GEN_INT (~n);
- output_asm_insn ("mvn%?\t%0, %1", operands);
- }
- else
- {
- int n_ones = 0;
- int i;
-
- /* If all else fails, make it out of ORRs or BICs as appropriate. */
- for (i = 0; i < 32; i++)
- if (n & 1 << i)
- n_ones++;
-
- if (n_ones > 16) /* Shorter to use MVN with BIC in this case. */
- output_multi_immediate (operands, "mvn%?\t%0, %1", "bic%?\t%0, %0, %1", 1, ~ n);
- else
- output_multi_immediate (operands, "mov%?\t%0, %1", "orr%?\t%0, %0, %1", 1, n);
- }
return "";
}
@@ -7841,7 +9072,7 @@ output_multi_immediate (rtx *operands, const char *instr1, const char *instr2,
}
}
}
-
+
return "";
}
@@ -7870,7 +9101,7 @@ arithmetic_instr (rtx op, int shift_first_arg)
return "and";
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -7885,12 +9116,20 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
const char * mnem;
enum rtx_code code = GET_CODE (op);
- if (GET_CODE (XEXP (op, 1)) == REG || GET_CODE (XEXP (op, 1)) == SUBREG)
- *amountp = -1;
- else if (GET_CODE (XEXP (op, 1)) == CONST_INT)
- *amountp = INTVAL (XEXP (op, 1));
- else
- abort ();
+ switch (GET_CODE (XEXP (op, 1)))
+ {
+ case REG:
+ case SUBREG:
+ *amountp = -1;
+ break;
+
+ case CONST_INT:
+ *amountp = INTVAL (XEXP (op, 1));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
switch (code)
{
@@ -7906,6 +9145,12 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
mnem = "lsr";
break;
+ case ROTATE:
+ gcc_assert (*amountp != -1);
+ *amountp = 32 - *amountp;
+
+ /* Fall through. */
+
case ROTATERT:
mnem = "ror";
break;
@@ -7913,14 +9158,12 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
case MULT:
/* We never have to worry about the amount being other than a
power of 2, since this case can never be reloaded from a reg. */
- if (*amountp != -1)
- *amountp = int_log2 (*amountp);
- else
- abort ();
+ gcc_assert (*amountp != -1);
+ *amountp = int_log2 (*amountp);
return "asl";
default:
- abort ();
+ gcc_unreachable ();
}
if (*amountp != -1)
@@ -7930,7 +9173,7 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
shift. >=32 is not a valid shift for "asl", so we must try and
output a shift that produces the correct arithmetical result.
Using lsr #32 is identical except for the fact that the carry bit
- is not set correctly if we set the flags; but we never use the
+ is not set correctly if we set the flags; but we never use the
carry bit from such an operation, so we can ignore that. */
if (code == ROTATERT)
/* Rotate is just modulo 32. */
@@ -7945,7 +9188,7 @@ shift_op (rtx op, HOST_WIDE_INT *amountp)
/* Shifts of 0 are no-ops. */
if (*amountp == 0)
return NULL;
- }
+ }
return mnem;
}
@@ -7959,16 +9202,21 @@ int_log2 (HOST_WIDE_INT power)
while ((((HOST_WIDE_INT) 1 << shift) & power) == 0)
{
- if (shift > 31)
- abort ();
+ gcc_assert (shift <= 31);
shift++;
}
return shift;
}
-/* Output a .ascii pseudo-op, keeping track of lengths. This is because
- /bin/as is horribly restrictive. */
+/* Output a .ascii pseudo-op, keeping track of lengths. This is
+ because /bin/as is horribly restrictive. The judgement about
+ whether or not each character is 'printable' (and can be output as
+ is) or not (and must be printed with an octal escape) must be made
+ with reference to the *host* character set -- the situation is
+ similar to that discussed in the comments above pp_c_char in
+ c-pretty-print.c. */
+
#define MAX_ASCII_LEN 51
void
@@ -7978,7 +9226,7 @@ output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len)
int len_so_far = 0;
fputs ("\t.ascii\t\"", stream);
-
+
for (i = 0; i < len; i++)
{
int c = p[i];
@@ -7989,71 +9237,34 @@ output_ascii_pseudo_op (FILE *stream, const unsigned char *p, int len)
len_so_far = 0;
}
- switch (c)
+ if (ISPRINT (c))
{
- case TARGET_TAB:
- fputs ("\\t", stream);
- len_so_far += 2;
- break;
-
- case TARGET_FF:
- fputs ("\\f", stream);
- len_so_far += 2;
- break;
-
- case TARGET_BS:
- fputs ("\\b", stream);
- len_so_far += 2;
- break;
-
- case TARGET_CR:
- fputs ("\\r", stream);
- len_so_far += 2;
- break;
-
- case TARGET_NEWLINE:
- fputs ("\\n", stream);
- c = p [i + 1];
- if ((c >= ' ' && c <= '~')
- || c == TARGET_TAB)
- /* This is a good place for a line break. */
- len_so_far = MAX_ASCII_LEN;
- else
- len_so_far += 2;
- break;
-
- case '\"':
- case '\\':
- putc ('\\', stream);
- len_so_far++;
- /* Drop through. */
-
- default:
- if (c >= ' ' && c <= '~')
+ if (c == '\\' || c == '\"')
{
- putc (c, stream);
+ putc ('\\', stream);
len_so_far++;
}
- else
- {
- fprintf (stream, "\\%03o", c);
- len_so_far += 4;
- }
- break;
+ putc (c, stream);
+ len_so_far++;
+ }
+ else
+ {
+ fprintf (stream, "\\%03o", c);
+ len_so_far += 4;
}
}
fputs ("\"\n", stream);
}
-/* Compute the register sabe mask for registers 0 through 12
- inclusive. This code is used by both arm_compute_save_reg_mask
- and arm_compute_initial_elimination_offset. */
+/* Compute the register save mask for registers 0 through 12
+ inclusive. This code is used by arm_compute_save_reg_mask. */
+
static unsigned long
arm_compute_save_reg0_reg12_mask (void)
{
unsigned long func_type = arm_current_func_type ();
- unsigned int save_reg_mask = 0;
+ unsigned long save_reg_mask = 0;
unsigned int reg;
if (IS_INTERRUPT (func_type))
@@ -8074,11 +9285,18 @@ arm_compute_save_reg0_reg12_mask (void)
max_reg = 7;
else
max_reg = 12;
-
+
for (reg = 0; reg <= max_reg; reg++)
if (regs_ever_live[reg]
|| (! current_function_is_leaf && call_used_regs [reg]))
save_reg_mask |= (1 << reg);
+
+ /* Also save the pic base register if necessary. */
+ if (flag_pic
+ && !TARGET_SINGLE_PIC_BASE
+ && arm_pic_register != INVALID_REGNUM
+ && current_function_uses_pic_offset_table)
+ save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
}
else
{
@@ -8098,11 +9316,27 @@ arm_compute_save_reg0_reg12_mask (void)
/* If we aren't loading the PIC register,
don't stack it even though it may be live. */
if (flag_pic
- && ! TARGET_SINGLE_PIC_BASE
- && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
+ && !TARGET_SINGLE_PIC_BASE
+ && arm_pic_register != INVALID_REGNUM
+ && (regs_ever_live[PIC_OFFSET_TABLE_REGNUM]
+ || current_function_uses_pic_offset_table))
save_reg_mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
}
+ /* Save registers so the exception handler can modify them. */
+ if (current_function_calls_eh_return)
+ {
+ unsigned int i;
+
+ for (i = 0; ; i++)
+ {
+ reg = EH_RETURN_DATA_REGNO (i);
+ if (reg == INVALID_REGNUM)
+ break;
+ save_reg_mask |= 1 << reg;
+ }
+ }
+
return save_reg_mask;
}
@@ -8147,7 +9381,8 @@ arm_compute_save_reg_mask (void)
if (regs_ever_live [LR_REGNUM]
|| (save_reg_mask
&& optimize_size
- && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL))
+ && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
+ && !current_function_calls_eh_return))
save_reg_mask |= 1 << LR_REGNUM;
if (cfun->machine->lr_save_eliminated)
@@ -8184,6 +9419,97 @@ arm_compute_save_reg_mask (void)
return save_reg_mask;
}
+
+/* Compute a bit mask of which registers need to be
+ saved on the stack for the current function. */
+static unsigned long
+thumb_compute_save_reg_mask (void)
+{
+ unsigned long mask;
+ unsigned reg;
+
+ mask = 0;
+ for (reg = 0; reg < 12; reg ++)
+ if (regs_ever_live[reg] && !call_used_regs[reg])
+ mask |= 1 << reg;
+
+ if (flag_pic
+ && !TARGET_SINGLE_PIC_BASE
+ && arm_pic_register != INVALID_REGNUM
+ && current_function_uses_pic_offset_table)
+ mask |= 1 << PIC_OFFSET_TABLE_REGNUM;
+
+ /* See if we might need r11 for calls to _interwork_r11_call_via_rN(). */
+ if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
+ mask |= 1 << ARM_HARD_FRAME_POINTER_REGNUM;
+
+ /* LR will also be pushed if any lo regs are pushed. */
+ if (mask & 0xff || thumb_force_lr_save ())
+ mask |= (1 << LR_REGNUM);
+
+ /* Make sure we have a low work register if we need one.
+ We will need one if we are going to push a high register,
+ but we are not currently intending to push a low register. */
+ if ((mask & 0xff) == 0
+ && ((mask & 0x0f00) || TARGET_BACKTRACE))
+ {
+ /* Use thumb_find_work_register to choose which register
+ we will use. If the register is live then we will
+ have to push it. Use LAST_LO_REGNUM as our fallback
+ choice for the register to select. */
+ reg = thumb_find_work_register (1 << LAST_LO_REGNUM);
+
+ if (! call_used_regs[reg])
+ mask |= 1 << reg;
+ }
+
+ return mask;
+}
+
+
+/* Return the number of bytes required to save VFP registers. */
+static int
+arm_get_vfp_saved_size (void)
+{
+ unsigned int regno;
+ int count;
+ int saved;
+
+ saved = 0;
+ /* Space for saved VFP registers. */
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ {
+ count = 0;
+ for (regno = FIRST_VFP_REGNUM;
+ regno < LAST_VFP_REGNUM;
+ regno += 2)
+ {
+ if ((!regs_ever_live[regno] || call_used_regs[regno])
+ && (!regs_ever_live[regno + 1] || call_used_regs[regno + 1]))
+ {
+ if (count > 0)
+ {
+ /* Workaround ARM10 VFPr1 bug. */
+ if (count == 2 && !arm_arch6)
+ count++;
+ saved += count * 8 + 4;
+ }
+ count = 0;
+ }
+ else
+ count++;
+ }
+ if (count > 0)
+ {
+ if (count == 2 && !arm_arch6)
+ count++;
+ saved += count * 8 + 4;
+ }
+ }
+ return saved;
+}
+
+
/* Generate a function exit sequence. If REALLY_RETURN is false, then do
everything bar the final return instruction. */
const char *
@@ -8191,9 +9517,10 @@ output_return_instruction (rtx operand, int really_return, int reverse)
{
char conditional[10];
char instr[100];
- int reg;
+ unsigned reg;
unsigned long live_regs_mask;
unsigned long func_type;
+ arm_stack_offsets *offsets;
func_type = arm_current_func_type ();
@@ -8208,20 +9535,19 @@ output_return_instruction (rtx operand, int really_return, int reverse)
if (really_return)
{
rtx ops[2];
-
+
/* Otherwise, trap an attempted return by aborting. */
ops[0] = operand;
- ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
+ ops[1] = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)"
: "abort");
assemble_external_libcall (ops[1]);
output_asm_insn (reverse ? "bl%D0\t%a1" : "bl%d0\t%a1", ops);
}
-
+
return "";
}
- if (current_function_calls_alloca && !really_return)
- abort ();
+ gcc_assert (!current_function_calls_alloca || really_return);
sprintf (conditional, "%%?%%%c0", reverse ? 'D' : 'd');
@@ -8233,8 +9559,8 @@ output_return_instruction (rtx operand, int really_return, int reverse)
{
const char * return_reg;
- /* If we do not have any special requirements for function exit
- (eg interworking, or ISR) then we can load the return address
+ /* If we do not have any special requirements for function exit
+ (e.g. interworking, or ISR) then we can load the return address
directly into the PC. Otherwise we must load it into LR. */
if (really_return
&& ! TARGET_INTERWORK)
@@ -8256,11 +9582,7 @@ output_return_instruction (rtx operand, int really_return, int reverse)
live_regs_mask |= (1 << SP_REGNUM);
}
else
- {
- if (! IS_INTERRUPT (func_type)
- && ! TARGET_REALLY_IWMMXT)
- abort ();
- }
+ gcc_assert (IS_INTERRUPT (func_type) || TARGET_REALLY_IWMMXT);
}
/* On some ARM architectures it is faster to use LDR rather than
@@ -8269,16 +9591,15 @@ output_return_instruction (rtx operand, int really_return, int reverse)
we have to use LDM to load the PC so that the CPSR is also
restored. */
for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
- {
- if (live_regs_mask == (unsigned int)(1 << reg))
- break;
- }
+ if (live_regs_mask == (1U << reg))
+ break;
+
if (reg <= LAST_ARM_REGNUM
&& (reg != LR_REGNUM
- || ! really_return
- || (TARGET_APCS_32 && ! IS_INTERRUPT (func_type))))
+ || ! really_return
+ || ! IS_INTERRUPT (func_type)))
{
- sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional,
+ sprintf (instr, "ldr%s\t%%|%s, [%%|sp], #4", conditional,
(reg == LR_REGNUM) ? return_reg : reg_names[reg]);
}
else
@@ -8292,18 +9613,18 @@ output_return_instruction (rtx operand, int really_return, int reverse)
points to the base of the saved core registers. */
if (live_regs_mask & (1 << SP_REGNUM))
{
- unsigned HOST_WIDE_INT stack_adjust =
- arm_get_frame_size () + current_function_outgoing_args_size;
-
- if (stack_adjust != 0 && stack_adjust != 4)
- abort ();
+ unsigned HOST_WIDE_INT stack_adjust;
+
+ offsets = arm_get_frame_offsets ();
+ stack_adjust = offsets->outgoing_args - offsets->saved_regs;
+ gcc_assert (stack_adjust == 0 || stack_adjust == 4);
if (stack_adjust && arm_arch5)
sprintf (instr, "ldm%sib\t%%|sp, {", conditional);
else
{
- /* If we can't use ldmib (SA110 bug), then try to pop r3
- instead. */
+ /* If we can't use ldmib (SA110 bug),
+ then try to pop r3 instead. */
if (stack_adjust)
live_regs_mask |= 1 << 3;
sprintf (instr, "ldm%sfd\t%%|sp, {", conditional);
@@ -8331,24 +9652,12 @@ output_return_instruction (rtx operand, int really_return, int reverse)
memcpy (p + 2, reg_names[reg], l);
p += l + 2;
}
-
+
if (live_regs_mask & (1 << LR_REGNUM))
{
sprintf (p, "%s%%|%s}", first ? "" : ", ", return_reg);
- /* Decide if we need to add the ^ symbol to the end of the
- register list. This causes the saved condition codes
- register to be copied into the current condition codes
- register. We do the copy if we are conforming to the 32-bit
- ABI and this is an interrupt function, or if we are
- conforming to the 26-bit ABI. There is a special case for
- the 26-bit ABI however, which is if we are writing back the
- stack pointer but not loading the PC. In this case adding
- the ^ symbol would create a type 2 LDM instruction, where
- writeback is UNPREDICTABLE. We are safe in leaving the ^
- character off in this case however, since the actual return
- instruction will be a MOVS which will restore the CPSR. */
- if ((TARGET_APCS_32 && IS_INTERRUPT (func_type))
- || (! TARGET_APCS_32 && really_return))
+ /* If returning from an interrupt, restore the CPSR. */
+ if (IS_INTERRUPT (func_type))
strcat (p, "^");
}
else
@@ -8387,13 +9696,11 @@ output_return_instruction (rtx operand, int really_return, int reverse)
break;
default:
- /* ARMv5 implementations always provide BX, so interworking
- is the default unless APCS-26 is in use. */
- if ((insn_flags & FL_ARCH5) != 0 && TARGET_APCS_32)
- sprintf (instr, "bx%s\t%%|lr", conditional);
+ /* Use bx if it's available. */
+ if (arm_arch5 || arm_arch4t)
+ sprintf (instr, "bx%s\t%%|lr", conditional);
else
- sprintf (instr, "mov%s%s\t%%|pc, %%|lr",
- conditional, TARGET_APCS_32 ? "" : "s");
+ sprintf (instr, "mov%s\t%%|pc, %%|lr", conditional);
break;
}
@@ -8438,7 +9745,7 @@ arm_poke_function_name (FILE *stream, const char *name)
length = strlen (name) + 1;
alignlength = ROUND_UP_WORD (length);
-
+
ASM_OUTPUT_ASCII (stream, name, length);
ASM_OUTPUT_ALIGN (stream, 2);
x = GEN_INT ((unsigned HOST_WIDE_INT) 0xff000000 + alignlength);
@@ -8457,13 +9764,12 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
thumb_output_function_prologue (f, frame_size);
return;
}
-
+
/* Sanity check. */
- if (arm_ccfsm_state || arm_target_insn)
- abort ();
+ gcc_assert (!arm_ccfsm_state && !arm_target_insn);
func_type = arm_current_func_type ();
-
+
switch ((int) ARM_FUNC_TYPE (func_type))
{
default:
@@ -8472,9 +9778,6 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
case ARM_FT_INTERWORKED:
asm_fprintf (f, "\t%@ Function supports interworking.\n");
break;
- case ARM_FT_EXCEPTION_HANDLER:
- asm_fprintf (f, "\t%@ C++ Exception Handler.\n");
- break;
case ARM_FT_ISR:
asm_fprintf (f, "\t%@ Interrupt Service Routine.\n");
break;
@@ -8485,7 +9788,7 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
asm_fprintf (f, "\t%@ ARM Exception Handler.\n");
break;
}
-
+
if (IS_NAKED (func_type))
asm_fprintf (f, "\t%@ Naked Function: prologue and epilogue provided by programmer.\n");
@@ -8494,7 +9797,7 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
if (IS_NESTED (func_type))
asm_fprintf (f, "\t%@ Nested: function declared inside another function.\n");
-
+
asm_fprintf (f, "\t%@ args = %d, pretend = %d, frame = %wd\n",
current_function_args_size,
current_function_pretend_args_size, frame_size);
@@ -8506,12 +9809,15 @@ arm_output_function_prologue (FILE *f, HOST_WIDE_INT frame_size)
if (cfun->machine->lr_save_eliminated)
asm_fprintf (f, "\t%@ link register save eliminated.\n");
+ if (current_function_calls_eh_return)
+ asm_fprintf (f, "\t@ Calls __builtin_eh_return.\n");
+
#ifdef AOF_ASSEMBLER
if (flag_pic)
asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, PIC_OFFSET_TABLE_REGNUM);
#endif
- return_used_this_function = 0;
+ return_used_this_function = 0;
}
const char *
@@ -8520,15 +9826,15 @@ arm_output_epilogue (rtx sibling)
int reg;
unsigned long saved_regs_mask;
unsigned long func_type;
- /* Floats_offset is the offset from the "virtual" frame. In an APCS
+ /* Floats_offset is the offset from the "virtual" frame. In an APCS
frame that is $fp + 4 for a non-variadic function. */
int floats_offset = 0;
rtx operands[3];
- int frame_size = arm_get_frame_size ();
FILE * f = asm_out_file;
- rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
unsigned int lrm_count = 0;
int really_return = (sibling == NULL);
+ int start_reg;
+ arm_stack_offsets *offsets;
/* If we have already generated the return instruction
then it is futile to generate anything else. */
@@ -8544,58 +9850,56 @@ arm_output_epilogue (rtx sibling)
if (IS_VOLATILE (func_type) && TARGET_ABORT_NORETURN)
{
rtx op;
-
+
/* A volatile function should never return. Call abort. */
op = gen_rtx_SYMBOL_REF (Pmode, NEED_PLT_RELOC ? "abort(PLT)" : "abort");
assemble_external_libcall (op);
output_asm_insn ("bl\t%a0", &op);
-
+
return "";
}
- if (ARM_FUNC_TYPE (func_type) == ARM_FT_EXCEPTION_HANDLER
- && ! really_return)
- /* If we are throwing an exception, then we really must
- be doing a return, so we can't tail-call. */
- abort ();
-
+ /* If we are throwing an exception, then we really must be doing a
+ return, so we can't tail-call. */
+ gcc_assert (!current_function_calls_eh_return || really_return);
+
+ offsets = arm_get_frame_offsets ();
saved_regs_mask = arm_compute_save_reg_mask ();
if (TARGET_IWMMXT)
lrm_count = bit_count (saved_regs_mask);
- /* XXX We should adjust floats_offset for any anonymous args, and then
- re-adjust vfp_offset below to compensate. */
-
+ floats_offset = offsets->saved_args;
/* Compute how far away the floats will be. */
for (reg = 0; reg <= LAST_ARM_REGNUM; reg++)
if (saved_regs_mask & (1 << reg))
floats_offset += 4;
-
+
if (frame_pointer_needed)
{
- int vfp_offset = 4;
+ /* This variable is for the Virtual Frame Pointer, not VFP regs. */
+ int vfp_offset = offsets->frame;
if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
{
- for (reg = LAST_ARM_FP_REGNUM; reg >= FIRST_ARM_FP_REGNUM; reg--)
+ for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
if (regs_ever_live[reg] && !call_used_regs[reg])
{
floats_offset += 12;
- asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n",
+ asm_fprintf (f, "\tldfe\t%r, [%r, #-%d]\n",
reg, FP_REGNUM, floats_offset - vfp_offset);
}
}
else
{
- int start_reg = LAST_ARM_FP_REGNUM;
+ start_reg = LAST_FPA_REGNUM;
- for (reg = LAST_ARM_FP_REGNUM; reg >= FIRST_ARM_FP_REGNUM; reg--)
+ for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
{
if (regs_ever_live[reg] && !call_used_regs[reg])
{
floats_offset += 12;
-
+
/* We can't unstack more than four registers at once. */
if (start_reg - reg == 3)
{
@@ -8621,6 +9925,39 @@ arm_output_epilogue (rtx sibling)
FP_REGNUM, floats_offset - vfp_offset);
}
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ {
+ int saved_size;
+
+ /* The fldmx insn does not have base+offset addressing modes,
+ so we use IP to hold the address. */
+ saved_size = arm_get_vfp_saved_size ();
+
+ if (saved_size > 0)
+ {
+ floats_offset += saved_size;
+ asm_fprintf (f, "\tsub\t%r, %r, #%d\n", IP_REGNUM,
+ FP_REGNUM, floats_offset - vfp_offset);
+ }
+ start_reg = FIRST_VFP_REGNUM;
+ for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
+ {
+ if ((!regs_ever_live[reg] || call_used_regs[reg])
+ && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
+ {
+ if (start_reg != reg)
+ arm_output_fldmx (f, IP_REGNUM,
+ (start_reg - FIRST_VFP_REGNUM) / 2,
+ (reg - start_reg) / 2);
+ start_reg = reg + 2;
+ }
+ }
+ if (start_reg != reg)
+ arm_output_fldmx (f, IP_REGNUM,
+ (start_reg - FIRST_VFP_REGNUM) / 2,
+ (reg - start_reg) / 2);
+ }
+
if (TARGET_IWMMXT)
{
/* The frame pointer is guaranteed to be non-double-word aligned.
@@ -8631,13 +9968,13 @@ arm_output_epilogue (rtx sibling)
We can ignore floats_offset since that was already included in
the live_regs_mask. */
lrm_count += (lrm_count % 2 ? 2 : 1);
-
- for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
+
+ for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--)
if (regs_ever_live[reg] && !call_used_regs[reg])
{
- asm_fprintf (f, "\twldrd\t%r, [%r, #-%d]\n",
+ asm_fprintf (f, "\twldrd\t%r, [%r, #-%d]\n",
reg, FP_REGNUM, lrm_count * 4);
- lrm_count += 2;
+ lrm_count += 2;
}
}
@@ -8645,8 +9982,7 @@ arm_output_epilogue (rtx sibling)
frame generation actually contains the old stack pointer. So a
quick way to unwind the stack is just pop the IP register directly
into the stack pointer. */
- if ((saved_regs_mask & (1 << IP_REGNUM)) == 0)
- abort ();
+ gcc_assert (saved_regs_mask & (1 << IP_REGNUM));
saved_regs_mask &= ~ (1 << IP_REGNUM);
saved_regs_mask |= (1 << SP_REGNUM);
@@ -8654,7 +9990,9 @@ arm_output_epilogue (rtx sibling)
only need to restore the LR register (the return address), but to
save time we can load it directly into the PC, unless we need a
special function exit sequence, or we are not really returning. */
- if (really_return && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL)
+ if (really_return
+ && ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
+ && !current_function_calls_eh_return)
/* Delete the LR from the register mask, so that the LR on
the stack is loaded into the PC in the register mask. */
saved_regs_mask &= ~ (1 << LR_REGNUM);
@@ -8670,8 +10008,7 @@ arm_output_epilogue (rtx sibling)
be reset correctly to the original value, should an interrupt
occur. If the stack pointer already points at the right
place, then omit the subtraction. */
- if (((frame_size + current_function_outgoing_args_size + floats_offset)
- != 4 * (1 + (int) bit_count (saved_regs_mask)))
+ if (offsets->outgoing_args != (1 + (int) bit_count (saved_regs_mask))
|| current_function_calls_alloca)
asm_fprintf (f, "\tsub\t%r, %r, #%d\n", SP_REGNUM, FP_REGNUM,
4 * bit_count (saved_regs_mask));
@@ -8685,26 +10022,25 @@ arm_output_epilogue (rtx sibling)
else
{
/* Restore stack pointer if necessary. */
- if (frame_size + current_function_outgoing_args_size != 0)
+ if (offsets->outgoing_args != offsets->saved_regs)
{
operands[0] = operands[1] = stack_pointer_rtx;
- operands[2] = GEN_INT (frame_size
- + current_function_outgoing_args_size);
+ operands[2] = GEN_INT (offsets->outgoing_args - offsets->saved_regs);
output_add_immediate (operands);
}
if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
{
- for (reg = FIRST_ARM_FP_REGNUM; reg <= LAST_ARM_FP_REGNUM; reg++)
+ for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
if (regs_ever_live[reg] && !call_used_regs[reg])
asm_fprintf (f, "\tldfe\t%r, [%r], #12\n",
reg, SP_REGNUM);
}
else
{
- int start_reg = FIRST_ARM_FP_REGNUM;
+ start_reg = FIRST_FPA_REGNUM;
- for (reg = FIRST_ARM_FP_REGNUM; reg <= LAST_ARM_FP_REGNUM; reg++)
+ for (reg = FIRST_FPA_REGNUM; reg <= LAST_FPA_REGNUM; reg++)
{
if (regs_ever_live[reg] && !call_used_regs[reg])
{
@@ -8721,7 +10057,7 @@ arm_output_epilogue (rtx sibling)
asm_fprintf (f, "\tlfmfd\t%r, %d, [%r]!\n",
start_reg, reg - start_reg,
SP_REGNUM);
-
+
start_reg = reg + 1;
}
}
@@ -8732,16 +10068,37 @@ arm_output_epilogue (rtx sibling)
start_reg, reg - start_reg, SP_REGNUM);
}
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ {
+ start_reg = FIRST_VFP_REGNUM;
+ for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
+ {
+ if ((!regs_ever_live[reg] || call_used_regs[reg])
+ && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
+ {
+ if (start_reg != reg)
+ arm_output_fldmx (f, SP_REGNUM,
+ (start_reg - FIRST_VFP_REGNUM) / 2,
+ (reg - start_reg) / 2);
+ start_reg = reg + 2;
+ }
+ }
+ if (start_reg != reg)
+ arm_output_fldmx (f, SP_REGNUM,
+ (start_reg - FIRST_VFP_REGNUM) / 2,
+ (reg - start_reg) / 2);
+ }
if (TARGET_IWMMXT)
for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
if (regs_ever_live[reg] && !call_used_regs[reg])
- asm_fprintf (f, "\twldrd\t%r, [%r, #+8]!\n", reg, SP_REGNUM);
+ asm_fprintf (f, "\twldrd\t%r, [%r], #8\n", reg, SP_REGNUM);
/* If we can, restore the LR into the PC. */
if (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
&& really_return
&& current_function_pretend_args_size == 0
- && saved_regs_mask & (1 << LR_REGNUM))
+ && saved_regs_mask & (1 << LR_REGNUM)
+ && !current_function_calls_eh_return)
{
saved_regs_mask &= ~ (1 << LR_REGNUM);
saved_regs_mask |= (1 << PC_REGNUM);
@@ -8751,18 +10108,13 @@ arm_output_epilogue (rtx sibling)
to load use the LDR instruction - it is faster. */
if (saved_regs_mask == (1 << LR_REGNUM))
{
- /* The exception handler ignores the LR, so we do
- not really need to load it off the stack. */
- if (eh_ofs)
- asm_fprintf (f, "\tadd\t%r, %r, #4\n", SP_REGNUM, SP_REGNUM);
- else
- asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
+ asm_fprintf (f, "\tldr\t%r, [%r], #4\n", LR_REGNUM, SP_REGNUM);
}
else if (saved_regs_mask)
{
if (saved_regs_mask & (1 << SP_REGNUM))
/* Note - write back to the stack register is not enabled
- (ie "ldmfd sp!..."). We know that the stack pointer is
+ (i.e. "ldmfd sp!..."). We know that the stack pointer is
in the list of registers and if we add writeback the
instruction becomes UNPREDICTABLE. */
print_multi_reg (f, "ldmfd\t%r", SP_REGNUM, saved_regs_mask);
@@ -8779,21 +10131,18 @@ arm_output_epilogue (rtx sibling)
}
}
- if (! really_return
- || (ARM_FUNC_TYPE (func_type) == ARM_FT_NORMAL
- && current_function_pretend_args_size == 0
- && saved_regs_mask & (1 << PC_REGNUM)))
+ /* We may have already restored PC directly from the stack. */
+ if (!really_return || saved_regs_mask & (1 << PC_REGNUM))
return "";
+ /* Stack adjustment for exception handler. */
+ if (current_function_calls_eh_return)
+ asm_fprintf (f, "\tadd\t%r, %r, %r\n", SP_REGNUM, SP_REGNUM,
+ ARM_EH_STACKADJ_REGNUM);
+
/* Generate the return instruction. */
switch ((int) ARM_FUNC_TYPE (func_type))
{
- case ARM_FT_EXCEPTION_HANDLER:
- /* Even in 26-bit mode we do a mov (rather than a movs)
- because we don't have the PSR bits set in the address. */
- asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, EXCEPTION_LR_REGNUM);
- break;
-
case ARM_FT_ISR:
case ARM_FT_FIQ:
asm_fprintf (f, "\tsubs\t%r, %r, #4\n", PC_REGNUM, LR_REGNUM);
@@ -8808,21 +10157,10 @@ arm_output_epilogue (rtx sibling)
break;
default:
- if (frame_pointer_needed)
- /* If we used the frame pointer then the return address
- will have been loaded off the stack directly into the
- PC, so there is no need to issue a MOV instruction
- here. */
- ;
- else if (current_function_pretend_args_size == 0
- && (saved_regs_mask & (1 << LR_REGNUM)))
- /* Similarly we may have been able to load LR into the PC
- even if we did not create a stack frame. */
- ;
- else if (TARGET_APCS_32)
- asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
+ if (arm_arch5 || arm_arch4t)
+ asm_fprintf (f, "\tbx\t%r\n", LR_REGNUM);
else
- asm_fprintf (f, "\tmovs\t%r, %r\n", PC_REGNUM, LR_REGNUM);
+ asm_fprintf (f, "\tmov\t%r, %r\n", PC_REGNUM, LR_REGNUM);
break;
}
@@ -8831,10 +10169,29 @@ arm_output_epilogue (rtx sibling)
static void
arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
- HOST_WIDE_INT frame_size)
+ HOST_WIDE_INT frame_size ATTRIBUTE_UNUSED)
{
+ arm_stack_offsets *offsets;
+
if (TARGET_THUMB)
{
+ int regno;
+
+ /* Emit any call-via-reg trampolines that are needed for v4t support
+ of call_reg and call_value_reg type insns. */
+ for (regno = 0; regno < LR_REGNUM; regno++)
+ {
+ rtx label = cfun->machine->call_via[regno];
+
+ if (label != NULL)
+ {
+ switch_to_section (function_section (current_function_decl));
+ targetm.asm_out.internal_label (asm_out_file, "L",
+ CODE_LABEL_NUMBER (label));
+ asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
+ }
+ }
+
/* ??? Probably not safe to set this here, since it assumes that a
function will be emitted as assembly immediately after we generate
RTL for it. This does not happen for inline functions. */
@@ -8843,13 +10200,12 @@ arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
else
{
/* We need to take into account any stack-frame rounding. */
- frame_size = arm_get_frame_size ();
+ offsets = arm_get_frame_offsets ();
- if (use_return_insn (FALSE, NULL)
- && return_used_this_function
- && (frame_size + current_function_outgoing_args_size) != 0
- && !frame_pointer_needed)
- abort ();
+ gcc_assert (!use_return_insn (FALSE, NULL)
+ || !return_used_this_function
+ || offsets->saved_regs == offsets->outgoing_args
+ || frame_pointer_needed);
/* Reset the ARM-specific per-function variables. */
after_arm_reorg = 0;
@@ -8861,7 +10217,7 @@ arm_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
semantics of the operation, we need to annotate the insn for the benefit
of DWARF2 frame unwind information. */
static rtx
-emit_multi_reg_push (int mask)
+emit_multi_reg_push (unsigned long mask)
{
int num_regs = 0;
int num_dwarf_regs;
@@ -8875,8 +10231,7 @@ emit_multi_reg_push (int mask)
if (mask & (1 << i))
num_regs++;
- if (num_regs == 0 || num_regs > 16)
- abort ();
+ gcc_assert (num_regs && num_regs <= 16);
/* We don't record the PC in the dwarf frame information. */
num_dwarf_regs = num_regs;
@@ -8888,7 +10243,7 @@ emit_multi_reg_push (int mask)
by the push_multi pattern in the arm.md file. The insn looks
something like this:
- (parallel [
+ (parallel [
(set (mem:BLK (pre_dec:BLK (reg:SI sp)))
(unspec:BLK [(reg:SI r4)] UNSPEC_PUSH_MULT))
(use (reg:SI 11 fp))
@@ -8904,7 +10259,7 @@ emit_multi_reg_push (int mask)
stack decrement per instruction. The RTL we generate for the note looks
something like this:
- (sequence [
+ (sequence [
(set (reg:SI sp) (plus:SI (reg:SI sp) (const_int -20)))
(set (mem:SI (reg:SI sp)) (reg:SI r4))
(set (mem:SI (plus:SI (reg:SI sp) (const_int 4))) (reg:SI fp))
@@ -8914,7 +10269,7 @@ emit_multi_reg_push (int mask)
This sequence is used both by the code to support stack unwinding for
exceptions handlers and the code to generate dwarf2 frame debugging. */
-
+
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_regs));
dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (num_dwarf_regs + 1));
dwarf_par_index = 1;
@@ -8927,9 +10282,9 @@ emit_multi_reg_push (int mask)
XVECEXP (par, 0, 0)
= gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (BLKmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
+ gen_frame_mem (BLKmode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
gen_rtx_UNSPEC (BLKmode,
gen_rtvec (1, reg),
UNSPEC_PUSH_MULT));
@@ -8937,7 +10292,7 @@ emit_multi_reg_push (int mask)
if (i != PC_REGNUM)
{
tmp = gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (SImode, stack_pointer_rtx),
+ gen_frame_mem (SImode, stack_pointer_rtx),
reg);
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (dwarf, 0, dwarf_par_index) = tmp;
@@ -8958,11 +10313,12 @@ emit_multi_reg_push (int mask)
if (i != PC_REGNUM)
{
- tmp = gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (SImode,
+ tmp
+ = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (SImode,
plus_constant (stack_pointer_rtx,
4 * j)),
- reg);
+ reg);
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (dwarf, 0, dwarf_par_index++) = tmp;
}
@@ -8972,20 +10328,32 @@ emit_multi_reg_push (int mask)
}
par = emit_insn (par);
-
- tmp = gen_rtx_SET (SImode,
+
+ tmp = gen_rtx_SET (VOIDmode,
stack_pointer_rtx,
- gen_rtx_PLUS (SImode,
- stack_pointer_rtx,
- GEN_INT (-4 * num_regs)));
+ plus_constant (stack_pointer_rtx, -4 * num_regs));
RTX_FRAME_RELATED_P (tmp) = 1;
XVECEXP (dwarf, 0, 0) = tmp;
-
+
REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
REG_NOTES (par));
return par;
}
+/* Calculate the size of the return value that is passed in registers. */
+static int
+arm_size_return_regs (void)
+{
+ enum machine_mode mode;
+
+ if (current_function_return_rtx != 0)
+ mode = GET_MODE (current_function_return_rtx);
+ else
+ mode = DECL_MODE (DECL_RESULT (current_function_decl));
+
+ return GET_MODE_SIZE (mode);
+}
+
static rtx
emit_sfm (int base_reg, int count)
{
@@ -8995,48 +10363,67 @@ emit_sfm (int base_reg, int count)
int i;
par = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
- dwarf = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (count));
+ dwarf = gen_rtx_SEQUENCE (VOIDmode, rtvec_alloc (count + 1));
reg = gen_rtx_REG (XFmode, base_reg++);
XVECEXP (par, 0, 0)
- = gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (BLKmode,
- gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
+ = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (BLKmode,
+ gen_rtx_PRE_DEC (BLKmode,
+ stack_pointer_rtx)),
gen_rtx_UNSPEC (BLKmode,
gen_rtvec (1, reg),
UNSPEC_PUSH_MULT));
- tmp
- = gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (XFmode,
- gen_rtx_PRE_DEC (BLKmode, stack_pointer_rtx)),
- reg);
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (XFmode, stack_pointer_rtx), reg);
RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, count - 1) = tmp;
-
+ XVECEXP (dwarf, 0, 1) = tmp;
+
for (i = 1; i < count; i++)
{
reg = gen_rtx_REG (XFmode, base_reg++);
XVECEXP (par, 0, i) = gen_rtx_USE (VOIDmode, reg);
- tmp = gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (XFmode,
- gen_rtx_PRE_DEC (BLKmode,
- stack_pointer_rtx)),
+ tmp = gen_rtx_SET (VOIDmode,
+ gen_frame_mem (XFmode,
+ plus_constant (stack_pointer_rtx,
+ i * 12)),
reg);
RTX_FRAME_RELATED_P (tmp) = 1;
- XVECEXP (dwarf, 0, count - i - 1) = tmp;
+ XVECEXP (dwarf, 0, i + 1) = tmp;
}
+ tmp = gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx, -12 * count));
+
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ XVECEXP (dwarf, 0, 0) = tmp;
+
par = emit_insn (par);
REG_NOTES (par) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
REG_NOTES (par));
return par;
}
+
+/* Return true if the current function needs to save/restore LR. */
+
+static bool
+thumb_force_lr_save (void)
+{
+ return !cfun->machine->lr_save_eliminated
+ && (!leaf_function_p ()
+ || thumb_far_jump_used_p ()
+ || regs_ever_live [LR_REGNUM]);
+}
+
+
/* Compute the distance from register FROM to register TO.
These can be the arg pointer (26), the soft frame pointer (25),
the stack pointer (13) or the hard frame pointer (11).
+ In thumb mode r7 is used as the soft frame pointer, if needed.
Typical stack layout looks like this:
old stack pointer -> | |
@@ -9059,7 +10446,7 @@ emit_sfm (int base_reg, int count)
| | \
| | local
| | variables
- | | /
+ locals base pointer -> | | /
--
| | \
| | outgoing
@@ -9076,60 +10463,131 @@ emit_sfm (int base_reg, int count)
The sign of the number returned reflects the direction of stack
growth, so the values are positive for all eliminations except
- from the soft frame pointer to the hard frame pointer. */
-unsigned int
-arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
+ from the soft frame pointer to the hard frame pointer.
+
+ SFP may point just inside the local variables block to ensure correct
+ alignment. */
+
+
+/* Calculate stack offsets. These are used to calculate register elimination
+ offsets and in prologue/epilogue code. */
+
+static arm_stack_offsets *
+arm_get_frame_offsets (void)
{
- unsigned int local_vars = arm_get_frame_size ();
- unsigned int outgoing_args = current_function_outgoing_args_size;
- unsigned int stack_frame;
- unsigned int call_saved_registers;
+ struct arm_stack_offsets *offsets;
unsigned long func_type;
-
- func_type = arm_current_func_type ();
+ int leaf;
+ int saved;
+ HOST_WIDE_INT frame_size;
- /* Volatile functions never return, so there is
- no need to save call saved registers. */
- call_saved_registers = 0;
- if (! IS_VOLATILE (func_type))
+ offsets = &cfun->machine->stack_offsets;
+
+ /* We need to know if we are a leaf function. Unfortunately, it
+ is possible to be called after start_sequence has been called,
+ which causes get_insns to return the insns for the sequence,
+ not the function, which will cause leaf_function_p to return
+ the incorrect result.
+
+ to know about leaf functions once reload has completed, and the
+ frame size cannot be changed after that time, so we can safely
+ use the cached value. */
+
+ if (reload_completed)
+ return offsets;
+
+ /* Initially this is the size of the local variables. It will translated
+ into an offset once we have determined the size of preceding data. */
+ frame_size = ROUND_UP_WORD (get_frame_size ());
+
+ leaf = leaf_function_p ();
+
+ /* Space for variadic functions. */
+ offsets->saved_args = current_function_pretend_args_size;
+
+ offsets->frame = offsets->saved_args + (frame_pointer_needed ? 4 : 0);
+
+ if (TARGET_ARM)
{
- unsigned int reg_mask;
- unsigned int reg;
+ unsigned int regno;
- /* Make sure that we compute which registers will be saved
- on the stack using the same algorithm that is used by
- the prologue creation code. */
- reg_mask = arm_compute_save_reg_mask ();
-
- /* Now count the number of bits set in save_reg_mask.
- If we have already counted the registers in the stack
- frame, do not count them again. Non call-saved registers
- might be saved in the call-save area of the stack, if
- doing so will preserve the stack's alignment. Hence we
- must count them here. For each set bit we need 4 bytes
- of stack space. */
- if (frame_pointer_needed)
- reg_mask &= 0x07ff;
- call_saved_registers += 4 * bit_count (reg_mask);
+ saved = bit_count (arm_compute_save_reg_mask ()) * 4;
- /* If the hard floating point registers are going to be
- used then they must be saved on the stack as well.
- Each register occupies 12 bytes of stack space. */
- for (reg = FIRST_ARM_FP_REGNUM; reg <= LAST_ARM_FP_REGNUM; reg++)
- if (regs_ever_live[reg] && ! call_used_regs[reg])
- call_saved_registers += 12;
+ /* We know that SP will be doubleword aligned on entry, and we must
+ preserve that condition at any subroutine call. We also require the
+ soft frame pointer to be doubleword aligned. */
if (TARGET_REALLY_IWMMXT)
- /* Check for the call-saved iWMMXt registers. */
- for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
- if (regs_ever_live[reg] && ! call_used_regs [reg])
- call_saved_registers += 8;
+ {
+ /* Check for the call-saved iWMMXt registers. */
+ for (regno = FIRST_IWMMXT_REGNUM;
+ regno <= LAST_IWMMXT_REGNUM;
+ regno++)
+ if (regs_ever_live [regno] && ! call_used_regs [regno])
+ saved += 8;
+ }
+
+ func_type = arm_current_func_type ();
+ if (! IS_VOLATILE (func_type))
+ {
+ /* Space for saved FPA registers. */
+ for (regno = FIRST_FPA_REGNUM; regno <= LAST_FPA_REGNUM; regno++)
+ if (regs_ever_live[regno] && ! call_used_regs[regno])
+ saved += 12;
+
+ /* Space for saved VFP registers. */
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ saved += arm_get_vfp_saved_size ();
+ }
+ }
+ else /* TARGET_THUMB */
+ {
+ saved = bit_count (thumb_compute_save_reg_mask ()) * 4;
+ if (TARGET_BACKTRACE)
+ saved += 16;
+ }
+
+ /* Saved registers include the stack frame. */
+ offsets->saved_regs = offsets->saved_args + saved;
+ offsets->soft_frame = offsets->saved_regs + CALLER_INTERWORKING_SLOT_SIZE;
+ /* A leaf function does not need any stack alignment if it has nothing
+ on the stack. */
+ if (leaf && frame_size == 0)
+ {
+ offsets->outgoing_args = offsets->soft_frame;
+ return offsets;
+ }
+
+ /* Ensure SFP has the correct alignment. */
+ if (ARM_DOUBLEWORD_ALIGN
+ && (offsets->soft_frame & 7))
+ offsets->soft_frame += 4;
+
+ offsets->locals_base = offsets->soft_frame + frame_size;
+ offsets->outgoing_args = (offsets->locals_base
+ + current_function_outgoing_args_size);
+
+ if (ARM_DOUBLEWORD_ALIGN)
+ {
+ /* Ensure SP remains doubleword aligned. */
+ if (offsets->outgoing_args & 7)
+ offsets->outgoing_args += 4;
+ gcc_assert (!(offsets->outgoing_args & 7));
}
- /* The stack frame contains 4 registers - the old frame pointer,
- the old stack pointer, the return address and PC of the start
- of the function. */
- stack_frame = frame_pointer_needed ? 16 : 0;
+ return offsets;
+}
+
+
+/* Calculate the relative offsets for the different stack pointers. Positive
+ offsets are in the direction of stack growth. */
+
+HOST_WIDE_INT
+arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
+{
+ arm_stack_offsets *offsets;
+
+ offsets = arm_get_frame_offsets ();
/* OK, now we have enough information to compute the distances.
There must be an entry in these switch tables for each pair
@@ -9146,29 +10604,27 @@ arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
case FRAME_POINTER_REGNUM:
/* This is the reverse of the soft frame pointer
to hard frame pointer elimination below. */
- if (call_saved_registers == 0 && stack_frame == 0)
- return 0;
- return (call_saved_registers + stack_frame - 4);
+ return offsets->soft_frame - offsets->saved_args;
case ARM_HARD_FRAME_POINTER_REGNUM:
/* If there is no stack frame then the hard
frame pointer and the arg pointer coincide. */
- if (stack_frame == 0 && call_saved_registers != 0)
+ if (offsets->frame == offsets->saved_regs)
return 0;
/* FIXME: Not sure about this. Maybe we should always return 0 ? */
return (frame_pointer_needed
- && current_function_needs_context
+ && cfun->static_chain_decl != NULL
&& ! cfun->machine->uses_anonymous_args) ? 4 : 0;
case STACK_POINTER_REGNUM:
/* If nothing has been pushed on the stack at all
then this will return -4. This *is* correct! */
- return call_saved_registers + stack_frame + local_vars + outgoing_args - 4;
+ return offsets->outgoing_args - (offsets->saved_args + 4);
default:
- abort ();
+ gcc_unreachable ();
}
- break;
+ gcc_unreachable ();
case FRAME_POINTER_REGNUM:
switch (to)
@@ -9181,17 +10637,16 @@ arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
stack frame. The soft frame pointer to the bottom entry
in the stack frame. If there is no stack frame at all,
then they are identical. */
- if (call_saved_registers == 0 && stack_frame == 0)
- return 0;
- return - (call_saved_registers + stack_frame - 4);
+
+ return offsets->frame - offsets->soft_frame;
case STACK_POINTER_REGNUM:
- return local_vars + outgoing_args;
+ return offsets->outgoing_args - offsets->soft_frame;
default:
- abort ();
+ gcc_unreachable ();
}
- break;
+ gcc_unreachable ();
default:
/* You cannot eliminate from the stack pointer.
@@ -9199,89 +10654,10 @@ arm_compute_initial_elimination_offset (unsigned int from, unsigned int to)
pointer to the stack pointer, but this will never
happen, since if a stack frame is not needed the
hard frame pointer will never be used. */
- abort ();
+ gcc_unreachable ();
}
}
-/* Calculate the size of the stack frame, taking into account any
- padding that is required to ensure stack-alignment. */
-HOST_WIDE_INT
-arm_get_frame_size (void)
-{
- int regno;
-
- int base_size = ROUND_UP_WORD (get_frame_size ());
- int entry_size = 0;
- unsigned long func_type = arm_current_func_type ();
- int leaf;
-
- if (! TARGET_ARM)
- abort();
-
- if (! TARGET_ATPCS)
- return base_size;
-
- /* We need to know if we are a leaf function. Unfortunately, it
- is possible to be called after start_sequence has been called,
- which causes get_insns to return the insns for the sequence,
- not the function, which will cause leaf_function_p to return
- the incorrect result.
-
- To work around this, we cache the computed frame size. This
- works because we will only be calling RTL expanders that need
- to know about leaf functions once reload has completed, and the
- frame size cannot be changed after that time, so we can safely
- use the cached value. */
-
- if (reload_completed)
- return cfun->machine->frame_size;
-
- leaf = leaf_function_p ();
-
- /* A leaf function does not need any stack alignment if it has nothing
- on the stack. */
- if (leaf && base_size == 0)
- {
- cfun->machine->frame_size = 0;
- return 0;
- }
-
- /* We know that SP will be word aligned on entry, and we must
- preserve that condition at any subroutine call. But those are
- the only constraints. */
-
- /* Space for variadic functions. */
- if (current_function_pretend_args_size)
- entry_size += current_function_pretend_args_size;
-
- /* Space for saved registers. */
- entry_size += bit_count (arm_compute_save_reg_mask ()) * 4;
-
- /* Space for saved FPA registers. */
- if (! IS_VOLATILE (func_type))
- {
- for (regno = FIRST_ARM_FP_REGNUM; regno <= LAST_ARM_FP_REGNUM; regno++)
- if (regs_ever_live[regno] && ! call_used_regs[regno])
- entry_size += 12;
- }
-
- if (TARGET_REALLY_IWMMXT)
- {
- /* Check for the call-saved iWMMXt registers. */
- for (regno = FIRST_IWMMXT_REGNUM; regno <= LAST_IWMMXT_REGNUM; regno++)
- if (regs_ever_live [regno] && ! call_used_regs [regno])
- entry_size += 8;
- }
-
- if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
- base_size += 4;
- if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
- abort ();
-
- cfun->machine->frame_size = base_size;
-
- return base_size;
-}
/* Generate the prologue instructions for entry into an ARM function. */
void
@@ -9295,7 +10671,9 @@ arm_expand_prologue (void)
unsigned long func_type;
int fp_offset = 0;
int saved_pretend_args = 0;
- unsigned int args_to_push;
+ int saved_regs = 0;
+ unsigned HOST_WIDE_INT args_to_push;
+ arm_stack_offsets *offsets;
func_type = arm_current_func_type ();
@@ -9305,7 +10683,7 @@ arm_expand_prologue (void)
/* Make a copy of c_f_p_a_s as we may need to modify it locally. */
args_to_push = current_function_pretend_args_size;
-
+
/* Compute which register we will have to save onto the stack. */
live_regs_mask = arm_compute_save_reg_mask ();
@@ -9325,7 +10703,7 @@ arm_expand_prologue (void)
stack decrement per function, and this is not it. If
this instruction is labeled as being part of the frame
creation sequence then dwarf2out_frame_debug_expr will
- abort when it encounters the assignment of IP to FP
+ die when it encounters the assignment of IP to FP
later on, since the use of SP here establishes SP as
the CFA register and not IP.
@@ -9339,7 +10717,7 @@ arm_expand_prologue (void)
To get around this need to find somewhere to store IP
whilst the frame is being created. We try the following
places in order:
-
+
1. The last argument register.
2. A slot on the stack above the frame. (This only
works if the function is not a varargs function).
@@ -9352,25 +10730,19 @@ arm_expand_prologue (void)
inherited from the caller. */
if (regs_ever_live[3] == 0)
- {
- insn = gen_rtx_REG (SImode, 3);
- insn = gen_rtx_SET (SImode, insn, ip_rtx);
- insn = emit_insn (insn);
- }
+ insn = emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
else if (args_to_push == 0)
{
rtx dwarf;
- insn = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx);
- insn = gen_rtx_MEM (SImode, insn);
- insn = gen_rtx_SET (VOIDmode, insn, ip_rtx);
- insn = emit_insn (insn);
+ insn = gen_rtx_PRE_DEC (SImode, stack_pointer_rtx);
+ insn = emit_set_insn (gen_frame_mem (SImode, insn), ip_rtx);
fp_offset = 4;
/* Just tell the dwarf backend that we adjusted SP. */
dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (SImode, stack_pointer_rtx,
- GEN_INT (-fp_offset)));
+ plus_constant (stack_pointer_rtx,
+ -fp_offset));
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
dwarf, REG_NOTES (insn));
@@ -9383,7 +10755,7 @@ arm_expand_prologue (void)
((0xf0 >> (args_to_push / 4)) & 0xf);
else
insn = emit_insn
- (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- args_to_push)));
RTX_FRAME_RELATED_P (insn) = 1;
@@ -9393,21 +10765,12 @@ arm_expand_prologue (void)
args_to_push = 0;
/* Now reuse r3 to preserve IP. */
- insn = gen_rtx_REG (SImode, 3);
- insn = gen_rtx_SET (SImode, insn, ip_rtx);
- (void) emit_insn (insn);
+ emit_set_insn (gen_rtx_REG (SImode, 3), ip_rtx);
}
}
- if (fp_offset)
- {
- insn = gen_rtx_PLUS (SImode, stack_pointer_rtx, GEN_INT (fp_offset));
- insn = gen_rtx_SET (SImode, ip_rtx, insn);
- }
- else
- insn = gen_movsi (ip_rtx, stack_pointer_rtx);
-
- insn = emit_insn (insn);
+ insn = emit_set_insn (ip_rtx,
+ plus_constant (stack_pointer_rtx, fp_offset));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9419,7 +10782,7 @@ arm_expand_prologue (void)
((0xf0 >> (args_to_push / 4)) & 0xf);
else
insn = emit_insn
- (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
+ (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (- args_to_push)));
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -9432,50 +10795,53 @@ arm_expand_prologue (void)
if ((func_type == ARM_FT_ISR || func_type == ARM_FT_FIQ)
&& (live_regs_mask & (1 << LR_REGNUM)) != 0
&& ! frame_pointer_needed)
- emit_insn (gen_rtx_SET (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- gen_rtx_PLUS (SImode,
- gen_rtx_REG (SImode, LR_REGNUM),
- GEN_INT (-4))));
+ {
+ rtx lr = gen_rtx_REG (SImode, LR_REGNUM);
+
+ emit_set_insn (lr, plus_constant (lr, -4));
+ }
if (live_regs_mask)
{
insn = emit_multi_reg_push (live_regs_mask);
+ saved_regs += bit_count (live_regs_mask) * 4;
RTX_FRAME_RELATED_P (insn) = 1;
}
if (TARGET_IWMMXT)
- for (reg = FIRST_IWMMXT_REGNUM; reg <= LAST_IWMMXT_REGNUM; reg++)
+ for (reg = LAST_IWMMXT_REGNUM; reg >= FIRST_IWMMXT_REGNUM; reg--)
if (regs_ever_live[reg] && ! call_used_regs [reg])
{
insn = gen_rtx_PRE_DEC (V2SImode, stack_pointer_rtx);
- insn = gen_rtx_MEM (V2SImode, insn);
- insn = emit_insn (gen_rtx_SET (VOIDmode, insn,
- gen_rtx_REG (V2SImode, reg)));
+ insn = gen_frame_mem (V2SImode, insn);
+ insn = emit_set_insn (insn, gen_rtx_REG (V2SImode, reg));
RTX_FRAME_RELATED_P (insn) = 1;
+ saved_regs += 8;
}
if (! IS_VOLATILE (func_type))
{
+ int start_reg;
+
/* Save any floating point call-saved registers used by this
function. */
if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
{
- for (reg = LAST_ARM_FP_REGNUM; reg >= FIRST_ARM_FP_REGNUM; reg--)
+ for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
if (regs_ever_live[reg] && !call_used_regs[reg])
{
insn = gen_rtx_PRE_DEC (XFmode, stack_pointer_rtx);
- insn = gen_rtx_MEM (XFmode, insn);
- insn = emit_insn (gen_rtx_SET (VOIDmode, insn,
- gen_rtx_REG (XFmode, reg)));
+ insn = gen_frame_mem (XFmode, insn);
+ insn = emit_set_insn (insn, gen_rtx_REG (XFmode, reg));
RTX_FRAME_RELATED_P (insn) = 1;
+ saved_regs += 12;
}
}
else
{
- int start_reg = LAST_ARM_FP_REGNUM;
+ start_reg = LAST_FPA_REGNUM;
- for (reg = LAST_ARM_FP_REGNUM; reg >= FIRST_ARM_FP_REGNUM; reg--)
+ for (reg = LAST_FPA_REGNUM; reg >= FIRST_FPA_REGNUM; reg--)
{
if (regs_ever_live[reg] && !call_used_regs[reg])
{
@@ -9483,6 +10849,7 @@ arm_expand_prologue (void)
{
insn = emit_sfm (reg, 4);
RTX_FRAME_RELATED_P (insn) = 1;
+ saved_regs += 48;
start_reg = reg - 1;
}
}
@@ -9492,6 +10859,7 @@ arm_expand_prologue (void)
{
insn = emit_sfm (reg + 1, start_reg - reg);
RTX_FRAME_RELATED_P (insn) = 1;
+ saved_regs += (start_reg - reg) * 12;
}
start_reg = reg - 1;
}
@@ -9500,9 +10868,29 @@ arm_expand_prologue (void)
if (start_reg != reg)
{
insn = emit_sfm (reg + 1, start_reg - reg);
+ saved_regs += (start_reg - reg) * 12;
RTX_FRAME_RELATED_P (insn) = 1;
}
}
+ if (TARGET_HARD_FLOAT && TARGET_VFP)
+ {
+ start_reg = FIRST_VFP_REGNUM;
+
+ for (reg = FIRST_VFP_REGNUM; reg < LAST_VFP_REGNUM; reg += 2)
+ {
+ if ((!regs_ever_live[reg] || call_used_regs[reg])
+ && (!regs_ever_live[reg + 1] || call_used_regs[reg + 1]))
+ {
+ if (start_reg != reg)
+ saved_regs += vfp_emit_fstmx (start_reg,
+ (reg - start_reg) / 2);
+ start_reg = reg + 2;
+ }
+ }
+ if (start_reg != reg)
+ saved_regs += vfp_emit_fstmx (start_reg,
+ (reg - start_reg) / 2);
+ }
}
if (frame_pointer_needed)
@@ -9511,7 +10899,7 @@ arm_expand_prologue (void)
insn = GEN_INT (-(4 + args_to_push + fp_offset));
insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, ip_rtx, insn));
RTX_FRAME_RELATED_P (insn) = 1;
-
+
if (IS_NESTED (func_type))
{
/* Recover the static chain register. */
@@ -9520,25 +10908,26 @@ arm_expand_prologue (void)
insn = gen_rtx_REG (SImode, 3);
else /* if (current_function_pretend_args_size == 0) */
{
- insn = gen_rtx_PLUS (SImode, hard_frame_pointer_rtx,
- GEN_INT (4));
- insn = gen_rtx_MEM (SImode, insn);
+ insn = plus_constant (hard_frame_pointer_rtx, 4);
+ insn = gen_frame_mem (SImode, insn);
}
- emit_insn (gen_rtx_SET (SImode, ip_rtx, insn));
+ emit_set_insn (ip_rtx, insn);
/* Add a USE to stop propagate_one_insn() from barfing. */
emit_insn (gen_prologue_use (ip_rtx));
}
}
- amount = GEN_INT (-(arm_get_frame_size ()
- + current_function_outgoing_args_size));
-
- if (amount != const0_rtx)
+ offsets = arm_get_frame_offsets ();
+ if (offsets->outgoing_args != offsets->saved_args + saved_regs)
{
/* This add can produce multiple insns for a large constant, so we
need to get tricky. */
rtx last = get_last_insn ();
+
+ amount = GEN_INT (offsets->saved_args + saved_regs
+ - offsets->outgoing_args);
+
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
amount));
do
@@ -9556,10 +10945,17 @@ arm_expand_prologue (void)
hard_frame_pointer_rtx));
}
+
+ if (flag_pic && arm_pic_register != INVALID_REGNUM)
+ arm_load_pic_register (0UL);
+
/* If we are profiling, make sure no instructions are scheduled before
the call to mcount. Similarly if the user has requested no
- scheduling in the prolog. */
- if (current_function_profile || TARGET_NO_SCHED_PRO)
+ scheduling in the prolog. Similarly if we want non-call exceptions
+ using the EABI unwinder, to prevent faulting instructions from being
+ swapped with a stack adjustment. */
+ if (current_function_profile || !TARGET_SCHED_PROLOG
+ || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions))
emit_insn (gen_blockage ());
/* If the link register is being kept alive, with the return address in it,
@@ -9596,7 +10992,7 @@ arm_print_operand (FILE *stream, rtx x, int code)
case '_':
fputs (user_label_prefix, stream);
return;
-
+
case '|':
fputs (REGISTER_PREFIX, stream);
return;
@@ -9604,8 +11000,17 @@ arm_print_operand (FILE *stream, rtx x, int code)
case '?':
if (arm_ccfsm_state == 3 || arm_ccfsm_state == 4)
{
- if (TARGET_THUMB || current_insn_predicate != NULL)
- abort ();
+ if (TARGET_THUMB)
+ {
+ output_operand_lossage ("predicated Thumb instruction");
+ break;
+ }
+ if (current_insn_predicate != NULL)
+ {
+ output_operand_lossage
+ ("predicated instruction in conditional sequence");
+ break;
+ }
fputs (arm_condition_codes[arm_current_cc], stream);
}
@@ -9614,7 +11019,10 @@ arm_print_operand (FILE *stream, rtx x, int code)
enum arm_cond_code code;
if (TARGET_THUMB)
- abort ();
+ {
+ output_operand_lossage ("predicated Thumb instruction");
+ break;
+ }
code = get_arm_condition_code (current_insn_predicate);
fputs (arm_condition_codes[code], stream);
@@ -9665,11 +11073,19 @@ arm_print_operand (FILE *stream, rtx x, int code)
case 'S':
{
HOST_WIDE_INT val;
- const char * shift = shift_op (x, &val);
+ const char *shift;
+
+ if (!shift_operator (x, SImode))
+ {
+ output_operand_lossage ("invalid shift operand");
+ break;
+ }
+
+ shift = shift_op (x, &val);
if (shift)
{
- fprintf (stream, ", %s ", shift_op (x, &val));
+ fprintf (stream, ", %s ", shift);
if (val == -1)
arm_print_operand (stream, XEXP (x, 1), 0);
else
@@ -9679,19 +11095,19 @@ arm_print_operand (FILE *stream, rtx x, int code)
return;
/* An explanation of the 'Q', 'R' and 'H' register operands:
-
+
In a pair of registers containing a DI or DF value the 'Q'
operand returns the register number of the register containing
the least significant part of the value. The 'R' operand returns
the register number of the register containing the most
significant part of the value.
-
+
The 'H' operand returns the higher of the two register numbers.
On a run where WORDS_BIG_ENDIAN is true the 'H' operand is the
same as the 'Q' operand, since the most significant part of the
value is held in the lower number register. The reverse is true
on systems where WORDS_BIG_ENDIAN is false.
-
+
The purpose of these operands is to distinguish between cases
where the endian-ness of the values is important (for example
when they are added together), and cases where the endian-ness
@@ -9706,25 +11122,37 @@ arm_print_operand (FILE *stream, rtx x, int code)
of the memory location is actually held in one of the registers
being overwritten by the load. */
case 'Q':
- if (REGNO (x) > LAST_ARM_REGNUM)
- abort ();
+ if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 1 : 0));
return;
case 'R':
- if (REGNO (x) > LAST_ARM_REGNUM)
- abort ();
+ if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
asm_fprintf (stream, "%r", REGNO (x) + (WORDS_BIG_ENDIAN ? 0 : 1));
return;
case 'H':
- if (REGNO (x) > LAST_ARM_REGNUM)
- abort ();
+ if (GET_CODE (x) != REG || REGNO (x) > LAST_ARM_REGNUM)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
asm_fprintf (stream, "%r", REGNO (x) + 1);
return;
case 'm':
- asm_fprintf (stream, "%r",
+ asm_fprintf (stream, "%r",
GET_CODE (XEXP (x, 0)) == REG
? REGNO (XEXP (x, 0)) : REGNO (XEXP (XEXP (x, 0), 0)));
return;
@@ -9739,16 +11167,30 @@ arm_print_operand (FILE *stream, rtx x, int code)
/* CONST_TRUE_RTX means always -- that's the default. */
if (x == const_true_rtx)
return;
-
+
+ if (!COMPARISON_P (x))
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
fputs (arm_condition_codes[get_arm_condition_code (x)],
stream);
return;
case 'D':
- /* CONST_TRUE_RTX means not always -- ie never. We shouldn't ever
+ /* CONST_TRUE_RTX means not always -- i.e. never. We shouldn't ever
want to do that. */
if (x == const_true_rtx)
- abort ();
+ {
+ output_operand_lossage ("instruction never exectued");
+ return;
+ }
+ if (!COMPARISON_P (x))
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
fputs (arm_condition_codes[ARM_INVERSE_CONDITION_CODE
(get_arm_condition_code (x))],
@@ -9764,8 +11206,8 @@ arm_print_operand (FILE *stream, rtx x, int code)
case 'X': /* Cirrus register in D mode. */
case 'Y': /* Cirrus register in FX mode. */
case 'Z': /* Cirrus register in DX mode. */
- if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
- abort ();
+ gcc_assert (GET_CODE (x) == REG
+ && REGNO_REG_CLASS (REGNO (x)) == CIRRUS_REGS);
fprintf (stream, "mv%s%s",
code == 'W' ? "f"
@@ -9780,7 +11222,10 @@ arm_print_operand (FILE *stream, rtx x, int code)
int mode = GET_MODE (x);
if (GET_CODE (x) != REG || REGNO_REG_CLASS (REGNO (x)) != CIRRUS_REGS)
- abort ();
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
fprintf (stream, "mv%s%s",
mode == DFmode ? "d"
@@ -9796,7 +11241,11 @@ arm_print_operand (FILE *stream, rtx x, int code)
|| REGNO (x) < FIRST_IWMMXT_GR_REGNUM
|| REGNO (x) > LAST_IWMMXT_GR_REGNUM)
/* Bad value for wCG register number. */
- abort ();
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
else
fprintf (stream, "%d", REGNO (x) - FIRST_IWMMXT_GR_REGNUM);
return;
@@ -9807,7 +11256,11 @@ arm_print_operand (FILE *stream, rtx x, int code)
|| INTVAL (x) < 0
|| INTVAL (x) >= 16)
/* Bad value for wC register number. */
- abort ();
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
else
{
static const char * wc_reg_names [16] =
@@ -9817,30 +11270,68 @@ arm_print_operand (FILE *stream, rtx x, int code)
"wCGR0", "wCGR1", "wCGR2", "wCGR3",
"wC12", "wC13", "wC14", "wC15"
};
-
+
fprintf (stream, wc_reg_names [INTVAL (x)]);
}
return;
+ /* Print a VFP double precision register name. */
+ case 'P':
+ {
+ int mode = GET_MODE (x);
+ int num;
+
+ if (mode != DImode && mode != DFmode)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
+ if (GET_CODE (x) != REG
+ || !IS_VFP_REGNUM (REGNO (x)))
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
+ num = REGNO(x) - FIRST_VFP_REGNUM;
+ if (num & 1)
+ {
+ output_operand_lossage ("invalid operand for code '%c'", code);
+ return;
+ }
+
+ fprintf (stream, "d%d", num >> 1);
+ }
+ return;
+
default:
if (x == 0)
- abort ();
+ {
+ output_operand_lossage ("missing operand");
+ return;
+ }
- if (GET_CODE (x) == REG)
- asm_fprintf (stream, "%r", REGNO (x));
- else if (GET_CODE (x) == MEM)
+ switch (GET_CODE (x))
{
+ case REG:
+ asm_fprintf (stream, "%r", REGNO (x));
+ break;
+
+ case MEM:
output_memory_reference_mode = GET_MODE (x);
output_address (XEXP (x, 0));
- }
- else if (GET_CODE (x) == CONST_DOUBLE)
- fprintf (stream, "#%s", fp_immediate_constant (x));
- else if (GET_CODE (x) == NEG)
- abort (); /* This should never happen now. */
- else
- {
+ break;
+
+ case CONST_DOUBLE:
+ fprintf (stream, "#%s", fp_immediate_constant (x));
+ break;
+
+ default:
+ gcc_assert (GET_CODE (x) != NEG);
fputc ('#', stream);
output_addr_const (stream, x);
+ break;
}
}
}
@@ -9874,12 +11365,11 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
return true;
}
- if (VECTOR_MODE_SUPPORTED_P (GET_MODE (x)))
+ if (arm_vector_mode_supported_p (GET_MODE (x)))
{
int i, units;
- if (GET_CODE (x) != CONST_VECTOR)
- abort ();
+ gcc_assert (GET_CODE (x) == CONST_VECTOR);
units = CONST_VECTOR_NUNITS (x);
@@ -9889,7 +11379,7 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
case V4HImode: size = 2; break;
case V8QImode: size = 1; break;
default:
- abort ();
+ gcc_unreachable ();
}
for (i = 0; i < units; i++)
@@ -9906,6 +11396,26 @@ arm_assemble_integer (rtx x, unsigned int size, int aligned_p)
return default_assemble_integer (x, size, aligned_p);
}
+
+
+/* Add a function to the list of static constructors. */
+
+static void
+arm_elf_asm_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
+{
+ if (!TARGET_AAPCS_BASED)
+ {
+ default_named_section_asm_out_constructor (symbol, priority);
+ return;
+ }
+
+ /* Put these in the .init_array section, using a special relocation. */
+ switch_to_section (ctors_section);
+ assemble_align (POINTER_SIZE);
+ fputs ("\t.word\t", asm_out_file);
+ output_addr_const (asm_out_file, symbol);
+ fputs ("(target1)\n", asm_out_file);
+}
#endif
/* A finite state machine takes care of noticing whether or not instructions
@@ -9967,8 +11477,7 @@ get_arm_condition_code (rtx comparison)
case CC_DLTUmode: code = ARM_CC;
dominance:
- if (comp_code != EQ && comp_code != NE)
- abort ();
+ gcc_assert (comp_code == EQ || comp_code == NE);
if (comp_code == EQ)
return ARM_INVERSE_CONDITION_CODE (code);
@@ -9981,7 +11490,7 @@ get_arm_condition_code (rtx comparison)
case EQ: return ARM_EQ;
case GE: return ARM_PL;
case LT: return ARM_MI;
- default: abort ();
+ default: gcc_unreachable ();
}
case CC_Zmode:
@@ -9989,7 +11498,7 @@ get_arm_condition_code (rtx comparison)
{
case NE: return ARM_NE;
case EQ: return ARM_EQ;
- default: abort ();
+ default: gcc_unreachable ();
}
case CC_Nmode:
@@ -9997,7 +11506,7 @@ get_arm_condition_code (rtx comparison)
{
case NE: return ARM_MI;
case EQ: return ARM_PL;
- default: abort ();
+ default: gcc_unreachable ();
}
case CCFPEmode:
@@ -10022,7 +11531,7 @@ get_arm_condition_code (rtx comparison)
/* UNEQ and LTGT do not have a representation. */
case UNEQ: /* Fall through. */
case LTGT: /* Fall through. */
- default: abort ();
+ default: gcc_unreachable ();
}
case CC_SWPmode:
@@ -10038,7 +11547,7 @@ get_arm_condition_code (rtx comparison)
case GTU: return ARM_CC;
case LEU: return ARM_CS;
case LTU: return ARM_HI;
- default: abort ();
+ default: gcc_unreachable ();
}
case CC_Cmode:
@@ -10046,9 +11555,9 @@ get_arm_condition_code (rtx comparison)
{
case LTU: return ARM_CS;
case GEU: return ARM_CC;
- default: abort ();
+ default: gcc_unreachable ();
}
-
+
case CCmode:
switch (comp_code)
{
@@ -10062,13 +11571,11 @@ get_arm_condition_code (rtx comparison)
case GTU: return ARM_HI;
case LEU: return ARM_LS;
case LTU: return ARM_CC;
- default: abort ();
+ default: gcc_unreachable ();
}
- default: abort ();
+ default: gcc_unreachable ();
}
-
- abort ();
}
void
@@ -10086,10 +11593,10 @@ arm_final_prescan_insn (rtx insn)
means that we have to grub around within the jump expression to find
out what the conditions are when the jump isn't taken. */
int jump_clobbers = 0;
-
+
/* If we start with a return insn, we only succeed if we find another one. */
int seeking_return = 0;
-
+
/* START_INSN will hold the insn from where we start looking. This is the
first insn after the following code_label if REVERSE is true. */
rtx start_insn = insn;
@@ -10146,12 +11653,11 @@ arm_final_prescan_insn (rtx insn)
return;
}
- if (arm_ccfsm_state != 0 && !reverse)
- abort ();
+ gcc_assert (!arm_ccfsm_state || reverse);
if (GET_CODE (insn) != JUMP_INSN)
return;
- /* This jump might be paralleled with a clobber of the condition codes
+ /* This jump might be paralleled with a clobber of the condition codes
the jump should always come first */
if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
body = XVECEXP (body, 0, 0);
@@ -10166,14 +11672,14 @@ arm_final_prescan_insn (rtx insn)
int then_not_else = TRUE;
rtx this_insn = start_insn, label = 0;
- /* If the jump cannot be done with one instruction, we cannot
+ /* If the jump cannot be done with one instruction, we cannot
conditionally execute the instruction in the inverse case. */
if (get_attr_conds (insn) == CONDS_JUMP_CLOB)
{
jump_clobbers = 1;
return;
}
-
+
/* Register the insn jumped to. */
if (reverse)
{
@@ -10195,7 +11701,7 @@ arm_final_prescan_insn (rtx insn)
then_not_else = FALSE;
}
else
- abort ();
+ gcc_unreachable ();
/* See how many insns this branch skips, and what kind of insns. If all
insns are okay, and the label or unconditional branch to the same
@@ -10231,8 +11737,8 @@ arm_final_prescan_insn (rtx insn)
case BARRIER:
/* Succeed if the following insn is the target label.
- Otherwise fail.
- If return insns are used then the last insn in a function
+ Otherwise fail.
+ If return insns are used then the last insn in a function
will be a barrier. */
this_insn = next_nonnote_insn (this_insn);
if (this_insn && this_insn == label)
@@ -10251,32 +11757,37 @@ arm_final_prescan_insn (rtx insn)
break;
case CALL_INSN:
- /* If using 32-bit addresses the cc is not preserved over
- calls. */
- if (TARGET_APCS_32)
+ /* The AAPCS says that conditional calls should not be
+ used since they make interworking inefficient (the
+ linker can't transform BL<cond> into BLX). That's
+ only a problem if the machine has BLX. */
+ if (arm_arch5)
{
- /* Succeed if the following insn is the target label,
- or if the following two insns are a barrier and
- the target label. */
- this_insn = next_nonnote_insn (this_insn);
- if (this_insn && GET_CODE (this_insn) == BARRIER)
- this_insn = next_nonnote_insn (this_insn);
+ fail = TRUE;
+ break;
+ }
+
+ /* Succeed if the following insn is the target label, or
+ if the following two insns are a barrier and the
+ target label. */
+ this_insn = next_nonnote_insn (this_insn);
+ if (this_insn && GET_CODE (this_insn) == BARRIER)
+ this_insn = next_nonnote_insn (this_insn);
- if (this_insn && this_insn == label
- && insns_skipped < max_insns_skipped)
+ if (this_insn && this_insn == label
+ && insns_skipped < max_insns_skipped)
+ {
+ if (jump_clobbers)
{
- if (jump_clobbers)
- {
- arm_ccfsm_state = 2;
- this_insn = next_nonnote_insn (this_insn);
- }
- else
- arm_ccfsm_state = 1;
- succeed = TRUE;
+ arm_ccfsm_state = 2;
+ this_insn = next_nonnote_insn (this_insn);
}
else
- fail = TRUE;
+ arm_ccfsm_state = 1;
+ succeed = TRUE;
}
+ else
+ fail = TRUE;
break;
case JUMP_INSN:
@@ -10299,7 +11810,7 @@ arm_final_prescan_insn (rtx insn)
else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
fail = TRUE;
}
- /* Fail if a conditional return is undesirable (eg on a
+ /* Fail if a conditional return is undesirable (e.g. on a
StrongARM), but still allow this if optimizing for size. */
else if (GET_CODE (scanbody) == RETURN
&& !use_return_insn (TRUE, NULL)
@@ -10323,7 +11834,7 @@ arm_final_prescan_insn (rtx insn)
}
}
else
- fail = TRUE; /* Unrecognized jump (eg epilogue). */
+ fail = TRUE; /* Unrecognized jump (e.g. epilogue). */
break;
@@ -10357,14 +11868,16 @@ arm_final_prescan_insn (rtx insn)
{
if ((!seeking_return) && (arm_ccfsm_state == 1 || reverse))
arm_target_label = CODE_LABEL_NUMBER (label);
- else if (seeking_return || arm_ccfsm_state == 2)
+ else
{
+ gcc_assert (seeking_return || arm_ccfsm_state == 2);
+
while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
{
this_insn = next_nonnote_insn (this_insn);
- if (this_insn && (GET_CODE (this_insn) == BARRIER
- || GET_CODE (this_insn) == CODE_LABEL))
- abort ();
+ gcc_assert (!this_insn
+ || (GET_CODE (this_insn) != BARRIER
+ && GET_CODE (this_insn) != CODE_LABEL));
}
if (!this_insn)
{
@@ -10376,13 +11889,10 @@ arm_final_prescan_insn (rtx insn)
}
arm_target_insn = this_insn;
}
- else
- abort ();
if (jump_clobbers)
{
- if (reverse)
- abort ();
- arm_current_cc =
+ gcc_assert (!reverse);
+ arm_current_cc =
get_arm_condition_code (XEXP (XEXP (XEXP (SET_SRC (body),
0), 0), 1));
if (GET_CODE (XEXP (XEXP (SET_SRC (body), 0), 0)) == AND)
@@ -10402,7 +11912,7 @@ arm_final_prescan_insn (rtx insn)
if (reverse || then_not_else)
arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
}
-
+
/* Restore recog_data (getting the attributes of other insns can
destroy this array, but final.c assumes that it remains intact
across this call; since the insn has been recognized already we
@@ -10412,13 +11922,15 @@ arm_final_prescan_insn (rtx insn)
}
/* Returns true if REGNO is a valid register
- for holding a quantity of tyoe MODE. */
+ for holding a quantity of type MODE. */
int
arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
{
if (GET_MODE_CLASS (mode) == MODE_CC)
- return regno == CC_REGNUM;
-
+ return (regno == CC_REGNUM
+ || (TARGET_HARD_FLOAT && TARGET_VFP
+ && regno == VFPCC_REGNUM));
+
if (TARGET_THUMB)
/* For the Thumb we only allow values bigger than SImode in
registers 0 - 6, so that there is always a second low
@@ -10427,7 +11939,8 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
start of an even numbered register pair. */
return (ARM_NUM_REGS (mode) < 2) || (regno < LAST_LO_REGNUM);
- if (IS_CIRRUS_REGNUM (regno))
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK
+ && IS_CIRRUS_REGNUM (regno))
/* We have outlawed SI values in Cirrus registers because they
reside in the lower 32 bits, but SF values reside in the
upper 32 bits. This causes gcc all sorts of grief. We can't
@@ -10435,26 +11948,44 @@ arm_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
get sign extended to 64bits-- aldyh. */
return (GET_MODE_CLASS (mode) == MODE_FLOAT) || (mode == DImode);
- if (IS_IWMMXT_GR_REGNUM (regno))
- return mode == SImode;
+ if (TARGET_HARD_FLOAT && TARGET_VFP
+ && IS_VFP_REGNUM (regno))
+ {
+ if (mode == SFmode || mode == SImode)
+ return TRUE;
- if (IS_IWMMXT_REGNUM (regno))
- return VALID_IWMMXT_REG_MODE (mode);
+ /* DFmode values are only valid in even register pairs. */
+ if (mode == DFmode)
+ return ((regno - FIRST_VFP_REGNUM) & 1) == 0;
+ return FALSE;
+ }
+ if (TARGET_REALLY_IWMMXT)
+ {
+ if (IS_IWMMXT_GR_REGNUM (regno))
+ return mode == SImode;
+
+ if (IS_IWMMXT_REGNUM (regno))
+ return VALID_IWMMXT_REG_MODE (mode);
+ }
+
+ /* We allow any value to be stored in the general registers.
+ Restrict doubleword quantities to even register pairs so that we can
+ use ldrd. */
if (regno <= LAST_ARM_REGNUM)
- /* We allow any value to be stored in the general registers. */
- return 1;
+ return !(TARGET_LDRD && GET_MODE_SIZE (mode) > 4 && (regno & 1) != 0);
- if ( regno == FRAME_POINTER_REGNUM
+ if (regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM)
/* We only allow integers in the fake hard registers. */
return GET_MODE_CLASS (mode) == MODE_INT;
/* The only registers left are the FPA registers
which we only allow to hold FP values. */
- return GET_MODE_CLASS (mode) == MODE_FLOAT
- && regno >= FIRST_ARM_FP_REGNUM
- && regno <= LAST_ARM_FP_REGNUM;
+ return (TARGET_HARD_FLOAT && TARGET_FPA
+ && GET_MODE_CLASS (mode) == MODE_FLOAT
+ && regno >= FIRST_FPA_REGNUM
+ && regno <= LAST_FPA_REGNUM);
}
int
@@ -10475,13 +12006,16 @@ arm_regno_class (int regno)
|| regno == FRAME_POINTER_REGNUM
|| regno == ARG_POINTER_REGNUM)
return GENERAL_REGS;
-
- if (regno == CC_REGNUM)
+
+ if (regno == CC_REGNUM || regno == VFPCC_REGNUM)
return NO_REGS;
if (IS_CIRRUS_REGNUM (regno))
return CIRRUS_REGS;
+ if (IS_VFP_REGNUM (regno))
+ return VFP_REGS;
+
if (IS_IWMMXT_REGNUM (regno))
return IWMMXT_REGS;
@@ -10510,13 +12044,13 @@ arm_debugger_arg_offset (int value, rtx addr)
an offset of 0 is correct. */
if (REGNO (addr) == (unsigned) HARD_FRAME_POINTER_REGNUM)
return 0;
-
+
/* If we are using the stack pointer to point at the
argument, then an offset of 0 is correct. */
if ((TARGET_THUMB || !frame_pointer_needed)
&& REGNO (addr) == SP_REGNUM)
return 0;
-
+
/* Oh dear. The argument is pointed to by a register rather
than being held in a register, or being stored at a known
offset from the frame pointer. Since GDB only understands
@@ -10526,12 +12060,12 @@ arm_debugger_arg_offset (int value, rtx addr)
looking to see where this register gets its value. If the
register is initialized from the frame pointer plus an offset
then we are in luck and we can continue, otherwise we give up.
-
+
This code is exercised by producing debugging information
for a function with arguments like this:
-
+
double func (double a, double b, int c, double d) {return d;}
-
+
Without this code the stab for parameter 'd' will be set to
an offset of 0 from the frame pointer, rather than 8. */
@@ -10546,10 +12080,10 @@ arm_debugger_arg_offset (int value, rtx addr)
a constant integer
then... */
-
+
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
- if ( GET_CODE (insn) == INSN
+ if ( GET_CODE (insn) == INSN
&& GET_CODE (PATTERN (insn)) == SET
&& REGNO (XEXP (PATTERN (insn), 0)) == REGNO (addr)
&& GET_CODE (XEXP (PATTERN (insn), 1)) == PLUS
@@ -10559,15 +12093,15 @@ arm_debugger_arg_offset (int value, rtx addr)
)
{
value = INTVAL (XEXP (XEXP (PATTERN (insn), 1), 1));
-
+
break;
}
}
-
+
if (value == 0)
{
debug_rtx (addr);
- warning ("unable to compute real location of stacked parameter");
+ warning (0, "unable to compute real location of stacked parameter");
value = 8; /* XXX magic hack */
}
@@ -10578,7 +12112,8 @@ arm_debugger_arg_offset (int value, rtx addr)
do \
{ \
if ((MASK) & insn_flags) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
+ lang_hooks.builtin_function ((NAME), (TYPE), (CODE), \
+ BUILT_IN_MD, NULL, NULL_TREE); \
} \
while (0)
@@ -10617,8 +12152,8 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN (ussubv4hi3, "wsubhus", WSUBUSH)
IWMMXT_BUILTIN (ussubv2si3, "wsubwus", WSUBUSW)
IWMMXT_BUILTIN (mulv4hi3, "wmulul", WMULUL)
- IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsh", WMULSH)
- IWMMXT_BUILTIN (umulv4hi3_highpart, "wmuluh", WMULUH)
+ IWMMXT_BUILTIN (smulv4hi3_highpart, "wmulsm", WMULSM)
+ IWMMXT_BUILTIN (umulv4hi3_highpart, "wmulum", WMULUM)
IWMMXT_BUILTIN (eqv8qi3, "wcmpeqb", WCMPEQB)
IWMMXT_BUILTIN (eqv4hi3, "wcmpeqh", WCMPEQH)
IWMMXT_BUILTIN (eqv2si3, "wcmpeqw", WCMPEQW)
@@ -10659,7 +12194,7 @@ static const struct builtin_description bdesc_2arg[] =
#define IWMMXT_BUILTIN2(code, builtin) \
{ FL_IWMMXT, CODE_FOR_##code, NULL, ARM_BUILTIN_##builtin, 0, 0 },
-
+
IWMMXT_BUILTIN2 (iwmmxt_wpackhss, WPACKHSS)
IWMMXT_BUILTIN2 (iwmmxt_wpackwss, WPACKWSS)
IWMMXT_BUILTIN2 (iwmmxt_wpackdss, WPACKDSS)
@@ -10677,13 +12212,13 @@ static const struct builtin_description bdesc_2arg[] =
IWMMXT_BUILTIN2 (lshrv2si3_di, WSRLW)
IWMMXT_BUILTIN2 (lshrv2si3, WSRLWI)
IWMMXT_BUILTIN2 (lshrdi3_di, WSRLD)
- IWMMXT_BUILTIN2 (lshrdi3, WSRLDI)
+ IWMMXT_BUILTIN2 (lshrdi3_iwmmxt, WSRLDI)
IWMMXT_BUILTIN2 (ashrv4hi3_di, WSRAH)
IWMMXT_BUILTIN2 (ashrv4hi3, WSRAHI)
IWMMXT_BUILTIN2 (ashrv2si3_di, WSRAW)
IWMMXT_BUILTIN2 (ashrv2si3, WSRAWI)
IWMMXT_BUILTIN2 (ashrdi3_di, WSRAD)
- IWMMXT_BUILTIN2 (ashrdi3, WSRADI)
+ IWMMXT_BUILTIN2 (ashrdi3_iwmmxt, WSRADI)
IWMMXT_BUILTIN2 (rorv4hi3_di, WRORH)
IWMMXT_BUILTIN2 (rorv4hi3, WRORHI)
IWMMXT_BUILTIN2 (rorv2si3_di, WRORW)
@@ -10726,6 +12261,10 @@ arm_init_iwmmxt_builtins (void)
size_t i;
tree endlink = void_list_node;
+ tree V2SI_type_node = build_vector_type_for_mode (intSI_type_node, V2SImode);
+ tree V4HI_type_node = build_vector_type_for_mode (intHI_type_node, V4HImode);
+ tree V8QI_type_node = build_vector_type_for_mode (intQI_type_node, V8QImode);
+
tree int_ftype_int
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, integer_type_node, endlink));
@@ -10940,7 +12479,7 @@ arm_init_iwmmxt_builtins (void)
break;
default:
- abort ();
+ gcc_unreachable ();
}
def_mbuiltin (d->mask, d->name, type, d->code);
@@ -11039,8 +12578,23 @@ arm_init_iwmmxt_builtins (void)
}
static void
+arm_init_tls_builtins (void)
+{
+ tree ftype;
+ tree nothrow = tree_cons (get_identifier ("nothrow"), NULL, NULL);
+ tree const_nothrow = tree_cons (get_identifier ("const"), NULL, nothrow);
+
+ ftype = build_function_type (ptr_type_node, void_list_node);
+ lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
+ ARM_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+ NULL, const_nothrow);
+}
+
+static void
arm_init_builtins (void)
{
+ arm_init_tls_builtins ();
+
if (TARGET_REALLY_IWMMXT)
arm_init_iwmmxt_builtins ();
}
@@ -11070,8 +12624,8 @@ arm_expand_binop_builtin (enum insn_code icode,
rtx pat;
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
@@ -11086,10 +12640,7 @@ arm_expand_binop_builtin (enum insn_code icode,
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
- /* In case the insn wants input operands in modes different from
- the result, abort. */
- if (GET_MODE (op0) != mode0 || GET_MODE (op1) != mode1)
- abort ();
+ gcc_assert (GET_MODE (op0) == mode0 && GET_MODE (op1) == mode1);
if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
op0 = copy_to_mode_reg (mode0, op0);
@@ -11111,7 +12662,7 @@ arm_expand_unop_builtin (enum insn_code icode,
{
rtx pat;
tree arg0 = TREE_VALUE (arglist);
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
@@ -11184,8 +12735,8 @@ arm_expand_builtin (tree exp,
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
mode0 = insn_data[icode].operand[1].mode;
mode1 = insn_data[icode].operand[2].mode;
@@ -11217,9 +12768,9 @@ arm_expand_builtin (tree exp,
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
tmode = insn_data[icode].operand[0].mode;
mode0 = insn_data[icode].operand[1].mode;
mode1 = insn_data[icode].operand[2].mode;
@@ -11248,14 +12799,14 @@ arm_expand_builtin (tree exp,
case ARM_BUILTIN_SETWCX:
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- emit_insn (gen_iwmmxt_tmcr (op0, op1));
+ op0 = force_reg (SImode, expand_normal (arg0));
+ op1 = expand_normal (arg1);
+ emit_insn (gen_iwmmxt_tmcr (op1, op0));
return 0;
case ARM_BUILTIN_GETWCX:
arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
target = gen_reg_rtx (SImode);
emit_insn (gen_iwmmxt_tmrc (target, op0));
return target;
@@ -11264,8 +12815,8 @@ arm_expand_builtin (tree exp,
icode = CODE_FOR_iwmmxt_wshufh;
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
tmode = insn_data[icode].operand[0].mode;
mode1 = insn_data[icode].operand[1].mode;
mode2 = insn_data[icode].operand[2].mode;
@@ -11319,9 +12870,9 @@ arm_expand_builtin (tree exp,
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
tmode = insn_data[icode].operand[0].mode;
mode0 = insn_data[icode].operand[1].mode;
mode1 = insn_data[icode].operand[2].mode;
@@ -11342,12 +12893,15 @@ arm_expand_builtin (tree exp,
return 0;
emit_insn (pat);
return target;
-
+
case ARM_BUILTIN_WZERO:
target = gen_reg_rtx (DImode);
emit_insn (gen_iwmmxt_clrdi (target));
return target;
+ case ARM_BUILTIN_THREAD_POINTER:
+ return arm_load_tp (target);
+
default:
break;
}
@@ -11364,42 +12918,11 @@ arm_expand_builtin (tree exp,
return NULL_RTX;
}
-/* Recursively search through all of the blocks in a function
- checking to see if any of the variables created in that
- function match the RTX called 'orig'. If they do then
- replace them with the RTX called 'new'. */
-static void
-replace_symbols_in_block (tree block, rtx orig, rtx new)
-{
- for (; block; block = BLOCK_CHAIN (block))
- {
- tree sym;
-
- if (!TREE_USED (block))
- continue;
-
- for (sym = BLOCK_VARS (block); sym; sym = TREE_CHAIN (sym))
- {
- if ( (DECL_NAME (sym) == 0 && TREE_CODE (sym) != TYPE_DECL)
- || DECL_IGNORED_P (sym)
- || TREE_CODE (sym) != VAR_DECL
- || DECL_EXTERNAL (sym)
- || !rtx_equal_p (DECL_RTL (sym), orig)
- )
- continue;
-
- SET_DECL_RTL (sym, new);
- }
-
- replace_symbols_in_block (BLOCK_SUBBLOCKS (block), orig, new);
- }
-}
-
/* Return the number (counting from 0) of
the least significant set bit in MASK. */
inline static int
-number_of_first_bit_set (int mask)
+number_of_first_bit_set (unsigned mask)
{
int bit;
@@ -11411,11 +12934,121 @@ number_of_first_bit_set (int mask)
return bit;
}
+/* Emit code to push or pop registers to or from the stack. F is the
+ assembly file. MASK is the registers to push or pop. PUSH is
+ nonzero if we should push, and zero if we should pop. For debugging
+ output, if pushing, adjust CFA_OFFSET by the amount of space added
+ to the stack. REAL_REGS should have the same number of bits set as
+ MASK, and will be used instead (in the same order) to describe which
+ registers were saved - this is used to mark the save slots when we
+ push high registers after moving them to low registers. */
+static void
+thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset,
+ unsigned long real_regs)
+{
+ int regno;
+ int lo_mask = mask & 0xFF;
+ int pushed_words = 0;
+
+ gcc_assert (mask);
+
+ if (lo_mask == 0 && !push && (mask & (1 << PC_REGNUM)))
+ {
+ /* Special case. Do not generate a POP PC statement here, do it in
+ thumb_exit() */
+ thumb_exit (f, -1);
+ return;
+ }
+
+ if (ARM_EABI_UNWIND_TABLES && push)
+ {
+ fprintf (f, "\t.save\t{");
+ for (regno = 0; regno < 15; regno++)
+ {
+ if (real_regs & (1 << regno))
+ {
+ if (real_regs & ((1 << regno) -1))
+ fprintf (f, ", ");
+ asm_fprintf (f, "%r", regno);
+ }
+ }
+ fprintf (f, "}\n");
+ }
+
+ fprintf (f, "\t%s\t{", push ? "push" : "pop");
+
+ /* Look at the low registers first. */
+ for (regno = 0; regno <= LAST_LO_REGNUM; regno++, lo_mask >>= 1)
+ {
+ if (lo_mask & 1)
+ {
+ asm_fprintf (f, "%r", regno);
+
+ if ((lo_mask & ~1) != 0)
+ fprintf (f, ", ");
+
+ pushed_words++;
+ }
+ }
+
+ if (push && (mask & (1 << LR_REGNUM)))
+ {
+ /* Catch pushing the LR. */
+ if (mask & 0xFF)
+ fprintf (f, ", ");
+
+ asm_fprintf (f, "%r", LR_REGNUM);
+
+ pushed_words++;
+ }
+ else if (!push && (mask & (1 << PC_REGNUM)))
+ {
+ /* Catch popping the PC. */
+ if (TARGET_INTERWORK || TARGET_BACKTRACE
+ || current_function_calls_eh_return)
+ {
+ /* The PC is never poped directly, instead
+ it is popped into r3 and then BX is used. */
+ fprintf (f, "}\n");
+
+ thumb_exit (f, -1);
+
+ return;
+ }
+ else
+ {
+ if (mask & 0xFF)
+ fprintf (f, ", ");
+
+ asm_fprintf (f, "%r", PC_REGNUM);
+ }
+ }
+
+ fprintf (f, "}\n");
+
+ if (push && pushed_words && dwarf2out_do_frame ())
+ {
+ char *l = dwarf2out_cfi_label ();
+ int pushed_mask = real_regs;
+
+ *cfa_offset += pushed_words * 4;
+ dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
+
+ pushed_words = 0;
+ pushed_mask = real_regs;
+ for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
+ {
+ if (pushed_mask & 1)
+ dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
+ }
+ }
+}
+
/* Generate code to return from a thumb function.
If 'reg_containing_return_addr' is -1, then the return address is
actually on the stack, at the stack pointer. */
static void
-thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
+thumb_exit (FILE *f, int reg_containing_return_addr)
{
unsigned regs_available_for_popping;
unsigned regs_to_pop;
@@ -11430,15 +13063,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
regs_to_pop = 0;
pops_needed = 0;
- /* There is an assumption here, that if eh_ofs is not NULL, the
- normal return address will have been pushed. */
- if (reg_containing_return_addr == -1 || eh_ofs)
+ if (reg_containing_return_addr == -1)
{
- /* When we are generating a return for __builtin_eh_return,
- reg_containing_return_addr must specify the return regno. */
- if (eh_ofs && reg_containing_return_addr == -1)
- abort ();
-
regs_to_pop |= 1 << LR_REGNUM;
++pops_needed;
}
@@ -11454,8 +13080,8 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
return. */
if (pops_needed == 0)
{
- if (eh_ofs)
- asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, REGNO (eh_ofs));
+ if (current_function_calls_eh_return)
+ asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
return;
@@ -11465,17 +13091,10 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
just pop the return address straight into the PC. */
else if (!TARGET_INTERWORK
&& !TARGET_BACKTRACE
- && !is_called_in_ARM_mode (current_function_decl))
+ && !is_called_in_ARM_mode (current_function_decl)
+ && !current_function_calls_eh_return)
{
- if (eh_ofs)
- {
- asm_fprintf (f, "\tadd\t%r, #4\n", SP_REGNUM);
- asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, REGNO (eh_ofs));
- asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
- }
- else
- asm_fprintf (f, "\tpop\t{%r}\n", PC_REGNUM);
-
+ asm_fprintf (f, "\tpop\t{%r}\n", PC_REGNUM);
return;
}
@@ -11484,11 +13103,10 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
/* If returning via __builtin_eh_return, the bottom three registers
all contain information needed for the return. */
- if (eh_ofs)
+ if (current_function_calls_eh_return)
size = 12;
else
{
-#ifdef RTX_CODE
/* If we can deduce the registers used from the function's
return value. This is more reliable that examining
regs_ever_live[] because that will be set if the register is
@@ -11498,7 +13116,6 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
if (current_function_return_rtx != 0)
mode = GET_MODE (current_function_return_rtx);
else
-#endif
mode = DECL_MODE (DECL_RESULT (current_function_decl));
size = GET_MODE_SIZE (mode);
@@ -11538,7 +13155,7 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
/* If we have any popping registers left over, remove them. */
if (available > 0)
regs_available_for_popping &= ~available;
-
+
/* Otherwise if we need another popping register we can use
the fourth argument register. */
else if (pops_needed)
@@ -11556,15 +13173,15 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
/* Register a4 is being used to hold part of the return value,
but we have dire need of a free, low register. */
restore_a4 = TRUE;
-
+
asm_fprintf (f, "\tmov\t%r, %r\n",IP_REGNUM, LAST_ARG_REGNUM);
}
-
+
if (reg_containing_return_addr != LAST_ARG_REGNUM)
{
/* The fourth argument register is available. */
regs_available_for_popping |= 1 << LAST_ARG_REGNUM;
-
+
--pops_needed;
}
}
@@ -11578,7 +13195,7 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
{
/* The return address was popped into the lowest numbered register. */
regs_to_pop &= ~(1 << LR_REGNUM);
-
+
reg_containing_return_addr =
number_of_first_bit_set (regs_available_for_popping);
@@ -11591,7 +13208,7 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
if (regs_available_for_popping)
{
int frame_pointer;
-
+
/* Work out which register currently contains the frame pointer. */
frame_pointer = number_of_first_bit_set (regs_available_for_popping);
@@ -11602,18 +13219,18 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
/* (Temporarily) remove it from the mask of popped registers. */
regs_available_for_popping &= ~(1 << frame_pointer);
regs_to_pop &= ~(1 << ARM_HARD_FRAME_POINTER_REGNUM);
-
+
if (regs_available_for_popping)
{
int stack_pointer;
-
+
/* We popped the stack pointer as well,
find the register that contains it. */
stack_pointer = number_of_first_bit_set (regs_available_for_popping);
/* Move it into the stack register. */
asm_fprintf (f, "\tmov\t%r, %r\n", SP_REGNUM, stack_pointer);
-
+
/* At this point we have popped all necessary registers, so
do not worry about restoring regs_available_for_popping
to its correct value:
@@ -11630,7 +13247,7 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
regs_available_for_popping |= (1 << frame_pointer);
}
}
-
+
/* If we still have registers left on the stack, but we no longer have
any registers into which we can pop them, then we must move the return
address into the link register and make available the register that
@@ -11638,10 +13255,10 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
if (regs_available_for_popping == 0 && pops_needed > 0)
{
regs_available_for_popping |= 1 << reg_containing_return_addr;
-
+
asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM,
reg_containing_return_addr);
-
+
reg_containing_return_addr = LR_REGNUM;
}
@@ -11651,7 +13268,7 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
{
int popped_into;
int move_to;
-
+
thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
regs_available_for_popping);
@@ -11666,13 +13283,13 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
--pops_needed;
}
-
+
/* If we still have not popped everything then we must have only
had one register available to us and we are now popping the SP. */
if (pops_needed > 0)
{
int popped_into;
-
+
thumb_pushpop (f, regs_available_for_popping, FALSE, NULL,
regs_available_for_popping);
@@ -11693,107 +13310,17 @@ thumb_exit (FILE *f, int reg_containing_return_addr, rtx eh_ofs)
asm_fprintf (f, "\tmov\t%r, %r\n", LR_REGNUM, LAST_ARG_REGNUM);
reg_containing_return_addr = LR_REGNUM;
}
-
+
asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
- if (eh_ofs)
- asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, REGNO (eh_ofs));
+ if (current_function_calls_eh_return)
+ asm_fprintf (f, "\tadd\t%r, %r\n", SP_REGNUM, ARM_EH_STACKADJ_REGNUM);
/* Return to caller. */
asm_fprintf (f, "\tbx\t%r\n", reg_containing_return_addr);
}
-/* Emit code to push or pop registers to or from the stack. F is the
- assembly file. MASK is the registers to push or pop. PUSH is
- non-zero if we should push, and zero if we should pop. For debugging
- output, if pushing, adjust CFA_OFFSET by the amount of space added
- to the stack. REAL_REGS should have the same number of bits set as
- MASK, and will be used instead (in the same order) to describe which
- registers were saved - this is used to mark the save slots when we
- push high registers after moving them to low registers. */
-static void
-thumb_pushpop (FILE *f, int mask, int push, int *cfa_offset, int real_regs)
-{
- int regno;
- int lo_mask = mask & 0xFF;
- int pushed_words = 0;
-
- if (lo_mask == 0 && !push && (mask & (1 << 15)))
- {
- /* Special case. Do not generate a POP PC statement here, do it in
- thumb_exit() */
- thumb_exit (f, -1, NULL_RTX);
- return;
- }
-
- fprintf (f, "\t%s\t{", push ? "push" : "pop");
-
- /* Look at the low registers first. */
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++, lo_mask >>= 1)
- {
- if (lo_mask & 1)
- {
- asm_fprintf (f, "%r", regno);
-
- if ((lo_mask & ~1) != 0)
- fprintf (f, ", ");
-
- pushed_words++;
- }
- }
-
- if (push && (mask & (1 << LR_REGNUM)))
- {
- /* Catch pushing the LR. */
- if (mask & 0xFF)
- fprintf (f, ", ");
-
- asm_fprintf (f, "%r", LR_REGNUM);
-
- pushed_words++;
- }
- else if (!push && (mask & (1 << PC_REGNUM)))
- {
- /* Catch popping the PC. */
- if (TARGET_INTERWORK || TARGET_BACKTRACE)
- {
- /* The PC is never poped directly, instead
- it is popped into r3 and then BX is used. */
- fprintf (f, "}\n");
-
- thumb_exit (f, -1, NULL_RTX);
-
- return;
- }
- else
- {
- if (mask & 0xFF)
- fprintf (f, ", ");
-
- asm_fprintf (f, "%r", PC_REGNUM);
- }
- }
-
- fprintf (f, "}\n");
-
- if (push && pushed_words && dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- int pushed_mask = real_regs;
-
- *cfa_offset += pushed_words * 4;
- dwarf2out_def_cfa (l, SP_REGNUM, *cfa_offset);
-
- pushed_words = 0;
- pushed_mask = real_regs;
- for (regno = 0; regno <= 14; regno++, pushed_mask >>= 1)
- {
- if (pushed_mask & 1)
- dwarf2out_reg_save (l, regno, 4 * pushed_words++ - *cfa_offset);
- }
- }
-}
void
thumb_final_prescan_insn (rtx insn)
@@ -11811,7 +13338,7 @@ thumb_shiftable_const (unsigned HOST_WIDE_INT val)
if (val == 0) /* XXX */
return 0;
-
+
for (i = 0; i < 25; i++)
if ((val & (mask << i)) == val)
return 1;
@@ -11821,14 +13348,14 @@ thumb_shiftable_const (unsigned HOST_WIDE_INT val)
/* Returns nonzero if the current function contains,
or might contain a far jump. */
-int
-thumb_far_jump_used_p (int in_prologue)
+static int
+thumb_far_jump_used_p (void)
{
rtx insn;
/* This test is only important for leaf functions. */
/* assert (!leaf_function_p ()); */
-
+
/* If we have already decided that far jumps may be used,
do not bother checking again, and always return true even if
it turns out that they are not being used. Once we have made
@@ -11840,7 +13367,7 @@ thumb_far_jump_used_p (int in_prologue)
/* If this function is not being called from the prologue/epilogue
generation code then it must be being called from the
INITIAL_ELIMINATION_OFFSET macro. */
- if (!in_prologue)
+ if (!(ARM_DOUBLEWORD_ALIGN || reload_completed))
{
/* In this case we know that we are being asked about the elimination
of the arg pointer register. If that register is not being used,
@@ -11859,7 +13386,10 @@ thumb_far_jump_used_p (int in_prologue)
A false negative will not result in bad code being generated, but it
will result in a needless push and pop of the link register. We
- hope that this does not occur too often. */
+ hope that this does not occur too often.
+
+ If we need doubleword stack alignment this could affect the other
+ elimination offsets so we can't risk getting it wrong. */
if (regs_ever_live [ARG_POINTER_REGNUM])
cfun->machine->arg_pointer_live = 1;
else if (!cfun->machine->arg_pointer_live)
@@ -11883,7 +13413,7 @@ thumb_far_jump_used_p (int in_prologue)
return 1;
}
}
-
+
return 0;
}
@@ -11891,14 +13421,13 @@ thumb_far_jump_used_p (int in_prologue)
int
is_called_in_ARM_mode (tree func)
{
- if (TREE_CODE (func) != FUNCTION_DECL)
- abort ();
+ gcc_assert (TREE_CODE (func) == FUNCTION_DECL);
- /* Ignore the problem about functions whoes address is taken. */
+ /* Ignore the problem about functions whose address is taken. */
if (TARGET_CALLEE_INTERWORKING && TREE_PUBLIC (func))
return TRUE;
-#ifdef ARM_PE
+#ifdef ARM_PE
return lookup_attribute ("interfacearm", DECL_ATTRIBUTES (func)) != NULL_TREE;
#else
return FALSE;
@@ -11910,11 +13439,10 @@ const char *
thumb_unexpanded_epilogue (void)
{
int regno;
- int live_regs_mask = 0;
+ unsigned long live_regs_mask = 0;
int high_regs_pushed = 0;
- int leaf_function = leaf_function_p ();
int had_to_push_lr;
- rtx eh_ofs = cfun->machine->eh_epilogue_sp_ofs;
+ int size;
if (return_used_this_function)
return "";
@@ -11922,16 +13450,17 @@ thumb_unexpanded_epilogue (void)
if (IS_NAKED (arm_current_func_type ()))
return "";
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- live_regs_mask |= 1 << regno;
+ live_regs_mask = thumb_compute_save_reg_mask ();
+ high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
- for (regno = 8; regno < 13; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- high_regs_pushed++;
+ /* If we can deduce the registers used from the function's return value.
+ This is more reliable that examining regs_ever_live[] because that
+ will be set if the register is ever used in the function, not just if
+ the register is used to hold a return value. */
+ size = arm_size_return_regs ();
/* The prolog may have pushed some high registers to use as
- work registers. eg the testsuite file:
+ work registers. e.g. the testsuite file:
gcc/testsuite/gcc/gcc.c-torture/execute/complex-2.c
compiles to produce:
push {r4, r5, r6, r7, lr}
@@ -11939,41 +13468,27 @@ thumb_unexpanded_epilogue (void)
mov r6, r8
push {r6, r7}
as part of the prolog. We have to undo that pushing here. */
-
+
if (high_regs_pushed)
{
- int mask = live_regs_mask;
+ unsigned long mask = live_regs_mask & 0xff;
int next_hi_reg;
- int size;
- int mode;
-
-#ifdef RTX_CODE
- /* If we can deduce the registers used from the function's return value.
- This is more reliable that examining regs_ever_live[] because that
- will be set if the register is ever used in the function, not just if
- the register is used to hold a return value. */
-
- if (current_function_return_rtx != 0)
- mode = GET_MODE (current_function_return_rtx);
- else
-#endif
- mode = DECL_MODE (DECL_RESULT (current_function_decl));
- size = GET_MODE_SIZE (mode);
-
- /* Unless we are returning a type of size > 12 register r3 is
- available. */
- if (size < 13)
+ /* The available low registers depend on the size of the value we are
+ returning. */
+ if (size <= 12)
mask |= 1 << 3;
+ if (size <= 8)
+ mask |= 1 << 2;
if (mask == 0)
/* Oh dear! We have no low registers into which we can pop
high registers! */
internal_error
("no low registers available for popping high registers");
-
+
for (next_hi_reg = 8; next_hi_reg < 13; next_hi_reg++)
- if (THUMB_REG_PUSHED_P (next_hi_reg))
+ if (live_regs_mask & (1 << next_hi_reg))
break;
while (high_regs_pushed)
@@ -12000,33 +13515,23 @@ thumb_unexpanded_epilogue (void)
{
asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", next_hi_reg,
regno);
-
+
for (next_hi_reg++; next_hi_reg < 13; next_hi_reg++)
- if (THUMB_REG_PUSHED_P (next_hi_reg))
+ if (live_regs_mask & (1 << next_hi_reg))
break;
}
}
}
+ live_regs_mask &= ~0x0f00;
}
- had_to_push_lr = (live_regs_mask || !leaf_function
- || thumb_far_jump_used_p (1));
-
- if (TARGET_BACKTRACE
- && ((live_regs_mask & 0xFF) == 0)
- && regs_ever_live [LAST_ARG_REGNUM] != 0)
- {
- /* The stack backtrace structure creation code had to
- push R7 in order to get a work register, so we pop
- it now. */
- live_regs_mask |= (1 << LAST_LO_REGNUM);
- }
-
+ had_to_push_lr = (live_regs_mask & (1 << LR_REGNUM)) != 0;
+ live_regs_mask &= 0xff;
+
if (current_function_pretend_args_size == 0 || TARGET_BACKTRACE)
{
- if (had_to_push_lr
- && !is_called_in_ARM_mode (current_function_decl)
- && !eh_ofs)
+ /* Pop the return address into the PC. */
+ if (had_to_push_lr)
live_regs_mask |= 1 << PC_REGNUM;
/* Either no argument registers were pushed or a backtrace
@@ -12035,43 +13540,54 @@ thumb_unexpanded_epilogue (void)
if (live_regs_mask)
thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
live_regs_mask);
-
- if (eh_ofs)
- thumb_exit (asm_out_file, 2, eh_ofs);
+
/* We have either just popped the return address into the
- PC or it is was kept in LR for the entire function or
- it is still on the stack because we do not want to
- return by doing a pop {pc}. */
- else if ((live_regs_mask & (1 << PC_REGNUM)) == 0)
- thumb_exit (asm_out_file,
- (had_to_push_lr
- && is_called_in_ARM_mode (current_function_decl)) ?
- -1 : LR_REGNUM, NULL_RTX);
+ PC or it is was kept in LR for the entire function. */
+ if (!had_to_push_lr)
+ thumb_exit (asm_out_file, LR_REGNUM);
}
else
{
/* Pop everything but the return address. */
- live_regs_mask &= ~(1 << PC_REGNUM);
-
if (live_regs_mask)
thumb_pushpop (asm_out_file, live_regs_mask, FALSE, NULL,
live_regs_mask);
if (had_to_push_lr)
- /* Get the return address into a temporary register. */
- thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL,
- 1 << LAST_ARG_REGNUM);
-
+ {
+ if (size > 12)
+ {
+ /* We have no free low regs, so save one. */
+ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", IP_REGNUM,
+ LAST_ARG_REGNUM);
+ }
+
+ /* Get the return address into a temporary register. */
+ thumb_pushpop (asm_out_file, 1 << LAST_ARG_REGNUM, 0, NULL,
+ 1 << LAST_ARG_REGNUM);
+
+ if (size > 12)
+ {
+ /* Move the return address to lr. */
+ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LR_REGNUM,
+ LAST_ARG_REGNUM);
+ /* Restore the low register. */
+ asm_fprintf (asm_out_file, "\tmov\t%r, %r\n", LAST_ARG_REGNUM,
+ IP_REGNUM);
+ regno = LR_REGNUM;
+ }
+ else
+ regno = LAST_ARG_REGNUM;
+ }
+ else
+ regno = LR_REGNUM;
+
/* Remove the argument registers that were pushed onto the stack. */
asm_fprintf (asm_out_file, "\tadd\t%r, %r, #%d\n",
SP_REGNUM, SP_REGNUM,
current_function_pretend_args_size);
-
- if (eh_ofs)
- thumb_exit (asm_out_file, 2, eh_ofs);
- else
- thumb_exit (asm_out_file,
- had_to_push_lr ? LAST_ARG_REGNUM : LR_REGNUM, NULL_RTX);
+
+ thumb_exit (asm_out_file, regno);
}
return "";
@@ -12084,7 +13600,7 @@ arm_init_machine_status (void)
struct machine_function *machine;
machine = (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
-#if ARM_FT_UNKNOWN != 0
+#if ARM_FT_UNKNOWN != 0
machine->func_type = ARM_FT_UNKNOWN;
#endif
return machine;
@@ -12098,14 +13614,7 @@ arm_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
if (count != 0)
return NULL_RTX;
- if (TARGET_APCS_32)
- return get_hard_reg_initial_val (Pmode, LR_REGNUM);
- else
- {
- rtx lr = gen_rtx_AND (Pmode, gen_rtx_REG (Pmode, LR_REGNUM),
- GEN_INT (RETURN_ADDR_MASK26));
- return get_func_hard_reg_initial_val (cfun, lr);
- }
+ return get_hard_reg_initial_val (Pmode, LR_REGNUM);
}
/* Do anything needed before RTL is emitted for each function. */
@@ -12114,106 +13623,86 @@ arm_init_expanders (void)
{
/* Arrange to initialize and mark the machine per-function status. */
init_machine_status = arm_init_machine_status;
-}
-
-HOST_WIDE_INT
-thumb_get_frame_size (void)
-{
- int regno;
- int base_size = ROUND_UP_WORD (get_frame_size ());
- int count_regs = 0;
- int entry_size = 0;
- int leaf;
-
- if (! TARGET_THUMB)
- abort ();
+ /* This is to stop the combine pass optimizing away the alignment
+ adjustment of va_arg. */
+ /* ??? It is claimed that this should not be necessary. */
+ if (cfun)
+ mark_reg_pointer (arg_pointer_rtx, PARM_BOUNDARY);
+}
- if (! TARGET_ATPCS)
- return base_size;
- /* We need to know if we are a leaf function. Unfortunately, it
- is possible to be called after start_sequence has been called,
- which causes get_insns to return the insns for the sequence,
- not the function, which will cause leaf_function_p to return
- the incorrect result.
-
- To work around this, we cache the computed frame size. This
- works because we will only be calling RTL expanders that need
- to know about leaf functions once reload has completed, and the
- frame size cannot be changed after that time, so we can safely
- use the cached value. */
+/* Like arm_compute_initial_elimination offset. Simpler because there
+ isn't an ABI specified frame pointer for Thumb. Instead, we set it
+ to point at the base of the local variables after static stack
+ space for a function has been allocated. */
- if (reload_completed)
- return cfun->machine->frame_size;
+HOST_WIDE_INT
+thumb_compute_initial_elimination_offset (unsigned int from, unsigned int to)
+{
+ arm_stack_offsets *offsets;
- leaf = leaf_function_p ();
+ offsets = arm_get_frame_offsets ();
- /* A leaf function does not need any stack alignment if it has nothing
- on the stack. */
- if (leaf && base_size == 0)
+ switch (from)
{
- cfun->machine->frame_size = 0;
- return 0;
- }
-
- /* We know that SP will be word aligned on entry, and we must
- preserve that condition at any subroutine call. But those are
- the only constraints. */
-
- /* Space for variadic functions. */
- if (current_function_pretend_args_size)
- entry_size += current_function_pretend_args_size;
+ case ARG_POINTER_REGNUM:
+ switch (to)
+ {
+ case STACK_POINTER_REGNUM:
+ return offsets->outgoing_args - offsets->saved_args;
- /* Space for pushed lo registers. */
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- count_regs++;
+ case FRAME_POINTER_REGNUM:
+ return offsets->soft_frame - offsets->saved_args;
- /* Space for backtrace structure. */
- if (TARGET_BACKTRACE)
- {
- if (count_regs == 0 && regs_ever_live[LAST_ARG_REGNUM] != 0)
- entry_size += 20;
- else
- entry_size += 16;
- }
+ case ARM_HARD_FRAME_POINTER_REGNUM:
+ return offsets->saved_regs - offsets->saved_args;
- if (count_regs || !leaf || thumb_far_jump_used_p (1))
- count_regs++; /* LR */
+ case THUMB_HARD_FRAME_POINTER_REGNUM:
+ return offsets->locals_base - offsets->saved_args;
- entry_size += count_regs * 4;
- count_regs = 0;
+ default:
+ gcc_unreachable ();
+ }
+ break;
- /* Space for pushed hi regs. */
- for (regno = 8; regno < 13; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- count_regs++;
+ case FRAME_POINTER_REGNUM:
+ switch (to)
+ {
+ case STACK_POINTER_REGNUM:
+ return offsets->outgoing_args - offsets->soft_frame;
- entry_size += count_regs * 4;
+ case ARM_HARD_FRAME_POINTER_REGNUM:
+ return offsets->saved_regs - offsets->soft_frame;
- if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
- base_size += 4;
- if ((entry_size + base_size + current_function_outgoing_args_size) & 7)
- abort ();
+ case THUMB_HARD_FRAME_POINTER_REGNUM:
+ return offsets->locals_base - offsets->soft_frame;
- cfun->machine->frame_size = base_size;
+ default:
+ gcc_unreachable ();
+ }
+ break;
- return base_size;
+ default:
+ gcc_unreachable ();
+ }
}
+
/* Generate the rest of a function's prologue. */
void
thumb_expand_prologue (void)
{
rtx insn, dwarf;
- HOST_WIDE_INT amount = (thumb_get_frame_size ()
- + current_function_outgoing_args_size);
+ HOST_WIDE_INT amount;
+ arm_stack_offsets *offsets;
unsigned long func_type;
+ int regno;
+ unsigned long live_regs_mask;
func_type = arm_current_func_type ();
-
+
/* Naked functions don't have prologues. */
if (IS_NAKED (func_type))
return;
@@ -12224,16 +13713,20 @@ thumb_expand_prologue (void)
return;
}
- if (frame_pointer_needed)
- {
- insn = emit_insn (gen_movsi (hard_frame_pointer_rtx, stack_pointer_rtx));
- RTX_FRAME_RELATED_P (insn) = 1;
- }
+ live_regs_mask = thumb_compute_save_reg_mask ();
+ /* Load the pic register before setting the frame pointer,
+ so we can use r7 as a temporary work register. */
+ if (flag_pic && arm_pic_register != INVALID_REGNUM)
+ arm_load_pic_register (live_regs_mask);
+
+ if (!frame_pointer_needed && CALLER_INTERWORKING_SLOT_SIZE > 0)
+ emit_move_insn (gen_rtx_REG (Pmode, ARM_HARD_FRAME_POINTER_REGNUM),
+ stack_pointer_rtx);
+ offsets = arm_get_frame_offsets ();
+ amount = offsets->outgoing_args - offsets->saved_regs;
if (amount)
{
- amount = ROUND_UP_WORD (amount);
-
if (amount < 512)
{
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
@@ -12242,7 +13735,6 @@ thumb_expand_prologue (void)
}
else
{
- int regno;
rtx reg;
/* The stack decrement is too big for an immediate value in a single
@@ -12260,17 +13752,17 @@ thumb_expand_prologue (void)
been pushed at the start of the prologue and so we can corrupt
it now. */
for (regno = LAST_ARG_REGNUM + 1; regno <= LAST_LO_REGNUM; regno++)
- if (THUMB_REG_PUSHED_P (regno)
+ if (live_regs_mask & (1 << regno)
&& !(frame_pointer_needed
&& (regno == THUMB_HARD_FRAME_POINTER_REGNUM)))
break;
if (regno > LAST_LO_REGNUM) /* Very unlikely. */
{
- rtx spare = gen_rtx (REG, SImode, IP_REGNUM);
+ rtx spare = gen_rtx_REG (SImode, IP_REGNUM);
/* Choose an arbitrary, non-argument low register. */
- reg = gen_rtx (REG, SImode, LAST_LO_REGNUM);
+ reg = gen_rtx_REG (SImode, LAST_LO_REGNUM);
/* Save it by copying it into a high, scratch register. */
emit_insn (gen_movsi (spare, reg));
@@ -12282,9 +13774,9 @@ thumb_expand_prologue (void)
insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, reg));
RTX_FRAME_RELATED_P (insn) = 1;
- dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
+ dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
- GEN_INT (- amount)));
+ -amount));
RTX_FRAME_RELATED_P (dwarf) = 1;
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
@@ -12292,7 +13784,7 @@ thumb_expand_prologue (void)
/* Restore the low register's original value. */
emit_insn (gen_movsi (reg, spare));
-
+
/* Emit a USE of the restored scratch register, so that flow
analysis will not consider the restore redundant. The
register won't be used again in this function and isn't
@@ -12301,16 +13793,16 @@ thumb_expand_prologue (void)
}
else
{
- reg = gen_rtx (REG, SImode, regno);
+ reg = gen_rtx_REG (SImode, regno);
emit_insn (gen_movsi (reg, GEN_INT (- amount)));
insn = emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx, reg));
RTX_FRAME_RELATED_P (insn) = 1;
- dwarf = gen_rtx_SET (SImode, stack_pointer_rtx,
+ dwarf = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
plus_constant (stack_pointer_rtx,
- GEN_INT (- amount)));
+ -amount));
RTX_FRAME_RELATED_P (dwarf) = 1;
REG_NOTES (insn)
= gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
@@ -12318,46 +13810,90 @@ thumb_expand_prologue (void)
}
}
}
-
- if (current_function_profile || TARGET_NO_SCHED_PRO)
+
+ if (frame_pointer_needed)
+ {
+ amount = offsets->outgoing_args - offsets->locals_base;
+
+ if (amount < 1024)
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ stack_pointer_rtx, GEN_INT (amount)));
+ else
+ {
+ emit_insn (gen_movsi (hard_frame_pointer_rtx, GEN_INT (amount)));
+ insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx,
+ stack_pointer_rtx));
+ dwarf = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
+ plus_constant (stack_pointer_rtx, amount));
+ RTX_FRAME_RELATED_P (dwarf) = 1;
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR, dwarf,
+ REG_NOTES (insn));
+ }
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* If we are profiling, make sure no instructions are scheduled before
+ the call to mcount. Similarly if the user has requested no
+ scheduling in the prolog. Similarly if we want non-call exceptions
+ using the EABI unwinder, to prevent faulting instructions from being
+ swapped with a stack adjustment. */
+ if (current_function_profile || !TARGET_SCHED_PROLOG
+ || (ARM_EABI_UNWIND_TABLES && flag_non_call_exceptions))
emit_insn (gen_blockage ());
+
+ cfun->machine->lr_save_eliminated = !thumb_force_lr_save ();
+ if (live_regs_mask & 0xff)
+ cfun->machine->lr_save_eliminated = 0;
+
+ /* If the link register is being kept alive, with the return address in it,
+ then make sure that it does not get reused by the ce2 pass. */
+ if (cfun->machine->lr_save_eliminated)
+ emit_insn (gen_prologue_use (gen_rtx_REG (SImode, LR_REGNUM)));
}
+
void
thumb_expand_epilogue (void)
{
- HOST_WIDE_INT amount = (thumb_get_frame_size ()
- + current_function_outgoing_args_size);
+ HOST_WIDE_INT amount;
+ arm_stack_offsets *offsets;
int regno;
/* Naked functions don't have prologues. */
if (IS_NAKED (arm_current_func_type ()))
return;
+ offsets = arm_get_frame_offsets ();
+ amount = offsets->outgoing_args - offsets->saved_regs;
+
if (frame_pointer_needed)
- emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
- else if (amount)
{
- amount = ROUND_UP_WORD (amount);
-
+ emit_insn (gen_movsi (stack_pointer_rtx, hard_frame_pointer_rtx));
+ amount = offsets->locals_base - offsets->saved_regs;
+ }
+
+ if (amount)
+ {
if (amount < 512)
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (amount)));
else
{
/* r3 is always free in the epilogue. */
- rtx reg = gen_rtx (REG, SImode, LAST_ARG_REGNUM);
+ rtx reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
emit_insn (gen_movsi (reg, GEN_INT (amount)));
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, reg));
}
}
-
+
/* Emit a USE (stack_pointer_rtx), so that
the stack adjustment will not be deleted. */
emit_insn (gen_prologue_use (stack_pointer_rtx));
- if (current_function_profile || TARGET_NO_SCHED_PRO)
+ if (current_function_profile || !TARGET_SCHED_PROLOG)
emit_insn (gen_blockage ());
/* Emit a clobber for each insn that will be restored in the epilogue,
@@ -12373,8 +13909,9 @@ thumb_expand_epilogue (void)
static void
thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
- int live_regs_mask = 0;
- int high_regs_pushed = 0;
+ unsigned long live_regs_mask = 0;
+ unsigned long l_mask;
+ unsigned high_regs_pushed = 0;
int cfa_offset = 0;
int regno;
@@ -12385,12 +13922,11 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
const char * name;
- if (GET_CODE (DECL_RTL (current_function_decl)) != MEM)
- abort ();
- if (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0)) != SYMBOL_REF)
- abort ();
+ gcc_assert (GET_CODE (DECL_RTL (current_function_decl)) == MEM);
+ gcc_assert (GET_CODE (XEXP (DECL_RTL (current_function_decl), 0))
+ == SYMBOL_REF);
name = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
-
+
/* Generate code sequence to switch us into Thumb mode. */
/* The .code 32 directive has already been emitted by
ASM_DECLARE_FUNCTION_NAME. */
@@ -12403,29 +13939,34 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
is called from a Thumb encoded function elsewhere in the
same file. Hence the definition of STUB_NAME here must
agree with the definition in gas/config/tc-arm.c. */
-
+
#define STUB_NAME ".real_start_of"
-
+
fprintf (f, "\t.code\t16\n");
#ifdef ARM_PE
if (arm_dllexport_name_p (name))
name = arm_strip_name_encoding (name);
-#endif
+#endif
asm_fprintf (f, "\t.globl %s%U%s\n", STUB_NAME, name);
fprintf (f, "\t.thumb_func\n");
asm_fprintf (f, "%s%U%s:\n", STUB_NAME, name);
}
-
+
if (current_function_pretend_args_size)
{
+ /* Output unwind directive for the stack adjustment. */
+ if (ARM_EABI_UNWIND_TABLES)
+ fprintf (f, "\t.pad #%d\n",
+ current_function_pretend_args_size);
+
if (cfun->machine->uses_anonymous_args)
{
int num_pushes;
-
+
fprintf (f, "\tpush\t{");
num_pushes = ARM_NUM_INTS (current_function_pretend_args_size);
-
+
for (regno = LAST_ARG_REGNUM + 1 - num_pushes;
regno <= LAST_ARG_REGNUM;
regno++)
@@ -12435,7 +13976,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
fprintf (f, "}\n");
}
else
- asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
+ asm_fprintf (f, "\tsub\t%r, %r, #%d\n",
SP_REGNUM, SP_REGNUM,
current_function_pretend_args_size);
@@ -12445,31 +13986,31 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
+
cfa_offset = cfa_offset + current_function_pretend_args_size;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
}
}
- for (regno = 0; regno <= LAST_LO_REGNUM; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- live_regs_mask |= 1 << regno;
-
- if (live_regs_mask || !leaf_function_p () || thumb_far_jump_used_p (1))
- live_regs_mask |= 1 << LR_REGNUM;
+ /* Get the registers we are going to push. */
+ live_regs_mask = thumb_compute_save_reg_mask ();
+ /* Extract a mask of the ones we can give to the Thumb's push instruction. */
+ l_mask = live_regs_mask & 0x40ff;
+ /* Then count how many other high registers will need to be pushed. */
+ high_regs_pushed = bit_count (live_regs_mask & 0x0f00);
if (TARGET_BACKTRACE)
{
- int offset;
- int work_register = 0;
- int wr;
-
+ unsigned offset;
+ unsigned work_register;
+
/* We have been asked to create a stack backtrace structure.
The code looks like this:
-
+
0 .align 2
0 func:
0 sub SP, #16 Reserve space for 4 registers.
- 2 push {R7} Get a work register.
+ 2 push {R7} Push low registers.
4 add R7, SP, #20 Get the stack pointer before the push.
6 str R7, [SP, #8] Store the stack pointer (before reserving the space).
8 mov R7, PC Get hold of the start of this code plus 12.
@@ -12481,25 +14022,11 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
20 add R7, SP, #16 Point at the start of the backtrace structure.
22 mov FP, R7 Put this value into the frame pointer. */
- if ((live_regs_mask & 0xFF) == 0)
- {
- /* See if the a4 register is free. */
+ work_register = thumb_find_work_register (live_regs_mask);
- if (regs_ever_live [LAST_ARG_REGNUM] == 0)
- work_register = LAST_ARG_REGNUM;
- else /* We must push a register of our own. */
- live_regs_mask |= (1 << LAST_LO_REGNUM);
- }
+ if (ARM_EABI_UNWIND_TABLES)
+ asm_fprintf (f, "\t.pad #16\n");
- if (work_register == 0)
- {
- /* Select a register from the list that will be pushed to
- use as our work register. */
- for (work_register = (LAST_LO_REGNUM + 1); work_register--;)
- if ((1 << work_register) & live_regs_mask)
- break;
- }
-
asm_fprintf
(f, "\tsub\t%r, %r, #16\t%@ Create stack backtrace structure\n",
SP_REGNUM, SP_REGNUM);
@@ -12507,26 +14034,28 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (dwarf2out_do_frame ())
{
char *l = dwarf2out_cfi_label ();
+
cfa_offset = cfa_offset + 16;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
}
- if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
-
- for (offset = 0, wr = 1 << 15; wr != 0; wr >>= 1)
- if (wr & live_regs_mask)
- offset += 4;
-
+ if (l_mask)
+ {
+ thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask);
+ offset = bit_count (l_mask) * UNITS_PER_WORD;
+ }
+ else
+ offset = 0;
+
asm_fprintf (f, "\tadd\t%r, %r, #%d\n", work_register, SP_REGNUM,
offset + 16 + current_function_pretend_args_size);
-
+
asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
offset + 4);
/* Make sure that the instruction fetching the PC is in the right place
to calculate "start of backtrace creation code + 12". */
- if (live_regs_mask)
+ if (l_mask)
{
asm_fprintf (f, "\tmov\t%r, %r\n", work_register, PC_REGNUM);
asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
@@ -12546,7 +14075,7 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
offset + 12);
}
-
+
asm_fprintf (f, "\tmov\t%r, %r\n", work_register, LR_REGNUM);
asm_fprintf (f, "\tstr\t%r, [%r, #%d]\n", work_register, SP_REGNUM,
offset + 8);
@@ -12555,67 +14084,68 @@ thumb_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
asm_fprintf (f, "\tmov\t%r, %r\t\t%@ Backtrace structure created\n",
ARM_HARD_FRAME_POINTER_REGNUM, work_register);
}
- else if (live_regs_mask)
- thumb_pushpop (f, live_regs_mask, 1, &cfa_offset, live_regs_mask);
-
- for (regno = 8; regno < 13; regno++)
- if (THUMB_REG_PUSHED_P (regno))
- high_regs_pushed++;
+ /* Optimization: If we are not pushing any low registers but we are going
+ to push some high registers then delay our first push. This will just
+ be a push of LR and we can combine it with the push of the first high
+ register. */
+ else if ((l_mask & 0xff) != 0
+ || (high_regs_pushed == 0 && l_mask))
+ thumb_pushpop (f, l_mask, 1, &cfa_offset, l_mask);
if (high_regs_pushed)
{
- int pushable_regs = 0;
- int mask = live_regs_mask & 0xff;
- int next_hi_reg;
+ unsigned pushable_regs;
+ unsigned next_hi_reg;
for (next_hi_reg = 12; next_hi_reg > LAST_LO_REGNUM; next_hi_reg--)
- if (THUMB_REG_PUSHED_P (next_hi_reg))
+ if (live_regs_mask & (1 << next_hi_reg))
break;
- pushable_regs = mask;
+ pushable_regs = l_mask & 0xff;
if (pushable_regs == 0)
- {
- /* Desperation time -- this probably will never happen. */
- if (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM))
- asm_fprintf (f, "\tmov\t%r, %r\n", IP_REGNUM, LAST_ARG_REGNUM);
- mask = 1 << LAST_ARG_REGNUM;
- }
+ pushable_regs = 1 << thumb_find_work_register (live_regs_mask);
while (high_regs_pushed > 0)
{
- int real_regs_mask = 0;
+ unsigned long real_regs_mask = 0;
- for (regno = LAST_LO_REGNUM; regno >= 0; regno--)
+ for (regno = LAST_LO_REGNUM; regno >= 0; regno --)
{
- if (mask & (1 << regno))
+ if (pushable_regs & (1 << regno))
{
asm_fprintf (f, "\tmov\t%r, %r\n", regno, next_hi_reg);
-
- high_regs_pushed--;
+
+ high_regs_pushed --;
real_regs_mask |= (1 << next_hi_reg);
-
+
if (high_regs_pushed)
{
- for (next_hi_reg--; next_hi_reg > LAST_LO_REGNUM;
- next_hi_reg--)
- if (THUMB_REG_PUSHED_P (next_hi_reg))
+ for (next_hi_reg --; next_hi_reg > LAST_LO_REGNUM;
+ next_hi_reg --)
+ if (live_regs_mask & (1 << next_hi_reg))
break;
}
else
{
- mask &= ~((1 << regno) - 1);
+ pushable_regs &= ~((1 << regno) - 1);
break;
}
}
}
- thumb_pushpop (f, mask, 1, &cfa_offset, real_regs_mask);
+ /* If we had to find a work register and we have not yet
+ saved the LR then add it to the list of regs to push. */
+ if (l_mask == (1 << LR_REGNUM))
+ {
+ thumb_pushpop (f, pushable_regs | (1 << LR_REGNUM),
+ 1, &cfa_offset,
+ real_regs_mask | (1 << LR_REGNUM));
+ l_mask = 0;
+ }
+ else
+ thumb_pushpop (f, pushable_regs, 1, &cfa_offset, real_regs_mask);
}
-
- if (pushable_regs == 0
- && (THUMB_REG_PUSHED_P (LAST_ARG_REGNUM)))
- asm_fprintf (f, "\tmov\t%r, %r\n", LAST_ARG_REGNUM, IP_REGNUM);
}
}
@@ -12630,22 +14160,18 @@ thumb_load_double_from_address (rtx *operands)
rtx offset;
rtx arg1;
rtx arg2;
-
- if (GET_CODE (operands[0]) != REG)
- abort ();
-
- if (GET_CODE (operands[1]) != MEM)
- abort ();
+
+ gcc_assert (GET_CODE (operands[0]) == REG);
+ gcc_assert (GET_CODE (operands[1]) == MEM);
/* Get the memory address. */
addr = XEXP (operands[1], 0);
-
+
/* Work out how the memory address is computed. */
switch (GET_CODE (addr))
{
case REG:
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[1], 0), 4));
+ operands[2] = adjust_address (operands[1], SImode, 4);
if (REGNO (operands[0]) == REGNO (addr))
{
@@ -12658,27 +14184,25 @@ thumb_load_double_from_address (rtx *operands)
output_asm_insn ("ldr\t%H0, %2", operands);
}
break;
-
+
case CONST:
/* Compute <address> + 4 for the high order load. */
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[1], 0), 4));
-
+ operands[2] = adjust_address (operands[1], SImode, 4);
+
output_asm_insn ("ldr\t%0, %1", operands);
output_asm_insn ("ldr\t%H0, %2", operands);
break;
-
+
case PLUS:
arg1 = XEXP (addr, 0);
arg2 = XEXP (addr, 1);
-
+
if (CONSTANT_P (arg1))
base = arg2, offset = arg1;
else
base = arg1, offset = arg2;
-
- if (GET_CODE (base) != REG)
- abort ();
+
+ gcc_assert (GET_CODE (base) == REG);
/* Catch the case of <address> = <reg> + <reg> */
if (GET_CODE (offset) == REG)
@@ -12686,17 +14210,17 @@ thumb_load_double_from_address (rtx *operands)
int reg_offset = REGNO (offset);
int reg_base = REGNO (base);
int reg_dest = REGNO (operands[0]);
-
+
/* Add the base and offset registers together into the
higher destination register. */
asm_fprintf (asm_out_file, "\tadd\t%r, %r, %r",
reg_dest + 1, reg_base, reg_offset);
-
+
/* Load the lower destination register from the address in
the higher destination register. */
asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #0]",
reg_dest, reg_dest + 1);
-
+
/* Load the higher destination register from its own address
plus 4. */
asm_fprintf (asm_out_file, "\tldr\t%r, [%r, #4]",
@@ -12705,9 +14229,8 @@ thumb_load_double_from_address (rtx *operands)
else
{
/* Compute <address> + 4 for the high order load. */
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[1], 0), 4));
-
+ operands[2] = adjust_address (operands[1], SImode, 4);
+
/* If the computed address is held in the low order register
then load the high order register first, otherwise always
load the low order register first. */
@@ -12727,18 +14250,16 @@ thumb_load_double_from_address (rtx *operands)
case LABEL_REF:
/* With no registers to worry about we can just load the value
directly. */
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[1], 0), 4));
-
+ operands[2] = adjust_address (operands[1], SImode, 4);
+
output_asm_insn ("ldr\t%H0, %2", operands);
output_asm_insn ("ldr\t%0, %1", operands);
break;
-
+
default:
- abort ();
- break;
+ gcc_unreachable ();
}
-
+
return "";
}
@@ -12779,21 +14300,52 @@ thumb_output_move_mem_multiple (int n, rtx *operands)
operands[4] = operands[5];
operands[5] = tmp;
}
-
+
output_asm_insn ("ldmia\t%1!, {%4, %5, %6}", operands);
output_asm_insn ("stmia\t%0!, {%4, %5, %6}", operands);
break;
default:
- abort ();
+ gcc_unreachable ();
+ }
+
+ return "";
+}
+
+/* Output a call-via instruction for thumb state. */
+const char *
+thumb_call_via_reg (rtx reg)
+{
+ int regno = REGNO (reg);
+ rtx *labelp;
+
+ gcc_assert (regno < LR_REGNUM);
+
+ /* If we are in the normal text section we can use a single instance
+ per compilation unit. If we are doing function sections, then we need
+ an entry per section, since we can't rely on reachability. */
+ if (in_section == text_section)
+ {
+ thumb_call_reg_needed = 1;
+
+ if (thumb_call_via_label[regno] == NULL)
+ thumb_call_via_label[regno] = gen_label_rtx ();
+ labelp = thumb_call_via_label + regno;
+ }
+ else
+ {
+ if (cfun->machine->call_via[regno] == NULL)
+ cfun->machine->call_via[regno] = gen_label_rtx ();
+ labelp = cfun->machine->call_via + regno;
}
+ output_asm_insn ("bl\t%a0", labelp);
return "";
}
/* Routines for generating rtl. */
void
-thumb_expand_movstrqi (rtx *operands)
+thumb_expand_movmemqi (rtx *operands)
{
rtx out = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
rtx in = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
@@ -12805,90 +14357,54 @@ thumb_expand_movstrqi (rtx *operands)
emit_insn (gen_movmem12b (out, in, out, in));
len -= 12;
}
-
+
if (len >= 8)
{
emit_insn (gen_movmem8b (out, in, out, in));
len -= 8;
}
-
+
if (len >= 4)
{
rtx reg = gen_reg_rtx (SImode);
- emit_insn (gen_movsi (reg, gen_rtx (MEM, SImode, in)));
- emit_insn (gen_movsi (gen_rtx (MEM, SImode, out), reg));
+ emit_insn (gen_movsi (reg, gen_rtx_MEM (SImode, in)));
+ emit_insn (gen_movsi (gen_rtx_MEM (SImode, out), reg));
len -= 4;
offset += 4;
}
-
+
if (len >= 2)
{
rtx reg = gen_reg_rtx (HImode);
- emit_insn (gen_movhi (reg, gen_rtx (MEM, HImode,
- plus_constant (in, offset))));
- emit_insn (gen_movhi (gen_rtx (MEM, HImode, plus_constant (out, offset)),
+ emit_insn (gen_movhi (reg, gen_rtx_MEM (HImode,
+ plus_constant (in, offset))));
+ emit_insn (gen_movhi (gen_rtx_MEM (HImode, plus_constant (out, offset)),
reg));
len -= 2;
offset += 2;
}
-
+
if (len)
{
rtx reg = gen_reg_rtx (QImode);
- emit_insn (gen_movqi (reg, gen_rtx (MEM, QImode,
- plus_constant (in, offset))));
- emit_insn (gen_movqi (gen_rtx (MEM, QImode, plus_constant (out, offset)),
+ emit_insn (gen_movqi (reg, gen_rtx_MEM (QImode,
+ plus_constant (in, offset))));
+ emit_insn (gen_movqi (gen_rtx_MEM (QImode, plus_constant (out, offset)),
reg));
}
}
-int
-thumb_cmp_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT
- && INTVAL (op) < 256
- && INTVAL (op) >= 0)
- || s_register_operand (op, mode));
-}
-
-int
-thumb_cmpneg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) < 0
- && INTVAL (op) > -256);
-}
-
-/* Return TRUE if a result can be stored in OP without clobbering the
- condition code register. Prior to reload we only accept a
- register. After reload we have to be able to handle memory as
- well, since a pseudo may not get a hard reg and reload cannot
- handle output-reloads on jump insns.
-
- We could possibly handle mem before reload as well, but that might
- complicate things with the need to handle increment
- side-effects. */
-
-int
-thumb_cbrch_target_operand (rtx op, enum machine_mode mode)
-{
- return (s_register_operand (op, mode)
- || ((reload_in_progress || reload_completed)
- && memory_operand (op, mode)));
-}
-
-/* Handle storing a half-word to memory during reload. */
void
thumb_reload_out_hi (rtx *operands)
{
emit_insn (gen_thumb_movhi_clobber (operands[0], operands[1], operands[2]));
}
-/* Handle reading a half-word from memory during reload. */
+/* Handle reading a half-word from memory during reload. */
void
thumb_reload_in_hi (rtx *operands ATTRIBUTE_UNUSED)
{
- abort ();
+ gcc_unreachable ();
}
/* Return the length of a function name prefix
@@ -12899,7 +14415,7 @@ arm_get_strip_length (int c)
switch (c)
{
ARM_NAME_ENCODING_LENGTHS
- default: return 0;
+ default: return 0;
}
}
@@ -12909,7 +14425,7 @@ const char *
arm_strip_name_encoding (const char *name)
{
int skip;
-
+
while ((skip = arm_get_strip_length (* name)))
name += skip;
@@ -12937,6 +14453,31 @@ arm_asm_output_labelref (FILE *stream, const char *name)
asm_fprintf (stream, "%U%s", name);
}
+static void
+arm_file_end (void)
+{
+ int regno;
+
+ if (! thumb_call_reg_needed)
+ return;
+
+ switch_to_section (text_section);
+ asm_fprintf (asm_out_file, "\t.code 16\n");
+ ASM_OUTPUT_ALIGN (asm_out_file, 1);
+
+ for (regno = 0; regno < LR_REGNUM; regno++)
+ {
+ rtx label = thumb_call_via_label[regno];
+
+ if (label != 0)
+ {
+ targetm.asm_out.internal_label (asm_out_file, "L",
+ CODE_LABEL_NUMBER (label));
+ asm_fprintf (asm_out_file, "\tbx\t%r\n", regno);
+ }
+ }
+}
+
rtx aof_pic_label;
#ifdef AOF_ASSEMBLER
@@ -12984,7 +14525,7 @@ aof_dump_pic_table (FILE *f)
PIC_OFFSET_TABLE_REGNUM,
PIC_OFFSET_TABLE_REGNUM);
fputs ("|x$adcons|\n", f);
-
+
for (chain = aof_pic_chain; chain; chain = chain->next)
{
fputs ("\tDCD\t", f);
@@ -12995,25 +14536,56 @@ aof_dump_pic_table (FILE *f)
int arm_text_section_count = 1;
-char *
-aof_text_section (void )
+/* A get_unnamed_section callback for switching to the text section. */
+
+static void
+aof_output_text_section_asm_op (const void *data ATTRIBUTE_UNUSED)
{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$code%d|, CODE, READONLY",
+ fprintf (asm_out_file, "\tAREA |C$$code%d|, CODE, READONLY",
arm_text_section_count++);
if (flag_pic)
- strcat (buf, ", PIC, REENTRANT");
- return buf;
+ fprintf (asm_out_file, ", PIC, REENTRANT");
+ fprintf (asm_out_file, "\n");
}
static int arm_data_section_count = 1;
-char *
-aof_data_section (void)
+/* A get_unnamed_section callback for switching to the data section. */
+
+static void
+aof_output_data_section_asm_op (const void *data ATTRIBUTE_UNUSED)
{
- static char buf[100];
- sprintf (buf, "\tAREA |C$$data%d|, DATA", arm_data_section_count++);
- return buf;
+ fprintf (asm_out_file, "\tAREA |C$$data%d|, DATA\n",
+ arm_data_section_count++);
+}
+
+/* Implement TARGET_ASM_INIT_SECTIONS.
+
+ AOF Assembler syntax is a nightmare when it comes to areas, since once
+ we change from one area to another, we can't go back again. Instead,
+ we must create a new area with the same attributes and add the new output
+ to that. Unfortunately, there is nothing we can do here to guarantee that
+ two areas with the same attributes will be linked adjacently in the
+ resulting executable, so we have to be careful not to do pc-relative
+ addressing across such boundaries. */
+
+static void
+aof_asm_init_sections (void)
+{
+ text_section = get_unnamed_section (SECTION_CODE,
+ aof_output_text_section_asm_op, NULL);
+ data_section = get_unnamed_section (SECTION_WRITE,
+ aof_output_data_section_asm_op, NULL);
+ readonly_data_section = text_section;
+}
+
+void
+zero_init_section (void)
+{
+ static int zero_init_count = 1;
+
+ fprintf (asm_out_file, "\tAREA |C$$zidata%d|,NOINIT\n", zero_init_count++);
+ in_section = NULL;
}
/* The AOF assembler is religiously strict about declarations of
@@ -13074,7 +14646,7 @@ aof_dump_imports (FILE *f)
automagically. */
if (arm_main_function)
{
- text_section ();
+ switch_to_section (text_section);
fputs ("\tIMPORT __main\n", f);
fputs ("\tDCD __main\n", f);
}
@@ -13125,7 +14697,7 @@ aof_file_start (void)
fputs ("__f5\tFN\t5\n", asm_out_file);
fputs ("__f6\tFN\t6\n", asm_out_file);
fputs ("__f7\tFN\t7\n", asm_out_file);
- text_section ();
+ switch_to_section (text_section);
}
static void
@@ -13133,67 +14705,12 @@ aof_file_end (void)
{
if (flag_pic)
aof_dump_pic_table (asm_out_file);
+ arm_file_end ();
aof_dump_imports (asm_out_file);
fputs ("\tEND\n", asm_out_file);
}
#endif /* AOF_ASSEMBLER */
-#ifdef OBJECT_FORMAT_ELF
-/* Switch to an arbitrary section NAME with attributes as specified
- by FLAGS. ALIGN specifies any known alignment requirements for
- the section; 0 if the default should be used.
-
- Differs from the default elf version only in the prefix character
- used before the section type. */
-
-static void
-arm_elf_asm_named_section (const char *name, unsigned int flags)
-{
- char flagchars[10], *f = flagchars;
-
- if (! named_section_first_declaration (name))
- {
- fprintf (asm_out_file, "\t.section\t%s\n", name);
- return;
- }
-
- if (!(flags & SECTION_DEBUG))
- *f++ = 'a';
- if (flags & SECTION_WRITE)
- *f++ = 'w';
- if (flags & SECTION_CODE)
- *f++ = 'x';
- if (flags & SECTION_SMALL)
- *f++ = 's';
- if (flags & SECTION_MERGE)
- *f++ = 'M';
- if (flags & SECTION_STRINGS)
- *f++ = 'S';
- if (flags & SECTION_TLS)
- *f++ = 'T';
- *f = '\0';
-
- fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
-
- if (!(flags & SECTION_NOTYPE))
- {
- const char *type;
-
- if (flags & SECTION_BSS)
- type = "nobits";
- else
- type = "progbits";
-
- fprintf (asm_out_file, ",%%%s", type);
-
- if (flags & SECTION_ENTSIZE)
- fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
- }
-
- putc ('\n', asm_out_file);
-}
-#endif
-
#ifndef ARM_PE
/* Symbols in the text segment can be accessed without indirecting via the
constant pool; it may take an extra binary operation, but this is still
@@ -13207,21 +14724,22 @@ arm_encode_section_info (tree decl, rtx rtl, int first)
/* This doesn't work with AOF syntax, since the string table may be in
a different AREA. */
#ifndef AOF_ASSEMBLER
- if (optimize > 0 && TREE_CONSTANT (decl)
- && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
+ if (optimize > 0 && TREE_CONSTANT (decl))
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
#endif
/* 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
or known to be defined in this file then encode a short call flag. */
- if (first && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
+ if (first && DECL_P (decl))
{
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_WEAK (decl))
arm_encode_call_attribute (decl, LONG_CALL_FLAG_CHAR);
else if (! TREE_PUBLIC (decl))
arm_encode_call_attribute (decl, SHORT_CALL_FLAG_CHAR);
}
+
+ default_encode_section_info (decl, rtl, first);
}
#endif /* !ARM_PE */
@@ -13247,6 +14765,7 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
{
static int thunk_label = 0;
char label[256];
+ char labelpc[256];
int mi_delta = delta;
const char *const mi_op = mi_delta < 0 ? "sub" : "add";
int shift = 0;
@@ -13261,6 +14780,23 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
fputs ("\tldr\tr12, ", file);
assemble_name (file, label);
fputc ('\n', file);
+ if (flag_pic)
+ {
+ /* If we are generating PIC, the ldr instruction below loads
+ "(target - 7) - .LTHUNKPCn" into r12. The pc reads as
+ the address of the add + 8, so we have:
+
+ r12 = (target - 7) - .LTHUNKPCn + (.LTHUNKPCn + 8)
+ = target + 1.
+
+ Note that we have "+ 1" because some versions of GNU ld
+ don't set the low bit of the result for R_ARM_REL32
+ relocations against thumb function symbols. */
+ ASM_GENERATE_INTERNAL_LABEL (labelpc, "LTHUNKPC", labelno);
+ assemble_name (file, labelpc);
+ fputs (":\n", file);
+ fputs ("\tadd\tr12, pc, r12\n", file);
+ }
}
while (mi_delta != 0)
{
@@ -13281,7 +14817,20 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
ASM_OUTPUT_ALIGN (file, 2);
assemble_name (file, label);
fputs (":\n", file);
- assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
+ if (flag_pic)
+ {
+ /* Output ".word .LTHUNKn-7-.LTHUNKPCn". */
+ rtx tem = XEXP (DECL_RTL (function), 0);
+ tem = gen_rtx_PLUS (GET_MODE (tem), tem, GEN_INT (-7));
+ tem = gen_rtx_MINUS (GET_MODE (tem),
+ tem,
+ gen_rtx_SYMBOL_REF (Pmode,
+ ggc_strdup (labelpc)));
+ assemble_integer (tem, 4, BITS_PER_WORD, 1);
+ }
+ else
+ /* Output ".word .LTHUNKn". */
+ assemble_integer (XEXP (DECL_RTL (function), 0), 4, BITS_PER_WORD, 1);
}
else
{
@@ -13299,15 +14848,14 @@ arm_emit_vector_const (FILE *file, rtx x)
int i;
const char * pattern;
- if (GET_CODE (x) != CONST_VECTOR)
- abort ();
+ gcc_assert (GET_CODE (x) == CONST_VECTOR);
switch (GET_MODE (x))
{
case V2SImode: pattern = "%08x"; break;
case V4HImode: pattern = "%04x"; break;
case V8QImode: pattern = "%02x"; break;
- default: abort ();
+ default: gcc_unreachable ();
}
fprintf (file, "0x");
@@ -13329,15 +14877,15 @@ arm_output_load_gr (rtx *operands)
rtx offset;
rtx wcgr;
rtx sum;
-
+
if (GET_CODE (operands [1]) != MEM
|| GET_CODE (sum = XEXP (operands [1], 0)) != PLUS
|| GET_CODE (reg = XEXP (sum, 0)) != REG
|| GET_CODE (offset = XEXP (sum, 1)) != CONST_INT
|| ((INTVAL (offset) < 1024) && (INTVAL (offset) > -1024)))
return "wldrw%?\t%0, %1";
-
- /* Fix up an out-of-range load of a GR register. */
+
+ /* Fix up an out-of-range load of a GR register. */
output_asm_insn ("str%?\t%0, [sp, #-4]!\t@ Start of GR load expansion", & reg);
wcgr = operands[0];
operands[0] = reg;
@@ -13350,3 +14898,740 @@ arm_output_load_gr (rtx *operands)
return "";
}
+
+/* Worker function for TARGET_SETUP_INCOMING_VARARGS.
+
+ On the ARM, PRETEND_SIZE is set in order to have the prologue push the last
+ named arg and all anonymous args onto the stack.
+ XXX I know the prologue shouldn't be pushing registers, but it is faster
+ that way. */
+
+static void
+arm_setup_incoming_varargs (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED,
+ int *pretend_size,
+ int second_time ATTRIBUTE_UNUSED)
+{
+ cfun->machine->uses_anonymous_args = 1;
+ if (cum->nregs < NUM_ARG_REGS)
+ *pretend_size = (NUM_ARG_REGS - cum->nregs) * UNITS_PER_WORD;
+}
+
+/* Return nonzero if the CONSUMER instruction (a store) does not need
+ PRODUCER's value to calculate the address. */
+
+int
+arm_no_early_store_addr_dep (rtx producer, rtx consumer)
+{
+ rtx value = PATTERN (producer);
+ rtx addr = PATTERN (consumer);
+
+ if (GET_CODE (value) == COND_EXEC)
+ value = COND_EXEC_CODE (value);
+ if (GET_CODE (value) == PARALLEL)
+ value = XVECEXP (value, 0, 0);
+ value = XEXP (value, 0);
+ if (GET_CODE (addr) == COND_EXEC)
+ addr = COND_EXEC_CODE (addr);
+ if (GET_CODE (addr) == PARALLEL)
+ addr = XVECEXP (addr, 0, 0);
+ addr = XEXP (addr, 0);
+
+ return !reg_overlap_mentioned_p (value, addr);
+}
+
+/* Return nonzero if the CONSUMER instruction (an ALU op) does not
+ have an early register shift value or amount dependency on the
+ result of PRODUCER. */
+
+int
+arm_no_early_alu_shift_dep (rtx producer, rtx consumer)
+{
+ rtx value = PATTERN (producer);
+ rtx op = PATTERN (consumer);
+ rtx early_op;
+
+ if (GET_CODE (value) == COND_EXEC)
+ value = COND_EXEC_CODE (value);
+ if (GET_CODE (value) == PARALLEL)
+ value = XVECEXP (value, 0, 0);
+ value = XEXP (value, 0);
+ if (GET_CODE (op) == COND_EXEC)
+ op = COND_EXEC_CODE (op);
+ if (GET_CODE (op) == PARALLEL)
+ op = XVECEXP (op, 0, 0);
+ op = XEXP (op, 1);
+
+ early_op = XEXP (op, 0);
+ /* This is either an actual independent shift, or a shift applied to
+ the first operand of another operation. We want the whole shift
+ operation. */
+ if (GET_CODE (early_op) == REG)
+ early_op = op;
+
+ return !reg_overlap_mentioned_p (value, early_op);
+}
+
+/* Return nonzero if the CONSUMER instruction (an ALU op) does not
+ have an early register shift value dependency on the result of
+ PRODUCER. */
+
+int
+arm_no_early_alu_shift_value_dep (rtx producer, rtx consumer)
+{
+ rtx value = PATTERN (producer);
+ rtx op = PATTERN (consumer);
+ rtx early_op;
+
+ if (GET_CODE (value) == COND_EXEC)
+ value = COND_EXEC_CODE (value);
+ if (GET_CODE (value) == PARALLEL)
+ value = XVECEXP (value, 0, 0);
+ value = XEXP (value, 0);
+ if (GET_CODE (op) == COND_EXEC)
+ op = COND_EXEC_CODE (op);
+ if (GET_CODE (op) == PARALLEL)
+ op = XVECEXP (op, 0, 0);
+ op = XEXP (op, 1);
+
+ early_op = XEXP (op, 0);
+
+ /* This is either an actual independent shift, or a shift applied to
+ the first operand of another operation. We want the value being
+ shifted, in either case. */
+ if (GET_CODE (early_op) != REG)
+ early_op = XEXP (early_op, 0);
+
+ return !reg_overlap_mentioned_p (value, early_op);
+}
+
+/* Return nonzero if the CONSUMER (a mul or mac op) does not
+ have an early register mult dependency on the result of
+ PRODUCER. */
+
+int
+arm_no_early_mul_dep (rtx producer, rtx consumer)
+{
+ rtx value = PATTERN (producer);
+ rtx op = PATTERN (consumer);
+
+ if (GET_CODE (value) == COND_EXEC)
+ value = COND_EXEC_CODE (value);
+ if (GET_CODE (value) == PARALLEL)
+ value = XVECEXP (value, 0, 0);
+ value = XEXP (value, 0);
+ if (GET_CODE (op) == COND_EXEC)
+ op = COND_EXEC_CODE (op);
+ if (GET_CODE (op) == PARALLEL)
+ op = XVECEXP (op, 0, 0);
+ op = XEXP (op, 1);
+
+ return (GET_CODE (op) == PLUS
+ && !reg_overlap_mentioned_p (value, XEXP (op, 0)));
+}
+
+
+/* We can't rely on the caller doing the proper promotion when
+ using APCS or ATPCS. */
+
+static bool
+arm_promote_prototypes (tree t ATTRIBUTE_UNUSED)
+{
+ return !TARGET_AAPCS_BASED;
+}
+
+
+/* AAPCS based ABIs use short enums by default. */
+
+static bool
+arm_default_short_enums (void)
+{
+ return TARGET_AAPCS_BASED && arm_abi != ARM_ABI_AAPCS_LINUX;
+}
+
+
+/* AAPCS requires that anonymous bitfields affect structure alignment. */
+
+static bool
+arm_align_anon_bitfield (void)
+{
+ return TARGET_AAPCS_BASED;
+}
+
+
+/* The generic C++ ABI says 64-bit (long long). The EABI says 32-bit. */
+
+static tree
+arm_cxx_guard_type (void)
+{
+ return TARGET_AAPCS_BASED ? integer_type_node : long_long_integer_type_node;
+}
+
+
+/* The EABI says test the least significant bit of a guard variable. */
+
+static bool
+arm_cxx_guard_mask_bit (void)
+{
+ return TARGET_AAPCS_BASED;
+}
+
+
+/* The EABI specifies that all array cookies are 8 bytes long. */
+
+static tree
+arm_get_cookie_size (tree type)
+{
+ tree size;
+
+ if (!TARGET_AAPCS_BASED)
+ return default_cxx_get_cookie_size (type);
+
+ size = build_int_cst (sizetype, 8);
+ return size;
+}
+
+
+/* The EABI says that array cookies should also contain the element size. */
+
+static bool
+arm_cookie_has_size (void)
+{
+ return TARGET_AAPCS_BASED;
+}
+
+
+/* The EABI says constructors and destructors should return a pointer to
+ the object constructed/destroyed. */
+
+static bool
+arm_cxx_cdtor_returns_this (void)
+{
+ return TARGET_AAPCS_BASED;
+}
+
+/* The EABI says that an inline function may never be the key
+ method. */
+
+static bool
+arm_cxx_key_method_may_be_inline (void)
+{
+ return !TARGET_AAPCS_BASED;
+}
+
+static void
+arm_cxx_determine_class_data_visibility (tree decl)
+{
+ if (!TARGET_AAPCS_BASED)
+ return;
+
+ /* In general, \S 3.2.5.5 of the ARM EABI requires that class data
+ is exported. However, on systems without dynamic vague linkage,
+ \S 3.2.5.6 says that COMDAT class data has hidden linkage. */
+ if (!TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P && DECL_COMDAT (decl))
+ DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+ else
+ DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+ DECL_VISIBILITY_SPECIFIED (decl) = 1;
+}
+
+static bool
+arm_cxx_class_data_always_comdat (void)
+{
+ /* \S 3.2.5.4 of the ARM C++ ABI says that class data only have
+ vague linkage if the class has no key function. */
+ return !TARGET_AAPCS_BASED;
+}
+
+
+/* The EABI says __aeabi_atexit should be used to register static
+ destructors. */
+
+static bool
+arm_cxx_use_aeabi_atexit (void)
+{
+ return TARGET_AAPCS_BASED;
+}
+
+
+void
+arm_set_return_address (rtx source, rtx scratch)
+{
+ arm_stack_offsets *offsets;
+ HOST_WIDE_INT delta;
+ rtx addr;
+ unsigned long saved_regs;
+
+ saved_regs = arm_compute_save_reg_mask ();
+
+ if ((saved_regs & (1 << LR_REGNUM)) == 0)
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
+ else
+ {
+ if (frame_pointer_needed)
+ addr = plus_constant(hard_frame_pointer_rtx, -4);
+ else
+ {
+ /* LR will be the first saved register. */
+ offsets = arm_get_frame_offsets ();
+ delta = offsets->outgoing_args - (offsets->frame + 4);
+
+
+ if (delta >= 4096)
+ {
+ emit_insn (gen_addsi3 (scratch, stack_pointer_rtx,
+ GEN_INT (delta & ~4095)));
+ addr = scratch;
+ delta &= 4095;
+ }
+ else
+ addr = stack_pointer_rtx;
+
+ addr = plus_constant (addr, delta);
+ }
+ emit_move_insn (gen_frame_mem (Pmode, addr), source);
+ }
+}
+
+
+void
+thumb_set_return_address (rtx source, rtx scratch)
+{
+ arm_stack_offsets *offsets;
+ HOST_WIDE_INT delta;
+ int reg;
+ rtx addr;
+ unsigned long mask;
+
+ emit_insn (gen_rtx_USE (VOIDmode, source));
+
+ mask = thumb_compute_save_reg_mask ();
+ if (mask & (1 << LR_REGNUM))
+ {
+ offsets = arm_get_frame_offsets ();
+
+ /* Find the saved regs. */
+ if (frame_pointer_needed)
+ {
+ delta = offsets->soft_frame - offsets->saved_args;
+ reg = THUMB_HARD_FRAME_POINTER_REGNUM;
+ }
+ else
+ {
+ delta = offsets->outgoing_args - offsets->saved_args;
+ reg = SP_REGNUM;
+ }
+ /* Allow for the stack frame. */
+ if (TARGET_BACKTRACE)
+ delta -= 16;
+ /* The link register is always the first saved register. */
+ delta -= 4;
+
+ /* Construct the address. */
+ addr = gen_rtx_REG (SImode, reg);
+ if ((reg != SP_REGNUM && delta >= 128)
+ || delta >= 1024)
+ {
+ emit_insn (gen_movsi (scratch, GEN_INT (delta)));
+ emit_insn (gen_addsi3 (scratch, scratch, stack_pointer_rtx));
+ addr = scratch;
+ }
+ else
+ addr = plus_constant (addr, delta);
+
+ emit_move_insn (gen_frame_mem (Pmode, addr), source);
+ }
+ else
+ emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source);
+}
+
+/* Implements target hook vector_mode_supported_p. */
+bool
+arm_vector_mode_supported_p (enum machine_mode mode)
+{
+ if ((mode == V2SImode)
+ || (mode == V4HImode)
+ || (mode == V8QImode))
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_SHIFT_TRUNCATION_MASK. SImode shifts use normal
+ ARM insns and therefore guarantee that the shift count is modulo 256.
+ DImode shifts (those implemented by lib1funcs.asm or by optabs.c)
+ guarantee no particular behavior for out-of-range counts. */
+
+static unsigned HOST_WIDE_INT
+arm_shift_truncation_mask (enum machine_mode mode)
+{
+ return mode == SImode ? 255 : 0;
+}
+
+
+/* Map internal gcc register numbers to DWARF2 register numbers. */
+
+unsigned int
+arm_dbx_register_number (unsigned int regno)
+{
+ if (regno < 16)
+ return regno;
+
+ /* TODO: Legacy targets output FPA regs as registers 16-23 for backwards
+ compatibility. The EABI defines them as registers 96-103. */
+ if (IS_FPA_REGNUM (regno))
+ return (TARGET_AAPCS_BASED ? 96 : 16) + regno - FIRST_FPA_REGNUM;
+
+ if (IS_VFP_REGNUM (regno))
+ return 64 + regno - FIRST_VFP_REGNUM;
+
+ if (IS_IWMMXT_GR_REGNUM (regno))
+ return 104 + regno - FIRST_IWMMXT_GR_REGNUM;
+
+ if (IS_IWMMXT_REGNUM (regno))
+ return 112 + regno - FIRST_IWMMXT_REGNUM;
+
+ gcc_unreachable ();
+}
+
+
+#ifdef TARGET_UNWIND_INFO
+/* Emit unwind directives for a store-multiple instruction. This should
+ only ever be generated by the function prologue code, so we expect it
+ to have a particular form. */
+
+static void
+arm_unwind_emit_stm (FILE * asm_out_file, rtx p)
+{
+ int i;
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT nregs;
+ int reg_size;
+ unsigned reg;
+ unsigned lastreg;
+ rtx e;
+
+ /* First insn will adjust the stack pointer. */
+ e = XVECEXP (p, 0, 0);
+ if (GET_CODE (e) != SET
+ || GET_CODE (XEXP (e, 0)) != REG
+ || REGNO (XEXP (e, 0)) != SP_REGNUM
+ || GET_CODE (XEXP (e, 1)) != PLUS)
+ abort ();
+
+ offset = -INTVAL (XEXP (XEXP (e, 1), 1));
+ nregs = XVECLEN (p, 0) - 1;
+
+ reg = REGNO (XEXP (XVECEXP (p, 0, 1), 1));
+ if (reg < 16)
+ {
+ /* The function prologue may also push pc, but not annotate it as it is
+ never restored. We turn this into a stack pointer adjustment. */
+ if (nregs * 4 == offset - 4)
+ {
+ fprintf (asm_out_file, "\t.pad #4\n");
+ offset -= 4;
+ }
+ reg_size = 4;
+ }
+ else if (IS_VFP_REGNUM (reg))
+ {
+ /* FPA register saves use an additional word. */
+ offset -= 4;
+ reg_size = 8;
+ }
+ else if (reg >= FIRST_FPA_REGNUM && reg <= LAST_FPA_REGNUM)
+ {
+ /* FPA registers are done differently. */
+ asm_fprintf (asm_out_file, "\t.save %r, %wd\n", reg, nregs);
+ return;
+ }
+ else
+ /* Unknown register type. */
+ abort ();
+
+ /* If the stack increment doesn't match the size of the saved registers,
+ something has gone horribly wrong. */
+ if (offset != nregs * reg_size)
+ abort ();
+
+ fprintf (asm_out_file, "\t.save {");
+
+ offset = 0;
+ lastreg = 0;
+ /* The remaining insns will describe the stores. */
+ for (i = 1; i <= nregs; i++)
+ {
+ /* Expect (set (mem <addr>) (reg)).
+ Where <addr> is (reg:SP) or (plus (reg:SP) (const_int)). */
+ e = XVECEXP (p, 0, i);
+ if (GET_CODE (e) != SET
+ || GET_CODE (XEXP (e, 0)) != MEM
+ || GET_CODE (XEXP (e, 1)) != REG)
+ abort ();
+
+ reg = REGNO (XEXP (e, 1));
+ if (reg < lastreg)
+ abort ();
+
+ if (i != 1)
+ fprintf (asm_out_file, ", ");
+ /* We can't use %r for vfp because we need to use the
+ double precision register names. */
+ if (IS_VFP_REGNUM (reg))
+ asm_fprintf (asm_out_file, "d%d", (reg - FIRST_VFP_REGNUM) / 2);
+ else
+ asm_fprintf (asm_out_file, "%r", reg);
+
+#ifdef ENABLE_CHECKING
+ /* Check that the addresses are consecutive. */
+ e = XEXP (XEXP (e, 0), 0);
+ if (GET_CODE (e) == PLUS)
+ {
+ offset += reg_size;
+ if (GET_CODE (XEXP (e, 0)) != REG
+ || REGNO (XEXP (e, 0)) != SP_REGNUM
+ || GET_CODE (XEXP (e, 1)) != CONST_INT
+ || offset != INTVAL (XEXP (e, 1)))
+ abort ();
+ }
+ else if (i != 1
+ || GET_CODE (e) != REG
+ || REGNO (e) != SP_REGNUM)
+ abort ();
+#endif
+ }
+ fprintf (asm_out_file, "}\n");
+}
+
+/* Emit unwind directives for a SET. */
+
+static void
+arm_unwind_emit_set (FILE * asm_out_file, rtx p)
+{
+ rtx e0;
+ rtx e1;
+
+ e0 = XEXP (p, 0);
+ e1 = XEXP (p, 1);
+ switch (GET_CODE (e0))
+ {
+ case MEM:
+ /* Pushing a single register. */
+ if (GET_CODE (XEXP (e0, 0)) != PRE_DEC
+ || GET_CODE (XEXP (XEXP (e0, 0), 0)) != REG
+ || REGNO (XEXP (XEXP (e0, 0), 0)) != SP_REGNUM)
+ abort ();
+
+ asm_fprintf (asm_out_file, "\t.save ");
+ if (IS_VFP_REGNUM (REGNO (e1)))
+ asm_fprintf(asm_out_file, "{d%d}\n",
+ (REGNO (e1) - FIRST_VFP_REGNUM) / 2);
+ else
+ asm_fprintf(asm_out_file, "{%r}\n", REGNO (e1));
+ break;
+
+ case REG:
+ if (REGNO (e0) == SP_REGNUM)
+ {
+ /* A stack increment. */
+ if (GET_CODE (e1) != PLUS
+ || GET_CODE (XEXP (e1, 0)) != REG
+ || REGNO (XEXP (e1, 0)) != SP_REGNUM
+ || GET_CODE (XEXP (e1, 1)) != CONST_INT)
+ abort ();
+
+ asm_fprintf (asm_out_file, "\t.pad #%wd\n",
+ -INTVAL (XEXP (e1, 1)));
+ }
+ else if (REGNO (e0) == HARD_FRAME_POINTER_REGNUM)
+ {
+ HOST_WIDE_INT offset;
+ unsigned reg;
+
+ if (GET_CODE (e1) == PLUS)
+ {
+ if (GET_CODE (XEXP (e1, 0)) != REG
+ || GET_CODE (XEXP (e1, 1)) != CONST_INT)
+ abort ();
+ reg = REGNO (XEXP (e1, 0));
+ offset = INTVAL (XEXP (e1, 1));
+ asm_fprintf (asm_out_file, "\t.setfp %r, %r, #%wd\n",
+ HARD_FRAME_POINTER_REGNUM, reg,
+ INTVAL (XEXP (e1, 1)));
+ }
+ else if (GET_CODE (e1) == REG)
+ {
+ reg = REGNO (e1);
+ asm_fprintf (asm_out_file, "\t.setfp %r, %r\n",
+ HARD_FRAME_POINTER_REGNUM, reg);
+ }
+ else
+ abort ();
+ }
+ else if (GET_CODE (e1) == REG && REGNO (e1) == SP_REGNUM)
+ {
+ /* Move from sp to reg. */
+ asm_fprintf (asm_out_file, "\t.movsp %r\n", REGNO (e0));
+ }
+ else if (GET_CODE (e1) == PLUS
+ && GET_CODE (XEXP (e1, 0)) == REG
+ && REGNO (XEXP (e1, 0)) == SP_REGNUM
+ && GET_CODE (XEXP (e1, 1)) == CONST_INT)
+ {
+ /* Set reg to offset from sp. */
+ asm_fprintf (asm_out_file, "\t.movsp %r, #%d\n",
+ REGNO (e0), (int)INTVAL(XEXP (e1, 1)));
+ }
+ else
+ abort ();
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+
+/* Emit unwind directives for the given insn. */
+
+static void
+arm_unwind_emit (FILE * asm_out_file, rtx insn)
+{
+ rtx pat;
+
+ if (!ARM_EABI_UNWIND_TABLES)
+ return;
+
+ if (GET_CODE (insn) == NOTE || !RTX_FRAME_RELATED_P (insn))
+ return;
+
+ pat = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
+ if (pat)
+ pat = XEXP (pat, 0);
+ else
+ pat = PATTERN (insn);
+
+ switch (GET_CODE (pat))
+ {
+ case SET:
+ arm_unwind_emit_set (asm_out_file, pat);
+ break;
+
+ case SEQUENCE:
+ /* Store multiple. */
+ arm_unwind_emit_stm (asm_out_file, pat);
+ break;
+
+ default:
+ abort();
+ }
+}
+
+
+/* Output a reference from a function exception table to the type_info
+ object X. The EABI specifies that the symbol should be relocated by
+ an R_ARM_TARGET2 relocation. */
+
+static bool
+arm_output_ttype (rtx x)
+{
+ fputs ("\t.word\t", asm_out_file);
+ output_addr_const (asm_out_file, x);
+ /* Use special relocations for symbol references. */
+ if (GET_CODE (x) != CONST_INT)
+ fputs ("(TARGET2)", asm_out_file);
+ fputc ('\n', asm_out_file);
+
+ return TRUE;
+}
+#endif /* TARGET_UNWIND_INFO */
+
+
+/* Output unwind directives for the start/end of a function. */
+
+void
+arm_output_fn_unwind (FILE * f, bool prologue)
+{
+ if (!ARM_EABI_UNWIND_TABLES)
+ return;
+
+ if (prologue)
+ fputs ("\t.fnstart\n", f);
+ else
+ fputs ("\t.fnend\n", f);
+}
+
+static bool
+arm_emit_tls_decoration (FILE *fp, rtx x)
+{
+ enum tls_reloc reloc;
+ rtx val;
+
+ val = XVECEXP (x, 0, 0);
+ reloc = INTVAL (XVECEXP (x, 0, 1));
+
+ output_addr_const (fp, val);
+
+ switch (reloc)
+ {
+ case TLS_GD32:
+ fputs ("(tlsgd)", fp);
+ break;
+ case TLS_LDM32:
+ fputs ("(tlsldm)", fp);
+ break;
+ case TLS_LDO32:
+ fputs ("(tlsldo)", fp);
+ break;
+ case TLS_IE32:
+ fputs ("(gottpoff)", fp);
+ break;
+ case TLS_LE32:
+ fputs ("(tpoff)", fp);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ switch (reloc)
+ {
+ case TLS_GD32:
+ case TLS_LDM32:
+ case TLS_IE32:
+ fputs (" + (. - ", fp);
+ output_addr_const (fp, XVECEXP (x, 0, 2));
+ fputs (" - ", fp);
+ output_addr_const (fp, XVECEXP (x, 0, 3));
+ fputc (')', fp);
+ break;
+ default:
+ break;
+ }
+
+ return TRUE;
+}
+
+bool
+arm_output_addr_const_extra (FILE *fp, rtx x)
+{
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_TLS)
+ return arm_emit_tls_decoration (fp, x);
+ else if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_PIC_LABEL)
+ {
+ char label[256];
+ int labelno = INTVAL (XVECEXP (x, 0, 0));
+
+ ASM_GENERATE_INTERNAL_LABEL (label, "LPIC", labelno);
+ assemble_name_raw (fp, label);
+
+ return TRUE;
+ }
+ else if (GET_CODE (x) == CONST_VECTOR)
+ return arm_emit_vector_const (fp, x);
+
+ return FALSE;
+}
+
+#include "gt-arm.h"
diff --git a/contrib/gcc/config/arm/arm.h b/contrib/gcc/config/arm/arm.h
index 94d8b94..784142c 100644
--- a/contrib/gcc/config/arm/arm.h
+++ b/contrib/gcc/config/arm/arm.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for ARM.
Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
and Martin Simmons (@harleqn.co.uk).
More major hacks by Richard Earnshaw (rearnsha@arm.com)
@@ -20,19 +20,24 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#ifndef GCC_ARM_H
#define GCC_ARM_H
+/* The architecture define. */
+extern char arm_arch_name[];
+
/* Target CPU builtins. */
#define TARGET_CPU_CPP_BUILTINS() \
do \
{ \
- if (TARGET_ARM) \
- builtin_define ("__arm__"); \
- else \
+ /* Define __arm__ even when in thumb mode, for \
+ consistency with armcc. */ \
+ builtin_define ("__arm__"); \
+ builtin_define ("__APCS_32__"); \
+ if (TARGET_THUMB) \
builtin_define ("__thumb__"); \
\
if (TARGET_BIG_END) \
@@ -50,60 +55,53 @@
builtin_define ("__THUMBEL__"); \
} \
\
- if (TARGET_APCS_32) \
- builtin_define ("__APCS_32__"); \
- else \
- builtin_define ("__APCS_26__"); \
- \
if (TARGET_SOFT_FLOAT) \
builtin_define ("__SOFTFP__"); \
\
- /* FIXME: TARGET_HARD_FLOAT currently implies \
- FPA. */ \
- if (TARGET_VFP && !TARGET_HARD_FLOAT) \
+ if (TARGET_VFP) \
builtin_define ("__VFP_FP__"); \
\
/* Add a define for interworking. \
Needed when building libgcc.a. */ \
- if (TARGET_INTERWORK) \
+ if (arm_cpp_interwork) \
builtin_define ("__THUMB_INTERWORK__"); \
\
builtin_assert ("cpu=arm"); \
builtin_assert ("machine=arm"); \
+ \
+ builtin_define (arm_arch_name); \
+ if (arm_arch_cirrus) \
+ builtin_define ("__MAVERICK__"); \
+ if (arm_arch_xscale) \
+ builtin_define ("__XSCALE__"); \
+ if (arm_arch_iwmmxt) \
+ builtin_define ("__IWMMXT__"); \
+ if (TARGET_AAPCS_BASED) \
+ builtin_define ("__ARM_EABI__"); \
} while (0)
-#define TARGET_CPU_arm2 0x0000
-#define TARGET_CPU_arm250 0x0000
-#define TARGET_CPU_arm3 0x0000
-#define TARGET_CPU_arm6 0x0001
-#define TARGET_CPU_arm600 0x0001
-#define TARGET_CPU_arm610 0x0002
-#define TARGET_CPU_arm7 0x0001
-#define TARGET_CPU_arm7m 0x0004
-#define TARGET_CPU_arm7dm 0x0004
-#define TARGET_CPU_arm7dmi 0x0004
-#define TARGET_CPU_arm700 0x0001
-#define TARGET_CPU_arm710 0x0002
-#define TARGET_CPU_arm7100 0x0002
-#define TARGET_CPU_arm7500 0x0002
-#define TARGET_CPU_arm7500fe 0x1001
-#define TARGET_CPU_arm7tdmi 0x0008
-#define TARGET_CPU_arm8 0x0010
-#define TARGET_CPU_arm810 0x0020
-#define TARGET_CPU_strongarm 0x0040
-#define TARGET_CPU_strongarm110 0x0040
-#define TARGET_CPU_strongarm1100 0x0040
-#define TARGET_CPU_arm9 0x0080
-#define TARGET_CPU_arm9tdmi 0x0080
-#define TARGET_CPU_xscale 0x0100
-#define TARGET_CPU_ep9312 0x0200
-#define TARGET_CPU_iwmmxt 0x0400
-#define TARGET_CPU_arm926ej_s 0x0800
-#define TARGET_CPU_arm1026ej_s 0x1000
-#define TARGET_CPU_arm1136j_s 0x2000
-#define TARGET_CPU_arm1136jf_s 0x4000
-/* Configure didn't specify. */
-#define TARGET_CPU_generic 0x8000
+/* The various ARM cores. */
+enum processor_type
+{
+#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
+ IDENT,
+#include "arm-cores.def"
+#undef ARM_CORE
+ /* Used to indicate that no processor has been specified. */
+ arm_none
+};
+
+enum target_cpus
+{
+#define ARM_CORE(NAME, IDENT, ARCH, FLAGS, COSTS) \
+ TARGET_CPU_##IDENT,
+#include "arm-cores.def"
+#undef ARM_CORE
+ TARGET_CPU_generic
+};
+
+/* The processor for which instructions should be scheduled. */
+extern enum processor_type arm_tune;
typedef enum arm_cond_code
{
@@ -119,10 +117,6 @@ extern arm_cc arm_current_cc;
extern int arm_target_label;
extern int arm_ccfsm_state;
extern GTY(()) rtx arm_target_insn;
-/* Run-time compilation parameters selecting different hardware subsets. */
-extern int target_flags;
-/* The floating point instruction architecture, can be 2 or 3 */
-extern const char * target_fp_name;
/* Define the information needed to generate branch insns. This is
stored from the compare operation. */
extern GTY(()) rtx arm_compare_op0;
@@ -140,147 +134,14 @@ extern GTY(()) rtx aof_pic_label;
#define TARGET_CPU_DEFAULT TARGET_CPU_generic
#endif
-/* If the configuration file doesn't specify the cpu, the subtarget may
- override it. If it doesn't, then default to an ARM6. */
-#if TARGET_CPU_DEFAULT == TARGET_CPU_generic
-#undef TARGET_CPU_DEFAULT
-
-#ifdef SUBTARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT SUBTARGET_CPU_DEFAULT
-#else
-#define TARGET_CPU_DEFAULT TARGET_CPU_arm6
-#endif
-#endif
-
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm2
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_2__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm6 || TARGET_CPU_DEFAULT == TARGET_CPU_arm610 || TARGET_CPU_DEFAULT == TARGET_CPU_arm7500fe
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_3__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7m
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_3M__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm7tdmi || TARGET_CPU_DEFAULT == TARGET_CPU_arm9 || TARGET_CPU_DEFAULT == TARGET_CPU_arm9tdmi
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_arm8 || TARGET_CPU_DEFAULT == TARGET_CPU_arm810 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm110 || TARGET_CPU_DEFAULT == TARGET_CPU_strongarm1100
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_xscale
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__"
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_4T__ -D__MAVERICK__"
-/* Set TARGET_DEFAULT to the default, but without soft-float. */
-#ifdef TARGET_DEFAULT
-#undef TARGET_DEFAULT
-#define TARGET_DEFAULT \
- (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS | ARM_FLAG_APCS_FRAME)
-#endif
-#else
-#if TARGET_CPU_DEFAULT == TARGET_CPU_iwmmxt
-#define CPP_ARCH_DEFAULT_SPEC "-D__ARM_ARCH_5TE__ -D__XSCALE__ -D__IWMMXT__"
-#else
-#error Unrecognized value in TARGET_CPU_DEFAULT.
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
-#endif
#undef CPP_SPEC
-#define CPP_SPEC "%(cpp_cpu_arch) %(subtarget_cpp_spec) \
-%{mapcs-32:%{mapcs-26: \
- %e-mapcs-26 and -mapcs-32 may not be used together}} \
+#define CPP_SPEC "%(subtarget_cpp_spec) \
%{msoft-float:%{mhard-float: \
%e-msoft-float and -mhard_float may not be used together}} \
%{mbig-endian:%{mlittle-endian: \
%e-mbig-endian and -mlittle-endian may not be used together}}"
-/* Set the architecture define -- if -march= is set, then it overrides
- the -mcpu= setting. */
-#define CPP_CPU_ARCH_SPEC "\
-%{march=arm2:-D__ARM_ARCH_2__} \
-%{march=arm250:-D__ARM_ARCH_2__} \
-%{march=arm3:-D__ARM_ARCH_2__} \
-%{march=arm6:-D__ARM_ARCH_3__} \
-%{march=arm600:-D__ARM_ARCH_3__} \
-%{march=arm610:-D__ARM_ARCH_3__} \
-%{march=arm7:-D__ARM_ARCH_3__} \
-%{march=arm700:-D__ARM_ARCH_3__} \
-%{march=arm710:-D__ARM_ARCH_3__} \
-%{march=arm720:-D__ARM_ARCH_3__} \
-%{march=arm7100:-D__ARM_ARCH_3__} \
-%{march=arm7500:-D__ARM_ARCH_3__} \
-%{march=arm7500fe:-D__ARM_ARCH_3__} \
-%{march=arm7m:-D__ARM_ARCH_3M__} \
-%{march=arm7dm:-D__ARM_ARCH_3M__} \
-%{march=arm7dmi:-D__ARM_ARCH_3M__} \
-%{march=arm7tdmi:-D__ARM_ARCH_4T__} \
-%{march=arm8:-D__ARM_ARCH_4__} \
-%{march=arm810:-D__ARM_ARCH_4__} \
-%{march=arm9:-D__ARM_ARCH_4T__} \
-%{march=arm920:-D__ARM_ARCH_4__} \
-%{march=arm920t:-D__ARM_ARCH_4T__} \
-%{march=arm9tdmi:-D__ARM_ARCH_4T__} \
-%{march=strongarm:-D__ARM_ARCH_4__} \
-%{march=strongarm110:-D__ARM_ARCH_4__} \
-%{march=strongarm1100:-D__ARM_ARCH_4__} \
-%{march=xscale:-D__ARM_ARCH_5TE__} \
-%{march=xscale:-D__XSCALE__} \
-%{march=ep9312:-D__ARM_ARCH_4T__} \
-%{march=ep9312:-D__MAVERICK__} \
-%{march=armv2:-D__ARM_ARCH_2__} \
-%{march=armv2a:-D__ARM_ARCH_2__} \
-%{march=armv3:-D__ARM_ARCH_3__} \
-%{march=armv3m:-D__ARM_ARCH_3M__} \
-%{march=armv4:-D__ARM_ARCH_4__} \
-%{march=armv4t:-D__ARM_ARCH_4T__} \
-%{march=armv5:-D__ARM_ARCH_5__} \
-%{march=armv5t:-D__ARM_ARCH_5T__} \
-%{march=armv5e:-D__ARM_ARCH_5E__} \
-%{march=armv5te:-D__ARM_ARCH_5TE__} \
-%{!march=*: \
- %{mcpu=arm2:-D__ARM_ARCH_2__} \
- %{mcpu=arm250:-D__ARM_ARCH_2__} \
- %{mcpu=arm3:-D__ARM_ARCH_2__} \
- %{mcpu=arm6:-D__ARM_ARCH_3__} \
- %{mcpu=arm600:-D__ARM_ARCH_3__} \
- %{mcpu=arm610:-D__ARM_ARCH_3__} \
- %{mcpu=arm7:-D__ARM_ARCH_3__} \
- %{mcpu=arm700:-D__ARM_ARCH_3__} \
- %{mcpu=arm710:-D__ARM_ARCH_3__} \
- %{mcpu=arm720:-D__ARM_ARCH_3__} \
- %{mcpu=arm7100:-D__ARM_ARCH_3__} \
- %{mcpu=arm7500:-D__ARM_ARCH_3__} \
- %{mcpu=arm7500fe:-D__ARM_ARCH_3__} \
- %{mcpu=arm7m:-D__ARM_ARCH_3M__} \
- %{mcpu=arm7dm:-D__ARM_ARCH_3M__} \
- %{mcpu=arm7dmi:-D__ARM_ARCH_3M__} \
- %{mcpu=arm7tdmi:-D__ARM_ARCH_4T__} \
- %{mcpu=arm8:-D__ARM_ARCH_4__} \
- %{mcpu=arm810:-D__ARM_ARCH_4__} \
- %{mcpu=arm9:-D__ARM_ARCH_4T__} \
- %{mcpu=arm920:-D__ARM_ARCH_4__} \
- %{mcpu=arm920t:-D__ARM_ARCH_4T__} \
- %{mcpu=arm9tdmi:-D__ARM_ARCH_4T__} \
- %{mcpu=strongarm:-D__ARM_ARCH_4__} \
- %{mcpu=strongarm110:-D__ARM_ARCH_4__} \
- %{mcpu=strongarm1100:-D__ARM_ARCH_4__} \
- %{mcpu=xscale:-D__ARM_ARCH_5TE__} \
- %{mcpu=xscale:-D__XSCALE__} \
- %{mcpu=ep9312:-D__ARM_ARCH_4T__} \
- %{mcpu=ep9312:-D__MAVERICK__} \
- %{mcpu=iwmmxt:-D__ARM_ARCH_5TE__} \
- %{mcpu=iwmmxt:-D__XSCALE__} \
- %{mcpu=iwmmxt:-D__IWMMXT__} \
- %{!mcpu*:%(cpp_cpu_arch_default)}} \
-"
-
#ifndef CC1_SPEC
#define CC1_SPEC ""
#endif
@@ -295,8 +156,6 @@ extern GTY(()) rtx aof_pic_label;
Do not define this macro if it does not need to do anything. */
#define EXTRA_SPECS \
- { "cpp_cpu_arch", CPP_CPU_ARCH_SPEC }, \
- { "cpp_cpu_arch_default", CPP_ARCH_DEFAULT_SPEC }, \
{ "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
SUBTARGET_EXTRA_SPECS
@@ -313,271 +172,77 @@ extern GTY(()) rtx aof_pic_label;
#define TARGET_VERSION fputs (" (ARM/generic)", stderr);
#endif
-/* Nonzero if the function prologue (and epilogue) should obey
- the ARM Procedure Call Standard. */
-#define ARM_FLAG_APCS_FRAME (1 << 0)
-
-/* Nonzero if the function prologue should output the function name to enable
- the post mortem debugger to print a backtrace (very useful on RISCOS,
- unused on RISCiX). Specifying this flag also enables
- -fno-omit-frame-pointer.
- XXX Must still be implemented in the prologue. */
-#define ARM_FLAG_POKE (1 << 1)
-
-/* Nonzero if floating point instructions are emulated by the FPE, in which
- case instruction scheduling becomes very uninteresting. */
-#define ARM_FLAG_FPE (1 << 2)
-
-/* Nonzero if destined for a processor in 32-bit program mode. Takes out bit
- that assume restoration of the condition flags when returning from a
- branch and link (ie a function). */
-#define ARM_FLAG_APCS_32 (1 << 3)
-
-/* FLAGS 0x0008 and 0x0010 are now spare (used to be arm3/6 selection). */
-
-/* Nonzero if stack checking should be performed on entry to each function
- which allocates temporary variables on the stack. */
-#define ARM_FLAG_APCS_STACK (1 << 4)
-
-/* Nonzero if floating point parameters should be passed to functions in
- floating point registers. */
-#define ARM_FLAG_APCS_FLOAT (1 << 5)
-
-/* Nonzero if re-entrant, position independent code should be generated.
- This is equivalent to -fpic. */
-#define ARM_FLAG_APCS_REENT (1 << 6)
-
-/* Nonzero if the MMU will trap unaligned word accesses, so shorts must
- be loaded using either LDRH or LDRB instructions. */
-#define ARM_FLAG_MMU_TRAPS (1 << 7)
-
-/* Nonzero if all floating point instructions are missing (and there is no
- emulator either). Generate function calls for all ops in this case. */
-#define ARM_FLAG_SOFT_FLOAT (1 << 8)
-
-/* Nonzero if we should compile with BYTES_BIG_ENDIAN set to 1. */
-#define ARM_FLAG_BIG_END (1 << 9)
-
-/* Nonzero if we should compile for Thumb interworking. */
-#define ARM_FLAG_INTERWORK (1 << 10)
-
-/* Nonzero if we should have little-endian words even when compiling for
- big-endian (for backwards compatibility with older versions of GCC). */
-#define ARM_FLAG_LITTLE_WORDS (1 << 11)
-
-/* Nonzero if we need to protect the prolog from scheduling */
-#define ARM_FLAG_NO_SCHED_PRO (1 << 12)
-
-/* Nonzero if a call to abort should be generated if a noreturn
- function tries to return. */
-#define ARM_FLAG_ABORT_NORETURN (1 << 13)
-
-/* Nonzero if function prologues should not load the PIC register. */
-#define ARM_FLAG_SINGLE_PIC_BASE (1 << 14)
-
-/* Nonzero if all call instructions should be indirect. */
-#define ARM_FLAG_LONG_CALLS (1 << 15)
-
-/* Nonzero means that the target ISA is the THUMB, not the ARM. */
-#define ARM_FLAG_THUMB (1 << 16)
-
-/* Set if a TPCS style stack frame should be generated, for non-leaf
- functions, even if they do not need one. */
-#define THUMB_FLAG_BACKTRACE (1 << 17)
-
-/* Set if a TPCS style stack frame should be generated, for leaf
- functions, even if they do not need one. */
-#define THUMB_FLAG_LEAF_BACKTRACE (1 << 18)
-
-/* Set if externally visible functions should assume that they
- might be called in ARM mode, from a non-thumb aware code. */
-#define THUMB_FLAG_CALLEE_SUPER_INTERWORKING (1 << 19)
-
-/* Set if calls via function pointers should assume that their
- destination is non-Thumb aware. */
-#define THUMB_FLAG_CALLER_SUPER_INTERWORKING (1 << 20)
-
-/* Nonzero means target uses VFP FP. */
-#define ARM_FLAG_VFP (1 << 21)
-
-/* Nonzero means to use ARM/Thumb Procedure Call Standard conventions. */
-#define ARM_FLAG_ATPCS (1 << 22)
-
-/* Fix invalid Cirrus instruction combinations by inserting NOPs. */
-#define CIRRUS_FIX_INVALID_INSNS (1 << 23)
-
-#define TARGET_APCS_FRAME (target_flags & ARM_FLAG_APCS_FRAME)
-#define TARGET_POKE_FUNCTION_NAME (target_flags & ARM_FLAG_POKE)
-#define TARGET_FPE (target_flags & ARM_FLAG_FPE)
-#define TARGET_APCS_32 (target_flags & ARM_FLAG_APCS_32)
-#define TARGET_APCS_STACK (target_flags & ARM_FLAG_APCS_STACK)
-#define TARGET_APCS_FLOAT (target_flags & ARM_FLAG_APCS_FLOAT)
-#define TARGET_APCS_REENT (target_flags & ARM_FLAG_APCS_REENT)
-#define TARGET_ATPCS (target_flags & ARM_FLAG_ATPCS)
-#define TARGET_MMU_TRAPS (target_flags & ARM_FLAG_MMU_TRAPS)
-#define TARGET_SOFT_FLOAT (target_flags & ARM_FLAG_SOFT_FLOAT)
-#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
-#define TARGET_CIRRUS (arm_is_cirrus)
-#define TARGET_ANY_HARD_FLOAT (TARGET_HARD_FLOAT || TARGET_CIRRUS)
+#define TARGET_SOFT_FLOAT (arm_float_abi == ARM_FLOAT_ABI_SOFT)
+/* Use hardware floating point instructions. */
+#define TARGET_HARD_FLOAT (arm_float_abi != ARM_FLOAT_ABI_SOFT)
+/* Use hardware floating point calling convention. */
+#define TARGET_HARD_FLOAT_ABI (arm_float_abi == ARM_FLOAT_ABI_HARD)
+#define TARGET_FPA (arm_fp_model == ARM_FP_MODEL_FPA)
+#define TARGET_MAVERICK (arm_fp_model == ARM_FP_MODEL_MAVERICK)
+#define TARGET_VFP (arm_fp_model == ARM_FP_MODEL_VFP)
#define TARGET_IWMMXT (arm_arch_iwmmxt)
#define TARGET_REALLY_IWMMXT (TARGET_IWMMXT && TARGET_ARM)
-#define TARGET_VFP (target_flags & ARM_FLAG_VFP)
-#define TARGET_BIG_END (target_flags & ARM_FLAG_BIG_END)
-#define TARGET_INTERWORK (target_flags & ARM_FLAG_INTERWORK)
-#define TARGET_LITTLE_WORDS (target_flags & ARM_FLAG_LITTLE_WORDS)
-#define TARGET_NO_SCHED_PRO (target_flags & ARM_FLAG_NO_SCHED_PRO)
-#define TARGET_ABORT_NORETURN (target_flags & ARM_FLAG_ABORT_NORETURN)
-#define TARGET_SINGLE_PIC_BASE (target_flags & ARM_FLAG_SINGLE_PIC_BASE)
-#define TARGET_LONG_CALLS (target_flags & ARM_FLAG_LONG_CALLS)
-#define TARGET_THUMB (target_flags & ARM_FLAG_THUMB)
+#define TARGET_IWMMXT_ABI (TARGET_ARM && arm_abi == ARM_ABI_IWMMXT)
#define TARGET_ARM (! TARGET_THUMB)
#define TARGET_EITHER 1 /* (TARGET_ARM | TARGET_THUMB) */
-#define TARGET_CALLEE_INTERWORKING (target_flags & THUMB_FLAG_CALLEE_SUPER_INTERWORKING)
-#define TARGET_CALLER_INTERWORKING (target_flags & THUMB_FLAG_CALLER_SUPER_INTERWORKING)
-#define TARGET_BACKTRACE (leaf_function_p () \
- ? (target_flags & THUMB_FLAG_LEAF_BACKTRACE) \
- : (target_flags & THUMB_FLAG_BACKTRACE))
-#define TARGET_CIRRUS_FIX_INVALID_INSNS (target_flags & CIRRUS_FIX_INVALID_INSNS)
-
-/* SUBTARGET_SWITCHES is used to add flags on a per-config basis. */
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
+#define TARGET_BACKTRACE (leaf_function_p () \
+ ? TARGET_TPCS_LEAF_FRAME \
+ : TARGET_TPCS_FRAME)
+#define TARGET_LDRD (arm_arch5e && ARM_DOUBLEWORD_ALIGN)
+#define TARGET_AAPCS_BASED \
+ (arm_abi != ARM_ABI_APCS && arm_abi != ARM_ABI_ATPCS)
+
+#define TARGET_HARD_TP (target_thread_pointer == TP_CP15)
+#define TARGET_SOFT_TP (target_thread_pointer == TP_SOFT)
+
+/* True iff the full BPABI is being used. If TARGET_BPABI is true,
+ then TARGET_AAPCS_BASED must be true -- but the converse does not
+ hold. TARGET_BPABI implies the use of the BPABI runtime library,
+ etc., in addition to just the AAPCS calling conventions. */
+#ifndef TARGET_BPABI
+#define TARGET_BPABI false
#endif
-#define TARGET_SWITCHES \
-{ \
- {"apcs", ARM_FLAG_APCS_FRAME, "" }, \
- {"apcs-frame", ARM_FLAG_APCS_FRAME, \
- N_("Generate APCS conformant stack frames") }, \
- {"no-apcs-frame", -ARM_FLAG_APCS_FRAME, "" }, \
- {"poke-function-name", ARM_FLAG_POKE, \
- N_("Store function names in object code") }, \
- {"no-poke-function-name", -ARM_FLAG_POKE, "" }, \
- {"fpe", ARM_FLAG_FPE, "" }, \
- {"apcs-32", ARM_FLAG_APCS_32, \
- N_("Use the 32-bit version of the APCS") }, \
- {"apcs-26", -ARM_FLAG_APCS_32, ""}, \
- {"apcs-stack-check", ARM_FLAG_APCS_STACK, "" }, \
- {"no-apcs-stack-check", -ARM_FLAG_APCS_STACK, "" }, \
- {"apcs-float", ARM_FLAG_APCS_FLOAT, \
- N_("Pass FP arguments in FP registers") }, \
- {"no-apcs-float", -ARM_FLAG_APCS_FLOAT, "" }, \
- {"apcs-reentrant", ARM_FLAG_APCS_REENT, \
- N_("Generate re-entrant, PIC code") }, \
- {"no-apcs-reentrant", -ARM_FLAG_APCS_REENT, "" }, \
- {"alignment-traps", ARM_FLAG_MMU_TRAPS, \
- N_("The MMU will trap on unaligned accesses") }, \
- {"no-alignment-traps", -ARM_FLAG_MMU_TRAPS, "" }, \
- {"soft-float", ARM_FLAG_SOFT_FLOAT, \
- N_("Use library calls to perform FP operations") }, \
- {"hard-float", -ARM_FLAG_SOFT_FLOAT, \
- N_("Use hardware floating point instructions") }, \
- {"big-endian", ARM_FLAG_BIG_END, \
- N_("Assume target CPU is configured as big endian") }, \
- {"little-endian", -ARM_FLAG_BIG_END, \
- N_("Assume target CPU is configured as little endian") }, \
- {"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 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, "" }, \
- {"no-sched-prolog", ARM_FLAG_NO_SCHED_PRO, \
- N_("Do not move instructions into a function's prologue") }, \
- {"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, "" }, \
- {"long-calls", ARM_FLAG_LONG_CALLS, \
- N_("Generate call insns as indirect calls, if necessary") }, \
- {"no-long-calls", -ARM_FLAG_LONG_CALLS, "" }, \
- {"thumb", ARM_FLAG_THUMB, \
- N_("Compile for the Thumb not the ARM") }, \
- {"no-thumb", -ARM_FLAG_THUMB, "" }, \
- {"arm", -ARM_FLAG_THUMB, "" }, \
- {"tpcs-frame", THUMB_FLAG_BACKTRACE, \
- N_("Thumb: Generate (non-leaf) stack frames even if not needed") }, \
- {"no-tpcs-frame", -THUMB_FLAG_BACKTRACE, "" }, \
- {"tpcs-leaf-frame", THUMB_FLAG_LEAF_BACKTRACE, \
- N_("Thumb: Generate (leaf) stack frames even if not needed") }, \
- {"no-tpcs-leaf-frame", -THUMB_FLAG_LEAF_BACKTRACE, "" }, \
- {"callee-super-interworking", THUMB_FLAG_CALLEE_SUPER_INTERWORKING, \
- N_("Thumb: Assume non-static functions may be called from ARM code") }, \
- {"no-callee-super-interworking", -THUMB_FLAG_CALLEE_SUPER_INTERWORKING, \
- "" }, \
- {"caller-super-interworking", THUMB_FLAG_CALLER_SUPER_INTERWORKING, \
- N_("Thumb: Assume function pointers may go to non-Thumb aware code") }, \
- {"no-caller-super-interworking", -THUMB_FLAG_CALLER_SUPER_INTERWORKING, \
- "" }, \
- {"cirrus-fix-invalid-insns", CIRRUS_FIX_INVALID_INSNS, \
- N_("Cirrus: Place NOPs to avoid invalid instruction combinations") }, \
- {"no-cirrus-fix-invalid-insns", -CIRRUS_FIX_INVALID_INSNS, \
- N_("Cirrus: Do not break up invalid instruction combinations with NOPs") },\
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT, "" } \
-}
-
-#define TARGET_OPTIONS \
-{ \
- {"cpu=", & arm_select[0].string, \
- N_("Specify the name of the target CPU"), 0}, \
- {"arch=", & arm_select[1].string, \
- N_("Specify the name of the target architecture"), 0}, \
- {"tune=", & arm_select[2].string, "", 0}, \
- {"fpe=", & target_fp_name, "" , 0}, \
- {"fp=", & target_fp_name, \
- N_("Specify the version of the floating point emulator"), 0},\
- {"structure-size-boundary=", & structure_size_string, \
- N_("Specify the minimum bit alignment of structures"), 0}, \
- {"pic-register=", & arm_pic_register_string, \
- N_("Specify the register to be used for PIC addressing"), 0} \
-}
-
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-arch is ignored if -march or -mcpu are specified.
--with-cpu is ignored if -march or -mcpu are specified, and is overridden
by --with-arch.
--with-tune is ignored if -mtune or -mcpu are specified (but not affected
by -march).
- --with-float is ignored if -mhard-float or -msoft-float are
- specified. */
+ --with-float is ignored if -mhard-float, -msoft-float or -mfloat-abi are
+ specified.
+ --with-fpu is ignored if -mfpu is specified.
+ --with-abi is ignored is -mabi is specified. */
#define OPTION_DEFAULT_SPECS \
{"arch", "%{!march=*:%{!mcpu=*:-march=%(VALUE)}}" }, \
{"cpu", "%{!march=*:%{!mcpu=*:-mcpu=%(VALUE)}}" }, \
{"tune", "%{!mcpu=*:%{!mtune=*:-mtune=%(VALUE)}}" }, \
- {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }
-
-struct arm_cpu_select
-{
- const char * string;
- const char * name;
- const struct processors * processors;
-};
-
-/* This is a magic array. If the user specifies a command line switch
- which matches one of the entries in TARGET_OPTIONS then the corresponding
- string pointer will be set to the value specified by the user. */
-extern struct arm_cpu_select arm_select[];
-
-enum prog_mode_type
+ {"float", \
+ "%{!msoft-float:%{!mhard-float:%{!mfloat-abi=*:-mfloat-abi=%(VALUE)}}}" }, \
+ {"fpu", "%{!mfpu=*:-mfpu=%(VALUE)}"}, \
+ {"abi", "%{!mabi=*:-mabi=%(VALUE)}"}, \
+ {"mode", "%{!marm:%{!mthumb:-m%(VALUE)}}"},
+
+/* Which floating point model to use. */
+enum arm_fp_model
{
- prog_mode26,
- prog_mode32
+ ARM_FP_MODEL_UNKNOWN,
+ /* FPA model (Hardware or software). */
+ ARM_FP_MODEL_FPA,
+ /* Cirrus Maverick floating point model. */
+ ARM_FP_MODEL_MAVERICK,
+ /* VFP floating point model. */
+ ARM_FP_MODEL_VFP
};
-/* Recast the program mode class to be the prog_mode attribute. */
-#define arm_prog_mode ((enum attr_prog_mode) arm_prgmode)
+extern enum arm_fp_model arm_fp_model;
-extern enum prog_mode_type arm_prgmode;
-
-/* What sort of floating point unit do we have? Hardware or software.
- If software, is it issue 2 or issue 3? */
+/* Which floating point hardware is available. Also update
+ fp_model_for_fpu in arm.c when adding entries to this list. */
enum fputype
{
- /* Software floating point, FPA style double fmt. */
- FPUTYPE_SOFT_FPA,
+ /* No FP hardware. */
+ FPUTYPE_NONE,
/* Full FPA support. */
FPUTYPE_FPA,
/* Emulated FPA hardware, Issue 2 emulator (no LFM/SFM). */
@@ -585,7 +250,9 @@ enum fputype
/* Emulated FPA hardware, Issue 3 emulator. */
FPUTYPE_FPA_EMU3,
/* Cirrus Maverick floating point co-processor. */
- FPUTYPE_MAVERICK
+ FPUTYPE_MAVERICK,
+ /* VFP. */
+ FPUTYPE_VFP
};
/* Recast the floating point class to be the floating point attribute. */
@@ -597,30 +264,62 @@ extern enum fputype arm_fpu_tune;
/* What type of floating point instructions are available */
extern enum fputype arm_fpu_arch;
-/* Default floating point architecture. Override in sub-target if
- necessary. */
-#ifndef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_FPA_EMU2
+enum float_abi_type
+{
+ ARM_FLOAT_ABI_SOFT,
+ ARM_FLOAT_ABI_SOFTFP,
+ ARM_FLOAT_ABI_HARD
+};
+
+extern enum float_abi_type arm_float_abi;
+
+#ifndef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
#endif
-#if TARGET_CPU_DEFAULT == TARGET_CPU_ep9312
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_MAVERICK
+/* Which ABI to use. */
+enum arm_abi_type
+{
+ ARM_ABI_APCS,
+ ARM_ABI_ATPCS,
+ ARM_ABI_AAPCS,
+ ARM_ABI_IWMMXT,
+ ARM_ABI_AAPCS_LINUX
+};
+
+extern enum arm_abi_type arm_abi;
+
+#ifndef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_APCS
#endif
-/* Nonzero if the processor has a fast multiply insn, and one that does
- a 64-bit multiply of two 32-bit values. */
-extern int arm_fast_multiply;
+/* Which thread pointer access sequence to use. */
+enum arm_tp_type {
+ TP_AUTO,
+ TP_SOFT,
+ TP_CP15
+};
-/* Nonzero if this chip supports the ARM Architecture 4 extensions */
+extern enum arm_tp_type target_thread_pointer;
+
+/* Nonzero if this chip supports the ARM Architecture 3M extensions. */
+extern int arm_arch3m;
+
+/* Nonzero if this chip supports the ARM Architecture 4 extensions. */
extern int arm_arch4;
-/* Nonzero if this chip supports the ARM Architecture 5 extensions */
+/* Nonzero if this chip supports the ARM Architecture 4T extensions. */
+extern int arm_arch4t;
+
+/* Nonzero if this chip supports the ARM Architecture 5 extensions. */
extern int arm_arch5;
-/* Nonzero if this chip supports the ARM Architecture 5E extensions */
+/* Nonzero if this chip supports the ARM Architecture 5E extensions. */
extern int arm_arch5e;
+/* Nonzero if this chip supports the ARM Architecture 6 extensions. */
+extern int arm_arch6;
+
/* Nonzero if this chip can benefit from load scheduling. */
extern int arm_ld_sched;
@@ -628,10 +327,10 @@ extern int arm_ld_sched;
extern int thumb_code;
/* Nonzero if this chip is a StrongARM. */
-extern int arm_is_strong;
+extern int arm_tune_strongarm;
/* Nonzero if this chip is a Cirrus variant. */
-extern int arm_is_cirrus;
+extern int arm_arch_cirrus;
/* Nonzero if this chip supports Intel XScale with Wireless MMX technology. */
extern int arm_arch_iwmmxt;
@@ -639,23 +338,27 @@ extern int arm_arch_iwmmxt;
/* Nonzero if this chip is an XScale. */
extern int arm_arch_xscale;
-/* Nonzero if tuning for XScale */
+/* Nonzero if tuning for XScale. */
extern int arm_tune_xscale;
-/* Nonzero if this chip is an ARM6 or an ARM7. */
-extern int arm_is_6_or_7;
+/* Nonzero if tuning for stores via the write buffer. */
+extern int arm_tune_wbuf;
+
+/* Nonzero if we should define __THUMB_INTERWORK__ in the
+ preprocessor.
+ XXX This is a bit of a hack, it's intended to help work around
+ problems in GLD which doesn't understand that armv5t code is
+ interworking clean. */
+extern int arm_cpp_interwork;
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_APCS_FRAME)
#endif
/* The frame pointer register used in gcc has nothing to do with debugging;
that is controlled by the APCS-FRAME option. */
#define CAN_DEBUG_WITHOUT_FP
-#undef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS 1
-
#define OVERRIDE_OPTIONS arm_override_options ()
/* Nonzero if PIC code requires explicit qualifiers to generate
@@ -671,13 +374,13 @@ extern int arm_is_6_or_7;
/* Nonzero if we need to refer to the GOT with a PC-relative
offset. In other words, generate
- .word _GLOBAL_OFFSET_TABLE_ - [. - (.Lxx + 8)]
+ .word _GLOBAL_OFFSET_TABLE_ - [. - (.Lxx + 8)]
rather than
.word _GLOBAL_OFFSET_TABLE_ - (.Lxx + 8)
- The default is true, which matches NetBSD. Subtargets can
+ The default is true, which matches NetBSD. Subtargets can
override this if required. */
#ifndef GOT_PCREL
#define GOT_PCREL 1
@@ -701,20 +404,21 @@ extern int arm_is_6_or_7;
if (MODE == QImode) \
UNSIGNEDP = 1; \
else if (MODE == HImode) \
- UNSIGNEDP = TARGET_MMU_TRAPS != 0; \
+ UNSIGNEDP = 1; \
(MODE) = SImode; \
}
-/* Define this macro if the promotion described by `PROMOTE_MODE'
- should also be done for outgoing function arguments. */
-/* This is required to ensure that push insns always push a word. */
-#define PROMOTE_FUNCTION_ARGS
+#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
+ if ((GET_MODE_CLASS (MODE) == MODE_INT \
+ || GET_MODE_CLASS (MODE) == MODE_COMPLEX_INT) \
+ && GET_MODE_SIZE (MODE) < 4) \
+ (MODE) = SImode; \
/* Define this if most significant bit is lowest numbered
in instructions that operate on numbered bit-fields. */
#define BITS_BIG_ENDIAN 0
-/* Define this if most significant byte of a word is the lowest numbered.
+/* Define this if most significant byte of a word is the lowest numbered.
Most ARM processors are run in little endian mode, so that is the default.
If you want to have it run-time selectable, change the definition in a
cover file to be TARGET_BIG_ENDIAN. */
@@ -740,13 +444,17 @@ extern int arm_is_6_or_7;
#define UNITS_PER_WORD 4
-#define PARM_BOUNDARY 32
+/* True if natural alignment is used for doubleword types. */
+#define ARM_DOUBLEWORD_ALIGN TARGET_AAPCS_BASED
-#define IWMMXT_ALIGNMENT 64
+#define DOUBLEWORD_ALIGNMENT 64
-#define STACK_BOUNDARY 32
+#define PARM_BOUNDARY 32
-#define PREFERRED_STACK_BOUNDARY (TARGET_ATPCS ? 64 : 32)
+#define STACK_BOUNDARY (ARM_DOUBLEWORD_ALIGN ? DOUBLEWORD_ALIGNMENT : 32)
+
+#define PREFERRED_STACK_BOUNDARY \
+ (arm_abi == ARM_ABI_ATPCS ? 64 : STACK_BOUNDARY)
#define FUNCTION_BOUNDARY 32
@@ -757,62 +465,30 @@ extern int arm_is_6_or_7;
#define EMPTY_FIELD_BOUNDARY 32
-#define BIGGEST_ALIGNMENT (TARGET_REALLY_IWMMXT ? 64 : 32)
-
-#define TYPE_NEEDS_IWMMXT_ALIGNMENT(TYPE) \
- (TARGET_REALLY_IWMMXT \
- && ((TREE_CODE (TYPE) == VECTOR_TYPE) || (TYPE_MODE (TYPE) == DImode) || (TYPE_MODE (TYPE) == DFmode)))
+#define BIGGEST_ALIGNMENT (ARM_DOUBLEWORD_ALIGN ? DOUBLEWORD_ALIGNMENT : 32)
/* XXX Blah -- this macro is used directly by libobjc. Since it
supports no vector modes, cut out the complexity and fall back
on BIGGEST_FIELD_ALIGNMENT. */
#ifdef IN_TARGET_LIBS
#define BIGGEST_FIELD_ALIGNMENT 64
-#else
-/* An expression for the alignment of a structure field FIELD if the
- alignment computed in the usual way is COMPUTED. GCC uses this
- value instead of the value in `BIGGEST_ALIGNMENT' or
- `BIGGEST_FIELD_ALIGNMENT', if defined, for structure fields only. */
-#define ADJUST_FIELD_ALIGN(FIELD, COMPUTED) \
- (TYPE_NEEDS_IWMMXT_ALIGNMENT (TREE_TYPE (FIELD)) \
- ? IWMMXT_ALIGNMENT \
- : (COMPUTED))
#endif
-/* If defined, a C expression to compute the alignment for a static variable.
- TYPE is the data type, and ALIGN is the alignment that the object
- would ordinarily have. The value of this macro is used instead of that
- alignment to align the object.
-
- If this macro is not defined, then ALIGN is used. */
-#define DATA_ALIGNMENT(TYPE, ALIGN) \
- (TYPE_NEEDS_IWMMXT_ALIGNMENT (TYPE) ? IWMMXT_ALIGNMENT : ALIGN)
-
-/* If defined, a C expression to compute the alignment for a
- variables in the local store. TYPE is the data type, and
- BASIC-ALIGN is the alignment that the object would ordinarily
- have. The value of this macro is used instead of that alignment
- to align the object.
-
- If this macro is not defined, then BASIC-ALIGN is used. */
-#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
- (TYPE_NEEDS_IWMMXT_ALIGNMENT (TYPE) ? IWMMXT_ALIGNMENT : ALIGN)
-
/* Make strings word-aligned so strcpy from constants will be faster. */
#define CONSTANT_ALIGNMENT_FACTOR (TARGET_THUMB || ! arm_tune_xscale ? 1 : 2)
-
+
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- ((TARGET_REALLY_IWMMXT && TREE_CODE (EXP) == VECTOR_TYPE) ? IWMMXT_ALIGNMENT : \
- (TREE_CODE (EXP) == STRING_CST \
- && (ALIGN) < BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR) \
- ? BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR : (ALIGN))
+ ((TREE_CODE (EXP) == STRING_CST \
+ && (ALIGN) < BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR) \
+ ? BITS_PER_WORD * CONSTANT_ALIGNMENT_FACTOR : (ALIGN))
/* Setting STRUCTURE_SIZE_BOUNDARY to 32 produces more efficient code, but the
value set in previous versions of this toolchain was 8, which produces more
compact structures. The command line option -mstructure_size_boundary=<n>
can be used to change this value. For compatibility with the ARM SDK
however the value should be left at 32. ARM SDT Reference Manual (ARM DUI
- 0020D) page 2-20 says "Structures are aligned on word boundaries". */
+ 0020D) page 2-20 says "Structures are aligned on word boundaries".
+ The AAPCS specifies a value of 8. */
#define STRUCTURE_SIZE_BOUNDARY arm_structure_size_boundary
extern int arm_structure_size_boundary;
@@ -824,12 +500,30 @@ extern int arm_structure_size_boundary;
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 32
#endif
-/* Used when parsing command line option -mstructure_size_boundary. */
-extern const char * structure_size_string;
-
/* Nonzero if move instructions will actually fail to work
when given unaligned data. */
#define STRICT_ALIGNMENT 1
+
+/* wchar_t is unsigned under the AAPCS. */
+#ifndef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "int")
+
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+#endif
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long unsigned int")
+#endif
+
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_AAPCS_BASED ? "int" : "long int")
+#endif
+
+/* AAPCS requires that structure alignment is affected by bitfields. */
+#ifndef PCC_BITFIELD_TYPE_MATTERS
+#define PCC_BITFIELD_TYPE_MATTERS TARGET_AAPCS_BASED
+#endif
+
/* Standard register usage. */
@@ -841,7 +535,7 @@ extern const char * structure_size_string;
r4-r8 S register variable
r9 S (rfp) register variable (real frame pointer)
-
+
r10 F S (sl) stack limit (used by -mapcs-stack-check)
r11 F S (fp) argument pointer
r12 (ip) temp workspace
@@ -872,6 +566,11 @@ extern const char * structure_size_string;
mvf1-mvf3 Cirrus floating point scratch
mvf4-mvf15 S Cirrus floating point variable. */
+/* s0-s15 VFP scratch (aka d0-d7).
+ s16-s31 S VFP variable (aka d8-d15).
+ vfpcc Not a real register. Represents the VFP condition
+ code flags. */
+
/* The stack backtrace structure is as follows:
fp points to here: | save code pointer | [fp]
| return link value | [fp, #-4]
@@ -896,17 +595,22 @@ extern const char * structure_size_string;
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator. */
-#define FIXED_REGISTERS \
-{ \
- 0,0,0,0,0,0,0,0, \
- 0,0,0,0,0,1,0,1, \
- 0,0,0,0,0,0,0,0, \
+#define FIXED_REGISTERS \
+{ \
+ 0,0,0,0,0,0,0,0, \
+ 0,0,0,0,0,1,0,1, \
+ 0,0,0,0,0,0,0,0, \
1,1,1, \
1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1,1,1,1,1, \
- 1,1,1,1 \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1 \
}
/* 1 for registers not available across function calls.
@@ -915,7 +619,7 @@ extern const char * structure_size_string;
The latter must include the registers where values are returned
and the register where structure-value addresses are passed.
Aside from that, you can include as many other registers as you like.
- The CC is not preserved over function calls on the ARM 6, so it is
+ The CC is not preserved over function calls on the ARM 6, so it is
easier to assume this for all. SFP is preserved, since FP is. */
#define CALL_USED_REGISTERS \
{ \
@@ -927,7 +631,12 @@ extern const char * structure_size_string;
1,1,1,1,1,1,1,1, \
1,1,1,1,1,1,1,1, \
1,1,1,1,1,1,1,1, \
- 1,1,1,1 \
+ 1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1,1,1,1,1,1,1,1, \
+ 1 \
}
#ifndef SUBTARGET_CONDITIONAL_REGISTER_USAGE
@@ -938,10 +647,10 @@ extern const char * structure_size_string;
{ \
int regno; \
\
- if (TARGET_SOFT_FLOAT || TARGET_THUMB) \
+ if (TARGET_SOFT_FLOAT || TARGET_THUMB || !TARGET_FPA) \
{ \
- for (regno = FIRST_ARM_FP_REGNUM; \
- regno <= LAST_ARM_FP_REGNUM; ++regno) \
+ for (regno = FIRST_FPA_REGNUM; \
+ regno <= LAST_FPA_REGNUM; ++regno) \
fixed_regs[regno] = call_used_regs[regno] = 1; \
} \
\
@@ -961,16 +670,28 @@ extern const char * structure_size_string;
if (TARGET_THUMB) \
fixed_regs[LR_REGNUM] = call_used_regs[LR_REGNUM] = 1; \
\
- if (TARGET_CIRRUS) \
+ if (TARGET_ARM && TARGET_HARD_FLOAT) \
{ \
- for (regno = FIRST_ARM_FP_REGNUM; \
- regno <= LAST_ARM_FP_REGNUM; ++ regno) \
- fixed_regs[regno] = call_used_regs[regno] = 1; \
- for (regno = FIRST_CIRRUS_FP_REGNUM; \
- regno <= LAST_CIRRUS_FP_REGNUM; ++ regno) \
+ if (TARGET_MAVERICK) \
{ \
- fixed_regs[regno] = 0; \
- call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; \
+ for (regno = FIRST_FPA_REGNUM; \
+ regno <= LAST_FPA_REGNUM; ++ regno) \
+ fixed_regs[regno] = call_used_regs[regno] = 1; \
+ for (regno = FIRST_CIRRUS_FP_REGNUM; \
+ regno <= LAST_CIRRUS_FP_REGNUM; ++ regno) \
+ { \
+ fixed_regs[regno] = 0; \
+ call_used_regs[regno] = regno < FIRST_CIRRUS_FP_REGNUM + 4; \
+ } \
+ } \
+ if (TARGET_VFP) \
+ { \
+ for (regno = FIRST_VFP_REGNUM; \
+ regno <= LAST_VFP_REGNUM; ++ regno) \
+ { \
+ fixed_regs[regno] = 0; \
+ call_used_regs[regno] = regno < FIRST_VFP_REGNUM + 16; \
+ } \
} \
} \
\
@@ -983,7 +704,7 @@ extern const char * structure_size_string;
scratch registers. */ \
for (regno = FIRST_IWMMXT_GR_REGNUM; \
regno <= LAST_IWMMXT_GR_REGNUM; ++ regno) \
- fixed_regs[regno] = call_used_regs[regno] = 0; \
+ fixed_regs[regno] = 0; \
/* The XScale ABI has wR0 - wR9 as scratch registers, \
the rest as call-preserved registers. */ \
for (regno = FIRST_IWMMXT_REGNUM; \
@@ -1004,14 +725,21 @@ extern const char * structure_size_string;
fixed_regs[10] = 1; \
call_used_regs[10] = 1; \
} \
- if (TARGET_APCS_FRAME) \
+ /* -mcaller-super-interworking reserves r11 for calls to \
+ _interwork_r11_call_via_rN(). Making the register global \
+ is an easy way of ensuring that it remains valid for all \
+ calls. */ \
+ if (TARGET_APCS_FRAME || TARGET_CALLER_INTERWORKING \
+ || TARGET_TPCS_FRAME || TARGET_TPCS_LEAF_FRAME) \
{ \
fixed_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
call_used_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
+ if (TARGET_CALLER_INTERWORKING) \
+ global_regs[ARM_HARD_FRAME_POINTER_REGNUM] = 1; \
} \
SUBTARGET_CONDITIONAL_REGISTER_USAGE \
}
-
+
/* These are a couple of extensions to the formats accepted
by asm_fprintf:
%@ prints out ASM_COMMENT_START
@@ -1032,7 +760,8 @@ extern const char * structure_size_string;
/* Convert fron bytes to ints. */
#define ARM_NUM_INTS(X) (((X) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-/* The number of (integer) registers required to hold a quantity of type MODE. */
+/* The number of (integer) registers required to hold a quantity of type MODE.
+ Also used for VFP registers. */
#define ARM_NUM_REGS(MODE) \
ARM_NUM_INTS (GET_MODE_SIZE (MODE))
@@ -1047,20 +776,6 @@ extern const char * structure_size_string;
/* Return the register number of the N'th (integer) argument. */
#define ARG_REGISTER(N) (N - 1)
-#if 0 /* FIXME: The ARM backend has special code to handle structure
- returns, and will reserve its own hidden first argument. So
- if this macro is enabled a *second* hidden argument will be
- reserved, which will break binary compatibility with old
- toolchains and also thunk handling. One day this should be
- fixed. */
-/* RTX for structure returns. NULL means use a hidden first argument. */
-#define STRUCT_VALUE 0
-#else
-/* Register in which address to store a structure value
- is passed to a function. */
-#define STRUCT_VALUE_REGNUM ARG_REGISTER (1)
-#endif
-
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@@ -1073,8 +788,20 @@ extern const char * structure_size_string;
#define FIRST_HI_REGNUM 8
#define LAST_HI_REGNUM 11
+#ifndef TARGET_UNWIND_INFO
+/* We use sjlj exceptions for backwards compatibility. */
+#define MUST_USE_SJLJ_EXCEPTIONS 1
+#endif
+
+/* We can generate DWARF2 Unwind info, even though we don't use it. */
+#define DWARF2_UNWIND_INFO 1
+
+/* Use r0 and r1 to pass exception handling information. */
+#define EH_RETURN_DATA_REGNO(N) (((N) < 2) ? N : INVALID_REGNUM)
+
/* The register that holds the return address in exception handlers. */
-#define EXCEPTION_LR_REGNUM 2
+#define ARM_EH_STACKADJ_REGNUM 2
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (SImode, ARM_EH_STACKADJ_REGNUM)
/* The native (Norcroft) Pascal compiler for the ARM passes the static chain
as an invisible last argument (possible since varargs don't exist in
@@ -1111,8 +838,10 @@ extern const char * structure_size_string;
#define STACK_POINTER_REGNUM SP_REGNUM
/* ARM floating pointer registers. */
-#define FIRST_ARM_FP_REGNUM 16
-#define LAST_ARM_FP_REGNUM 23
+#define FIRST_FPA_REGNUM 16
+#define LAST_FPA_REGNUM 23
+#define IS_FPA_REGNUM(REGNUM) \
+ (((REGNUM) >= FIRST_FPA_REGNUM) && ((REGNUM) <= LAST_FPA_REGNUM))
#define FIRST_IWMMXT_GR_REGNUM 43
#define LAST_IWMMXT_GR_REGNUM 46
@@ -1134,19 +863,33 @@ extern const char * structure_size_string;
#define IS_CIRRUS_REGNUM(REGNUM) \
(((REGNUM) >= FIRST_CIRRUS_FP_REGNUM) && ((REGNUM) <= LAST_CIRRUS_FP_REGNUM))
+#define FIRST_VFP_REGNUM 63
+#define LAST_VFP_REGNUM 94
+#define IS_VFP_REGNUM(REGNUM) \
+ (((REGNUM) >= FIRST_VFP_REGNUM) && ((REGNUM) <= LAST_VFP_REGNUM))
+
/* The number of hard registers is 16 ARM + 8 FPA + 1 CC + 1 SFP + 1 AFP. */
/* + 16 Cirrus registers take us up to 43. */
/* Intel Wireless MMX Technology registers add 16 + 4 more. */
-#define FIRST_PSEUDO_REGISTER 63
+/* VFP adds 32 + 1 more. */
+#define FIRST_PSEUDO_REGISTER 96
+
+#define DBX_REGISTER_NUMBER(REGNO) arm_dbx_register_number (REGNO)
/* 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.
+ via the stack pointer) in functions that seem suitable.
If we have to have a frame pointer we might as well make use of it.
APCS says that the frame pointer does not need to be pushed in leaf
functions, or simple tail call functions. */
+
+#ifndef SUBTARGET_FRAME_POINTER_REQUIRED
+#define SUBTARGET_FRAME_POINTER_REQUIRED 0
+#endif
+
#define FRAME_POINTER_REQUIRED \
(current_function_has_nonlocal_label \
+ || SUBTARGET_FRAME_POINTER_REQUIRED \
|| (TARGET_ARM && TARGET_APCS_FRAME && ! leaf_function_p ()))
/* Return number of consecutive hard regs needed starting at reg REGNO
@@ -1158,9 +901,10 @@ extern const char * structure_size_string;
mode. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
((TARGET_ARM \
- && REGNO >= FIRST_ARM_FP_REGNUM \
+ && REGNO >= FIRST_FPA_REGNUM \
&& REGNO != FRAME_POINTER_REGNUM \
&& REGNO != ARG_POINTER_REGNUM) \
+ && !IS_VFP_REGNUM (REGNO) \
? 1 : ARM_NUM_REGS (MODE))
/* Return true if REGNO is suitable for holding a quantity of type MODE. */
@@ -1174,18 +918,16 @@ extern const char * structure_size_string;
#define MODES_TIEABLE_P(MODE1, MODE2) \
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2))
-#define VECTOR_MODE_SUPPORTED_P(MODE) \
- ((MODE) == V2SImode || (MODE) == V4HImode || (MODE) == V8QImode)
-
#define VALID_IWMMXT_REG_MODE(MODE) \
- (VECTOR_MODE_SUPPORTED_P (MODE) || (MODE) == DImode)
+ (arm_vector_mode_supported_p (MODE) || (MODE) == DImode)
/* The order in which register should be allocated. It is good to use ip
since no saving is required (though calls clobber it) and it never contains
function parameters. It is quite good to use lr since other calls may
- clobber it anyway. Allocate r0 through r3 in reverse order since r3 is
+ clobber it anyway. Allocate r0 through r3 in reverse order since r3 is
least likely to contain a function parameter; in addition results are
returned in r0. */
+
#define REG_ALLOC_ORDER \
{ \
3, 2, 1, 0, 12, 14, 4, 5, \
@@ -1196,7 +938,12 @@ extern const char * structure_size_string;
43, 44, 45, 46, 47, 48, 49, 50, \
51, 52, 53, 54, 55, 56, 57, 58, \
59, 60, 61, 62, \
- 24, 25, 26 \
+ 24, 25, 26, \
+ 78, 77, 76, 75, 74, 73, 72, 71, \
+ 70, 69, 68, 67, 66, 65, 64, 63, \
+ 79, 80, 81, 82, 83, 84, 85, 86, \
+ 87, 88, 89, 90, 91, 92, 93, 94, \
+ 95 \
}
/* Interrupt functions can only use registers that have already been
@@ -1215,6 +962,7 @@ enum reg_class
NO_REGS,
FPA_REGS,
CIRRUS_REGS,
+ VFP_REGS,
IWMMXT_GR_REGS,
IWMMXT_REGS,
LO_REGS,
@@ -1222,6 +970,7 @@ enum reg_class
BASE_REGS,
HI_REGS,
CC_REG,
+ VFPCC_REG,
GENERAL_REGS,
ALL_REGS,
LIM_REG_CLASSES
@@ -1235,6 +984,7 @@ enum reg_class
"NO_REGS", \
"FPA_REGS", \
"CIRRUS_REGS", \
+ "VFP_REGS", \
"IWMMXT_GR_REGS", \
"IWMMXT_REGS", \
"LO_REGS", \
@@ -1242,6 +992,7 @@ enum reg_class
"BASE_REGS", \
"HI_REGS", \
"CC_REG", \
+ "VFPCC_REG", \
"GENERAL_REGS", \
"ALL_REGS", \
}
@@ -1249,20 +1000,22 @@ enum reg_class
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
-#define REG_CLASS_CONTENTS \
-{ \
- { 0x00000000, 0x0 }, /* NO_REGS */ \
- { 0x00FF0000, 0x0 }, /* FPA_REGS */ \
- { 0xF8000000, 0x000007FF }, /* CIRRUS_REGS */ \
- { 0x00000000, 0x00007800 }, /* IWMMXT_GR_REGS */\
- { 0x00000000, 0x7FFF8000 }, /* IWMMXT_REGS */ \
- { 0x000000FF, 0x0 }, /* LO_REGS */ \
- { 0x00002000, 0x0 }, /* STACK_REG */ \
- { 0x000020FF, 0x0 }, /* BASE_REGS */ \
- { 0x0000FF00, 0x0 }, /* HI_REGS */ \
- { 0x01000000, 0x0 }, /* CC_REG */ \
- { 0x0200FFFF, 0x0 }, /* GENERAL_REGS */\
- { 0xFAFFFFFF, 0x7FFFFFFF } /* ALL_REGS */ \
+#define REG_CLASS_CONTENTS \
+{ \
+ { 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
+ { 0x00FF0000, 0x00000000, 0x00000000 }, /* FPA_REGS */ \
+ { 0xF8000000, 0x000007FF, 0x00000000 }, /* CIRRUS_REGS */ \
+ { 0x00000000, 0x80000000, 0x7FFFFFFF }, /* VFP_REGS */ \
+ { 0x00000000, 0x00007800, 0x00000000 }, /* IWMMXT_GR_REGS */ \
+ { 0x00000000, 0x7FFF8000, 0x00000000 }, /* IWMMXT_REGS */ \
+ { 0x000000FF, 0x00000000, 0x00000000 }, /* LO_REGS */ \
+ { 0x00002000, 0x00000000, 0x00000000 }, /* STACK_REG */ \
+ { 0x000020FF, 0x00000000, 0x00000000 }, /* BASE_REGS */ \
+ { 0x0000FF00, 0x00000000, 0x00000000 }, /* HI_REGS */ \
+ { 0x01000000, 0x00000000, 0x00000000 }, /* CC_REG */ \
+ { 0x00000000, 0x00000000, 0x80000000 }, /* VFPCC_REG */ \
+ { 0x0200FFFF, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0xFAFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF } /* ALL_REGS */ \
}
/* The same information, inverted:
@@ -1271,11 +1024,21 @@ enum reg_class
or could index an array. */
#define REGNO_REG_CLASS(REGNO) arm_regno_class (REGNO)
-/* FPA registers can't do dubreg as all values are reformatted to internal
- precision. */
+/* FPA registers can't do subreg as all values are reformatted to internal
+ precision. VFP registers may only be accessed in the mode they
+ were set. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
(GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? reg_classes_intersect_p (FPA_REGS, (CLASS)) : 0)
+ ? reg_classes_intersect_p (FPA_REGS, (CLASS)) \
+ || reg_classes_intersect_p (VFP_REGS, (CLASS)) \
+ : 0)
+
+/* We need to define this for LO_REGS on thumb. Otherwise we can end up
+ using r0-r4 for function arguments, r7 for the stack frame and don't
+ have enough left over to do doubleword arithmetic. */
+#define CLASS_LIKELY_SPILLED_P(CLASS) \
+ ((TARGET_THUMB && (CLASS) == LO_REGS) \
+ || (CLASS) == CC_REG)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS (TARGET_THUMB ? LO_REGS : GENERAL_REGS)
@@ -1283,12 +1046,14 @@ enum reg_class
/* For the Thumb the high registers cannot be used as base registers
when addressing quantities in QI or HI mode; if we don't know the
- mode, then we must be conservative. After reload we must also be
- conservative, since we can't support SP+reg addressing, and we
- can't fix up any bad substitutions. */
+ mode, then we must be conservative. */
#define MODE_BASE_REG_CLASS(MODE) \
(TARGET_ARM ? GENERAL_REGS : \
- (((MODE) == SImode && !reload_completed) ? BASE_REGS : LO_REGS))
+ (((MODE) == SImode) ? BASE_REGS : LO_REGS))
+
+/* For Thumb we can not support SP+reg addressing, so we return LO_REGS
+ instead of BASE_REGS. */
+#define MODE_BASE_REG_REG_CLASS(MODE) BASE_REG_CLASS
/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
registers explicitly used in the rtl to be used as spill registers
@@ -1296,89 +1061,6 @@ enum reg_class
registers. */
#define SMALL_REGISTER_CLASSES TARGET_THUMB
-/* Get reg_class from a letter such as appears in the machine description.
- We only need constraint `f' for FPA_REGS (`r' == GENERAL_REGS) for the
- ARM, but several more letters for the Thumb. */
-#define REG_CLASS_FROM_LETTER(C) \
- ( (C) == 'f' ? FPA_REGS \
- : (C) == 'v' ? CIRRUS_REGS \
- : (C) == 'y' ? IWMMXT_REGS \
- : (C) == 'z' ? IWMMXT_GR_REGS \
- : (C) == 'l' ? (TARGET_ARM ? GENERAL_REGS : LO_REGS) \
- : TARGET_ARM ? NO_REGS \
- : (C) == 'h' ? HI_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'k' ? STACK_REG \
- : (C) == 'c' ? CC_REG \
- : 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.
- I: immediate arithmetic operand (i.e. 8 bits shifted as required).
- J: valid indexing constants.
- K: ~value ok in rhs argument of data operand.
- L: -value ok in rhs argument of data operand.
- M: 0..32, or a power of 2 (for shifts, or mult done by shift). */
-#define CONST_OK_FOR_ARM_LETTER(VALUE, C) \
- ((C) == 'I' ? const_ok_for_arm (VALUE) : \
- (C) == 'J' ? ((VALUE) < 4096 && (VALUE) > -4096) : \
- (C) == 'K' ? (const_ok_for_arm (~(VALUE))) : \
- (C) == 'L' ? (const_ok_for_arm (-(VALUE))) : \
- (C) == 'M' ? (((VALUE >= 0 && VALUE <= 32)) \
- || (((VALUE) & ((VALUE) - 1)) == 0)) \
- : 0)
-
-#define CONST_OK_FOR_THUMB_LETTER(VAL, C) \
- ((C) == 'I' ? (unsigned HOST_WIDE_INT) (VAL) < 256 : \
- (C) == 'J' ? (VAL) > -256 && (VAL) < 0 : \
- (C) == 'K' ? thumb_shiftable_const (VAL) : \
- (C) == 'L' ? (VAL) > -8 && (VAL) < 8 : \
- (C) == 'M' ? ((unsigned HOST_WIDE_INT) (VAL) < 1024 \
- && ((VAL) & 3) == 0) : \
- (C) == 'N' ? ((unsigned HOST_WIDE_INT) (VAL) < 32) : \
- (C) == 'O' ? ((VAL) >= -508 && (VAL) <= 508) \
- : 0)
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- (TARGET_ARM ? \
- CONST_OK_FOR_ARM_LETTER (VALUE, C) : CONST_OK_FOR_THUMB_LETTER (VALUE, C))
-
-/* Constant letter 'G' for the FPA immediate constants.
- 'H' means the same constant negated. */
-#define CONST_DOUBLE_OK_FOR_ARM_LETTER(X, C) \
- ((C) == 'G' ? const_double_rtx_ok_for_fpa (X) : \
- (C) == 'H' ? neg_const_double_rtx_ok_for_fpa (X) : 0)
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(X, C) \
- (TARGET_ARM ? \
- CONST_DOUBLE_OK_FOR_ARM_LETTER (X, C) : 0)
-
-/* For the ARM, `Q' means that this is a memory operand that is just
- an offset from a register.
- `S' means any symbol that has the SYMBOL_REF_FLAG set or a CONSTANT_POOL
- address. This means that the symbol is in the text segment and can be
- accessed without using a load. */
-
-#define EXTRA_CONSTRAINT_ARM(OP, C) \
- ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG : \
- (C) == 'R' ? (GET_CODE (OP) == MEM \
- && GET_CODE (XEXP (OP, 0)) == SYMBOL_REF \
- && CONSTANT_POOL_ADDRESS_P (XEXP (OP, 0))) : \
- (C) == 'S' ? (optimize > 0 && CONSTANT_ADDRESS_P (OP)) : \
- (C) == 'T' ? cirrus_memory_offset (OP) : \
- 0)
-
-#define EXTRA_CONSTRAINT_THUMB(X, C) \
- ((C) == 'Q' ? (GET_CODE (X) == MEM \
- && GET_CODE (XEXP (X, 0)) == LABEL_REF) : 0)
-
-#define EXTRA_CONSTRAINT(X, C) \
- (TARGET_ARM ? \
- EXTRA_CONSTRAINT_ARM (X, C) : EXTRA_CONSTRAINT_THUMB (X, C))
-
/* 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 for the Thumb we prefer
@@ -1406,15 +1088,27 @@ enum reg_class
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
- (TARGET_ARM ? \
- (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
+ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
+ ((TARGET_VFP && TARGET_HARD_FLOAT \
+ && (CLASS) == VFP_REGS) \
+ ? coproc_secondary_reload_class (MODE, X, FALSE) \
+ : (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) \
+ ? coproc_secondary_reload_class (MODE, X, TRUE) \
+ : TARGET_ARM \
+ ? (((MODE) == HImode && ! arm_arch4 && true_regnum (X) == -1) \
? GENERAL_REGS : NO_REGS) \
: THUMB_SECONDARY_OUTPUT_RELOAD_CLASS (CLASS, MODE, X))
-
+
/* If we need to load shorts byte-at-a-time, then we need a scratch. */
#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ /* Restrict which direct reloads are allowed for VFP/iWMMXt regs. */ \
+ ((TARGET_VFP && TARGET_HARD_FLOAT \
+ && (CLASS) == VFP_REGS) \
+ ? coproc_secondary_reload_class (MODE, X, FALSE) : \
+ (TARGET_IWMMXT && (CLASS) == IWMMXT_REGS) ? \
+ coproc_secondary_reload_class (MODE, X, TRUE) : \
/* Cannot load constants into Cirrus registers. */ \
- ((TARGET_CIRRUS \
+ (TARGET_MAVERICK && TARGET_HARD_FLOAT \
&& (CLASS) == CIRRUS_REGS \
&& (CONSTANT_P (X) || GET_CODE (X) == SYMBOL_REF)) \
? GENERAL_REGS : \
@@ -1422,7 +1116,7 @@ enum reg_class
(((CLASS) == IWMMXT_REGS || (CLASS) == IWMMXT_GR_REGS) \
&& CONSTANT_P (X)) \
? GENERAL_REGS : \
- (((MODE) == HImode && ! arm_arch4 && TARGET_MMU_TRAPS \
+ (((MODE) == HImode && ! arm_arch4 \
&& (GET_CODE (X) == MEM \
|| ((GET_CODE (X) == REG || GET_CODE (X) == SUBREG) \
&& true_regnum (X) == -1))) \
@@ -1448,9 +1142,9 @@ enum reg_class
HOST_WIDE_INT val = INTVAL (XEXP (X, 1)); \
HOST_WIDE_INT low, high; \
\
- if (MODE == DImode || (TARGET_SOFT_FLOAT && MODE == DFmode)) \
+ if (MODE == DImode || (MODE == DFmode && TARGET_SOFT_FLOAT)) \
low = ((val & 0xf) ^ 0x8) - 0x8; \
- else if (TARGET_CIRRUS) \
+ else if (TARGET_MAVERICK && TARGET_HARD_FLOAT) \
/* Need to be careful, -256 is not a valid offset. */ \
low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
else if (MODE == SImode \
@@ -1462,7 +1156,7 @@ enum reg_class
/* Need to be careful, -256 is not a valid offset. */ \
low = val >= 0 ? (val & 0xff) : -((-val) & 0xff); \
else if (GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && TARGET_HARD_FLOAT) \
+ && TARGET_HARD_FLOAT && TARGET_FPA) \
/* Need to be careful, -1024 is not a valid offset. */ \
low = val >= 0 ? (val & 0x3ff) : -((-val) & 0x3ff); \
else \
@@ -1497,30 +1191,22 @@ enum reg_class
/* We could probably achieve better results by defining PROMOTE_MODE to help
cope with the variances between the Thumb's signed and unsigned byte and
halfword load instructions. */
-#define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
-{ \
- if (GET_CODE (X) == PLUS \
- && GET_MODE_SIZE (MODE) < 4 \
- && GET_CODE (XEXP (X, 0)) == REG \
- && XEXP (X, 0) == stack_pointer_rtx \
- && GET_CODE (XEXP (X, 1)) == CONST_INT \
- && ! thumb_legitimate_offset_p (MODE, INTVAL (XEXP (X, 1)))) \
- { \
- rtx orig_X = X; \
- X = copy_rtx (X); \
- push_reload (orig_X, NULL_RTX, &X, NULL, \
- MODE_BASE_REG_CLASS (MODE), \
- Pmode, VOIDmode, 0, 0, OPNUM, TYPE); \
- goto WIN; \
- } \
-}
+#define THUMB_LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_L, WIN) \
+do { \
+ rtx new_x = thumb_legitimize_reload_address (&X, MODE, OPNUM, TYPE, IND_L); \
+ if (new_x) \
+ { \
+ X = new_x; \
+ goto WIN; \
+ } \
+} while (0)
#define LEGITIMIZE_RELOAD_ADDRESS(X, MODE, OPNUM, TYPE, IND_LEVELS, WIN) \
if (TARGET_ARM) \
ARM_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN); \
else \
THUMB_LEGITIMIZE_RELOAD_ADDRESS (X, MODE, OPNUM, TYPE, IND_LEVELS, WIN)
-
+
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS.
ARM regs are UNITS_PER_WORD bits while FPA regs can hold any FP mode */
@@ -1535,6 +1221,8 @@ enum reg_class
(TARGET_ARM ? \
((FROM) == FPA_REGS && (TO) != FPA_REGS ? 20 : \
(FROM) != FPA_REGS && (TO) == FPA_REGS ? 20 : \
+ (FROM) == VFP_REGS && (TO) != VFP_REGS ? 10 : \
+ (FROM) != VFP_REGS && (TO) == VFP_REGS ? 10 : \
(FROM) == IWMMXT_REGS && (TO) != IWMMXT_REGS ? 4 : \
(FROM) != IWMMXT_REGS && (TO) == IWMMXT_REGS ? 4 : \
(FROM) == IWMMXT_GR_REGS || (TO) == IWMMXT_GR_REGS ? 20 : \
@@ -1550,12 +1238,26 @@ enum reg_class
makes the stack pointer a smaller address. */
#define STACK_GROWS_DOWNWARD 1
-/* Define this if the nominal address of the stack frame
+/* Define this to nonzero if the nominal address of the stack frame
is at the high-address end of the local variables;
that is, each additional local variable allocated
goes at a more negative offset in the frame. */
#define FRAME_GROWS_DOWNWARD 1
+/* The amount of scratch space needed by _interwork_{r7,r11}_call_via_rN().
+ When present, it is one word in size, and sits at the top of the frame,
+ between the soft frame pointer and either r7 or r11.
+
+ We only need _interwork_rM_call_via_rN() for -mcaller-super-interworking,
+ and only then if some outgoing arguments are passed on the stack. It would
+ be tempting to also check whether the stack arguments are passed by indirect
+ calls, but there seems to be no reason in principle why a post-reload pass
+ couldn't convert a direct call into an indirect one. */
+#define CALLER_INTERWORKING_SLOT_SIZE \
+ (TARGET_CALLER_INTERWORKING \
+ && current_function_outgoing_args_size != 0 \
+ ? UNITS_PER_WORD : 0)
+
/* 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
@@ -1590,11 +1292,13 @@ enum reg_class
/* Define how to find the value returned by a library function
assuming the value has mode MODE. */
#define LIBCALL_VALUE(MODE) \
- (TARGET_ARM && TARGET_HARD_FLOAT && GET_MODE_CLASS (MODE) == MODE_FLOAT \
- ? gen_rtx_REG (MODE, FIRST_ARM_FP_REGNUM) \
- : TARGET_ARM && TARGET_CIRRUS && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ (TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_FPA \
+ && GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ ? gen_rtx_REG (MODE, FIRST_FPA_REGNUM) \
+ : TARGET_ARM && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK \
+ && GET_MODE_CLASS (MODE) == MODE_FLOAT \
? gen_rtx_REG (MODE, FIRST_CIRRUS_FP_REGNUM) \
- : TARGET_REALLY_IWMMXT && VECTOR_MODE_SUPPORTED_P (MODE) \
+ : TARGET_IWMMXT_ABI && arm_vector_mode_supported_p (MODE) \
? gen_rtx_REG (MODE, FIRST_IWMMXT_REGNUM) \
: gen_rtx_REG (MODE, ARG_REGISTER (1)))
@@ -1603,16 +1307,22 @@ enum reg_class
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0. */
#define FUNCTION_VALUE(VALTYPE, FUNC) \
- LIBCALL_VALUE (TYPE_MODE (VALTYPE))
+ arm_function_value (VALTYPE, FUNC);
/* 1 if N is a possible register number for a function value.
On the ARM, only r0 and f0 can return results. */
/* On a Cirrus chip, mvf0 can return results. */
#define FUNCTION_VALUE_REGNO_P(REGNO) \
((REGNO) == ARG_REGISTER (1) \
- || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) && TARGET_CIRRUS) \
- || (TARGET_ARM && ((REGNO) == FIRST_IWMMXT_REGNUM) && TARGET_IWMMXT) \
- || (TARGET_ARM && ((REGNO) == FIRST_ARM_FP_REGNUM) && TARGET_HARD_FLOAT))
+ || (TARGET_ARM && ((REGNO) == FIRST_CIRRUS_FP_REGNUM) \
+ && TARGET_HARD_FLOAT_ABI && TARGET_MAVERICK) \
+ || ((REGNO) == FIRST_IWMMXT_REGNUM && TARGET_IWMMXT_ABI) \
+ || (TARGET_ARM && ((REGNO) == FIRST_FPA_REGNUM) \
+ && TARGET_HARD_FLOAT_ABI && TARGET_FPA))
+
+/* Amount of memory needed for an untyped call to save all possible return
+ registers. */
+#define APPLY_RESULT_SIZE arm_apply_result_size()
/* How large values are returned */
/* A C expression which can inhibit the returning of certain function values
@@ -1630,7 +1340,7 @@ enum reg_class
#define CALL_SHORT 0x00000002 /* Never call indirect. */
/* These bits describe the different types of function supported
- by the ARM backend. They are exclusive. ie a function cannot be both a
+ by the ARM backend. They are exclusive. i.e. a function cannot be both a
normal function and an interworked function, for example. Knowing the
type of a function is important for determining its prologue and
epilogue sequences.
@@ -1643,7 +1353,6 @@ enum reg_class
#define ARM_FT_UNKNOWN 0 /* Type has not yet been determined. */
#define ARM_FT_NORMAL 1 /* Your normal, straightforward function. */
#define ARM_FT_INTERWORKED 2 /* A function that supports interworking. */
-#define ARM_FT_EXCEPTION_HANDLER 3 /* A C++ exception handler. */
#define ARM_FT_ISR 4 /* An interrupt service routine. */
#define ARM_FT_FIQ 5 /* A fast interrupt service routine. */
#define ARM_FT_EXCEPTION 6 /* An ARM exception handler (subcase of ISR). */
@@ -1664,6 +1373,23 @@ enum reg_class
#define IS_NAKED(t) (t & ARM_FT_NAKED)
#define IS_NESTED(t) (t & ARM_FT_NESTED)
+
+/* Structure used to hold the function stack frame layout. Offsets are
+ relative to the stack pointer on function entry. Positive offsets are
+ in the direction of stack growth.
+ Only soft_frame is used in thumb mode. */
+
+typedef struct arm_stack_offsets GTY(())
+{
+ int saved_args; /* ARG_POINTER_REGNUM. */
+ int frame; /* ARM_HARD_FRAME_POINTER_REGNUM. */
+ int saved_regs;
+ int soft_frame; /* FRAME_POINTER_REGNUM. */
+ int locals_base; /* THUMB_HARD_FRAME_POINTER_REGNUM. */
+ int outgoing_args; /* STACK_POINTER_REGNUM. */
+}
+arm_stack_offsets;
+
/* A C structure for machine-specific, per-function data.
This is added to the cfun structure. */
typedef struct machine_function GTY(())
@@ -1677,7 +1403,7 @@ typedef struct machine_function GTY(())
/* Records if the save of LR has been eliminated. */
int lr_save_eliminated;
/* The size of the stack frame. Only valid after reload. */
- int frame_size;
+ arm_stack_offsets stack_offsets;
/* Records the type of the current function. */
unsigned long func_type;
/* Record if the function has a variable argument list. */
@@ -1685,9 +1411,19 @@ typedef struct machine_function GTY(())
/* Records if sibcalls are blocked because an argument
register is needed to preserve stack alignment. */
int sibcall_blocked;
+ /* The PIC register for this function. This might be a pseudo. */
+ rtx pic_reg;
+ /* Labels for per-function Thumb call-via stubs. One per potential calling
+ register. We can never call via LR or PC. We can call via SP if a
+ trampoline happens to be on the top of the stack. */
+ rtx call_via[14];
}
machine_function;
+/* As in the machine_function, a global set of call-via labels, for code
+ that is in text_section. */
+extern GTY(()) rtx thumb_call_via_label[14];
+
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the
type `int' suffices and can hold the number of bytes of argument so far. */
@@ -1701,6 +1437,7 @@ typedef struct
int nargs;
/* One of CALL_NORMAL, CALL_LONG or CALL_SHORT. */
int call_cookie;
+ int can_split;
} CUMULATIVE_ARGS;
/* Define where to put the arguments to a function.
@@ -1718,28 +1455,22 @@ typedef struct
On the ARM, normally the first 16 bytes are passed in registers r0-r3; all
other arguments are passed on the stack. If (NAMED == 0) (which happens
- only in assign_parms, since SETUP_INCOMING_VARARGS is defined), say it is
- passed in the stack (function_prologue will indeed make it pass in the
- stack if necessary). */
+ only in assign_parms, since TARGET_SETUP_INCOMING_VARARGS is
+ defined), say it is passed in the stack (function_prologue will
+ indeed make it pass in the stack if necessary). */
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
arm_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
-/* 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) \
- (VECTOR_MODE_SUPPORTED_P (MODE) ? 0 : \
- NUM_ARG_REGS > (CUM).nregs \
- && (NUM_ARG_REGS < ((CUM).nregs + ARM_NUM_REGS2 (MODE, TYPE))) \
- ? NUM_ARG_REGS - (CUM).nregs : 0)
-
-/* A C expression that indicates when an argument must be passed by
- reference. If nonzero for an argument, a copy of that argument is
- made in memory and a pointer to the argument is passed instead of
- the argument itself. The pointer is passed in whatever way is
- appropriate for passing a pointer to that type. */
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- arm_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (arm_pad_arg_upward (MODE, TYPE) ? upward : downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+ (arm_pad_reg_upward (MODE, TYPE, FIRST) ? upward : downward)
+
+/* For AAPCS, padding should never be below the argument. For other ABIs,
+ * mimic the default. */
+#define PAD_VARARGS_DOWN \
+ ((TARGET_AAPCS_BASED) ? 0 : BYTES_BIG_ENDIAN)
/* Initialize a variable CUM of type CUMULATIVE_ARGS
for a call to a function whose data type is FNTYPE.
@@ -1753,52 +1484,28 @@ typedef struct
(TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
(CUM).nargs += 1; \
- if (VECTOR_MODE_SUPPORTED_P (MODE)) \
- if ((CUM).named_count <= (CUM).nargs) \
- (CUM).nregs += 2; \
- else \
- (CUM).iwmmxt_nregs += 1; \
+ if (arm_vector_mode_supported_p (MODE) \
+ && (CUM).named_count > (CUM).nargs) \
+ (CUM).iwmmxt_nregs += 1; \
else \
- (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
+ (CUM).nregs += ARM_NUM_REGS2 (MODE, TYPE)
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. If it is not defined,
`PARM_BOUNDARY' is used for all arguments. */
#define FUNCTION_ARG_BOUNDARY(MODE,TYPE) \
- (TARGET_REALLY_IWMMXT && (VALID_IWMMXT_REG_MODE (MODE) || ((MODE) == DFmode)) \
- ? IWMMXT_ALIGNMENT : PARM_BOUNDARY)
+ ((ARM_DOUBLEWORD_ALIGN && arm_needs_doubleword_align (MODE, TYPE)) \
+ ? DOUBLEWORD_ALIGNMENT \
+ : PARM_BOUNDARY )
/* 1 if N is a possible register number for function argument passing.
On the ARM, r0-r3 are used to pass args. */
#define FUNCTION_ARG_REGNO_P(REGNO) \
(IN_RANGE ((REGNO), 0, 3) \
- || (TARGET_REALLY_IWMMXT && IN_RANGE ((REGNO), FIRST_IWMMXT_REGNUM, FIRST_IWMMXT_REGNUM + 9)))
-
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- arm_va_arg (valist, type)
+ || (TARGET_IWMMXT_ABI \
+ && IN_RANGE ((REGNO), FIRST_IWMMXT_REGNUM, FIRST_IWMMXT_REGNUM + 9)))
-/* Perform any actions needed for a function that is receiving a variable
- number of arguments. CUM is as above. MODE and TYPE are the mode and type
- of the current parameter. PRETEND_SIZE is a variable that should be set to
- the amount of stack that must be pushed by the prolog to pretend that our
- caller pushed it.
-
- Normally, this macro will push all remaining incoming registers on the
- stack and set PRETEND_SIZE to the length of the registers pushed.
-
- On the ARM, PRETEND_SIZE is set in order to have the prologue push the last
- named arg and all anonymous args onto the stack.
- XXX I know the prologue shouldn't be pushing registers, but it is faster
- that way. */
-#define SETUP_INCOMING_VARARGS(CUM, MODE, TYPE, PRETEND_SIZE, NO_RTL) \
-{ \
- cfun->machine->uses_anonymous_args = 1; \
- if ((CUM).nregs < NUM_ARG_REGS) \
- (PRETEND_SIZE) = (NUM_ARG_REGS - (CUM).nregs) * UNITS_PER_WORD; \
-}
-
/* If your target environment doesn't prefix user functions with an
underscore, you may wish to re-define this to prevent any conflicts.
e.g. AOF may prefix mcount with an underscore. */
@@ -1836,7 +1543,7 @@ typedef struct
assemble_name (STREAM, ARM_MCOUNT_NAME); \
fputc ('\n', STREAM); \
ASM_GENERATE_INTERNAL_LABEL (temp, "LP", LABELNO); \
- sym = gen_rtx (SYMBOL_REF, Pmode, temp); \
+ sym = gen_rtx_SYMBOL_REF (Pmode, temp); \
assemble_aligned_integer (UNITS_PER_WORD, sym); \
}
#endif
@@ -1906,64 +1613,17 @@ typedef struct
((TO) == THUMB_HARD_FRAME_POINTER_REGNUM && TARGET_ARM) ? 0 : \
1)
-#define THUMB_REG_PUSHED_P(reg) \
- (regs_ever_live [reg] \
- && (! call_used_regs [reg] \
- || (flag_pic && (reg) == PIC_OFFSET_TABLE_REGNUM)) \
- && !(TARGET_SINGLE_PIC_BASE && ((reg) == arm_pic_register)))
-
/* Define the offset between two registers, one to be eliminated, and the
other its replacement, at the start of a routine. */
-#define ARM_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- do \
- { \
- (OFFSET) = arm_compute_initial_elimination_offset (FROM, TO); \
- } \
- while (0)
-
-/* Note: This macro must match the code in thumb_function_prologue(). */
-#define THUMB_INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
-{ \
- (OFFSET) = 0; \
- if ((FROM) == ARG_POINTER_REGNUM) \
- { \
- int count_regs = 0; \
- int regno; \
- for (regno = 8; regno < 13; regno ++) \
- if (THUMB_REG_PUSHED_P (regno)) \
- count_regs ++; \
- if (count_regs) \
- (OFFSET) += 4 * count_regs; \
- count_regs = 0; \
- for (regno = 0; regno <= LAST_LO_REGNUM; regno ++) \
- if (THUMB_REG_PUSHED_P (regno)) \
- count_regs ++; \
- if (count_regs || ! leaf_function_p () || thumb_far_jump_used_p (0))\
- (OFFSET) += 4 * (count_regs + 1); \
- if (TARGET_BACKTRACE) \
- { \
- if ((count_regs & 0xFF) == 0 && (regs_ever_live[3] != 0)) \
- (OFFSET) += 20; \
- else \
- (OFFSET) += 16; \
- } \
- } \
- if ((TO) == STACK_POINTER_REGNUM) \
- { \
- (OFFSET) += current_function_outgoing_args_size; \
- (OFFSET) += thumb_get_frame_size (); \
- } \
-}
-
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
if (TARGET_ARM) \
- ARM_INITIAL_ELIMINATION_OFFSET (FROM, TO, OFFSET); \
+ (OFFSET) = arm_compute_initial_elimination_offset (FROM, TO); \
else \
- THUMB_INITIAL_ELIMINATION_OFFSET (FROM, TO, OFFSET)
-
+ (OFFSET) = thumb_compute_initial_elimination_offset (FROM, TO)
+
/* Special case handling of the location of arguments passed on the stack. */
#define DEBUGGER_ARG_OFFSET(value, addr) value ? value : arm_debugger_arg_offset (value, addr)
-
+
/* Initialize data used by insn expanders. This is called from insn_emit,
once for every function before code is generated. */
#define INIT_EXPANDERS arm_init_expanders ()
@@ -2016,13 +1676,14 @@ typedef struct
ARM_TRAMPOLINE_TEMPLATE (FILE) \
else \
THUMB_TRAMPOLINE_TEMPLATE (FILE)
-
+
/* Length in units of the trampoline for entering a nested function. */
#define TRAMPOLINE_SIZE (TARGET_ARM ? 16 : 24)
/* Alignment required for a trampoline in bits. */
#define TRAMPOLINE_ALIGNMENT 32
+
/* 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. */
@@ -2037,6 +1698,9 @@ typedef struct
plus_constant (TRAMP, \
TARGET_ARM ? 12 : 20)), \
FNADDR); \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
+ 0, VOIDmode, 2, TRAMP, Pmode, \
+ plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
}
#endif
@@ -2077,6 +1741,11 @@ typedef struct
? THUMB_REGNO_MODE_OK_FOR_BASE_P (REGNO, MODE) \
: ARM_REGNO_OK_FOR_BASE_P (REGNO))
+/* Nonzero if X can be the base register in a reg+reg addressing mode.
+ For Thumb, we can not use SP + reg, so reject SP. */
+#define REGNO_MODE_OK_FOR_REG_BASE_P(X, MODE) \
+ REGNO_OK_FOR_INDEX_P (X)
+
/* For ARM code, we don't care about the mode, but for Thumb, the index
must be suitable for use in a QImode load. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
@@ -2109,7 +1778,7 @@ typedef struct
On the ARM, allow any integer (invalid ones are removed later by insn
patterns), nice doubles and symbol_refs which refer to the function's
constant pool XXX.
-
+
When generating pic allow anything. */
#define ARM_LEGITIMATE_CONSTANT_P(X) (flag_pic || ! label_mentioned_p (X))
@@ -2119,8 +1788,10 @@ typedef struct
|| CONSTANT_ADDRESS_P (X) \
|| flag_pic)
-#define LEGITIMATE_CONSTANT_P(X) \
- (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) : THUMB_LEGITIMATE_CONSTANT_P (X))
+#define LEGITIMATE_CONSTANT_P(X) \
+ (!arm_tls_referenced_p (X) \
+ && (TARGET_ARM ? ARM_LEGITIMATE_CONSTANT_P (X) \
+ : THUMB_LEGITIMATE_CONSTANT_P (X)))
/* Special characters prefixed to function names
in order to encode attribute like information.
@@ -2146,7 +1817,7 @@ typedef struct
case SHORT_CALL_FLAG_CHAR: return 1; \
case LONG_CALL_FLAG_CHAR: return 1; \
case '*': return 1; \
- SUBTARGET_NAME_ENCODING_LENGTHS
+ SUBTARGET_NAME_ENCODING_LENGTHS
/* This is how to output a reference to a user-level label named NAME.
`assemble_name' uses this. */
@@ -2154,8 +1825,75 @@ typedef struct
#define ASM_OUTPUT_LABELREF(FILE, NAME) \
arm_asm_output_labelref (FILE, NAME)
+/* The EABI specifies that constructors should go in .init_array.
+ Other targets use .ctors for compatibility. */
+#ifndef ARM_EABI_CTORS_SECTION_OP
+#define ARM_EABI_CTORS_SECTION_OP \
+ "\t.section\t.init_array,\"aw\",%init_array"
+#endif
+#ifndef ARM_EABI_DTORS_SECTION_OP
+#define ARM_EABI_DTORS_SECTION_OP \
+ "\t.section\t.fini_array,\"aw\",%fini_array"
+#endif
+#define ARM_CTORS_SECTION_OP \
+ "\t.section\t.ctors,\"aw\",%progbits"
+#define ARM_DTORS_SECTION_OP \
+ "\t.section\t.dtors,\"aw\",%progbits"
+
+/* Define CTORS_SECTION_ASM_OP. */
+#undef CTORS_SECTION_ASM_OP
+#undef DTORS_SECTION_ASM_OP
+#ifndef IN_LIBGCC2
+# define CTORS_SECTION_ASM_OP \
+ (TARGET_AAPCS_BASED ? ARM_EABI_CTORS_SECTION_OP : ARM_CTORS_SECTION_OP)
+# define DTORS_SECTION_ASM_OP \
+ (TARGET_AAPCS_BASED ? ARM_EABI_DTORS_SECTION_OP : ARM_DTORS_SECTION_OP)
+#else /* !defined (IN_LIBGCC2) */
+/* In libgcc, CTORS_SECTION_ASM_OP must be a compile-time constant,
+ so we cannot use the definition above. */
+# ifdef __ARM_EABI__
+/* The .ctors section is not part of the EABI, so we do not define
+ CTORS_SECTION_ASM_OP when in libgcc; that prevents crtstuff
+ from trying to use it. We do define it when doing normal
+ compilation, as .init_array can be used instead of .ctors. */
+/* There is no need to emit begin or end markers when using
+ init_array; the dynamic linker will compute the size of the
+ array itself based on special symbols created by the static
+ linker. However, we do need to arrange to set up
+ exception-handling here. */
+# define CTOR_LIST_BEGIN asm (ARM_EABI_CTORS_SECTION_OP)
+# define CTOR_LIST_END /* empty */
+# define DTOR_LIST_BEGIN asm (ARM_EABI_DTORS_SECTION_OP)
+# define DTOR_LIST_END /* empty */
+# else /* !defined (__ARM_EABI__) */
+# define CTORS_SECTION_ASM_OP ARM_CTORS_SECTION_OP
+# define DTORS_SECTION_ASM_OP ARM_DTORS_SECTION_OP
+# endif /* !defined (__ARM_EABI__) */
+#endif /* !defined (IN_LIBCC2) */
+
+/* True if the operating system can merge entities with vague linkage
+ (e.g., symbols in COMDAT group) during dynamic linking. */
+#ifndef TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P
+#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P true
+#endif
+
+/* Set the short-call flag for any function compiled in the current
+ compilation unit. We skip this for functions with the section
+ attribute when long-calls are in effect as this tells the compiler
+ that the section might be placed a long way from the caller.
+ See arm_is_longcall_p() for more information. */
#define ARM_DECLARE_FUNCTION_SIZE(STREAM, NAME, DECL) \
- arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
+ if (!TARGET_LONG_CALLS || ! DECL_SECTION_NAME (DECL)) \
+ arm_encode_call_attribute (DECL, SHORT_CALL_FLAG_CHAR)
+
+#define ARM_OUTPUT_FN_UNWIND(F, PROLOGUE) arm_output_fn_unwind (F, PROLOGUE)
+
+#ifdef TARGET_UNWIND_INFO
+#define ARM_EABI_UNWIND_TABLES \
+ ((!USING_SJLJ_EXCEPTIONS && flag_exceptions) || flag_unwind_tables)
+#else
+#define ARM_EABI_UNWIND_TABLES 0
+#endif
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
@@ -2214,12 +1952,16 @@ typedef struct
? THUMB_REG_OK_FOR_INDEX_P (X) \
: ARM_REG_OK_FOR_INDEX_P (X))
+/* Nonzero if X can be the base register in a reg+reg addressing mode.
+ For Thumb, we can not use SP + reg, so reject SP. */
+#define REG_MODE_OK_FOR_REG_BASE_P(X, MODE) \
+ REG_OK_FOR_INDEX_P (X)
/* 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. */
-
+
#define ARM_BASE_REGISTER_RTX_P(X) \
(GET_CODE (X) == REG && ARM_REG_OK_FOR_BASE_P (X))
@@ -2228,7 +1970,7 @@ typedef struct
#define ARM_GO_IF_LEGITIMATE_ADDRESS(MODE,X,WIN) \
{ \
- if (arm_legitimate_address_p (MODE, X, REG_STRICT_P)) \
+ if (arm_legitimate_address_p (MODE, X, SET, REG_STRICT_P)) \
goto WIN; \
}
@@ -2242,7 +1984,7 @@ typedef struct
if (TARGET_ARM) \
ARM_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN) \
else /* if (TARGET_THUMB) */ \
- THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
+ THUMB_GO_IF_LEGITIMATE_ADDRESS (MODE, X, WIN)
/* Try machine-dependent ways of modifying an illegitimate address
@@ -2250,15 +1992,11 @@ typedef struct
#define ARM_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
do { \
X = arm_legitimize_address (X, OLDX, MODE); \
- \
- if (memory_address_p (MODE, X)) \
- goto WIN; \
} while (0)
-#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
-do { \
- if (flag_pic) \
- (X) = legitimize_pic_address (OLDX, MODE, NULL_RTX); \
+#define THUMB_LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
+do { \
+ X = thumb_legitimize_address (X, OLDX, MODE); \
} while (0)
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
@@ -2267,8 +2005,11 @@ do { \
ARM_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
else \
THUMB_LEGITIMIZE_ADDRESS (X, OLDX, MODE, WIN); \
+ \
+ if (memory_address_p (MODE, X)) \
+ goto WIN; \
} while (0)
-
+
/* Go to LABEL if ADDR (a legitimate address expression)
has an effect that depends on the machine mode it is used for. */
#define ARM_GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
@@ -2281,28 +2022,19 @@ do { \
/* Nothing helpful to do for the Thumb */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
if (TARGET_ARM) \
- ARM_GO_IF_MODE_DEPENDENT_ADDRESS (ADDR, LABEL)
+ ARM_GO_IF_MODE_DEPENDENT_ADDRESS (ADDR, LABEL)
/* Specify the machine mode that this machine uses
for the index in the tablejump instruction. */
#define CASE_VECTOR_MODE Pmode
-/* Define as C expression which evaluates to nonzero if the tablejump
- instruction expects the table to contain offsets from the address of the
- table.
- Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE 1 */
-
/* signed 'char' is most compatible, but RISC OS wants it unsigned.
unsigned is probably best, but may break some code. */
#ifndef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR 0
#endif
-/* Don't cse the address of the function being compiled. */
-#define NO_RECURSIVE_FUNCTION_CSE 1
-
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
#define MOVE_MAX 4
@@ -2317,17 +2049,17 @@ do { \
/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
will either zero-extend or sign-extend. The value of this macro should
be the code that says which one of the two operations is implicitly
- done, NIL if none. */
+ done, UNKNOWN if none. */
#define LOAD_EXTEND_OP(MODE) \
(TARGET_THUMB ? ZERO_EXTEND : \
((arm_arch4 || (MODE) == QImode) ? ZERO_EXTEND \
- : ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : NIL)))
+ : ((BYTES_BIG_ENDIAN && (MODE) == HImode) ? SIGN_EXTEND : UNKNOWN)))
/* Nonzero if access to memory by bytes is slow and undesirable. */
#define SLOW_BYTE_ACCESS 0
#define SLOW_UNALIGNED_ACCESS(MODE, ALIGN) 1
-
+
/* Immediate shift counts are truncated by the output routines (or was it
the assembler?). Shift counts in a register are truncated by ARM. Note
that the native compiler puts too large (> 32) immediate shift counts
@@ -2345,9 +2077,6 @@ do { \
/* Calling from registers is a massive pain. */
#define NO_FUNCTION_CSE 1
-/* Chars and shorts should be passed as ints. */
-#define PROMOTE_PROTOTYPES 1
-
/* The machine modes of pointers and functions */
#define Pmode SImode
#define FUNCTION_MODE Pmode
@@ -2361,7 +2090,7 @@ do { \
(TARGET_ARM ? 10 : \
((GET_MODE_SIZE (M) < 4 ? 8 : 2 * GET_MODE_SIZE (M)) \
* (CLASS == LO_REGS ? 1 : 2)))
-
+
/* Try to generate sequences that don't involve branches, we can then use
conditional instructions */
#define BRANCH_COST \
@@ -2371,26 +2100,23 @@ do { \
/* We decide which register to use based on the compilation options and
the assembler in use; this is more general than the APCS restriction of
using sb (r9) all the time. */
-extern int arm_pic_register;
-
-/* Used when parsing command line option -mpic-register=. */
-extern const char * arm_pic_register_string;
+extern unsigned arm_pic_register;
/* The register number of the register used to address a table of static
data addresses in memory. */
#define PIC_OFFSET_TABLE_REGNUM arm_pic_register
-#define FINALIZE_PIC arm_finalize_pic (1)
-
/* We can't directly access anything that contains a symbol,
- nor can we indirect via the constant pool. */
+ nor can we indirect via the constant pool. One exception is
+ UNSPEC_TLS, which is always PIC. */
#define LEGITIMATE_PIC_OPERAND_P(X) \
(!(symbol_mentioned_p (X) \
|| label_mentioned_p (X) \
|| (GET_CODE (X) == SYMBOL_REF \
&& CONSTANT_POOL_ADDRESS_P (X) \
&& (symbol_mentioned_p (get_pool_constant (X)) \
- || label_mentioned_p (get_pool_constant (X))))))
+ || label_mentioned_p (get_pool_constant (X))))) \
+ || tls_mentioned_p (X))
/* We need to know when we are making a constant pool; this determines
whether data needs to be in the GOT or can be referenced via a GOT
@@ -2410,7 +2136,12 @@ extern int making_const_table;
#define SELECT_CC_MODE(OP, X, Y) arm_select_cc_mode (OP, X, Y)
-#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode)
+#define REVERSIBLE_CC_MODE(MODE) 1
+
+#define REVERSE_CONDITION(CODE,MODE) \
+ (((MODE) == CCFPmode || (MODE) == CCFPEmode) \
+ ? reverse_condition_maybe_unordered (code) \
+ : reverse_condition (code))
#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
do \
@@ -2420,7 +2151,8 @@ extern int making_const_table;
|| (const_ok_for_arm (- INTVAL (OP1))))) \
{ \
rtx const_op = OP1; \
- CODE = arm_canonicalize_comparison ((CODE), &const_op); \
+ CODE = arm_canonicalize_comparison ((CODE), GET_MODE (OP0), \
+ &const_op); \
OP1 = const_op; \
} \
} \
@@ -2593,7 +2325,7 @@ extern int making_const_table;
} \
\
default: \
- abort(); \
+ gcc_unreachable (); \
} \
} \
else if (GET_CODE (X) == PRE_INC || GET_CODE (X) == POST_INC \
@@ -2601,8 +2333,7 @@ extern int making_const_table;
{ \
extern enum machine_mode output_memory_reference_mode; \
\
- if (GET_CODE (XEXP (X, 0)) != REG) \
- abort (); \
+ gcc_assert (GET_CODE (XEXP (X, 0)) == REG); \
\
if (GET_CODE (X) == PRE_DEC || GET_CODE (X) == PRE_INC) \
asm_fprintf (STREAM, "[%r, #%s%d]!", \
@@ -2646,8 +2377,7 @@ extern int making_const_table;
asm_fprintf (STREAM, "%r!", REGNO (XEXP (X, 0))); \
else if (GET_CODE (X) == PLUS) \
{ \
- if (GET_CODE (XEXP (X, 0)) != REG) \
- abort (); \
+ gcc_assert (GET_CODE (XEXP (X, 0)) == REG); \
if (GET_CODE (XEXP (X, 1)) == CONST_INT) \
asm_fprintf (STREAM, "[%r, #%wd]", \
REGNO (XEXP (X, 0)), \
@@ -2667,10 +2397,9 @@ extern int making_const_table;
else \
THUMB_PRINT_OPERAND_ADDRESS (STREAM, X)
-#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
- if (GET_CODE (X) != CONST_VECTOR \
- || ! arm_emit_vector_const (FILE, X)) \
- goto FAIL;
+#define OUTPUT_ADDR_CONST_EXTRA(file, x, fail) \
+ if (arm_output_addr_const_extra (file, x) == FALSE) \
+ goto fail
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame. */
@@ -2678,7 +2407,7 @@ extern int making_const_table;
#define RETURN_ADDR_RTX(COUNT, FRAME) \
arm_return_addr (COUNT, FRAME)
-/* Mask of the bits in the PC that contain the real return address
+/* Mask of the bits in the PC that contain the real return address
when running in 26-bit mode. */
#define RETURN_ADDR_MASK26 (0x03fffffc)
@@ -2695,61 +2424,11 @@ extern int making_const_table;
in 26 bit mode, the condition codes must be masked out of the \
return address. This does not apply to ARM6 and later processors \
when running in 32 bit mode. */ \
- ((!TARGET_APCS_32) ? (gen_int_mode (RETURN_ADDR_MASK26, Pmode)) \
- : (arm_arch4 || TARGET_THUMB) ? \
- (gen_int_mode ((unsigned long)0xffffffff, Pmode)) \
+ ((arm_arch4 || TARGET_THUMB) \
+ ? (gen_int_mode ((unsigned long)0xffffffff, Pmode)) \
: arm_gen_return_addr_mask ())
-/* Define the codes that are matched by predicates in arm.c */
-#define PREDICATE_CODES \
- {"s_register_operand", {SUBREG, REG}}, \
- {"arm_hard_register_operand", {REG}}, \
- {"f_register_operand", {SUBREG, REG}}, \
- {"arm_add_operand", {SUBREG, REG, CONST_INT}}, \
- {"arm_addimm_operand", {CONST_INT}}, \
- {"fpa_add_operand", {SUBREG, REG, CONST_DOUBLE}}, \
- {"fpa_rhs_operand", {SUBREG, REG, CONST_DOUBLE}}, \
- {"arm_rhs_operand", {SUBREG, REG, CONST_INT}}, \
- {"arm_not_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_int_operand", {SUBREG, REG, CONST_INT}}, \
- {"index_operand", {SUBREG, REG, CONST_INT}}, \
- {"thumb_cmp_operand", {SUBREG, REG, CONST_INT}}, \
- {"thumb_cmpneg_operand", {CONST_INT}}, \
- {"thumb_cbrch_target_operand", {SUBREG, REG, MEM}}, \
- {"offsettable_memory_operand", {MEM}}, \
- {"bad_signed_byte_operand", {MEM}}, \
- {"alignable_memory_operand", {MEM}}, \
- {"shiftable_operator", {PLUS, MINUS, AND, IOR, XOR}}, \
- {"minmax_operator", {SMIN, SMAX, UMIN, UMAX}}, \
- {"shift_operator", {ASHIFT, ASHIFTRT, LSHIFTRT, ROTATERT, MULT}}, \
- {"di_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE, MEM}}, \
- {"nonimmediate_di_operand", {SUBREG, REG, MEM}}, \
- {"soft_df_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
- {"nonimmediate_soft_df_operand", {SUBREG, REG, MEM}}, \
- {"load_multiple_operation", {PARALLEL}}, \
- {"store_multiple_operation", {PARALLEL}}, \
- {"equality_operator", {EQ, NE}}, \
- {"arm_comparison_operator", {EQ, NE, LE, LT, GE, GT, GEU, GTU, LEU, \
- LTU, UNORDERED, ORDERED, UNLT, UNLE, \
- UNGE, UNGT}}, \
- {"arm_rhsm_operand", {SUBREG, REG, CONST_INT, MEM}}, \
- {"const_shift_operand", {CONST_INT}}, \
- {"multi_register_push", {PARALLEL}}, \
- {"cc_register", {REG}}, \
- {"logical_binary_operator", {AND, IOR, XOR}}, \
- {"cirrus_register_operand", {REG}}, \
- {"cirrus_fp_register", {REG}}, \
- {"cirrus_shift_const", {CONST_INT}}, \
- {"dominant_cc_register", {REG}},
-
-/* Define this if you have special predicates that know special things
- about modes. Genrecog will warn about certain forms of
- match_operand without a mode; if the operand predicate is listed in
- SPECIAL_MODE_PREDICATES, the warning will be suppressed. */
-#define SPECIAL_MODE_PREDICATES \
- "cc_register", "dominant_cc_register",
-
enum arm_builtins
{
ARM_BUILTIN_GETWCX,
@@ -2860,8 +2539,8 @@ enum arm_builtins
ARM_BUILTIN_WMINUH,
ARM_BUILTIN_WMINUB,
- ARM_BUILTIN_WMULUH,
- ARM_BUILTIN_WMULSH,
+ ARM_BUILTIN_WMULUM,
+ ARM_BUILTIN_WMULSM,
ARM_BUILTIN_WMULUL,
ARM_BUILTIN_PSADBH,
@@ -2912,6 +2591,8 @@ enum arm_builtins
ARM_BUILTIN_WUNPCKELUH,
ARM_BUILTIN_WUNPCKELUW,
+ ARM_BUILTIN_THREAD_POINTER,
+
ARM_BUILTIN_MAX
};
#endif /* ! GCC_ARM_H */
diff --git a/contrib/gcc/config/arm/arm.md b/contrib/gcc/config/arm/arm.md
index 0a5e647..b28e3d0 100644
--- a/contrib/gcc/config/arm/arm.md
+++ b/contrib/gcc/config/arm/arm.md
@@ -1,6 +1,6 @@
;;- Machine description for ARM for GNU compiler
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003 2004 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;; and Martin Simmons (@harleqn.co.uk).
;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -19,8 +19,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
@@ -30,12 +30,15 @@
;; Register numbers
(define_constants
- [(IP_REGNUM 12) ; Scratch register
+ [(R0_REGNUM 0) ; First CORE register
+ (IP_REGNUM 12) ; Scratch register
(SP_REGNUM 13) ; Stack pointer
(LR_REGNUM 14) ; Return address register
(PC_REGNUM 15) ; Program counter
(CC_REGNUM 24) ; Condition code pseudo register
- (LAST_ARM_REGNUM 15)
+ (LAST_ARM_REGNUM 15) ;
+ (FPA_F0_REGNUM 16) ; FIRST_FPA_REGNUM
+ (FPA_F7_REGNUM 23) ; LAST_FPA_REGNUM
]
)
;; 3rd operand to select_dominance_cc_mode
@@ -87,6 +90,9 @@
(UNSPEC_CLRDI 17) ; Used by the intrinsic form of the iWMMXt CLRDI instruction.
(UNSPEC_WMADDS 18) ; Used by the intrinsic form of the iWMMXt WMADDS instruction.
(UNSPEC_WMADDU 19) ; Used by the intrinsic form of the iWMMXt WMADDU instruction.
+ (UNSPEC_TLS 20) ; A symbol that has been treated properly for TLS usage.
+ (UNSPEC_PIC_LABEL 21) ; A label used for PIC access that does not appear in the
+ ; instruction stream.
]
)
@@ -117,6 +123,8 @@
(VUNSPEC_WCMP_EQ 11) ; Used by the iWMMXt WCMPEQ instructions
(VUNSPEC_WCMP_GTU 12) ; Used by the iWMMXt WCMPGTU instructions
(VUNSPEC_WCMP_GT 13) ; Used by the iwMMXT WCMPGT instructions
+ (VUNSPEC_EH_RETURN 20); Use to override the return address for exception
+ ; handling.
]
)
@@ -128,24 +136,21 @@
; patterns that share the same RTL in both ARM and Thumb code.
(define_attr "is_thumb" "no,yes" (const (symbol_ref "thumb_code")))
-; PROG_MODE attribute is used to determine whether condition codes are
-; clobbered by a call insn: they are if in prog32 mode. This is controlled
-; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
-(define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
-
; IS_STRONGARM is set to 'yes' when compiling for StrongARM, it affects
; scheduling decisions for the load unit and the multiplier.
-(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
+(define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_tune_strongarm")))
+
+; IS_XSCALE is set to 'yes' when compiling for XScale.
+(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
;; Operand number of an input operand that is shifted. Zero if the
;; given instruction does not shift one of its input operands.
-(define_attr "is_xscale" "no,yes" (const (symbol_ref "arm_tune_xscale")))
(define_attr "shift" "" (const_int 0))
; Floating Point Unit. If we only have floating point emulation, then there
; is no point in scheduling the floating point insns. (Well, for best
; performance we should try and group them together).
-(define_attr "fpu" "softfpa,fpa,fpe2,fpe3,maverick"
+(define_attr "fpu" "none,fpa,fpe2,fpe3,maverick,vfp"
(const (symbol_ref "arm_fpu_attr")))
; LENGTH of an instruction (in bytes)
@@ -167,13 +172,26 @@
(set_attr "length" "4")
(set_attr "pool_range" "250")])
+;; The instruction used to implement a particular pattern. This
+;; information is used by pipeline descriptions to provide accurate
+;; scheduling information.
+
+(define_attr "insn"
+ "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx,smmul,smmulr,other"
+ (const_string "other"))
+
; TYPE attribute is used to detect floating point instructions which, if
; running on a co-processor can run in parallel with other, basic instructions
; If write-buffer scheduling is enabled then it can also be used in the
; scheduling of writes.
; Classification of each insn
-; normal any data instruction that doesn't hit memory or fp regs
+; alu any alu instruction that doesn't hit memory or fp
+; regs or have a shifted source operand
+; alu_shift any data instruction that doesn't hit memory or fp
+; regs, but has a source operand shifted by a constant
+; alu_shift_reg any data instruction that doesn't hit memory or fp
+; regs, but has a source operand shifted by a register value
; mult a multiply instruction
; block blockage insn, this blocks all functional units
; float a floating point arithmetic operation (subject to expansion)
@@ -187,23 +205,35 @@
; even on a machine with an fpa.
; f_load a floating point load from memory
; f_store a floating point store to memory
+; f_load[sd] single/double load from memory
+; f_store[sd] single/double store to memory
+; f_flag a transfer of co-processor flags to the CPSR
; f_mem_r a transfer of a floating point register to a real reg via mem
; r_mem_f the reverse of f_mem_r
; f_2_r fast transfer float to arm (no memory needed)
; r_2_f fast transfer arm to float
+; f_cvt convert floating<->integral
+; branch a branch
; call a subroutine call
-; load any load from memory
-; store1 store 1 word to memory from arm registers
+; load_byte load byte(s) from memory to arm registers
+; load1 load 1 word from memory to arm registers
+; load2 load 2 words from memory to arm registers
+; load3 load 3 words from memory to arm registers
+; load4 load 4 words from memory to arm registers
+; store store 1 word to memory from arm registers
; store2 store 2 words
; store3 store 3 words
-; store4 store 4 words
+; store4 store 4 (or more) words
; Additions for Cirrus Maverick co-processor:
; mav_farith Floating point arithmetic (4 cycle)
; mav_dmult Double multiplies (7 cycle)
;
(define_attr "type"
- "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4,mav_farith,mav_dmult"
- (const_string "normal"))
+ "alu,alu_shift,alu_shift_reg,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,f_flag,float_em,f_load,f_store,f_loads,f_loadd,f_stores,f_stored,f_mem_r,r_mem_f,f_2_r,r_2_f,f_cvt,branch,call,load_byte,load1,load2,load3,load4,store1,store2,store3,store4,mav_farith,mav_dmult"
+ (if_then_else
+ (eq_attr "insn" "smulxy,smlaxy,smlalxy,smulwy,smlawx,mul,muls,mla,mlas,umull,umulls,umlal,umlals,smull,smulls,smlal,smlals")
+ (const_string "mult")
+ (const_string "alu")))
; Load scheduling, set from the arm_ld_sched variable
; initialized by arm_override_options()
@@ -231,8 +261,7 @@
(define_attr "conds" "use,set,clob,jump_clob,nocond"
(if_then_else (eq_attr "type" "call")
- (if_then_else (eq_attr "prog_mode" "prog32")
- (const_string "clob") (const_string "nocond"))
+ (const_string "clob")
(const_string "nocond")))
; Predicable means that the insn can be conditionally executed based on
@@ -245,13 +274,13 @@
; have one. Later ones, such as StrongARM, have write-back caches, so don't
; suffer blockages enough to warrant modelling this (and it can adversely
; affect the schedule).
-(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
+(define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_tune_wbuf")))
; WRITE_CONFLICT implies that a read following an unrelated write is likely
; to stall the processor. Used with model_wbuf above.
(define_attr "write_conflict" "no,yes"
(if_then_else (eq_attr "type"
- "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
+ "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load1")
(const_string "yes")
(const_string "no")))
@@ -259,7 +288,7 @@
; than one on the main cpu execution unit.
(define_attr "core_cycles" "single,multi"
(if_then_else (eq_attr "type"
- "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
+ "alu,alu_shift,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
(const_string "single")
(const_string "multi")))
@@ -267,115 +296,47 @@
;; distant label. Only applicable to Thumb code.
(define_attr "far_jump" "yes,no" (const_string "no"))
-(define_automaton "arm")
-;; Write buffer
-;
-; Strictly, we should model a 4-deep write buffer for ARM7xx based chips
-;
-; The write buffer on some of the arm6 processors is hard to model exactly.
-; There is room in the buffer for up to two addresses and up to eight words
-; of memory, but the two needn't be split evenly. When writing the two
-; addresses are fully pipelined. However, a read from memory that is not
-; currently in the cache will block until the writes have completed.
-; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
-; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
-; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
-; cycle to add as well.
-(define_cpu_unit "write_buf" "arm")
-
-;; Write blockage unit
-;
-; The write_blockage unit models (partially), the fact that reads will stall
-; until the write buffer empties.
-; The f_mem_r and r_mem_f could also block, but they are to the stack,
-; so we don't model them here
-(define_cpu_unit "write_blockage" "arm")
+;;---------------------------------------------------------------------------
+;; Mode macros
-;; Core
-;
-(define_cpu_unit "core" "arm")
-
-(define_insn_reservation "r_mem_f_wbuf" 5
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "r_mem_f"))
- "core+write_buf*3")
-
-(define_insn_reservation "store1_wbuf" 5
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store1"))
- "core+write_buf*3+write_blockage*5")
-
-(define_insn_reservation "store2_wbuf" 7
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store2"))
- "core+write_buf*4+write_blockage*7")
-
-(define_insn_reservation "store3_wbuf" 9
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store3"))
- "core+write_buf*5+write_blockage*9")
-
-(define_insn_reservation "store4_wbuf" 11
- (and (eq_attr "model_wbuf" "yes")
- (eq_attr "type" "store4"))
- "core+write_buf*6+write_blockage*11")
-
-(define_insn_reservation "store2" 3
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store2"))
- "core*3")
-
-(define_insn_reservation "store3" 4
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store3"))
- "core*4")
-
-(define_insn_reservation "store4" 5
- (and (eq_attr "model_wbuf" "no")
- (eq_attr "type" "store4"))
- "core*5")
-
-(define_insn_reservation "store1_ldsched" 1
- (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1"))
- "core")
-
-(define_insn_reservation "load_ldsched_xscale" 3
- (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
- (eq_attr "is_xscale" "yes"))
- "core")
-
-(define_insn_reservation "load_ldsched" 2
- (and (and (eq_attr "ldsched" "yes") (eq_attr "type" "load"))
- (eq_attr "is_xscale" "no"))
- "core")
-
-(define_insn_reservation "load_or_store" 2
- (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1"))
- "core*2")
-
-(define_insn_reservation "mult" 16
- (and (eq_attr "ldsched" "no") (eq_attr "type" "mult"))
- "core*16")
-
-(define_insn_reservation "mult_ldsched_strongarm" 3
- (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
- (eq_attr "type" "mult"))
- "core*2")
-
-(define_insn_reservation "mult_ldsched" 4
- (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
- (eq_attr "type" "mult"))
- "core*4")
-
-(define_insn_reservation "multi_cycle" 32
- (and (eq_attr "core_cycles" "multi")
- (eq_attr "type" "!mult,load,store1,store2,store3,store4"))
- "core*32")
-
-(define_insn_reservation "single_cycle" 1
- (eq_attr "core_cycles" "single")
- "core")
+; A list of modes that are exactly 64 bits in size. We use this to expand
+; some splits that are the same for all modes when operating on ARM
+; registers.
+(define_mode_macro ANY64 [DI DF V8QI V4HI V2SI V2SF])
+
+;;---------------------------------------------------------------------------
+;; Predicates
+
+(include "predicates.md")
+(include "constraints.md")
+
+;;---------------------------------------------------------------------------
+;; Pipeline descriptions
+
+;; Processor type. This is created automatically from arm-cores.def.
+(include "arm-tune.md")
+
+;; True if the generic scheduling description should be used.
+
+(define_attr "generic_sched" "yes,no"
+ (const (if_then_else
+ (eq_attr "tune" "arm926ejs,arm1020e,arm1026ejs,arm1136js,arm1136jfs")
+ (const_string "no")
+ (const_string "yes"))))
+
+(define_attr "generic_vfp" "yes,no"
+ (const (if_then_else
+ (and (eq_attr "fpu" "vfp")
+ (eq_attr "tune" "!arm1020e,arm1022e"))
+ (const_string "yes")
+ (const_string "no"))))
+
+(include "arm-generic.md")
+(include "arm926ejs.md")
+(include "arm1020e.md")
+(include "arm1026ejs.md")
+(include "arm1136jfs.md")
;;---------------------------------------------------------------------------
@@ -397,7 +358,7 @@
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
- if (TARGET_CIRRUS)
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK)
{
if (!cirrus_fp_register (operands[0], DImode))
operands[0] = force_reg (DImode, operands[0]);
@@ -433,7 +394,7 @@
(plus:DI (match_operand:DI 1 "s_register_operand" "%0, 0")
(match_operand:DI 2 "s_register_operand" "r, 0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !TARGET_CIRRUS"
+ "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
"TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
@@ -461,7 +422,7 @@
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !TARGET_CIRRUS"
+ "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
"TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
@@ -490,7 +451,7 @@
(match_operand:SI 2 "s_register_operand" "r,r"))
(match_operand:DI 1 "s_register_operand" "r,0")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && !TARGET_CIRRUS"
+ "TARGET_ARM && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)"
"#"
"TARGET_ARM && reload_completed"
[(parallel [(set (reg:CC_C CC_REGNUM)
@@ -519,9 +480,9 @@
"
if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (PLUS, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0], operands[1],
+ optimize && !no_new_pseudos);
DONE;
}
"
@@ -531,8 +492,8 @@
; addition.
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
+ (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))]
"TARGET_ARM &&
!(const_ok_for_arm (INTVAL (operands[2]))
@@ -558,7 +519,8 @@
|| const_ok_for_arm (-INTVAL (operands[2])))"
[(clobber (const_int 0))]
"
- arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
+ arm_split_constant (PLUS, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0],
operands[1], 0);
DONE;
"
@@ -598,15 +560,14 @@
;; Reloading and elimination of the frame pointer can
;; sometimes cause this optimization to be missed.
(define_peephole2
- [(set (match_operand:SI 0 "register_operand" "")
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))
(set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "")))]
+ (plus:SI (match_dup 0) (reg:SI SP_REGNUM)))]
"TARGET_THUMB
- && REGNO (operands[2]) == STACK_POINTER_REGNUM
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
&& (INTVAL (operands[1]) & 3) == 0"
- [(set (match_dup 0) (plus:SI (match_dup 2) (match_dup 1)))]
+ [(set (match_dup 0) (plus:SI (reg:SI SP_REGNUM) (match_dup 1)))]
""
)
@@ -638,32 +599,13 @@
[(set_attr "conds" "set")]
)
-;; These patterns are the same ones as the two regular addsi3_compare0
-;; patterns, except we write them slightly different - the combiner
-;; tends to generate them this way.
-(define_insn "*addsi3_compare0_for_combiner"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (match_operand:SI 1 "s_register_operand" "r,r")
- (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
- (set (match_operand:SI 0 "s_register_operand" "=r,r")
- (plus:SI (match_dup 1) (match_dup 2)))]
+(define_insn "*compare_negsi_si"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
+ (neg:SI (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM"
- "@
- add%?s\\t%0, %1, %2
- sub%?s\\t%0, %1, #%n2"
- [(set_attr "conds" "set")]
-)
-
-(define_insn "*addsi3_compare0_scratch_for_combiner"
- [(set (reg:CC CC_REGNUM)
- (compare:CC
- (match_operand:SI 0 "s_register_operand" "r,r")
- (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
- "TARGET_ARM"
- "@
- cmn%?\\t%0, %1
- cmp%?\\t%0, #%n1"
+ "cmn%?\\t%1, %0"
[(set_attr "conds" "set")]
)
@@ -694,8 +636,8 @@
;; similarly for the beq variant using bcc.
;; This is a common looping idiom (while (n--))
(define_peephole2
- [(set (match_operand:SI 0 "s_register_operand" "")
- (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
+ (plus:SI (match_operand:SI 1 "arm_general_register_operand" "")
(const_int -1)))
(set (match_operand 2 "cc_register" "")
(compare (match_dup 0) (const_int -1)))
@@ -801,7 +743,10 @@
(match_operand:SI 1 "s_register_operand" "r"))))]
"TARGET_ARM"
"adc%?\\t%0, %1, %3%S2"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*addsi3_carryin_alt1"
@@ -864,10 +809,10 @@
(define_expand "addsf3"
[(set (match_operand:SF 0 "s_register_operand" "")
(plus:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "fpa_add_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_add_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS
+ if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], SFmode))
operands[2] = force_reg (SFmode, operands[2]);
")
@@ -875,10 +820,10 @@
(define_expand "adddf3"
[(set (match_operand:DF 0 "s_register_operand" "")
(plus:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "fpa_add_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_add_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS
+ if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], DFmode))
operands[2] = force_reg (DFmode, operands[2]);
")
@@ -891,7 +836,7 @@
(clobber (reg:CC CC_REGNUM))])]
"TARGET_EITHER"
"
- if (TARGET_CIRRUS
+ if (TARGET_HARD_FLOAT && TARGET_MAVERICK
&& TARGET_ARM
&& cirrus_fp_register (operands[0], DImode)
&& cirrus_fp_register (operands[1], DImode))
@@ -1002,10 +947,9 @@
{
if (TARGET_ARM)
{
- arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
- operands[2],
- (no_new_pseudos ? 0
- : preserve_subexpressions_p ()));
+ arm_split_constant (MINUS, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0],
+ operands[2], optimize && !no_new_pseudos);
DONE;
}
else /* TARGET_THUMB */
@@ -1036,8 +980,8 @@
&& !const_ok_for_arm (INTVAL (operands[1]))"
[(clobber (const_int 0))]
"
- arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
- operands[2], 0);
+ arm_split_constant (MINUS, SImode, curr_insn,
+ INTVAL (operands[1]), operands[0], operands[2], 0);
DONE;
"
[(set_attr "length" "4,16")
@@ -1046,9 +990,9 @@
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
(minus:SI (match_operand:SI 1 "const_int_operand" "")
- (match_operand:SI 2 "s_register_operand" "")))]
+ (match_operand:SI 2 "arm_general_register_operand" "")))]
"TARGET_ARM
&& !const_ok_for_arm (INTVAL (operands[1]))
&& const_ok_for_arm (~INTVAL (operands[1]))"
@@ -1087,11 +1031,11 @@
(define_expand "subsf3"
[(set (match_operand:SF 0 "s_register_operand" "")
- (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "")
- (match_operand:SF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
if (!cirrus_fp_register (operands[1], SFmode))
operands[1] = force_reg (SFmode, operands[1]);
@@ -1102,11 +1046,11 @@
(define_expand "subdf3"
[(set (match_operand:DF 0 "s_register_operand" "")
- (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "")
- (match_operand:DF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
if (!cirrus_fp_register (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[1]);
@@ -1133,7 +1077,7 @@
(match_operand:SI 1 "s_register_operand" "%?r,0")))]
"TARGET_ARM"
"mul%?\\t%0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "mul")
(set_attr "predicable" "yes")]
)
@@ -1149,12 +1093,12 @@
"TARGET_THUMB"
"*
if (which_alternative < 2)
- return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
+ return \"mov\\t%0, %1\;mul\\t%0, %2\";
else
- return \"mul\\t%0, %0, %2\";
+ return \"mul\\t%0, %2\";
"
[(set_attr "length" "4,4,2")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mul")]
)
(define_insn "*mulsi3_compare0"
@@ -1165,10 +1109,10 @@
(const_int 0)))
(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
(mult:SI (match_dup 2) (match_dup 1)))]
- "TARGET_ARM && !arm_arch_xscale"
+ "TARGET_ARM"
"mul%?s\\t%0, %2, %1"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "muls")]
)
(define_insn "*mulsi_compare0_scratch"
@@ -1178,10 +1122,10 @@
(match_operand:SI 1 "s_register_operand" "%?r,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r"))]
- "TARGET_ARM && !arm_arch_xscale"
+ "TARGET_ARM"
"mul%?s\\t%0, %2, %1"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "muls")]
)
;; Unnamed templates to match MLA instruction.
@@ -1194,7 +1138,7 @@
(match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
"TARGET_ARM"
"mla%?\\t%0, %2, %1, %3"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "mla")
(set_attr "predicable" "yes")]
)
@@ -1209,10 +1153,10 @@
(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
(plus:SI (mult:SI (match_dup 2) (match_dup 1))
(match_dup 3)))]
- "TARGET_ARM && !arm_arch_xscale"
+ "TARGET_ARM"
"mla%?s\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mlas")]
)
(define_insn "*mulsi3addsi_compare0_scratch"
@@ -1224,10 +1168,10 @@
(match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
(const_int 0)))
(clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
- "TARGET_ARM && !arm_arch_xscale"
+ "TARGET_ARM"
"mla%?s\\t%0, %2, %1, %3"
[(set_attr "conds" "set")
- (set_attr "type" "mult")]
+ (set_attr "insn" "mlas")]
)
;; Unnamed template to match long long multiply-accumulate (smlal)
@@ -1239,9 +1183,9 @@
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
(sign_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
(match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"smlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smlal")
(set_attr "predicable" "yes")]
)
@@ -1250,9 +1194,9 @@
(mult:DI
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"smull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smull")
(set_attr "predicable" "yes")]
)
@@ -1261,9 +1205,9 @@
(mult:DI
(zero_extend:DI (match_operand:SI 1 "s_register_operand" "%r"))
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r"))))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"umull%?\\t%Q0, %R0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umull")
(set_attr "predicable" "yes")]
)
@@ -1276,9 +1220,9 @@
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "%r"))
(zero_extend:DI (match_operand:SI 3 "s_register_operand" "r")))
(match_operand:DI 1 "s_register_operand" "0")))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"umlal%?\\t%Q0, %R0, %3, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umlal")
(set_attr "predicable" "yes")]
)
@@ -1291,9 +1235,9 @@
(sign_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"smull%?\\t%3, %0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smull")
(set_attr "predicable" "yes")]
)
@@ -1306,9 +1250,9 @@
(zero_extend:DI (match_operand:SI 2 "s_register_operand" "r,r")))
(const_int 32))))
(clobber (match_scratch:SI 3 "=&r,&r"))]
- "TARGET_ARM && arm_fast_multiply"
+ "TARGET_ARM && arm_arch3m"
"umull%?\\t%3, %0, %2, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "umull")
(set_attr "predicable" "yes")]
)
@@ -1320,7 +1264,7 @@
(match_operand:HI 2 "s_register_operand" "r"))))]
"TARGET_ARM && arm_arch5e"
"smulbb%?\\t%0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smulxy")
(set_attr "predicable" "yes")]
)
@@ -1333,7 +1277,7 @@
(match_operand:HI 2 "s_register_operand" "r"))))]
"TARGET_ARM && arm_arch5e"
"smultb%?\\t%0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smulxy")
(set_attr "predicable" "yes")]
)
@@ -1346,7 +1290,7 @@
(const_int 16))))]
"TARGET_ARM && arm_arch5e"
"smulbt%?\\t%0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smulxy")
(set_attr "predicable" "yes")]
)
@@ -1360,7 +1304,7 @@
(const_int 16))))]
"TARGET_ARM && arm_arch5e"
"smultt%?\\t%0, %1, %2"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smulxy")
(set_attr "predicable" "yes")]
)
@@ -1373,7 +1317,7 @@
(match_operand:HI 3 "s_register_operand" "r")))))]
"TARGET_ARM && arm_arch5e"
"smlabb%?\\t%0, %2, %3, %1"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smlaxy")
(set_attr "predicable" "yes")]
)
@@ -1387,16 +1331,16 @@
(match_operand:HI 3 "s_register_operand" "r")))))]
"TARGET_ARM && arm_arch5e"
"smlalbb%?\\t%Q0, %R0, %2, %3"
- [(set_attr "type" "mult")
+ [(set_attr "insn" "smlalxy")
(set_attr "predicable" "yes")])
(define_expand "mulsf3"
[(set (match_operand:SF 0 "s_register_operand" "")
(mult:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS
+ if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], SFmode))
operands[2] = force_reg (SFmode, operands[2]);
")
@@ -1404,10 +1348,10 @@
(define_expand "muldf3"
[(set (match_operand:DF 0 "s_register_operand" "")
(mult:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS
+ if (TARGET_MAVERICK
&& !cirrus_fp_register (operands[2], DFmode))
operands[2] = force_reg (DFmode, operands[2]);
")
@@ -1416,16 +1360,16 @@
(define_expand "divsf3"
[(set (match_operand:SF 0 "s_register_operand" "")
- (div:SF (match_operand:SF 1 "fpa_rhs_operand" "")
- (match_operand:SF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "")
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"")
(define_expand "divdf3"
[(set (match_operand:DF 0 "s_register_operand" "")
- (div:DF (match_operand:DF 1 "fpa_rhs_operand" "")
- (match_operand:DF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "")
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"")
;; Modulo insns
@@ -1433,15 +1377,15 @@
(define_expand "modsf3"
[(set (match_operand:SF 0 "s_register_operand" "")
(mod:SF (match_operand:SF 1 "s_register_operand" "")
- (match_operand:SF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"")
(define_expand "moddf3"
[(set (match_operand:DF 0 "s_register_operand" "")
(mod:DF (match_operand:DF 1 "s_register_operand" "")
- (match_operand:DF 2 "fpa_rhs_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"")
;; Boolean and,ior,xor insns
@@ -1578,10 +1522,10 @@
{
if (GET_CODE (operands[2]) == CONST_INT)
{
- arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos
- ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (AND, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0],
+ operands[1], optimize && !no_new_pseudos);
+
DONE;
}
}
@@ -1645,8 +1589,8 @@
|| const_ok_for_arm (~INTVAL (operands[2])))"
[(clobber (const_int 0))]
"
- arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
- operands[1], 0);
+ arm_split_constant (AND, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0], operands[1], 0);
DONE;
"
[(set_attr "length" "4,4,16")
@@ -1712,7 +1656,7 @@
[(set_attr "conds" "set")]
)
-(define_insn "*ne_zeroextractsi"
+(define_insn_and_split "*ne_zeroextractsi"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(ne:SI (zero_extract:SI
(match_operand:SI 1 "s_register_operand" "r")
@@ -1725,11 +1669,112 @@
&& INTVAL (operands[2]) > 0
&& INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
&& INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
- "*
+ "#"
+ "TARGET_ARM
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (const_int 1)))]
+ "
operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
- << INTVAL (operands[3]));
- output_asm_insn (\"ands\\t%0, %1, %2\", operands);
- return \"movne\\t%0, #1\";
+ << INTVAL (operands[3]));
+ "
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ne_zeroextractsi_shifted"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (ne:SI (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (const_int 0))
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "#"
+ "TARGET_ARM"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (const_int 1)))]
+ "
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
+ "
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ite_ne_zeroextractsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (if_then_else:SI (ne (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "const_int_operand" "n"))
+ (const_int 0))
+ (match_operand:SI 4 "arm_not_operand" "rIK")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
+ "#"
+ "TARGET_ARM
+ && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
+ && INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
+ && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)
+ && !reg_overlap_mentioned_p (operands[0], operands[4])"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (and:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (match_dup 4)))]
+ "
+ operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
+ << INTVAL (operands[3]));
+ "
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
+(define_insn_and_split "*ite_ne_zeroextractsi_shifted"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (if_then_else:SI (ne (zero_extract:SI
+ (match_operand:SI 1 "s_register_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (const_int 0))
+ (const_int 0))
+ (match_operand:SI 3 "arm_not_operand" "rIK")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
+ "#"
+ "TARGET_ARM && !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(parallel [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV (ashift:SI (match_dup 1) (match_dup 2))
+ (const_int 0)))
+ (set (match_dup 0) (ashift:SI (match_dup 1) (match_dup 2)))])
+ (set (match_dup 0)
+ (if_then_else:SI (eq (reg:CC_NOOV CC_REGNUM) (const_int 0))
+ (match_dup 0) (match_dup 3)))]
+ "
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));
"
[(set_attr "conds" "clob")
(set_attr "length" "8")]
@@ -1860,9 +1905,10 @@
HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
- emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
+ emit_insn (gen_andsi3 (op1, operands[0],
+ gen_int_mode (~mask2, SImode)));
emit_insn (gen_iorsi3 (subtarget, op1,
- GEN_INT (op3_value << start_bit)));
+ gen_int_mode (op3_value << start_bit, SImode)));
}
else if (start_bit == 0
&& !(const_ok_for_arm (mask)
@@ -1898,7 +1944,7 @@
}
else
{
- rtx op0 = GEN_INT (mask);
+ rtx op0 = gen_int_mode (mask, SImode);
rtx op1 = gen_reg_rtx (SImode);
rtx op2 = gen_reg_rtx (SImode);
@@ -1917,7 +1963,7 @@
&& (const_ok_for_arm (mask << start_bit)
|| const_ok_for_arm (~(mask << start_bit))))
{
- op0 = GEN_INT (~(mask << start_bit));
+ op0 = gen_int_mode (~(mask << start_bit), SImode);
emit_insn (gen_andsi3 (op2, operands[0], op0));
}
else
@@ -2048,16 +2094,18 @@
)
(define_insn "andsi_not_shiftsi_si"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (and:SI (not:SI (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 2 "s_register_operand" "r")
- (match_operand:SI 3 "arm_rhs_operand" "rM")]))
- (match_operand:SI 1 "s_register_operand" "r")))]
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (and:SI (not:SI (match_operator:SI 4 "shift_operator"
+ [(match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 3 "arm_rhs_operand" "rM")]))
+ (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_ARM"
"bic%?\\t%0, %1, %2%S4"
[(set_attr "predicable" "yes")
(set_attr "shift" "2")
- ]
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*andsi_notsi_si_compare0"
@@ -2129,10 +2177,9 @@
{
if (TARGET_ARM)
{
- arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
- operands[1],
- (no_new_pseudos
- ? 0 : preserve_subexpressions_p ()));
+ arm_split_constant (IOR, SImode, NULL_RTX,
+ INTVAL (operands[2]), operands[0], operands[1],
+ optimize && !no_new_pseudos);
DONE;
}
else /* TARGET_THUMB */
@@ -2154,8 +2201,8 @@
&& !const_ok_for_arm (INTVAL (operands[2]))"
[(clobber (const_int 0))]
"
- arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
- operands[1], 0);
+ arm_split_constant (IOR, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0], operands[1], 0);
DONE;
"
[(set_attr "length" "4,16")
@@ -2173,8 +2220,8 @@
(define_peephole2
[(match_scratch:SI 3 "r")
- (set (match_operand:SI 0 "s_register_operand" "")
- (ior:SI (match_operand:SI 1 "s_register_operand" "")
+ (set (match_operand:SI 0 "arm_general_register_operand" "")
+ (ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))]
"TARGET_ARM
&& !const_ok_for_arm (INTVAL (operands[2]))
@@ -2427,32 +2474,93 @@
;; Minimum and maximum insns
-(define_insn "smaxsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+(define_expand "smaxsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_ARM"
+ "
+ if (operands[2] == const0_rtx || operands[2] == constm1_rtx)
+ {
+ /* No need for a clobber of the condition code register here. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SMAX (SImode, operands[1],
+ operands[2])));
+ DONE;
+ }
+")
+
+(define_insn "*smax_0"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 0)))]
+ "TARGET_ARM"
+ "bic%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*smax_m1"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int -1)))]
+ "TARGET_ARM"
+ "orr%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*smax_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (smax:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
+ (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"@
cmp\\t%1, %2\;movlt\\t%0, %2
- cmp\\t%1, %2\;movge\\t%0, %1
cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
[(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
+ (set_attr "length" "8,12")]
)
-(define_insn "sminsi3"
- [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
- (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
- (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
+(define_expand "sminsi3"
+ [(parallel [
+ (set (match_operand:SI 0 "s_register_operand" "")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "arm_rhs_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ "TARGET_ARM"
+ "
+ if (operands[2] == const0_rtx)
+ {
+ /* No need for a clobber of the condition code register here. */
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SMIN (SImode, operands[1],
+ operands[2])));
+ DONE;
+ }
+")
+
+(define_insn "*smin_0"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "r")
+ (const_int 0)))]
+ "TARGET_ARM"
+ "and%?\\t%0, %1, %1, asr #31"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*smin_insn"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (smin:SI (match_operand:SI 1 "s_register_operand" "%0,?r")
+ (match_operand:SI 2 "arm_rhs_operand" "rI,rI")))
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"@
cmp\\t%1, %2\;movge\\t%0, %2
- cmp\\t%1, %2\;movlt\\t%0, %1
cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
[(set_attr "conds" "clob")
- (set_attr "length" "8,8,12")]
+ (set_attr "length" "8,12")]
)
(define_insn "umaxsi3"
@@ -2491,8 +2599,8 @@
(clobber (reg:CC CC_REGNUM))]
"TARGET_ARM"
"*
- operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
- operands[2]);
+ operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode,
+ operands[1], operands[2]);
output_asm_insn (\"cmp\\t%1, %2\", operands);
output_asm_insn (\"str%d3\\t%1, %0\", operands);
output_asm_insn (\"str%D3\\t%2, %0\", operands);
@@ -2513,16 +2621,13 @@
(match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
(match_operand:SI 1 "s_register_operand" "0,?r")]))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM
- && (GET_CODE (operands[1]) != REG
- || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
- && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
+ "TARGET_ARM && !arm_eliminable_register (operands[1])"
"*
{
enum rtx_code code = GET_CODE (operands[4]);
- operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
- operands[3]);
+ operands[5] = gen_rtx_fmt_ee (minmax_code (operands[5]), SImode,
+ operands[2], operands[3]);
output_asm_insn (\"cmp\\t%2, %3\", operands);
output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
if (which_alternative != 0 || operands[3] != const0_rtx
@@ -2537,6 +2642,41 @@
;; Shift and rotation insns
+(define_expand "ashldi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_ARM"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_ashldi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT && !(TARGET_HARD_FLOAT && TARGET_MAVERICK))
+ FAIL;
+ "
+)
+
+(define_insn "arm_ashldi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (ashift:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "movs\\t%Q0, %Q1, asl #1\;adc\\t%R0, %R1, %R1"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(ashift:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2561,6 +2701,41 @@
[(set_attr "length" "2")]
)
+(define_expand "ashrdi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_ARM"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_ashrdi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT)
+ FAIL;
+ "
+)
+
+(define_insn "arm_ashrdi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (ashiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "movs\\t%R0, %R1, asr #1\;mov\\t%Q0, %Q1, rrx"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "ashrsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2582,6 +2757,41 @@
[(set_attr "length" "2")]
)
+(define_expand "lshrdi3"
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "")
+ (match_operand:SI 2 "reg_or_int_operand" "")))]
+ "TARGET_ARM"
+ "
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ if ((HOST_WIDE_INT) INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_arm_lshrdi3_1bit (operands[0], operands[1]));
+ DONE;
+ }
+ /* Ideally we shouldn't fail here if we could know that operands[1]
+ ends up already living in an iwmmxt register. Otherwise it's
+ cheaper to have the alternate code being generated than moving
+ values to iwmmxt regs and back. */
+ FAIL;
+ }
+ else if (!TARGET_REALLY_IWMMXT)
+ FAIL;
+ "
+)
+
+(define_insn "arm_lshrdi3_1bit"
+ [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
+ (lshiftrt:DI (match_operand:DI 1 "s_register_operand" "?r,0")
+ (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ARM"
+ "movs\\t%R0, %R1, lsr #1\;mov\\t%Q0, %Q1, rrx"
+ [(set_attr "conds" "clob")
+ (set_attr "length" "8")]
+)
+
(define_expand "lshrsi3"
[(set (match_operand:SI 0 "s_register_operand" "")
(lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
@@ -2652,19 +2862,6 @@
[(set_attr "length" "2")]
)
-(define_expand "ashldi3"
- [(set (match_operand:DI 0 "s_register_operand" "")
- (ashift:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- "TARGET_ARM && (TARGET_IWMMXT || TARGET_CIRRUS)"
- "
- if (! s_register_operand (operands[1], DImode))
- operands[1] = copy_to_mode_reg (DImode, operands[1]);
- if (! s_register_operand (operands[2], SImode))
- operands[2] = copy_to_mode_reg (SImode, operands[2]);
- "
-)
-
(define_insn "*arm_shiftsi3"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(match_operator:SI 3 "shift_operator"
@@ -2674,7 +2871,9 @@
"mov%?\\t%0, %1%S3"
[(set_attr "predicable" "yes")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*shiftsi3_compare0"
@@ -2689,7 +2888,9 @@
"mov%?s\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*shiftsi3_compare0_scratch"
@@ -2702,8 +2903,7 @@
"TARGET_ARM"
"mov%?s\\t%0, %1%S3"
[(set_attr "conds" "set")
- (set_attr "shift" "1")
- ]
+ (set_attr "shift" "1")]
)
(define_insn "*notsi_shiftsi"
@@ -2715,7 +2915,9 @@
"mvn%?\\t%0, %1%S3"
[(set_attr "predicable" "yes")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*notsi_shiftsi_compare0"
@@ -2730,7 +2932,9 @@
"mvn%?s\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*not_shiftsi_compare0_scratch"
@@ -2744,7 +2948,9 @@
"mvn%?s\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
;; We don't really have extzv, but defining this using shifts helps
@@ -2841,14 +3047,14 @@
(define_expand "negsf2"
[(set (match_operand:SF 0 "s_register_operand" "")
(neg:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
""
)
(define_expand "negdf2"
[(set (match_operand:DF 0 "s_register_operand" "")
(neg:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"")
;; abssi2 doesn't really clobber the condition codes if a different register
@@ -2895,25 +3101,25 @@
(define_expand "abssf2"
[(set (match_operand:SF 0 "s_register_operand" "")
(abs:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"")
(define_expand "absdf2"
[(set (match_operand:DF 0 "s_register_operand" "")
(abs:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"")
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "s_register_operand" "")
(sqrt:SF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"")
(define_expand "sqrtdf2"
[(set (match_operand:DF 0 "s_register_operand" "")
(sqrt:DF (match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"")
(define_insn_and_split "one_cmpldi2"
@@ -2984,9 +3190,9 @@
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "s_register_operand" "")
(float:SF (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
emit_insn (gen_cirrus_floatsisf2 (operands[0], operands[1]));
DONE;
@@ -2996,9 +3202,9 @@
(define_expand "floatsidf2"
[(set (match_operand:DF 0 "s_register_operand" "")
(float:DF (match_operand:SI 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
emit_insn (gen_cirrus_floatsidf2 (operands[0], operands[1]));
DONE;
@@ -3008,9 +3214,9 @@
(define_expand "fix_truncsfsi2"
[(set (match_operand:SI 0 "s_register_operand" "")
(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" ""))))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
if (!cirrus_fp_register (operands[0], SImode))
operands[0] = force_reg (SImode, operands[0]);
@@ -3024,9 +3230,9 @@
(define_expand "fix_truncdfsi2"
[(set (match_operand:SI 0 "s_register_operand" "")
(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" ""))))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS)
+ if (TARGET_MAVERICK)
{
if (!cirrus_fp_register (operands[1], DFmode))
operands[1] = force_reg (DFmode, operands[0]);
@@ -3041,7 +3247,7 @@
[(set (match_operand:SF 0 "s_register_operand" "")
(float_truncate:SF
(match_operand:DF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
""
)
@@ -3070,7 +3276,7 @@
ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
[(set_attr "length" "8")
(set_attr "predicable" "yes")
- (set_attr "type" "*,load")
+ (set_attr "type" "*,load_byte")
(set_attr "pool_range" "*,4092")
(set_attr "neg_pool_range" "*,4084")]
)
@@ -3099,72 +3305,38 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM)
+ if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
{
- if (arm_arch4 && GET_CODE (operands[1]) == MEM)
- {
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- here because the insn below will generate an LDRH instruction
- rather than an LDR instruction, so we cannot get an unaligned
- word access. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_ZERO_EXTEND (SImode,
- operands[1])));
- DONE;
- }
- if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
- {
- emit_insn (gen_movhi_bytes (operands[0], operands[1]));
- DONE;
- }
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ DONE;
}
- else /* TARGET_THUMB */
- {
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx tmp;
- tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
- tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
- emit_insn (tmp);
- }
- else
- {
- rtx ops[3];
-
- if (!s_register_operand (operands[1], HImode))
- operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
+ if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
+ {
+ emit_insn (gen_movhi_bytes (operands[0], operands[1]));
+ DONE;
+ }
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (16);
+ if (!s_register_operand (operands[1], HImode))
+ operands[1] = copy_to_mode_reg (HImode, operands[1]);
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_LSHIFTRT (SImode, ops[1],
- ops[2])));
- }
- DONE;
+ if (arm_arch6)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_ZERO_EXTEND (SImode, operands[1])));
+ DONE;
}
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
}"
)
(define_insn "*thumb_zero_extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_THUMB"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_THUMB && !arm_arch6"
"*
rtx mem = XEXP (operands[1], 0);
@@ -3199,49 +3371,89 @@
return \"ldrh\\t%0, %1\";
"
[(set_attr "length" "4")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "60")]
)
+(define_insn "*thumb_zero_extendhisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))]
+ "TARGET_THUMB && arm_arch6"
+ "*
+ rtx mem;
+
+ if (which_alternative == 0)
+ return \"uxth\\t%0, %1\";
+
+ mem = XEXP (operands[1], 0);
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ /* This can happen due to bugs in reload. */
+ if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
+ {
+ rtx ops[2];
+ ops[0] = operands[0];
+ ops[1] = a;
+
+ output_asm_insn (\"mov %0, %1\", ops);
+
+ XEXP (mem, 0) = operands[0];
+ }
+
+ else if ( GET_CODE (a) == LABEL_REF
+ && GET_CODE (b) == CONST_INT)
+ return \"ldr\\t%0, %1\";
+ }
+
+ return \"ldrh\\t%0, %1\";
+ "
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,60")]
+)
+
(define_insn "*arm_zero_extendhisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
"ldr%?h\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_zero_extendhisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ uxth%?\\t%0, %1
+ ldr%?h\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 3 "shiftable_operator"
- [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
- (match_operand:SI 4 "s_register_operand" "")]))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0)
- (match_op_dup 3
- [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_zero_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6"
+ "uxtah%?\\t%0, %2, %1"
+ [(set_attr "type" "alu_shift")
+ (set_attr "predicable" "yes")]
)
(define_expand "zero_extendqisi2"
@@ -3249,7 +3461,7 @@
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
"TARGET_EITHER"
"
- if (GET_CODE (operands[1]) != MEM)
+ if (!arm_arch6 && GET_CODE (operands[1]) != MEM)
{
if (TARGET_ARM)
{
@@ -3285,26 +3497,61 @@
)
(define_insn "*thumb_zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_THUMB"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_THUMB && !arm_arch6"
"ldrb\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "32")]
)
+(define_insn "*thumb_zero_extendqisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,m")))]
+ "TARGET_THUMB && arm_arch6"
+ "@
+ uxtb\\t%0, %1
+ ldrb\\t%0, %1"
+ [(set_attr "length" "2,2")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,32")]
+)
+
(define_insn "*arm_zero_extendqisi2"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ARM"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_ARM && !arm_arch6"
"ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "4096")
(set_attr "neg_pool_range" "4084")]
)
+(define_insn "*arm_zero_extendqisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ uxtb%?\\t%0, %1
+ ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,4096")
+ (set_attr "neg_pool_range" "*,4084")]
+)
+
+(define_insn "*arm_zero_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (zero_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6"
+ "uxtab%?\\t%0, %2, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "alu_shift")]
+)
+
(define_split
[(set (match_operand:SI 0 "s_register_operand" "")
(zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
@@ -3315,6 +3562,16 @@
""
)
+(define_split
+ [(set (match_operand:SI 0 "s_register_operand" "")
+ (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 3)))
+ (clobber (match_operand:SI 2 "s_register_operand" ""))]
+ "TARGET_ARM && (GET_CODE (operands[1]) != MEM) && BYTES_BIG_ENDIAN"
+ [(set (match_dup 2) (match_dup 1))
+ (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
+ ""
+)
+
(define_insn "*compareqi_eq0"
[(set (reg:CC_Z CC_REGNUM)
(compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
@@ -3334,55 +3591,51 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
+ if (GET_CODE (operands[1]) == MEM)
{
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- here because the insn below will generate an LDRH instruction
- rather than an LDR instruction, so we cannot get an unaligned
- word access. */
- emit_insn (gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_SIGN_EXTEND (SImode, operands[1])));
- DONE;
+ if (TARGET_THUMB)
+ {
+ emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
+ DONE;
+ }
+ else if (arm_arch4)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ DONE;
+ }
}
- if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
+ if (TARGET_ARM && GET_CODE (operands[1]) == MEM)
{
emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
DONE;
}
+
if (!s_register_operand (operands[1], HImode))
operands[1] = copy_to_mode_reg (HImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
- if (TARGET_THUMB)
+ if (arm_arch6)
{
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
-
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (16);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
-
+ if (TARGET_THUMB)
+ emit_insn (gen_thumb_extendhisi2 (operands[0], operands[1]));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+
DONE;
}
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
}"
)
-(define_insn "*thumb_extendhisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
- (clobber (match_scratch:SI 2 "=&l"))]
- "TARGET_THUMB"
+(define_insn "thumb_extendhisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
+ (clobber (match_scratch:SI 2 "=&l"))]
+ "TARGET_THUMB && !arm_arch6"
"*
{
rtx ops[4];
@@ -3419,12 +3672,8 @@
ops[1] = mem;
ops[2] = const0_rtx;
}
-
- if (GET_CODE (ops[1]) != REG)
- {
- debug_rtx (ops[1]);
- abort ();
- }
+
+ gcc_assert (GET_CODE (ops[1]) == REG);
ops[0] = operands[0];
ops[3] = operands[2];
@@ -3432,10 +3681,79 @@
return \"\";
}"
[(set_attr "length" "4")
- (set_attr "type" "load")
+ (set_attr "type" "load_byte")
(set_attr "pool_range" "1020")]
)
+;; We used to have an early-clobber on the scratch register here.
+;; However, there's a bug somewhere in reload which means that this
+;; can be partially ignored during spill allocation if the memory
+;; address also needs reloading; this causes us to die later on when
+;; we try to verify the operands. Fortunately, we don't really need
+;; the early-clobber: we can always use operand 0 if operand 2
+;; overlaps the address.
+(define_insn "*thumb_extendhisi2_insn_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "l,m")))
+ (clobber (match_scratch:SI 2 "=X,l"))]
+ "TARGET_THUMB && arm_arch6"
+ "*
+ {
+ rtx ops[4];
+ rtx mem;
+
+ if (which_alternative == 0)
+ return \"sxth\\t%0, %1\";
+
+ mem = XEXP (operands[1], 0);
+
+ /* This code used to try to use 'V', and fix the address only if it was
+ offsettable, but this fails for e.g. REG+48 because 48 is outside the
+ range of QImode offsets, and offsettable_address_p does a QImode
+ address check. */
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ if (GET_CODE (a) == LABEL_REF
+ && GET_CODE (b) == CONST_INT)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (b) == REG)
+ return \"ldrsh\\t%0, %1\";
+
+ ops[1] = a;
+ ops[2] = b;
+ }
+ else
+ {
+ ops[1] = mem;
+ ops[2] = const0_rtx;
+ }
+
+ gcc_assert (GET_CODE (ops[1]) == REG);
+
+ ops[0] = operands[0];
+ if (reg_mentioned_p (operands[2], ops[1]))
+ ops[3] = ops[0];
+ else
+ ops[3] = operands[2];
+ output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
+ return \"\";
+ }"
+ [(set_attr "length" "2,4")
+ (set_attr "type" "alu_shift,load_byte")
+ (set_attr "pool_range" "*,1020")]
+)
+
(define_expand "extendhisi2_mem"
[(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
(set (match_dup 3)
@@ -3449,10 +3767,8 @@
rtx mem1, mem2;
rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- mem1 = gen_rtx_MEM (QImode, addr);
- MEM_COPY_ATTRIBUTES (mem1, operands[1]);
- mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
- MEM_COPY_ATTRIBUTES (mem2, operands[1]);
+ mem1 = change_address (operands[1], QImode, addr);
+ mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = mem1;
operands[2] = gen_reg_rtx (SImode);
@@ -3473,44 +3789,36 @@
}"
)
-(define_insn "*arm_extendhisi_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
+(define_insn "*arm_extendhisi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
"ldr%?sh\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
- "
- if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_extendhisi2_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ sxth%?\\t%0, %1
+ ldr%?sh\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operator:SI 3 "shiftable_operator"
- [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
- (match_operand:SI 4 "s_register_operand" "")]))
- (clobber (match_operand:SI 2 "s_register_operand" ""))]
- "TARGET_ARM && (!arm_arch4)"
- [(set (match_dup 2) (match_dup 1))
- (set (match_dup 0)
- (match_op_dup 3
- [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
- "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
- FAIL;
- "
+(define_insn "*arm_extendhisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (match_operand:HI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6"
+ "sxtah%?\\t%0, %2, %1"
)
(define_expand "extendqihi2"
@@ -3538,59 +3846,17 @@
}"
)
-; Rather than restricting all byte accesses to memory addresses that ldrsb
-; can handle, we fix up the ones that ldrsb can't grok with a split.
(define_insn "*extendqihi_insn"
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+ [(set (match_operand:HI 0 "s_register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "memory_operand" "Uq")))]
"TARGET_ARM && arm_arch4"
- "*
- /* If the address is invalid, this will split the instruction into two. */
- if (bad_signed_byte_operand (operands[1], VOIDmode))
- return \"#\";
- return \"ldr%?sb\\t%0, %1\";
- "
- [(set_attr "type" "load")
+ "ldr%?sb\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
- (set_attr "length" "8")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:HI 0 "s_register_operand" "")
- (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
- "TARGET_ARM && arm_arch4 && reload_completed"
- [(set (match_dup 3) (match_dup 1))
- (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
- "
- {
- HOST_WIDE_INT offset;
-
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
- operands[2] = gen_rtx_MEM (QImode, operands[3]);
- MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
- operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
- && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
- || const_ok_for_arm (-offset)))
- {
- HOST_WIDE_INT low = (offset > 0
- ? (offset & 0xff) : -((-offset) & 0xff));
- XEXP (operands[2], 0) = plus_constant (operands[3], low);
- operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
- }
- /* Ensure the sum is in correct canonical form. */
- else if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
- && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
- operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
- XEXP (operands[1], 1),
- XEXP (operands[1], 0));
- }"
-)
-
(define_expand "extendqisi2"
[(set (match_dup 2)
(ashift:SI (match_operand:QI 1 "general_operand" "")
@@ -3601,97 +3867,66 @@
"TARGET_EITHER"
"
{
- if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
+ if ((TARGET_THUMB || arm_arch4) && GET_CODE (operands[1]) == MEM)
{
- emit_insn (gen_rtx_SET (VOIDmode,
- operands[0],
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
gen_rtx_SIGN_EXTEND (SImode, operands[1])));
DONE;
}
+
if (!s_register_operand (operands[1], QImode))
operands[1] = copy_to_mode_reg (QImode, operands[1]);
- operands[1] = gen_lowpart (SImode, operands[1]);
- operands[2] = gen_reg_rtx (SImode);
-
- if (TARGET_THUMB)
- {
- rtx ops[3];
-
- ops[0] = operands[2];
- ops[1] = operands[1];
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
- ops[0] = operands[0];
- ops[1] = operands[2];
- ops[2] = GEN_INT (24);
-
- emit_insn (gen_rtx_SET (VOIDmode, ops[0],
- gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
-
- DONE;
+ if (arm_arch6)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_SIGN_EXTEND (SImode, operands[1])));
+ DONE;
}
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ operands[2] = gen_reg_rtx (SImode);
}"
)
-; Rather than restricting all byte accesses to memory addresses that ldrsb
-; can handle, we fix up the ones that ldrsb can't grok with a split.
-(define_insn "*arm_extendqisi_insn"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ARM && arm_arch4"
- "*
- /* If the address is invalid, this will split the instruction into two. */
- if (bad_signed_byte_operand (operands[1], VOIDmode))
- return \"#\";
- return \"ldr%?sb\\t%0, %1\";
- "
- [(set_attr "type" "load")
+(define_insn "*arm_extendqisi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "Uq")))]
+ "TARGET_ARM && arm_arch4 && !arm_arch6"
+ "ldr%?sb\\t%0, %1"
+ [(set_attr "type" "load_byte")
(set_attr "predicable" "yes")
- (set_attr "length" "8")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")]
)
-(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
- "TARGET_ARM && arm_arch4 && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
- "
- {
- HOST_WIDE_INT offset;
-
- operands[2] = gen_rtx_MEM (QImode, operands[0]);
- MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
- operands[1] = XEXP (operands[1], 0);
- if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
- && !(const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
- || const_ok_for_arm (-offset)))
- {
- HOST_WIDE_INT low = (offset > 0
- ? (offset & 0xff) : -((-offset) & 0xff));
- XEXP (operands[2], 0) = plus_constant (operands[0], low);
- operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
- }
- /* Ensure the sum is in correct canonical form. */
- else if (GET_CODE (operands[1]) == PLUS
- && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
- && !s_register_operand (XEXP (operands[1], 1), VOIDmode))
- operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
- XEXP (operands[1], 1),
- XEXP (operands[1], 0));
- }"
+(define_insn "*arm_extendqisi_v6"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uq")))]
+ "TARGET_ARM && arm_arch6"
+ "@
+ sxtb%?\\t%0, %1
+ ldr%?sb\\t%0, %1"
+ [(set_attr "type" "alu_shift,load_byte")
+ (set_attr "predicable" "yes")
+ (set_attr "pool_range" "*,256")
+ (set_attr "neg_pool_range" "*,244")]
)
-(define_insn "*thumb_extendqisi2_insn"
- [(set (match_operand:SI 0 "register_operand" "=l,l")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
- "TARGET_THUMB"
+(define_insn "*arm_extendqisi2addsi"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (plus:SI (sign_extend:SI (match_operand:QI 1 "s_register_operand" "r"))
+ (match_operand:SI 2 "s_register_operand" "r")))]
+ "TARGET_ARM && arm_arch6"
+ "sxtab%?\\t%0, %2, %1"
+ [(set_attr "type" "alu_shift")
+ (set_attr "predicable" "yes")]
+)
+
+(define_insn "*thumb_extendqisi2"
+ [(set (match_operand:SI 0 "register_operand" "=l,l")
+ (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
+ "TARGET_THUMB && !arm_arch6"
"*
{
rtx ops[3];
@@ -3733,10 +3968,9 @@
else
output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
}
- else if (GET_CODE (b) != REG)
- abort ();
else
{
+ gcc_assert (GET_CODE (b) == REG);
if (REGNO (b) == REGNO (ops[0]))
{
output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
@@ -3763,14 +3997,94 @@
return \"\";
}"
[(set_attr "length" "2,6")
- (set_attr "type" "load,load")
+ (set_attr "type" "load_byte,load_byte")
(set_attr "pool_range" "32,32")]
)
+(define_insn "*thumb_extendqisi2_v6"
+ [(set (match_operand:SI 0 "register_operand" "=l,l,l")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "l,V,m")))]
+ "TARGET_THUMB && arm_arch6"
+ "*
+ {
+ rtx ops[3];
+ rtx mem;
+
+ if (which_alternative == 0)
+ return \"sxtb\\t%0, %1\";
+
+ mem = XEXP (operands[1], 0);
+
+ if (GET_CODE (mem) == CONST)
+ mem = XEXP (mem, 0);
+
+ if (GET_CODE (mem) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (GET_CODE (mem) == PLUS
+ && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
+ return \"ldr\\t%0, %1\";
+
+ if (which_alternative == 0)
+ return \"ldrsb\\t%0, %1\";
+
+ ops[0] = operands[0];
+
+ if (GET_CODE (mem) == PLUS)
+ {
+ rtx a = XEXP (mem, 0);
+ rtx b = XEXP (mem, 1);
+
+ ops[1] = a;
+ ops[2] = b;
+
+ if (GET_CODE (a) == REG)
+ {
+ if (GET_CODE (b) == REG)
+ output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
+ else if (REGNO (a) == REGNO (ops[0]))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%1, %2]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ else
+ {
+ gcc_assert (GET_CODE (b) == REG);
+ if (REGNO (b) == REGNO (ops[0]))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%2, %1]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ }
+ else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
+ {
+ output_asm_insn (\"ldrb\\t%0, [%0, #0]\", ops);
+ output_asm_insn (\"sxtb\\t%0, %0\", ops);
+ }
+ else
+ {
+ ops[1] = mem;
+ ops[2] = const0_rtx;
+
+ output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
+ }
+ return \"\";
+ }"
+ [(set_attr "length" "2,2,4")
+ (set_attr "type" "alu_shift,load_byte,load_byte")
+ (set_attr "pool_range" "*,32,32")]
+)
+
(define_expand "extendsfdf2"
[(set (match_operand:DF 0 "s_register_operand" "")
(float_extend:DF (match_operand:SF 1 "s_register_operand" "")))]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT"
""
)
@@ -3840,28 +4154,128 @@
(match_operand:DI 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_THUMB)
+ if (!no_new_pseudos)
{
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (DImode, operands[1]);
- }
+ if (GET_CODE (operands[0]) != REG)
+ operands[1] = force_reg (DImode, operands[1]);
}
"
)
(define_insn "*arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>")
- (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
- "TARGET_ARM && !TARGET_CIRRUS && ! TARGET_IWMMXT"
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, r, r, m")
+ (match_operand:DI 1 "di_operand" "rDa,Db,Dc,mi,r"))]
+ "TARGET_ARM
+ && !(TARGET_HARD_FLOAT && (TARGET_MAVERICK || TARGET_VFP))
+ && !TARGET_IWMMXT
+ && ( register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
"*
- return (output_move_double (operands));
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ case 2:
+ return \"#\";
+ default:
+ return output_move_double (operands);
+ }
+ "
+ [(set_attr "length" "8,12,16,8,8")
+ (set_attr "type" "*,*,*,load2,store2")
+ (set_attr "pool_range" "*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,*,*,1008,*")]
+)
+
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "const_double_operand" ""))]
+ "TARGET_ARM
+ && reload_completed
+ && (arm_const_double_inline_cost (operands[1])
+ <= ((optimize_size || arm_ld_sched) ? 3 : 4))"
+ [(const_int 0)]
+ "
+ arm_split_constant (SET, SImode, curr_insn,
+ INTVAL (gen_lowpart (SImode, operands[1])),
+ gen_lowpart (SImode, operands[0]), NULL_RTX, 0);
+ arm_split_constant (SET, SImode, curr_insn,
+ INTVAL (gen_highpart_mode (SImode,
+ GET_MODE (operands[0]),
+ operands[1])),
+ gen_highpart (SImode, operands[0]), NULL_RTX, 0);
+ DONE;
+ "
+)
+
+; If optimizing for size, or if we have load delay slots, then
+; we want to split the constant into two separate operations.
+; In both cases this may split a trivial part into a single data op
+; leaving a single complex constant to load. We can also get longer
+; offsets in a LDR which means we get better chances of sharing the pool
+; entries. Finally, we can normally do a better job of scheduling
+; LDR instructions than we can with LDM.
+; This pattern will only match if the one above did not.
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "const_double_operand" ""))]
+ "TARGET_ARM && reload_completed
+ && arm_const_double_by_parts (operands[1])"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart_mode (SImode, GET_MODE (operands[0]),
+ operands[1]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ "
+)
+
+(define_split
+ [(set (match_operand:ANY64 0 "arm_general_register_operand" "")
+ (match_operand:ANY64 1 "arm_general_register_operand" ""))]
+ "TARGET_EITHER && reload_completed"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[3] = gen_highpart (SImode, operands[1]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[1] = gen_lowpart (SImode, operands[1]);
+
+ /* Handle a partial overlap. */
+ if (rtx_equal_p (operands[0], operands[3]))
+ {
+ rtx tmp0 = operands[0];
+ rtx tmp1 = operands[1];
+
+ operands[0] = operands[2];
+ operands[1] = operands[3];
+ operands[2] = tmp0;
+ operands[3] = tmp1;
+ }
+ "
+)
+
+;; We can't actually do base+index doubleword loads if the index and
+;; destination overlap. Split here so that we at least have chance to
+;; schedule.
+(define_split
+ [(set (match_operand:DI 0 "s_register_operand" "")
+ (mem:DI (plus:SI (match_operand:SI 1 "s_register_operand" "")
+ (match_operand:SI 2 "s_register_operand" ""))))]
+ "TARGET_LDRD
+ && reg_overlap_mentioned_p (operands[0], operands[1])
+ && reg_overlap_mentioned_p (operands[0], operands[2])"
+ [(set (match_dup 4)
+ (plus:SI (match_dup 1)
+ (match_dup 2)))
+ (set (match_dup 0)
+ (mem:DI (match_dup 4)))]
+ "
+ operands[4] = gen_rtx_REG (SImode, REGNO(operands[0]));
"
- [(set_attr "length" "8")
- (set_attr "type" "*,load,store2")
- (set_attr "pool_range" "*,1020,*")
- (set_attr "neg_pool_range" "*,1008,*")]
)
;;; ??? This should have alternatives for constants.
@@ -3872,7 +4286,7 @@
[(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l, m,*r")
(match_operand:DI 1 "general_operand" "l, I,J,>,l,mi,l,*r"))]
"TARGET_THUMB
- && !TARGET_CIRRUS
+ && !(TARGET_HARD_FLOAT && TARGET_MAVERICK)
&& ( register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode))"
"*
@@ -3896,7 +4310,7 @@
case 5:
return thumb_load_double_from_address (operands);
case 6:
- operands[2] = gen_rtx (MEM, SImode,
+ operands[2] = gen_rtx_MEM (SImode,
plus_constant (XEXP (operands[0], 0), 4));
output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
return \"\";
@@ -3907,7 +4321,7 @@
}
}"
[(set_attr "length" "4,4,6,2,2,6,4,4")
- (set_attr "type" "*,*,*,load,store2,load,store2,*")
+ (set_attr "type" "*,*,*,load2,store2,load2,store2,*")
(set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
)
@@ -3921,14 +4335,14 @@
/* Everything except mem = const or mem = mem can be done easily. */
if (GET_CODE (operands[0]) == MEM)
operands[1] = force_reg (SImode, operands[1]);
- if (GET_CODE (operands[1]) == CONST_INT
+ if (arm_general_register_operand (operands[0], SImode)
+ && GET_CODE (operands[1]) == CONST_INT
&& !(const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1]))))
{
- arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
- NULL_RTX,
- (no_new_pseudos ? 0
- : preserve_subexpressions_p ()));
+ arm_split_constant (SET, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0], NULL_RTX,
+ optimize && !no_new_pseudos);
DONE;
}
}
@@ -3940,13 +4354,37 @@
operands[1] = force_reg (SImode, operands[1]);
}
}
-
- if (flag_pic
- && (CONSTANT_P (operands[1])
- || symbol_mentioned_p (operands[1])
- || label_mentioned_p (operands[1])))
- operands[1] = legitimize_pic_address (operands[1], SImode,
- (no_new_pseudos ? operands[0] : 0));
+
+ /* Recognize the case where operand[1] is a reference to thread-local
+ data and load its address to a register. */
+ if (arm_tls_referenced_p (operands[1]))
+ {
+ rtx tmp = operands[1];
+ rtx addend = NULL;
+
+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (tmp, 0), 1);
+ tmp = XEXP (XEXP (tmp, 0), 0);
+ }
+
+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+ tmp = legitimize_tls_address (tmp, no_new_pseudos ? operands[0] : 0);
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (SImode, tmp, addend);
+ tmp = force_operand (tmp, operands[0]);
+ }
+ operands[1] = tmp;
+ }
+ else if (flag_pic
+ && (CONSTANT_P (operands[1])
+ || symbol_mentioned_p (operands[1])
+ || label_mentioned_p (operands[1])))
+ operands[1] = legitimize_pic_address (operands[1], SImode,
+ (no_new_pseudos ? operands[0] : 0));
"
)
@@ -3954,6 +4392,7 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m")
(match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
"TARGET_ARM && ! TARGET_IWMMXT
+ && !(TARGET_HARD_FLOAT && TARGET_VFP)
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
@@ -3961,22 +4400,22 @@
mvn%?\\t%0, #%B1
ldr%?\\t%0, %1
str%?\\t%1, %0"
- [(set_attr "type" "*,*,load,store1")
+ [(set_attr "type" "*,*,load1,store1")
(set_attr "predicable" "yes")
(set_attr "pool_range" "*,*,4096,*")
(set_attr "neg_pool_range" "*,*,4084,*")]
)
(define_split
- [(set (match_operand:SI 0 "s_register_operand" "")
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
"TARGET_ARM
&& (!(const_ok_for_arm (INTVAL (operands[1]))
|| const_ok_for_arm (~INTVAL (operands[1]))))"
[(clobber (const_int 0))]
"
- arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
- NULL_RTX, 0);
+ arm_split_constant (SET, SImode, NULL_RTX,
+ INTVAL (operands[1]), operands[0], NULL_RTX, 0);
DONE;
"
)
@@ -3998,14 +4437,14 @@
str\\t%1, %0
mov\\t%0, %1"
[(set_attr "length" "2,2,4,4,2,2,2,2,2")
- (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
+ (set_attr "type" "*,*,*,*,load1,store1,load1,store1,*")
(set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
)
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
+ "TARGET_THUMB && satisfies_constraint_J (operands[1])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (neg:SI (match_dup 0)))]
"operands[1] = GEN_INT (- INTVAL (operands[1]));"
@@ -4014,7 +4453,7 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "const_int_operand" ""))]
- "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
+ "TARGET_THUMB && satisfies_constraint_K (operands[1])"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
"
@@ -4050,7 +4489,7 @@
(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
"TARGET_ARM && flag_pic"
"ldr%?\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set (attr "pool_range") (const_int 4096))
(set (attr "neg_pool_range") (const_int 4084))]
)
@@ -4060,7 +4499,7 @@
(unspec:SI [(match_operand:SI 1 "" "mX")] UNSPEC_PIC_SYM))]
"TARGET_THUMB && flag_pic"
"ldr\\t%0, %1"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set (attr "pool_range") (const_int 1024))]
)
@@ -4070,7 +4509,7 @@
[(set (match_operand:SI 0 "s_register_operand" "")
(unspec:SI [(match_operand 1 "" "") (match_dup 2)] UNSPEC_PIC_SYM))]
"TARGET_ARM && flag_pic"
- "operands[2] = pic_offset_table_rtx;"
+ "operands[2] = cfun->machine->pic_reg;"
)
(define_insn "*pic_load_addr_based_insn"
@@ -4078,7 +4517,7 @@
(unspec:SI [(match_operand 1 "" "")
(match_operand 2 "s_register_operand" "r")]
UNSPEC_PIC_SYM))]
- "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
+ "TARGET_EITHER && flag_pic && operands[2] == cfun->machine->pic_reg"
"*
#ifdef AOF_ASSEMBLER
operands[1] = aof_pic_entry (operands[1]);
@@ -4086,7 +4525,7 @@
output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
return \"\";
"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set (attr "pool_range")
(if_then_else (eq_attr "is_thumb" "yes")
(const_int 1024)
@@ -4098,41 +4537,79 @@
)
(define_insn "pic_add_dot_plus_four"
- [(set (match_operand:SI 0 "register_operand" "+r")
- (unspec:SI [(plus:SI (match_dup 0)
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "0")
(const (plus:SI (pc) (const_int 4))))]
UNSPEC_PIC_BASE))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_THUMB && flag_pic"
+ (use (match_operand 2 "" ""))]
+ "TARGET_THUMB"
"*
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (operands[1]));
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
return \"add\\t%0, %|pc\";
"
[(set_attr "length" "2")]
)
(define_insn "pic_add_dot_plus_eight"
- [(set (match_operand:SI 0 "register_operand" "+r")
- (unspec:SI [(plus:SI (match_dup 0)
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
(const (plus:SI (pc) (const_int 8))))]
UNSPEC_PIC_BASE))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_ARM && flag_pic"
+ (use (match_operand 2 "" ""))]
+ "TARGET_ARM"
"*
- (*targetm.asm_out.internal_label) (asm_out_file, \"L\",
- CODE_LABEL_NUMBER (operands[1]));
- return \"add%?\\t%0, %|pc, %0\";
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
+ return \"add%?\\t%0, %|pc, %1\";
"
[(set_attr "predicable" "yes")]
)
+(define_insn "tls_load_dot_plus_eight"
+ [(set (match_operand:SI 0 "register_operand" "+r")
+ (mem:SI (unspec:SI [(plus:SI (match_operand:SI 1 "register_operand" "r")
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE)))
+ (use (match_operand 2 "" ""))]
+ "TARGET_ARM"
+ "*
+ (*targetm.asm_out.internal_label) (asm_out_file, \"LPIC\",
+ INTVAL (operands[2]));
+ return \"ldr%?\\t%0, [%|pc, %1]\t\t@ tls_load_dot_plus_eight\";
+ "
+ [(set_attr "predicable" "yes")]
+)
+
+;; PIC references to local variables can generate pic_add_dot_plus_eight
+;; followed by a load. These sequences can be crunched down to
+;; tls_load_dot_plus_eight by a peephole.
+
+(define_peephole2
+ [(parallel [(set (match_operand:SI 0 "register_operand" "")
+ (unspec:SI [(plus:SI (match_operand:SI 3 "register_operand" "")
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE))
+ (use (label_ref (match_operand 1 "" "")))])
+ (set (match_operand:SI 2 "register_operand" "") (mem:SI (match_dup 0)))]
+ "TARGET_ARM && peep2_reg_dead_p (2, operands[0])"
+ [(parallel [(set (match_dup 2)
+ (mem:SI (unspec:SI [(plus:SI (match_dup 3)
+ (const (plus:SI (pc) (const_int 8))))]
+ UNSPEC_PIC_BASE)))
+ (use (label_ref (match_dup 1)))])]
+ ""
+)
+
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
"
{
- arm_finalize_pic (0);
+ /* r3 is clobbered by set/longjmp, so we can use it as a scratch
+ register. */
+ if (arm_pic_register != INVALID_REGNUM)
+ arm_load_pic_register (1UL << 3);
DONE;
}")
@@ -4323,7 +4800,7 @@
emit_insn (gen_movsi (reg, GEN_INT (val)));
operands[1] = gen_lowpart (HImode, reg);
}
- else if (arm_arch4 && !no_new_pseudos && optimize > 0
+ else if (arm_arch4 && optimize && !no_new_pseudos
&& GET_CODE (operands[1]) == MEM)
{
rtx reg = gen_reg_rtx (SImode);
@@ -4333,89 +4810,39 @@
}
else if (!arm_arch4)
{
- /* Note: We do not have to worry about TARGET_MMU_TRAPS
- for v4 and up architectures because LDRH instructions will
- be used to access the HI values, and these cannot generate
- unaligned word access faults in the MMU. */
if (GET_CODE (operands[1]) == MEM)
{
- if (TARGET_MMU_TRAPS)
- {
- rtx base;
- rtx offset = const0_rtx;
- rtx reg = gen_reg_rtx (SImode);
-
- if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
- || (GET_CODE (base) == PLUS
- && (GET_CODE (offset = XEXP (base, 1))
- == CONST_INT)
- && ((INTVAL(offset) & 1) != 1)
- && GET_CODE (base = XEXP (base, 0)) == REG))
- && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
- {
- HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
- rtx new;
-
- new = gen_rtx_MEM (SImode,
- plus_constant (base, new_offset));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_movsi (reg, new));
- if (((INTVAL (offset) & 2) != 0)
- ^ (BYTES_BIG_ENDIAN ? 1 : 0))
- {
- rtx reg2 = gen_reg_rtx (SImode);
-
- emit_insn (gen_lshrsi3 (reg2, reg,
- GEN_INT (16)));
- reg = reg2;
- }
- }
- else
- emit_insn (gen_movhi_bytes (reg, operands[1]));
-
- operands[1] = gen_lowpart (HImode, reg);
- }
- else if (BYTES_BIG_ENDIAN)
+ rtx base;
+ rtx offset = const0_rtx;
+ rtx reg = gen_reg_rtx (SImode);
+
+ if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
+ || (GET_CODE (base) == PLUS
+ && (GET_CODE (offset = XEXP (base, 1))
+ == CONST_INT)
+ && ((INTVAL(offset) & 1) != 1)
+ && GET_CODE (base = XEXP (base, 0)) == REG))
+ && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
{
- rtx base;
- rtx offset = const0_rtx;
-
- if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
- || (GET_CODE (base) == PLUS
- && (GET_CODE (offset = XEXP (base, 1))
- == CONST_INT)
- && GET_CODE (base = XEXP (base, 0)) == REG))
- && REGNO_POINTER_ALIGN (REGNO (base)) >= 32)
- {
- rtx reg = gen_reg_rtx (SImode);
- rtx new;
-
- if ((INTVAL (offset) & 2) == 2)
- {
- HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
- new = gen_rtx_MEM (SImode,
- plus_constant (base,
- new_offset));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_movsi (reg, new));
- }
- else
- {
- new = gen_rtx_MEM (SImode,
- XEXP (operands[1], 0));
- MEM_COPY_ATTRIBUTES (new, operands[1]);
- emit_insn (gen_rotated_loadsi (reg, new));
- }
-
- operands[1] = gen_lowpart (HImode, reg);
- }
- else
- {
- emit_insn (gen_movhi_bigend (operands[0],
- operands[1]));
- DONE;
- }
+ rtx new;
+
+ new = widen_memory_access (operands[1], SImode,
+ ((INTVAL (offset) & ~3)
+ - INTVAL (offset)));
+ emit_insn (gen_movsi (reg, new));
+ if (((INTVAL (offset) & 2) != 0)
+ ^ (BYTES_BIG_ENDIAN ? 1 : 0))
+ {
+ rtx reg2 = gen_reg_rtx (SImode);
+
+ emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
+ reg = reg2;
+ }
}
+ else
+ emit_insn (gen_movhi_bytes (reg, operands[1]));
+
+ operands[1] = gen_lowpart (HImode, reg);
}
}
}
@@ -4426,8 +4853,7 @@
{
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == REG);
operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
emit_insn (gen_movsi (operands[0], operands[1]));
@@ -4438,8 +4864,13 @@
{
if (!no_new_pseudos)
{
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (HImode, operands[1]);
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
@@ -4462,17 +4893,28 @@
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
+
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendhisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (HImode, reg);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (HImode, operands[1]);
}
- /* Handle loading a large integer during reload. */
else if (GET_CODE (operands[1]) == CONST_INT
- && !CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
+ && !satisfies_constraint_I (operands[1]))
{
+ /* Handle loading a large integer during reload. */
+
/* Writing a constant to memory needs a scratch, which should
be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == REG);
- operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
+ operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
emit_insn (gen_movsi (operands[0], operands[1]));
DONE;
}
@@ -4494,7 +4936,7 @@
case 3: return \"mov %0, %1\";
case 4: return \"mov %0, %1\";
case 5: return \"mov %0, %1\";
- default: abort ();
+ default: gcc_unreachable ();
case 1:
/* The stack pointer can end up being taken as an index register.
Catch this case here and deal with it. */
@@ -4514,28 +4956,10 @@
return \"ldrh %0, %1\";
}"
[(set_attr "length" "2,4,2,2,2,2")
- (set_attr "type" "*,load,store1,*,*,*")]
+ (set_attr "type" "*,load1,store1,*,*,*")]
)
-(define_insn "rotated_loadsi"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
- (const_int 16)))]
- "TARGET_ARM && (!TARGET_MMU_TRAPS)"
- "*
- {
- rtx ops[2];
-
- ops[0] = operands[0];
- ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
- output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
- return \"\";
- }"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
(define_expand "movhi_bytes"
[(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
(set (match_dup 3)
@@ -4548,10 +4972,8 @@
rtx mem1, mem2;
rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- mem1 = gen_rtx_MEM (QImode, addr);
- MEM_COPY_ATTRIBUTES (mem1, operands[1]);
- mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
- MEM_COPY_ATTRIBUTES (mem2, operands[1]);
+ mem1 = change_address (operands[1], QImode, addr);
+ mem2 = change_address (operands[1], QImode, plus_constant (addr, 1));
operands[0] = gen_lowpart (SImode, operands[0]);
operands[1] = mem1;
operands[2] = gen_reg_rtx (SImode);
@@ -4599,86 +5021,39 @@
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi
- str%?h\\t%1, %0\\t%@ movhi
+ str%?h\\t%1, %0\\t%@ movhi
ldr%?h\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "*,*,store1,load")
+ [(set_attr "type" "*,*,store1,load1")
(set_attr "predicable" "yes")
(set_attr "pool_range" "*,*,*,256")
(set_attr "neg_pool_range" "*,*,*,244")]
)
-(define_insn "*movhi_insn_littleend"
- [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
- (match_operand:HI 1 "general_operand" "rI,K,m"))]
- "TARGET_ARM
- && !arm_arch4
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && (GET_CODE (operands[1]) != CONST_INT
- || const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1])))"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi
- ldr%?\\t%0, %1\\t%@ movhi"
- [(set_attr "type" "*,*,load")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")]
-)
-
-(define_insn "*movhi_insn_bigend"
- [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
- (match_operand:HI 1 "general_operand" "rI,K,m"))]
- "TARGET_ARM
- && !arm_arch4
- && BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && (GET_CODE (operands[1]) != CONST_INT
- || const_ok_for_arm (INTVAL (operands[1]))
- || const_ok_for_arm (~INTVAL (operands[1])))"
- "@
- mov%?\\t%0, %1\\t%@ movhi
- mvn%?\\t%0, #%B1\\t%@ movhi
- ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
- [(set_attr "type" "*,*,load")
- (set_attr "predicable" "yes")
- (set_attr "length" "4,4,8")
- (set_attr "pool_range" "*,*,4092")
- (set_attr "neg_pool_range" "*,*,4084")]
-)
-
-(define_insn "*loadhi_si_bigend"
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
- (const_int 16)))]
- "TARGET_ARM
- && BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS"
- "ldr%?\\t%0, %1\\t%@ movhi_bigend"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")
- (set_attr "pool_range" "4096")
- (set_attr "neg_pool_range" "4084")]
-)
-
(define_insn "*movhi_bytes"
[(set (match_operand:HI 0 "s_register_operand" "=r,r")
(match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
- "TARGET_ARM && TARGET_MMU_TRAPS"
+ "TARGET_ARM"
"@
mov%?\\t%0, %1\\t%@ movhi
mvn%?\\t%0, #%B1\\t%@ movhi"
[(set_attr "predicable" "yes")]
)
-(define_insn "thumb_movhi_clobber"
- [(set (match_operand:HI 0 "memory_operand" "=m")
- (match_operand:HI 1 "register_operand" "l"))
- (clobber (match_operand:SI 2 "register_operand" "=&l"))]
+(define_expand "thumb_movhi_clobber"
+ [(set (match_operand:HI 0 "memory_operand" "")
+ (match_operand:HI 1 "register_operand" ""))
+ (clobber (match_operand:DI 2 "register_operand" ""))]
"TARGET_THUMB"
- "*
- abort ();"
+ "
+ if (strict_memory_address_p (HImode, XEXP (operands[0], 0))
+ && REGNO (operands[1]) <= LAST_LO_REGNUM)
+ {
+ emit_insn (gen_movhi (operands[0], operands[1]));
+ DONE;
+ }
+ /* XXX Fixme, need to handle other cases here as well. */
+ gcc_unreachable ();
+ "
)
;; We use a DImode scratch because we may occasionally need an additional
@@ -4701,7 +5076,7 @@
[(parallel [(match_operand:HI 0 "s_register_operand" "=r")
(match_operand:HI 1 "arm_reload_memory_operand" "o")
(match_operand:DI 2 "s_register_operand" "=&r")])]
- "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
+ "TARGET_EITHER"
"
if (TARGET_ARM)
arm_reload_in_hi (operands);
@@ -4715,37 +5090,20 @@
(match_operand:QI 1 "general_operand" ""))]
"TARGET_EITHER"
"
- if (TARGET_ARM)
- {
- /* Everything except mem = const or mem = mem can be done easily */
-
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[1]) == CONST_INT)
- {
- rtx reg = gen_reg_rtx (SImode);
-
- emit_insn (gen_movsi (reg, operands[1]));
- operands[1] = gen_lowpart (QImode, reg);
- }
- if (GET_CODE (operands[1]) == MEM && optimize > 0)
- {
- rtx reg = gen_reg_rtx (SImode);
+ /* Everything except mem = const or mem = mem can be done easily */
- emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
- operands[1] = gen_lowpart (QImode, reg);
- }
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (QImode, operands[1]);
- }
- }
- else /* TARGET_THUMB */
+ if (!no_new_pseudos)
{
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (QImode, operands[1]);
+ if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+
+ if (TARGET_THUMB)
+ {
/* ??? We shouldn't really get invalid addresses here, but this can
happen if we are passed a SP (never OK for HImode/QImode) or
virtual register (rejected by GO_IF_LEGITIMATE_ADDRESS for
@@ -4766,20 +5124,32 @@
operands[1]
= replace_equiv_address (operands[1],
copy_to_reg (XEXP (operands[1], 0)));
- }
+ }
+
+ if (GET_CODE (operands[1]) == MEM && optimize > 0)
+ {
+ rtx reg = gen_reg_rtx (SImode);
+
+ emit_insn (gen_zero_extendqisi2 (reg, operands[1]));
+ operands[1] = gen_lowpart (QImode, reg);
+ }
+
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (QImode, operands[1]);
+ }
+ else if (TARGET_THUMB
+ && GET_CODE (operands[1]) == CONST_INT
+ && !satisfies_constraint_I (operands[1]))
+ {
/* Handle loading a large integer during reload. */
- else if (GET_CODE (operands[1]) == CONST_INT
- && !CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
- {
- /* Writing a constant to memory needs a scratch, which should
- be handled with SECONDARY_RELOADs. */
- if (GET_CODE (operands[0]) != REG)
- abort ();
- operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
- emit_insn (gen_movsi (operands[0], operands[1]));
- DONE;
- }
+ /* Writing a constant to memory needs a scratch, which should
+ be handled with SECONDARY_RELOADs. */
+ gcc_assert (GET_CODE (operands[0]) == REG);
+
+ operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
+ emit_insn (gen_movsi (operands[0], operands[1]));
+ DONE;
}
"
)
@@ -4796,7 +5166,7 @@
mvn%?\\t%0, #%B1
ldr%?b\\t%0, %1
str%?b\\t%1, %0"
- [(set_attr "type" "*,*,load,store1")
+ [(set_attr "type" "*,*,load1,store1")
(set_attr "predicable" "yes")]
)
@@ -4814,7 +5184,7 @@
mov\\t%0, %1
mov\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "*,load,store1,*,*,*")
+ (set_attr "type" "*,load1,store1,*,*,*")
(set_attr "pool_range" "*,32,*,*,*,*")]
)
@@ -4839,11 +5209,12 @@
"
)
+;; Transform a floating-point move of a constant into a core register into
+;; an SImode operation.
(define_split
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
+ [(set (match_operand:SF 0 "arm_general_register_operand" "")
(match_operand:SF 1 "immediate_operand" ""))]
"TARGET_ARM
- && !TARGET_HARD_FLOAT
&& reload_completed
&& GET_CODE (operands[1]) == CONST_DOUBLE"
[(set (match_dup 2) (match_dup 3))]
@@ -4859,7 +5230,6 @@
[(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
(match_operand:SF 1 "general_operand" "r,mE,r"))]
"TARGET_ARM
- && !TARGET_CIRRUS
&& TARGET_SOFT_FLOAT
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], SFmode))"
@@ -4869,7 +5239,7 @@
str%?\\t%1, %0\\t%@ float"
[(set_attr "length" "4,4,4")
(set_attr "predicable" "yes")
- (set_attr "type" "*,load,store1")
+ (set_attr "type" "*,load1,store1")
(set_attr "pool_range" "*,4096,*")
(set_attr "neg_pool_range" "*,4084,*")]
)
@@ -4890,7 +5260,7 @@
mov\\t%0, %1
mov\\t%0, %1"
[(set_attr "length" "2")
- (set_attr "type" "*,load,store1,load,store1,*,*")
+ (set_attr "type" "*,load1,store1,load1,store1,*,*")
(set_attr "pool_range" "*,*,*,1020,*,*,*")]
)
@@ -4948,7 +5318,8 @@
emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
XEXP (XEXP (operands[0], 0), 1)));
- emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
+ emit_insn (gen_rtx_SET (VOIDmode,
+ replace_equiv_address (operands[0], operands[2]),
operands[1]));
if (code == POST_DEC)
@@ -4959,14 +5330,24 @@
)
(define_insn "*movdf_soft_insn"
- [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
- (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
+ [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,r,r,m")
+ (match_operand:DF 1 "soft_df_operand" "rDa,Db,Dc,mF,r"))]
"TARGET_ARM && TARGET_SOFT_FLOAT
- && !TARGET_CIRRUS
+ && ( register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ "*
+ switch (which_alternative)
+ {
+ case 0:
+ case 1:
+ case 2:
+ return \"#\";
+ default:
+ return output_move_double (operands);
+ }
"
- "* return output_move_double (operands);"
- [(set_attr "length" "8,8,8")
- (set_attr "type" "*,load,store2")
+ [(set_attr "length" "8,12,16,8,8")
+ (set_attr "type" "*,*,*,load2,store2")
(set_attr "pool_range" "1020")
(set_attr "neg_pool_range" "1008")]
)
@@ -4996,8 +5377,8 @@
case 3:
return thumb_load_double_from_address (operands);
case 4:
- operands[2] = gen_rtx (MEM, SImode,
- plus_constant (XEXP (operands[0], 0), 4));
+ operands[2] = gen_rtx_MEM (SImode,
+ plus_constant (XEXP (operands[0], 0), 4));
output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
return \"\";
case 5:
@@ -5007,10 +5388,20 @@
}
"
[(set_attr "length" "4,2,2,6,4,4")
- (set_attr "type" "*,load,store2,load,store2,*")
+ (set_attr "type" "*,load2,store2,load2,store2,*")
(set_attr "pool_range" "*,*,*,1020,*,*")]
)
+(define_expand "movxf"
+ [(set (match_operand:XF 0 "general_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
+ "
+ if (GET_CODE (operands[0]) == MEM)
+ operands[1] = force_reg (XFmode, operands[1]);
+ "
+)
+
;; Vector Moves
(define_expand "movv2si"
[(set (match_operand:V2SI 0 "nonimmediate_operand" "")
@@ -5045,7 +5436,7 @@
"TARGET_ARM"
{
HOST_WIDE_INT offset = 0;
-
+
/* Support only fixed point registers. */
if (GET_CODE (operands[2]) != CONST_INT
|| INTVAL (operands[2]) > 14
@@ -5060,7 +5451,6 @@
= arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
force_reg (SImode, XEXP (operands[1], 0)),
TRUE, FALSE, operands[1], &offset);
-
})
;; Load multiple with write-back
@@ -5080,10 +5470,28 @@
(mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 5"
"ldm%?ia\\t%1!, {%3, %4, %5, %6}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load4")
(set_attr "predicable" "yes")]
)
+(define_insn "*ldmsi_postinc4_thumb"
+ [(match_parallel 0 "load_multiple_operation"
+ [(set (match_operand:SI 1 "s_register_operand" "=l")
+ (plus:SI (match_operand:SI 2 "s_register_operand" "1")
+ (const_int 16)))
+ (set (match_operand:SI 3 "arm_hard_register_operand" "")
+ (mem:SI (match_dup 2)))
+ (set (match_operand:SI 4 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 4))))
+ (set (match_operand:SI 5 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 8))))
+ (set (match_operand:SI 6 "arm_hard_register_operand" "")
+ (mem:SI (plus:SI (match_dup 2) (const_int 12))))])]
+ "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
+ "ldmia\\t%1!, {%3, %4, %5, %6}"
+ [(set_attr "type" "load4")]
+)
+
(define_insn "*ldmsi_postinc3"
[(match_parallel 0 "load_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@@ -5097,7 +5505,7 @@
(mem:SI (plus:SI (match_dup 2) (const_int 8))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
"ldm%?ia\\t%1!, {%3, %4, %5}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load3")
(set_attr "predicable" "yes")]
)
@@ -5112,7 +5520,7 @@
(mem:SI (plus:SI (match_dup 2) (const_int 4))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
"ldm%?ia\\t%1!, {%3, %4}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load2")
(set_attr "predicable" "yes")]
)
@@ -5130,7 +5538,7 @@
(mem:SI (plus:SI (match_dup 1) (const_int 12))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 4"
"ldm%?ia\\t%1, {%2, %3, %4, %5}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load4")
(set_attr "predicable" "yes")]
)
@@ -5144,7 +5552,7 @@
(mem:SI (plus:SI (match_dup 1) (const_int 8))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 3"
"ldm%?ia\\t%1, {%2, %3, %4}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load3")
(set_attr "predicable" "yes")]
)
@@ -5156,7 +5564,7 @@
(mem:SI (plus:SI (match_dup 1) (const_int 4))))])]
"TARGET_ARM && XVECLEN (operands[0], 0) == 2"
"ldm%?ia\\t%1, {%2, %3}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load2")
(set_attr "predicable" "yes")]
)
@@ -5205,6 +5613,24 @@
(set_attr "type" "store4")]
)
+(define_insn "*stmsi_postinc4_thumb"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (match_operand:SI 1 "s_register_operand" "=l")
+ (plus:SI (match_operand:SI 2 "s_register_operand" "1")
+ (const_int 16)))
+ (set (mem:SI (match_dup 2))
+ (match_operand:SI 3 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 4)))
+ (match_operand:SI 4 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 8)))
+ (match_operand:SI 5 "arm_hard_register_operand" ""))
+ (set (mem:SI (plus:SI (match_dup 2) (const_int 12)))
+ (match_operand:SI 6 "arm_hard_register_operand" ""))])]
+ "TARGET_THUMB && XVECLEN (operands[0], 0) == 5"
+ "stmia\\t%1!, {%3, %4, %5, %6}"
+ [(set_attr "type" "store4")]
+)
+
(define_insn "*stmsi_postinc3"
[(match_parallel 0 "store_multiple_operation"
[(set (match_operand:SI 1 "s_register_operand" "=r")
@@ -5285,7 +5711,7 @@
;; We could let this apply for blocks of less than this, but it clobbers so
;; many registers that there is then probably a better way.
-(define_expand "movstrqi"
+(define_expand "movmemqi"
[(match_operand:BLK 0 "general_operand" "")
(match_operand:BLK 1 "general_operand" "")
(match_operand:SI 2 "const_int_operand" "")
@@ -5294,7 +5720,7 @@
"
if (TARGET_ARM)
{
- if (arm_gen_movstrqi (operands))
+ if (arm_gen_movmemqi (operands))
DONE;
FAIL;
}
@@ -5304,7 +5730,7 @@
|| INTVAL (operands[2]) > 48)
FAIL;
- thumb_expand_movstrqi (operands);
+ thumb_expand_movmemqi (operands);
DONE;
}
"
@@ -5527,7 +5953,7 @@
(define_insn "*negated_cbranchsi4"
[(set (pc)
(if_then_else
- (match_operator 0 "arm_comparison_operator"
+ (match_operator 0 "equality_operator"
[(match_operand:SI 1 "s_register_operand" "l")
(neg:SI (match_operand:SI 2 "s_register_operand" "l"))])
(label_ref (match_operand 3 "" ""))
@@ -5603,6 +6029,50 @@
(const_int 8))))]
)
+(define_insn "*tlobits_cbranch"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(zero_extract:SI (match_operand:SI 1 "s_register_operand" "l")
+ (match_operand:SI 2 "const_int_operand" "i")
+ (const_int 0))
+ (const_int 0)])
+ (label_ref (match_operand 3 "" ""))
+ (pc)))
+ (clobber (match_scratch:SI 4 "=l"))]
+ "TARGET_THUMB"
+ "*
+ {
+ rtx op[3];
+ op[0] = operands[4];
+ op[1] = operands[1];
+ op[2] = GEN_INT (32 - INTVAL (operands[2]));
+
+ output_asm_insn (\"lsl\\t%0, %1, %2\", op);
+ switch (get_attr_length (insn))
+ {
+ case 4: return \"b%d0\\t%l3\";
+ case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
+ default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
+ }
+ }"
+ [(set (attr "far_jump")
+ (if_then_else
+ (eq_attr "length" "8")
+ (const_string "yes")
+ (const_string "no")))
+ (set (attr "length")
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -250))
+ (le (minus (match_dup 3) (pc)) (const_int 256)))
+ (const_int 4)
+ (if_then_else
+ (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
+ (le (minus (match_dup 3) (pc)) (const_int 2048)))
+ (const_int 6)
+ (const_int 8))))]
+)
+
(define_insn "*tstsi3_cbranch"
[(set (pc)
(if_then_else
@@ -6215,7 +6685,7 @@
(match_operator 3 "comparison_operator"
[(plus:SI
(match_operand:SI 1 "s_register_operand" "%l,l,l,0")
- (match_operand:SI 2 "reg_or_int_operand" "J,l,I,L"))
+ (match_operand:SI 2 "reg_or_int_operand" "J,l,L,IJ"))
(const_int 0)])
(label_ref (match_operand 4 "" ""))
(pc)))
@@ -6236,10 +6706,16 @@
output_asm_insn (\"cmn\t%1, %2\", operands);
break;
case 2:
- output_asm_insn (\"add\t%0, %1, %2\", operands);
+ if (INTVAL (operands[2]) < 0)
+ output_asm_insn (\"sub\t%0, %1, %2\", operands);
+ else
+ output_asm_insn (\"add\t%0, %1, %2\", operands);
break;
case 3:
- output_asm_insn (\"add\t%0, %0, %2\", operands);
+ if (INTVAL (operands[2]) < 0)
+ output_asm_insn (\"sub\t%0, %0, %2\", operands);
+ else
+ output_asm_insn (\"add\t%0, %0, %2\", operands);
break;
}
@@ -6407,12 +6883,9 @@
(define_expand "cmpsf"
[(match_operand:SF 0 "s_register_operand" "")
- (match_operand:SF 1 "fpa_rhs_operand" "")]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:SF 1 "arm_float_compare_operand" "")]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], SFmode))
- operands[1] = force_reg (SFmode, operands[1]);
-
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
DONE;
@@ -6421,12 +6894,9 @@
(define_expand "cmpdf"
[(match_operand:DF 0 "s_register_operand" "")
- (match_operand:DF 1 "fpa_rhs_operand" "")]
- "TARGET_ARM && TARGET_ANY_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_compare_operand" "")]
+ "TARGET_ARM && TARGET_HARD_FLOAT"
"
- if (TARGET_CIRRUS && !cirrus_fp_register (operands[1], DFmode))
- operands[1] = force_reg (DFmode, operands[1]);
-
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
DONE;
@@ -6454,7 +6924,9 @@
"cmp%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*cmpsi_shiftsi_swp"
@@ -6467,20 +6939,24 @@
"cmp%?\\t%0, %1%S3"
[(set_attr "conds" "set")
(set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
-(define_insn "*cmpsi_neg_shiftsi"
- [(set (reg:CC CC_REGNUM)
- (compare:CC (match_operand:SI 0 "s_register_operand" "r")
- (neg:SI (match_operator:SI 3 "shift_operator"
- [(match_operand:SI 1 "s_register_operand" "r")
- (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
+(define_insn "*cmpsi_negshiftsi_si"
+ [(set (reg:CC_Z CC_REGNUM)
+ (compare:CC_Z
+ (neg:SI (match_operator:SI 1 "shift_operator"
+ [(match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 3 "reg_or_int_operand" "rM")]))
+ (match_operand:SI 0 "s_register_operand" "r")))]
"TARGET_ARM"
- "cmn%?\\t%0, %1%S3"
+ "cmn%?\\t%0, %2%S1"
[(set_attr "conds" "set")
- (set_attr "shift" "1")
- ]
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
;; Cirrus SF compare instruction
@@ -6488,7 +6964,7 @@
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:SF 0 "cirrus_fp_register" "v")
(match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcmps%?\\tr15, %V0, %V1"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "compare")]
@@ -6499,7 +6975,7 @@
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:DF 0 "cirrus_fp_register" "v")
(match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcmpd%?\\tr15, %V0, %V1"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "compare")]
@@ -6509,7 +6985,7 @@
(define_expand "cmpdi"
[(match_operand:DI 0 "cirrus_fp_register" "")
(match_operand:DI 1 "cirrus_fp_register" "")]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"{
arm_compare_op0 = operands[0];
arm_compare_op1 = operands[1];
@@ -6520,7 +6996,7 @@
[(set (reg:CC CC_REGNUM)
(compare:CC (match_operand:DI 0 "cirrus_fp_register" "v")
(match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcmp64%?\\tr15, %V0, %V1"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "compare")]
@@ -6638,7 +7114,7 @@
(if_then_else (unordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -6648,7 +7124,7 @@
(if_then_else (ordered (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -6658,7 +7134,7 @@
(if_then_else (ungt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0, arm_compare_op1);"
)
@@ -6667,7 +7143,7 @@
(if_then_else (unlt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0, arm_compare_op1);"
)
@@ -6676,7 +7152,7 @@
(if_then_else (unge (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0, arm_compare_op1);"
)
@@ -6685,7 +7161,7 @@
(if_then_else (unle (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0, arm_compare_op1);"
)
@@ -6696,7 +7172,7 @@
(if_then_else (uneq (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNEQ, arm_compare_op0, arm_compare_op1);"
)
@@ -6705,7 +7181,7 @@
(if_then_else (ltgt (match_dup 1) (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (LTGT, arm_compare_op0, arm_compare_op1);"
)
@@ -6719,10 +7195,9 @@
(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
return \"bvs\\t%l0\;beq\\t%l0\";
"
@@ -6736,10 +7211,9 @@
(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
(label_ref (match_operand 0 "" ""))
(pc)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
return \"bmi\\t%l0\;bgt\\t%l0\";
"
@@ -6762,7 +7236,8 @@
}
return \"b%d1\\t%l0\";
"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set_attr "type" "branch")]
)
; Special pattern to match reversed UNEQ.
@@ -6771,10 +7246,9 @@
(if_then_else (uneq (match_operand 1 "cc_register" "") (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
return \"bmi\\t%l0\;bgt\\t%l0\";
"
@@ -6788,10 +7262,9 @@
(if_then_else (ltgt (match_operand 1 "cc_register" "") (const_int 0))
(pc)
(label_ref (match_operand 0 "" ""))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"*
- if (arm_ccfsm_state != 0)
- abort ();
+ gcc_assert (!arm_ccfsm_state);
return \"bvs\\t%l0\;beq\\t%l0\";
"
@@ -6814,7 +7287,8 @@
}
return \"b%D1\\t%l0\";
"
- [(set_attr "conds" "use")]
+ [(set_attr "conds" "use")
+ (set_attr "type" "branch")]
)
@@ -6894,7 +7368,7 @@
(define_expand "sunordered"
[(set (match_operand:SI 0 "s_register_operand" "")
(unordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -6902,7 +7376,7 @@
(define_expand "sordered"
[(set (match_operand:SI 0 "s_register_operand" "")
(ordered:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (ORDERED, arm_compare_op0,
arm_compare_op1);"
)
@@ -6910,7 +7384,7 @@
(define_expand "sungt"
[(set (match_operand:SI 0 "s_register_operand" "")
(ungt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGT, arm_compare_op0,
arm_compare_op1);"
)
@@ -6918,7 +7392,7 @@
(define_expand "sunge"
[(set (match_operand:SI 0 "s_register_operand" "")
(unge:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNGE, arm_compare_op0,
arm_compare_op1);"
)
@@ -6926,7 +7400,7 @@
(define_expand "sunlt"
[(set (match_operand:SI 0 "s_register_operand" "")
(unlt:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLT, arm_compare_op0,
arm_compare_op1);"
)
@@ -6934,7 +7408,7 @@
(define_expand "sunle"
[(set (match_operand:SI 0 "s_register_operand" "")
(unle:SI (match_dup 1) (const_int 0)))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"operands[1] = arm_gen_compare_reg (UNLE, arm_compare_op0,
arm_compare_op1);"
)
@@ -6945,15 +7419,15 @@
; (define_expand "suneq"
; [(set (match_operand:SI 0 "s_register_operand" "")
; (uneq:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "abort ();"
+; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+; "gcc_unreachable ();"
; )
;
; (define_expand "sltgt"
; [(set (match_operand:SI 0 "s_register_operand" "")
; (ltgt:SI (match_dup 1) (const_int 0)))]
-; "TARGET_ARM && TARGET_HARD_FLOAT"
-; "abort ();"
+; "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
+; "gcc_unreachable ();"
; )
(define_insn "*mov_scc"
@@ -7004,7 +7478,7 @@
FAIL;
ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -7023,13 +7497,13 @@
FAIL;
/* When compiling for SOFT_FLOAT, ensure both arms are in registers.
- Otherwise, ensure it is a valid FP add operand. */
- if ((!TARGET_HARD_FLOAT)
- || (!fpa_add_operand (operands[3], SFmode)))
+ Otherwise, ensure it is a valid FP add operand */
+ if ((!(TARGET_HARD_FLOAT && TARGET_FPA))
+ || (!arm_float_add_operand (operands[3], SFmode)))
operands[3] = force_reg (SFmode, operands[3]);
ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -7037,8 +7511,8 @@
[(set (match_operand:DF 0 "s_register_operand" "")
(if_then_else:DF (match_operand 1 "arm_comparison_operator" "")
(match_operand:DF 2 "s_register_operand" "")
- (match_operand:DF 3 "fpa_add_operand" "")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 3 "arm_float_add_operand" "")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && (TARGET_FPA || TARGET_VFP)"
"
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -7048,7 +7522,7 @@
FAIL;
ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
- operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (code, VOIDmode, ccreg, const0_rtx);
}"
)
@@ -7161,18 +7635,30 @@
invoked it. */
callee = XEXP (operands[0], 0);
- if (GET_CODE (callee) != REG
- && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
+ if ((GET_CODE (callee) == SYMBOL_REF
+ && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
+ || (GET_CODE (callee) != SYMBOL_REF
+ && GET_CODE (callee) != REG))
XEXP (operands[0], 0) = force_reg (Pmode, callee);
}"
)
-(define_insn "*call_reg"
+(define_insn "*call_reg_armv5"
[(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
+ "TARGET_ARM && arm_arch5"
+ "blx%?\\t%0"
+ [(set_attr "type" "call")]
+)
+
+(define_insn "*call_reg_arm"
+ [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_ARM && !arm_arch5"
"*
return output_call (operands);
"
@@ -7182,7 +7668,7 @@
)
(define_insn "*call_mem"
- [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
+ [(call (mem:SI (match_operand:SI 0 "call_memory_operand" "m"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
@@ -7194,35 +7680,33 @@
(set_attr "type" "call")]
)
-(define_insn "*call_indirect"
+(define_insn "*call_reg_thumb_v5"
[(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB"
- "*
- {
- if (TARGET_CALLER_INTERWORKING)
- return \"bl\\t%__interwork_call_via_%0\";
- else
- return \"bl\\t%__call_via_%0\";
- }"
- [(set_attr "type" "call")]
+ "TARGET_THUMB && arm_arch5"
+ "blx\\t%0"
+ [(set_attr "length" "2")
+ (set_attr "type" "call")]
)
-(define_insn "*call_value_indirect"
- [(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
- (match_operand 2 "" "")))
- (use (match_operand 3 "" ""))
+(define_insn "*call_reg_thumb"
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_THUMB"
+ "TARGET_THUMB && !arm_arch5"
"*
{
- if (TARGET_CALLER_INTERWORKING)
- return \"bl\\t%__interwork_call_via_%1\";
+ if (!TARGET_CALLER_INTERWORKING)
+ return thumb_call_via_reg (operands[0]);
+ else if (operands[1] == const0_rtx)
+ return \"bl\\t%__interwork_call_via_%0\";
+ else if (frame_pointer_needed)
+ return \"bl\\t%__interwork_r7_call_via_%0\";
else
- return \"bl\\t%__call_via_%1\";
+ return \"bl\\t%__interwork_r11_call_via_%0\";
}"
[(set_attr "type" "call")]
)
@@ -7243,19 +7727,32 @@
operands[3] = const0_rtx;
/* See the comment in define_expand \"call\". */
- if (GET_CODE (callee) != REG
- && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
+ if ((GET_CODE (callee) == SYMBOL_REF
+ && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
+ || (GET_CODE (callee) != SYMBOL_REF
+ && GET_CODE (callee) != REG))
XEXP (operands[1], 0) = force_reg (Pmode, callee);
}"
)
-(define_insn "*call_value_reg"
+(define_insn "*call_value_reg_armv5"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
- "TARGET_ARM"
+ "TARGET_ARM && arm_arch5"
+ "blx%?\\t%1"
+ [(set_attr "type" "call")]
+)
+
+(define_insn "*call_value_reg_arm"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_ARM && !arm_arch5"
"*
return output_call (&operands[1]);
"
@@ -7265,7 +7762,7 @@
(define_insn "*call_value_mem"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
+ (call (mem:SI (match_operand:SI 1 "call_memory_operand" "m"))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
(clobber (reg:SI LR_REGNUM))]
@@ -7277,6 +7774,39 @@
(set_attr "type" "call")]
)
+(define_insn "*call_value_reg_thumb_v5"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_THUMB && arm_arch5"
+ "blx\\t%1"
+ [(set_attr "length" "2")
+ (set_attr "type" "call")]
+)
+
+(define_insn "*call_value_reg_thumb"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
+ (match_operand 2 "" "")))
+ (use (match_operand 3 "" ""))
+ (clobber (reg:SI LR_REGNUM))]
+ "TARGET_THUMB && !arm_arch5"
+ "*
+ {
+ if (!TARGET_CALLER_INTERWORKING)
+ return thumb_call_via_reg (operands[1]);
+ else if (operands[2] == const0_rtx)
+ return \"bl\\t%__interwork_call_via_%1\";
+ else if (frame_pointer_needed)
+ return \"bl\\t%__interwork_r7_call_via_%1\";
+ else
+ return \"bl\\t%__interwork_r11_call_via_%1\";
+ }"
+ [(set_attr "type" "call")]
+)
+
;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
@@ -7296,7 +7826,7 @@
)
(define_insn "*call_value_symbol"
- [(set (match_operand 0 "s_register_operand" "")
+ [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "" ""))
(match_operand:SI 2 "" "")))
(use (match_operand 3 "" ""))
@@ -7325,7 +7855,7 @@
)
(define_insn "*call_value_insn"
- [(set (match_operand 0 "register_operand" "")
+ [(set (match_operand 0 "" "")
(call (mem:SI (match_operand 1 "" ""))
(match_operand 2 "" "")))
(use (match_operand 3 "" ""))
@@ -7353,7 +7883,7 @@
)
(define_expand "sibcall_value"
- [(parallel [(set (match_operand 0 "register_operand" "")
+ [(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "memory_operand" "")
(match_operand 2 "general_operand" "")))
(return)
@@ -7379,7 +7909,7 @@
)
(define_insn "*sibcall_value_insn"
- [(set (match_operand 0 "s_register_operand" "")
+ [(set (match_operand 0 "" "")
(call (mem:SI (match_operand:SI 1 "" "X"))
(match_operand 2 "" "")))
(return)
@@ -7404,7 +7934,7 @@
}
return output_return_instruction (const_true_rtx, TRUE, FALSE);
}"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set_attr "length" "12")
(set_attr "predicable" "yes")]
)
@@ -7427,7 +7957,7 @@
}"
[(set_attr "conds" "use")
(set_attr "length" "12")
- (set_attr "type" "load")]
+ (set_attr "type" "load1")]
)
(define_insn "*cond_return_inverted"
@@ -7447,7 +7977,8 @@
return output_return_instruction (operands[0], TRUE, TRUE);
}"
[(set_attr "conds" "use")
- (set_attr "type" "load")]
+ (set_attr "length" "12")
+ (set_attr "type" "load1")]
)
;; Generate a sequence of instructions to determine if the processor is
@@ -7484,18 +8015,59 @@
(const_int 0))
(match_operand 1 "" "")
(match_operand 2 "" "")])]
- "TARGET_ARM"
+ "TARGET_EITHER"
"
{
int i;
+ rtx par = gen_rtx_PARALLEL (VOIDmode,
+ rtvec_alloc (XVECLEN (operands[2], 0)));
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx mem;
+ int size = 0;
- emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, const0_rtx));
+ emit_move_insn (addr, XEXP (operands[1], 0));
+ mem = change_address (operands[1], BLKmode, addr);
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
- rtx set = XVECEXP (operands[2], 0, i);
+ rtx src = SET_SRC (XVECEXP (operands[2], 0, i));
- emit_move_insn (SET_DEST (set), SET_SRC (set));
+ /* Default code only uses r0 as a return value, but we could
+ be using anything up to 4 registers. */
+ if (REGNO (src) == R0_REGNUM)
+ src = gen_rtx_REG (TImode, R0_REGNUM);
+
+ XVECEXP (par, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, src,
+ GEN_INT (size));
+ size += GET_MODE_SIZE (GET_MODE (src));
+ }
+
+ emit_call_insn (GEN_CALL_VALUE (par, operands[0], const0_rtx, NULL,
+ const0_rtx));
+
+ size = 0;
+
+ for (i = 0; i < XVECLEN (par, 0); i++)
+ {
+ HOST_WIDE_INT offset = 0;
+ rtx reg = XEXP (XVECEXP (par, 0, i), 0);
+
+ if (size != 0)
+ emit_move_insn (addr, plus_constant (addr, size));
+
+ mem = change_address (mem, GET_MODE (reg), NULL);
+ if (REGNO (reg) == R0_REGNUM)
+ {
+ /* On thumb we have to use a write-back instruction. */
+ emit_insn (arm_gen_store_multiple (R0_REGNUM, 4, addr, TRUE,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
+ size = TARGET_ARM ? 16 : 0;
+ }
+ else
+ {
+ emit_move_insn (mem, reg);
+ size = GET_MODE_SIZE (GET_MODE (reg));
+ }
}
/* The optimizer does not know that the call sets the function value
@@ -7508,6 +8080,55 @@
}"
)
+(define_expand "untyped_return"
+ [(match_operand:BLK 0 "memory_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_EITHER"
+ "
+ {
+ int i;
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx mem;
+ int size = 0;
+
+ emit_move_insn (addr, XEXP (operands[0], 0));
+ mem = change_address (operands[0], BLKmode, addr);
+
+ for (i = 0; i < XVECLEN (operands[1], 0); i++)
+ {
+ HOST_WIDE_INT offset = 0;
+ rtx reg = SET_DEST (XVECEXP (operands[1], 0, i));
+
+ if (size != 0)
+ emit_move_insn (addr, plus_constant (addr, size));
+
+ mem = change_address (mem, GET_MODE (reg), NULL);
+ if (REGNO (reg) == R0_REGNUM)
+ {
+ /* On thumb we have to use a write-back instruction. */
+ emit_insn (arm_gen_load_multiple (R0_REGNUM, 4, addr, TRUE,
+ TARGET_THUMB ? TRUE : FALSE, mem, &offset));
+ size = TARGET_ARM ? 16 : 0;
+ }
+ else
+ {
+ emit_move_insn (reg, mem);
+ size = GET_MODE_SIZE (GET_MODE (reg));
+ }
+ }
+
+ /* Emit USE insns before the return. */
+ for (i = 0; i < XVECLEN (operands[1], 0); i++)
+ emit_insn (gen_rtx_USE (VOIDmode,
+ SET_DEST (XVECEXP (operands[1], 0, i))));
+
+ /* Construct the return. */
+ expand_naked_return ();
+
+ 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.
@@ -7576,6 +8197,7 @@
""
)
+;; NB Never uses BX.
(define_insn "*arm_indirect_jump"
[(set (pc)
(match_operand:SI 0 "s_register_operand" "r"))]
@@ -7584,19 +8206,18 @@
[(set_attr "predicable" "yes")]
)
-;; Although not supported by the define_expand above,
-;; cse/combine may generate this form.
(define_insn "*load_indirect_jump"
[(set (pc)
(match_operand:SI 0 "memory_operand" "m"))]
"TARGET_ARM"
"ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
- [(set_attr "type" "load")
+ [(set_attr "type" "load1")
(set_attr "pool_range" "4096")
(set_attr "neg_pool_range" "4084")
(set_attr "predicable" "yes")]
)
+;; NB Never uses BX.
(define_insn "*thumb_indirect_jump"
[(set (pc)
(match_operand:SI 0 "register_operand" "l*r"))]
@@ -7637,7 +8258,9 @@
"%i1%?\\t%0, %2, %4%S3"
[(set_attr "predicable" "yes")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_split
@@ -7673,7 +8296,9 @@
"%i1%?s\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*arith_shiftsi_compare0_scratch"
@@ -7689,7 +8314,9 @@
"%i1%?s\\t%0, %2, %4%S3"
[(set_attr "conds" "set")
(set_attr "shift" "4")
- ]
+ (set (attr "type") (if_then_else (match_operand 5 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi"
@@ -7702,7 +8329,9 @@
"sub%?\\t%0, %1, %3%S2"
[(set_attr "predicable" "yes")
(set_attr "shift" "3")
- ]
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi_compare0"
@@ -7719,8 +8348,10 @@
"TARGET_ARM"
"sub%?s\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
- (set_attr "shift" "3")
- ]
+ (set_attr "shift" "3")
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*sub_shiftsi_compare0_scratch"
@@ -7735,8 +8366,10 @@
"TARGET_ARM"
"sub%?s\\t%0, %1, %3%S2"
[(set_attr "conds" "set")
- (set_attr "shift" "3")
- ]
+ (set_attr "shift" "3")
+ (set (attr "type") (if_then_else (match_operand 4 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
@@ -8609,7 +9242,10 @@
mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
[(set_attr "conds" "use")
(set_attr "shift" "2")
- (set_attr "length" "4,8,8")]
+ (set_attr "length" "4,8,8")
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_move_shift"
@@ -8645,7 +9281,10 @@
mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
[(set_attr "conds" "use")
(set_attr "shift" "2")
- (set_attr "length" "4,8,8")]
+ (set_attr "length" "4,8,8")
+ (set (attr "type") (if_then_else (match_operand 3 "const_int_operand" "")
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_shift_shift"
@@ -8682,7 +9321,12 @@
"mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
[(set_attr "conds" "use")
(set_attr "shift" "1")
- (set_attr "length" "8")]
+ (set_attr "length" "8")
+ (set (attr "type") (if_then_else
+ (and (match_operand 2 "const_int_operand" "")
+ (match_operand 4 "const_int_operand" ""))
+ (const_string "alu_shift")
+ (const_string "alu_shift_reg")))]
)
(define_insn "*ifcompare_not_arith"
@@ -8822,7 +9466,8 @@
{
rtx ldm[3];
rtx arith[4];
- int val1 = 0, val2 = 0;
+ rtx base_reg;
+ HOST_WIDE_INT val1 = 0, val2 = 0;
if (REGNO (operands[0]) > REGNO (operands[4]))
{
@@ -8834,12 +9479,21 @@
ldm[1] = operands[0];
ldm[2] = operands[4];
}
- if (GET_CODE (XEXP (operands[2], 0)) != REG)
- val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
- if (GET_CODE (XEXP (operands[3], 0)) != REG)
+
+ base_reg = XEXP (operands[2], 0);
+
+ if (!REG_P (base_reg))
+ {
+ val1 = INTVAL (XEXP (base_reg, 1));
+ base_reg = XEXP (base_reg, 0);
+ }
+
+ if (!REG_P (XEXP (operands[3], 0)))
val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
+
arith[0] = operands[0];
arith[3] = operands[1];
+
if (val1 < val2)
{
arith[1] = ldm[1];
@@ -8850,21 +9504,41 @@
arith[1] = ldm[2];
arith[2] = ldm[1];
}
- if (val1 && val2)
+
+ ldm[0] = base_reg;
+ if (val1 !=0 && val2 != 0)
{
rtx ops[3];
- ldm[0] = ops[0] = operands[4];
- ops[1] = XEXP (XEXP (operands[2], 0), 0);
- ops[2] = XEXP (XEXP (operands[2], 0), 1);
- output_add_immediate (ops);
- if (val1 < val2)
- output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
+
+ if (val1 == 4 || val2 == 4)
+ /* Other val must be 8, since we know they are adjacent and neither
+ is zero. */
+ output_asm_insn (\"ldm%?ib\\t%0, {%1, %2}\", ldm);
+ else if (const_ok_for_arm (val1) || const_ok_for_arm (-val1))
+ {
+ ldm[0] = ops[0] = operands[4];
+ ops[1] = base_reg;
+ ops[2] = GEN_INT (val1);
+ output_add_immediate (ops);
+ if (val1 < val2)
+ output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
+ else
+ output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
+ }
else
- output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
+ {
+ /* Offset is out of range for a single add, so use two ldr. */
+ ops[0] = ldm[1];
+ ops[1] = base_reg;
+ ops[2] = GEN_INT (val1);
+ output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
+ ops[0] = ldm[2];
+ ops[2] = GEN_INT (val2);
+ output_asm_insn (\"ldr%?\\t%0, [%1, %2]\", ops);
+ }
}
- else if (val1)
+ else if (val1 != 0)
{
- ldm[0] = XEXP (operands[3], 0);
if (val1 < val2)
output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
else
@@ -8872,7 +9546,6 @@
}
else
{
- ldm[0] = XEXP (operands[2], 0);
if (val1 < val2)
output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
else
@@ -8883,516 +9556,17 @@
}"
[(set_attr "length" "12")
(set_attr "predicable" "yes")
- (set_attr "type" "load")]
-)
-
-;; the arm can support extended pre-inc instructions
-
-;; In all these cases, we use operands 0 and 1 for the register being
-;; incremented because those are the operands that local-alloc will
-;; tie and these are the pair most likely to be tieable (and the ones
-;; that will benefit the most).
-
-;; We reject the frame pointer if it occurs anywhere in these patterns since
-;; elimination will cause too many headaches.
-
-(define_insn "*strqi_preinc"
- [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?b\\t%3, [%0, %2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_predec"
- [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?b\\t%3, [%0, -%2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_preinc"
- [(set (match_operand:QI 3 "s_register_operand" "=r")
- (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, %2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_predec"
- [(set (match_operand:QI 3 "s_register_operand" "=r")
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, -%2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqisi_preinc"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (zero_extend:SI
- (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqisi_predec"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (zero_extend:SI
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_preinc"
- [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ")))
- (match_operand:SI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?\\t%3, [%0, %2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_predec"
- [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r")))
- (match_operand:SI 3 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "str%?\\t%3, [%0, -%2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_preinc"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, %2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_predec"
- [(set (match_operand:SI 3 "s_register_operand" "=r")
- (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, -%2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadhi_preinc"
- [(set (match_operand:HI 3 "s_register_operand" "=r")
- (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
- (match_operand:SI 2 "index_operand" "rJ"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadhi_predec"
- [(set (match_operand:HI 3 "s_register_operand" "=r")
- (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operand:SI 2 "s_register_operand" "r"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && (GET_CODE (operands[2]) != REG
- || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
- "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_shiftpreinc"
- [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0")))
- (match_operand:QI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?b\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strqi_shiftpredec"
- [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])))
- (match_operand:QI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?b\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_shiftpreinc"
- [(set (match_operand:QI 5 "s_register_operand" "=r")
- (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?b\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadqi_shiftpredec"
- [(set (match_operand:QI 5 "s_register_operand" "=r")
- (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?b\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_shiftpreinc"
- [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0")))
- (match_operand:SI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*strsi_shiftpredec"
- [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])))
- (match_operand:SI 5 "s_register_operand" "r"))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "str%?\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "store1")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_shiftpreinc"
- [(set (match_operand:SI 5 "s_register_operand" "=r")
- (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, %3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadsi_shiftpredec"
- [(set (match_operand:SI 5 "s_register_operand" "=r")
- (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, -%3%S2]!"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")])
-
-(define_insn "*loadhi_shiftpreinc"
- [(set (match_operand:HI 5 "s_register_operand" "=r")
- (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")])
- (match_operand:SI 1 "s_register_operand" "0"))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
- (match_dup 1)))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-(define_insn "*loadhi_shiftpredec"
- [(set (match_operand:HI 5 "s_register_operand" "=r")
- (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
- (match_operator:SI 2 "shift_operator"
- [(match_operand:SI 3 "s_register_operand" "r")
- (match_operand:SI 4 "const_shift_operand" "n")]))))
- (set (match_operand:SI 0 "s_register_operand" "=r")
- (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
- (match_dup 4)])))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != FRAME_POINTER_REGNUM
- && REGNO (operands[1]) != FRAME_POINTER_REGNUM
- && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
- "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
- [(set_attr "type" "load")
- (set_attr "predicable" "yes")]
-)
-
-; It can also support extended post-inc expressions, but combine doesn't
-; try these....
-; It doesn't seem worth adding peepholes for anything but the most common
-; cases since, unlike combine, the increment must immediately follow the load
-; for this pattern to match.
-; We must watch to see that the source/destination register isn't also the
-; same as the base address register, and that if the index is a register,
-; that it is not the same as the base address register. In such cases the
-; instruction that we would generate would have UNPREDICTABLE behavior so
-; we cannot use it.
-
-(define_peephole
- [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
- (match_operand:QI 2 "s_register_operand" "r"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?b\\t%2, [%0], %1"
-)
-
-(define_peephole
- [(set (match_operand:QI 0 "s_register_operand" "=r")
- (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?b\\t%0, [%1], %2"
-)
-
-(define_peephole
- [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
- (match_operand:SI 2 "s_register_operand" "r"))
- (set (match_dup 0)
- (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?\\t%2, [%0], %1"
-)
-
-(define_peephole
- [(set (match_operand:HI 0 "s_register_operand" "=r")
- (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && !BYTES_BIG_ENDIAN
- && !TARGET_MMU_TRAPS
- && !arm_arch4
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?\\t%0, [%1], %2\\t%@ loadhi"
-)
-
-(define_peephole
- [(set (match_operand:SI 0 "s_register_operand" "=r")
- (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
- (set (match_dup 1)
- (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
- "TARGET_ARM
- && REGNO (operands[0]) != REGNO(operands[1])
- && (GET_CODE (operands[2]) != REG
- || REGNO(operands[0]) != REGNO (operands[2]))"
- "ldr%?\\t%0, [%1], %2"
-)
-
-(define_peephole
- [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
- (match_operand:SI 1 "index_operand" "rJ")))
- (match_operand:QI 2 "s_register_operand" "r"))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
- "TARGET_ARM
- && (REGNO (operands[2]) != REGNO (operands[0]))
- && (GET_CODE (operands[1]) != REG
- || (REGNO (operands[1]) != REGNO (operands[0])))"
- "str%?b\\t%2, [%0, %1]!"
-)
-
-(define_peephole
- [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
- [(match_operand:SI 0 "s_register_operand" "r")
- (match_operand:SI 1 "const_int_operand" "n")])
- (match_operand:SI 2 "s_register_operand" "+r")))
- (match_operand:QI 3 "s_register_operand" "r"))
- (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
- (match_dup 2)))]
- "TARGET_ARM
- && (REGNO (operands[3]) != REGNO (operands[2]))
- && (REGNO (operands[0]) != REGNO (operands[2]))"
- "str%?b\\t%3, [%2, %0%S4]!"
+ (set_attr "type" "load1")]
)
; This pattern is never tried by combine, so do it as a peephole
(define_peephole2
- [(set (match_operand:SI 0 "s_register_operand" "")
- (match_operand:SI 1 "s_register_operand" ""))
+ [(set (match_operand:SI 0 "arm_general_register_operand" "")
+ (match_operand:SI 1 "arm_general_register_operand" ""))
(set (reg:CC CC_REGNUM)
(compare:CC (match_dup 1) (const_int 0)))]
- "TARGET_ARM
- && (!TARGET_CIRRUS
- || (!cirrus_fp_register (operands[0], SImode)
- && !cirrus_fp_register (operands[1], SImode)))
- "
+ "TARGET_ARM"
[(parallel [(set (reg:CC CC_REGNUM) (compare:CC (match_dup 1) (const_int 0)))
(set (match_dup 0) (match_dup 1))])]
""
@@ -9527,9 +9701,11 @@
)
(define_expand "epilogue"
- [(unspec_volatile [(return)] VUNSPEC_EPILOGUE)]
+ [(clobber (const_int 0))]
"TARGET_EITHER"
"
+ if (current_function_calls_eh_return)
+ emit_insn (gen_prologue_use (gen_rtx_REG (Pmode, 2)));
if (TARGET_THUMB)
thumb_expand_epilogue ();
else if (USE_RETURN_INSN (FALSE))
@@ -9715,7 +9891,7 @@
enum rtx_code rc = GET_CODE (operands[1]);
operands[6] = gen_rtx_REG (mode, CC_REGNUM);
- operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
+ operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
if (mode == CCFPmode || mode == CCFPEmode)
rc = reverse_condition_maybe_unordered (rc);
else
@@ -9833,7 +10009,7 @@
[(set (match_operand:BLK 0 "memory_operand" "=m")
(unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")]
UNSPEC_PUSH_MULT))])]
- "TARGET_ARM"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"*
{
char pattern[100];
@@ -9858,7 +10034,7 @@
(define_insn "align_8"
[(unspec_volatile [(const_int 0)] VUNSPEC_ALIGN8)]
- "TARGET_REALLY_IWMMXT"
+ "TARGET_EITHER"
"*
assemble_align (64);
return \"\";
@@ -9965,6 +10141,7 @@
"
)
+;; NB never uses BX.
(define_insn "*thumb_tablejump"
[(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
(use (label_ref (match_operand 1 "" "")))]
@@ -10047,9 +10224,81 @@
"%@ %0 needed for prologue"
)
+
+;; Patterns for exception handling
+
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand" ""))]
+ "TARGET_EITHER"
+ "
+ {
+ if (TARGET_ARM)
+ emit_insn (gen_arm_eh_return (operands[0]));
+ else
+ emit_insn (gen_thumb_eh_return (operands[0]));
+ DONE;
+ }"
+)
+
+;; We can't expand this before we know where the link register is stored.
+(define_insn_and_split "arm_eh_return"
+ [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "r")]
+ VUNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&r"))]
+ "TARGET_ARM"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "
+ {
+ arm_set_return_address (operands[0], operands[1]);
+ DONE;
+ }"
+)
+
+(define_insn_and_split "thumb_eh_return"
+ [(unspec_volatile [(match_operand:SI 0 "s_register_operand" "l")]
+ VUNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&l"))]
+ "TARGET_THUMB"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+ "
+ {
+ thumb_set_return_address (operands[0], operands[1]);
+ DONE;
+ }"
+)
+
+
+;; TLS support
+
+(define_insn "load_tp_hard"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(const_int 0)] UNSPEC_TLS))]
+ "TARGET_HARD_TP"
+ "mrc%?\\tp15, 0, %0, c13, c0, 3\\t@ load_tp_hard"
+ [(set_attr "predicable" "yes")]
+)
+
+;; Doesn't clobber R1-R3. Must use r0 for the first operand.
+(define_insn "load_tp_soft"
+ [(set (reg:SI 0) (unspec:SI [(const_int 0)] UNSPEC_TLS))
+ (clobber (reg:SI LR_REGNUM))
+ (clobber (reg:SI IP_REGNUM))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_SOFT_TP"
+ "bl\\t__aeabi_read_tp\\t@ load_tp_soft"
+ [(set_attr "conds" "clob")]
+)
+
;; Load the FPA co-processor patterns
(include "fpa.md")
;; Load the Maverick co-processor patterns
(include "cirrus.md")
;; Load the Intel Wireless Multimedia Extension patterns
(include "iwmmxt.md")
+;; Load the VFP co-processor patterns
+(include "vfp.md")
+
diff --git a/contrib/gcc/config/arm/arm.opt b/contrib/gcc/config/arm/arm.opt
new file mode 100644
index 0000000..8f85ffb
--- /dev/null
+++ b/contrib/gcc/config/arm/arm.opt
@@ -0,0 +1,155 @@
+; Options for the ARM port of the compiler.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mabi=
+Target RejectNegative Joined Var(target_abi_name)
+Specify an ABI
+
+mabort-on-noreturn
+Target Report Mask(ABORT_NORETURN)
+Generate a call to abort if a noreturn function returns
+
+mapcs
+Target RejectNegative Mask(APCS_FRAME) MaskExists Undocumented
+
+mapcs-float
+Target Report Mask(APCS_FLOAT)
+Pass FP arguments in FP registers
+
+mapcs-frame
+Target Report Mask(APCS_FRAME)
+Generate APCS conformant stack frames
+
+mapcs-reentrant
+Target Report Mask(APCS_REENT)
+Generate re-entrant, PIC code
+
+mapcs-stack-check
+Target Report Mask(APCS_STACK) Undocumented
+
+march=
+Target RejectNegative Joined
+Specify the name of the target architecture
+
+marm
+Target RejectNegative InverseMask(THUMB) Undocumented
+
+mbig-endian
+Target Report RejectNegative Mask(BIG_END)
+Assume target CPU is configured as big endian
+
+mcallee-super-interworking
+Target Report Mask(CALLEE_INTERWORKING)
+Thumb: Assume non-static functions may be called from ARM code
+
+mcaller-super-interworking
+Target Report Mask(CALLER_INTERWORKING)
+Thumb: Assume function pointers may go to non-Thumb aware code
+
+mcirrus-fix-invalid-insns
+Target Report Mask(CIRRUS_FIX_INVALID_INSNS)
+Cirrus: Place NOPs to avoid invalid instruction combinations
+
+mcpu=
+Target RejectNegative Joined
+Specify the name of the target CPU
+
+mfloat-abi=
+Target RejectNegative Joined Var(target_float_abi_name)
+Specify if floating point hardware should be used
+
+mfp=
+Target RejectNegative Joined Undocumented Var(target_fpe_name)
+
+;; Now ignored.
+mfpe
+Target RejectNegative Mask(FPE) Undocumented
+
+mfpe=
+Target RejectNegative Joined Undocumented Var(target_fpe_name)
+
+mfpu=
+Target RejectNegative Joined Var(target_fpu_name)
+Specify the name of the target floating point hardware/format
+
+mhard-float
+Target RejectNegative
+Alias for -mfloat-abi=hard
+
+mlittle-endian
+Target Report RejectNegative InverseMask(BIG_END)
+Assume target CPU is configured as little endian
+
+mlong-calls
+Target Report Mask(LONG_CALLS)
+Generate call insns as indirect calls, if necessary
+
+mpic-register=
+Target RejectNegative Joined Var(arm_pic_register_string)
+Specify the register to be used for PIC addressing
+
+mpoke-function-name
+Target Report Mask(POKE_FUNCTION_NAME)
+Store function names in object code
+
+msched-prolog
+Target Report Mask(SCHED_PROLOG)
+Permit scheduling of a function's prologue sequence
+
+msingle-pic-base
+Target Report Mask(SINGLE_PIC_BASE)
+Do not load the PIC register in function prologues
+
+msoft-float
+Target RejectNegative
+Alias for -mfloat-abi=soft
+
+mstructure-size-boundary=
+Target RejectNegative Joined Var(structure_size_string)
+Specify the minimum bit alignment of structures
+
+mthumb
+Target Report Mask(THUMB)
+Compile for the Thumb not the ARM
+
+mthumb-interwork
+Target Report Mask(INTERWORK)
+Support calls between Thumb and ARM instruction sets
+
+mtp=
+Target RejectNegative Joined Var(target_thread_switch)
+Specify how to access the thread pointer
+
+mtpcs-frame
+Target Report Mask(TPCS_FRAME)
+Thumb: Generate (non-leaf) stack frames even if not needed
+
+mtpcs-leaf-frame
+Target Report Mask(TPCS_LEAF_FRAME)
+Thumb: Generate (leaf) stack frames even if not needed
+
+mtune=
+Target RejectNegative Joined
+Tune code for the given processor
+
+mwords-little-endian
+Target Report RejectNegative Mask(LITTLE_WORDS)
+Assume big endian bytes, little endian words
diff --git a/contrib/gcc/config/arm/arm1020e.md b/contrib/gcc/config/arm/arm1020e.md
new file mode 100644
index 0000000..32a5d95
--- /dev/null
+++ b/contrib/gcc/config/arm/arm1020e.md
@@ -0,0 +1,388 @@
+;; ARM 1020E & ARM 1022E Pipeline Description
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;; Contributed by Richard Earnshaw (richard.earnshaw@arm.com)
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+;; These descriptions are based on the information contained in the
+;; ARM1020E Technical Reference Manual, Copyright (c) 2003 ARM
+;; Limited.
+;;
+
+;; This automaton provides a pipeline description for the ARM
+;; 1020E core.
+;;
+;; The model given here assumes that the condition for all conditional
+;; instructions is "true", i.e., that all of the instructions are
+;; actually executed.
+
+(define_automaton "arm1020e")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pipelines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; There are two pipelines:
+;;
+;; - An Arithmetic Logic Unit (ALU) pipeline.
+;;
+;; The ALU pipeline has fetch, issue, decode, execute, memory, and
+;; write stages. We only need to model the execute, memory and write
+;; stages.
+;;
+;; - A Load-Store Unit (LSU) pipeline.
+;;
+;; The LSU pipeline has decode, execute, memory, and write stages.
+;; We only model the execute, memory and write stages.
+
+(define_cpu_unit "1020a_e,1020a_m,1020a_w" "arm1020e")
+(define_cpu_unit "1020l_e,1020l_m,1020l_w" "arm1020e")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ALU Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ALU instructions require three cycles to execute, and use the ALU
+;; pipeline in each of the three stages. The results are available
+;; after the execute stage stage has finished.
+;;
+;; If the destination register is the PC, the pipelines are stalled
+;; for several cycles. That case is not modeled here.
+
+;; ALU operations with no shifted operand
+(define_insn_reservation "1020alu_op" 1
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "alu"))
+ "1020a_e,1020a_m,1020a_w")
+
+;; ALU operations with a shift-by-constant operand
+(define_insn_reservation "1020alu_shift_op" 1
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "alu_shift"))
+ "1020a_e,1020a_m,1020a_w")
+
+;; ALU operations with a shift-by-register operand
+;; These really stall in the decoder, in order to read
+;; the shift value in a second cycle. Pretend we take two cycles in
+;; the execute stage.
+(define_insn_reservation "1020alu_shift_reg_op" 2
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "alu_shift_reg"))
+ "1020a_e*2,1020a_m,1020a_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Multiplication Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Multiplication instructions loop in the execute stage until the
+;; instruction has been passed through the multiplier array enough
+;; times.
+
+;; The result of the "smul" and "smulw" instructions is not available
+;; until after the memory stage.
+(define_insn_reservation "1020mult1" 2
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "smulxy,smulwy"))
+ "1020a_e,1020a_m,1020a_w")
+
+;; The "smlaxy" and "smlawx" instructions require two iterations through
+;; the execute stage; the result is available immediately following
+;; the execute stage.
+(define_insn_reservation "1020mult2" 2
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "smlaxy,smlalxy,smlawx"))
+ "1020a_e*2,1020a_m,1020a_w")
+
+;; The "smlalxy", "mul", and "mla" instructions require two iterations
+;; through the execute stage; the result is not available until after
+;; the memory stage.
+(define_insn_reservation "1020mult3" 3
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "smlalxy,mul,mla"))
+ "1020a_e*2,1020a_m,1020a_w")
+
+;; The "muls" and "mlas" instructions loop in the execute stage for
+;; four iterations in order to set the flags. The value result is
+;; available after three iterations.
+(define_insn_reservation "1020mult4" 3
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "muls,mlas"))
+ "1020a_e*4,1020a_m,1020a_w")
+
+;; Long multiply instructions that produce two registers of
+;; output (such as umull) make their results available in two cycles;
+;; the least significant word is available before the most significant
+;; word. That fact is not modeled; instead, the instructions are
+;; described.as if the entire result was available at the end of the
+;; cycle in which both words are available.
+
+;; The "umull", "umlal", "smull", and "smlal" instructions all take
+;; three iterations through the execute cycle, and make their results
+;; available after the memory cycle.
+(define_insn_reservation "1020mult5" 4
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "umull,umlal,smull,smlal"))
+ "1020a_e*3,1020a_m,1020a_w")
+
+;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
+;; the execute stage for five iterations in order to set the flags.
+;; The value result is available after four iterations.
+(define_insn_reservation "1020mult6" 4
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "insn" "umulls,umlals,smulls,smlals"))
+ "1020a_e*5,1020a_m,1020a_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load/Store Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The models for load/store instructions do not accurately describe
+;; the difference between operations with a base register writeback
+;; (such as "ldm!"). These models assume that all memory references
+;; hit in dcache.
+
+;; LSU instructions require six cycles to execute. They use the ALU
+;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
+;; three through six.
+;; Loads and stores which use a scaled register offset or scaled
+;; register pre-indexed addressing mode take three cycles EXCEPT for
+;; those that are base + offset with LSL of 0 or 2, or base - offset
+;; with LSL of zero. The remainder take 1 cycle to execute.
+;; For 4byte loads there is a bypass from the load stage
+
+(define_insn_reservation "1020load1_op" 2
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "load_byte,load1"))
+ "1020a_e+1020l_e,1020l_m,1020l_w")
+
+(define_insn_reservation "1020store1_op" 0
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "store1"))
+ "1020a_e+1020l_e,1020l_m,1020l_w")
+
+;; A load's result can be stored by an immediately following store
+(define_bypass 1 "1020load1_op" "1020store1_op" "arm_no_early_store_addr_dep")
+
+;; On a LDM/STM operation, the LSU pipeline iterates until all of the
+;; registers have been processed.
+;;
+;; The time it takes to load the data depends on whether or not the
+;; base address is 64-bit aligned; if it is not, an additional cycle
+;; is required. This model assumes that the address is always 64-bit
+;; aligned. Because the processor can load two registers per cycle,
+;; that assumption means that we use the same instruction reservations
+;; for loading 2k and 2k - 1 registers.
+;;
+;; The ALU pipeline is decoupled after the first cycle unless there is
+;; a register dependency; the dependency is cleared as soon as the LDM/STM
+;; has dealt with the corresponding register. So for example,
+;; stmia sp, {r0-r3}
+;; add r0, r0, #4
+;; will have one fewer stalls than
+;; stmia sp, {r0-r3}
+;; add r3, r3, #4
+;;
+;; As with ALU operations, if one of the destination registers is the
+;; PC, there are additional stalls; that is not modeled.
+
+(define_insn_reservation "1020load2_op" 2
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "load2"))
+ "1020a_e+1020l_e,1020l_m,1020l_w")
+
+(define_insn_reservation "1020store2_op" 0
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "store2"))
+ "1020a_e+1020l_e,1020l_m,1020l_w")
+
+(define_insn_reservation "1020load34_op" 3
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "load3,load4"))
+ "1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
+
+(define_insn_reservation "1020store34_op" 0
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "store3,store4"))
+ "1020a_e+1020l_e,1020l_e+1020l_m,1020l_m,1020l_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Branch and Call Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Branch instructions are difficult to model accurately. The ARM
+;; core can predict most branches. If the branch is predicted
+;; correctly, and predicted early enough, the branch can be completely
+;; eliminated from the instruction stream. Some branches can
+;; therefore appear to require zero cycles to execute. We assume that
+;; all branches are predicted correctly, and that the latency is
+;; therefore the minimum value.
+
+(define_insn_reservation "1020branch_op" 0
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "branch"))
+ "1020a_e")
+
+;; The latency for a call is not predictable. Therefore, we use 32 as
+;; roughly equivalent to positive infinity.
+
+(define_insn_reservation "1020call_op" 32
+ (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "type" "call"))
+ "1020a_e*32")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; VFP
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_cpu_unit "v10_fmac" "arm1020e")
+
+(define_cpu_unit "v10_ds" "arm1020e")
+
+(define_cpu_unit "v10_fmstat" "arm1020e")
+
+(define_cpu_unit "v10_ls1,v10_ls2,v10_ls3" "arm1020e")
+
+;; fmstat is a serializing instruction. It will stall the core until
+;; the mac and ds units have completed.
+(exclusion_set "v10_fmac,v10_ds" "v10_fmstat")
+
+(define_attr "vfp10" "yes,no"
+ (const (if_then_else (and (eq_attr "tune" "arm1020e,arm1022e")
+ (eq_attr "fpu" "vfp"))
+ (const_string "yes") (const_string "no"))))
+
+;; The VFP "type" attributes differ from those used in the FPA model.
+;; ffarith Fast floating point insns, e.g. abs, neg, cpy, cmp.
+;; farith Most arithmetic insns.
+;; fmul Double precision multiply.
+;; fdivs Single precision sqrt or division.
+;; fdivd Double precision sqrt or division.
+;; f_flag fmstat operation
+;; f_load Floating point load from memory.
+;; f_store Floating point store to memory.
+;; f_2_r Transfer vfp to arm reg.
+;; r_2_f Transfer arm to vfp reg.
+
+;; Note, no instruction can issue to the VFP if the core is stalled in the
+;; first execute state. We model this by using 1020a_e in the first cycle.
+(define_insn_reservation "v10_ffarith" 5
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "ffarith"))
+ "1020a_e+v10_fmac")
+
+(define_insn_reservation "v10_farith" 5
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "farith"))
+ "1020a_e+v10_fmac")
+
+(define_insn_reservation "v10_cvt" 5
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_cvt"))
+ "1020a_e+v10_fmac")
+
+(define_insn_reservation "v10_fmul" 6
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "fmul"))
+ "1020a_e+v10_fmac*2")
+
+(define_insn_reservation "v10_fdivs" 18
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "fdivs"))
+ "1020a_e+v10_ds*14")
+
+(define_insn_reservation "v10_fdivd" 32
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "fdivd"))
+ "1020a_e+v10_fmac+v10_ds*28")
+
+(define_insn_reservation "v10_floads" 4
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_loads"))
+ "1020a_e+1020l_e+v10_ls1,v10_ls2")
+
+;; We model a load of a double as needing all the vfp ls* stage in cycle 1.
+;; This gives the correct mix between single-and double loads where a flds
+;; followed by and fldd will stall for one cycle, but two back-to-back fldd
+;; insns stall for two cycles.
+(define_insn_reservation "v10_floadd" 5
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_loadd"))
+ "1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
+
+;; Moves to/from arm regs also use the load/store pipeline.
+
+(define_insn_reservation "v10_c2v" 4
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "r_2_f"))
+ "1020a_e+1020l_e+v10_ls1,v10_ls2")
+
+(define_insn_reservation "v10_fstores" 1
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_stores"))
+ "1020a_e+1020l_e+v10_ls1,v10_ls2")
+
+(define_insn_reservation "v10_fstored" 1
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_stored"))
+ "1020a_e+1020l_e+v10_ls1+v10_ls2+v10_ls3,v10_ls2+v10_ls3,v10_ls3")
+
+(define_insn_reservation "v10_v2c" 1
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_2_r"))
+ "1020a_e+1020l_e,1020l_m,1020l_w")
+
+(define_insn_reservation "v10_to_cpsr" 2
+ (and (eq_attr "vfp10" "yes")
+ (eq_attr "type" "f_flag"))
+ "1020a_e+v10_fmstat,1020a_e+1020l_e,1020l_m,1020l_w")
+
+;; VFP bypasses
+
+;; There are bypasses for most operations other than store
+
+(define_bypass 3
+ "v10_c2v,v10_floads"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd,v10_cvt")
+
+(define_bypass 4
+ "v10_floadd"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
+
+;; Arithmetic to other arithmetic saves a cycle due to forwarding
+(define_bypass 4
+ "v10_ffarith,v10_farith"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
+
+(define_bypass 5
+ "v10_fmul"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
+
+(define_bypass 17
+ "v10_fdivs"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
+
+(define_bypass 31
+ "v10_fdivd"
+ "v10_ffarith,v10_farith,v10_fmul,v10_fdivs,v10_fdivd")
+
+;; VFP anti-dependencies.
+
+;; There is one anti-dependence in the following case (not yet modelled):
+;; - After a store: one extra cycle for both fsts and fstd
+;; Note, back-to-back fstd instructions will overload the load/store datapath
+;; causing a two-cycle stall.
diff --git a/contrib/gcc/config/arm/arm1026ejs.md b/contrib/gcc/config/arm/arm1026ejs.md
new file mode 100644
index 0000000..a2404ec
--- /dev/null
+++ b/contrib/gcc/config/arm/arm1026ejs.md
@@ -0,0 +1,241 @@
+;; ARM 1026EJ-S Pipeline Description
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Written by CodeSourcery, LLC.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+;; These descriptions are based on the information contained in the
+;; ARM1026EJ-S Technical Reference Manual, Copyright (c) 2003 ARM
+;; Limited.
+;;
+
+;; This automaton provides a pipeline description for the ARM
+;; 1026EJ-S core.
+;;
+;; The model given here assumes that the condition for all conditional
+;; instructions is "true", i.e., that all of the instructions are
+;; actually executed.
+
+(define_automaton "arm1026ejs")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pipelines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; There are two pipelines:
+;;
+;; - An Arithmetic Logic Unit (ALU) pipeline.
+;;
+;; The ALU pipeline has fetch, issue, decode, execute, memory, and
+;; write stages. We only need to model the execute, memory and write
+;; stages.
+;;
+;; - A Load-Store Unit (LSU) pipeline.
+;;
+;; The LSU pipeline has decode, execute, memory, and write stages.
+;; We only model the execute, memory and write stages.
+
+(define_cpu_unit "a_e,a_m,a_w" "arm1026ejs")
+(define_cpu_unit "l_e,l_m,l_w" "arm1026ejs")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ALU Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ALU instructions require three cycles to execute, and use the ALU
+;; pipeline in each of the three stages. The results are available
+;; after the execute stage stage has finished.
+;;
+;; If the destination register is the PC, the pipelines are stalled
+;; for several cycles. That case is not modeled here.
+
+;; ALU operations with no shifted operand
+(define_insn_reservation "alu_op" 1
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "alu"))
+ "a_e,a_m,a_w")
+
+;; ALU operations with a shift-by-constant operand
+(define_insn_reservation "alu_shift_op" 1
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "alu_shift"))
+ "a_e,a_m,a_w")
+
+;; ALU operations with a shift-by-register operand
+;; These really stall in the decoder, in order to read
+;; the shift value in a second cycle. Pretend we take two cycles in
+;; the execute stage.
+(define_insn_reservation "alu_shift_reg_op" 2
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "alu_shift_reg"))
+ "a_e*2,a_m,a_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Multiplication Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Multiplication instructions loop in the execute stage until the
+;; instruction has been passed through the multiplier array enough
+;; times.
+
+;; The result of the "smul" and "smulw" instructions is not available
+;; until after the memory stage.
+(define_insn_reservation "mult1" 2
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "smulxy,smulwy"))
+ "a_e,a_m,a_w")
+
+;; The "smlaxy" and "smlawx" instructions require two iterations through
+;; the execute stage; the result is available immediately following
+;; the execute stage.
+(define_insn_reservation "mult2" 2
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "smlaxy,smlalxy,smlawx"))
+ "a_e*2,a_m,a_w")
+
+;; The "smlalxy", "mul", and "mla" instructions require two iterations
+;; through the execute stage; the result is not available until after
+;; the memory stage.
+(define_insn_reservation "mult3" 3
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "smlalxy,mul,mla"))
+ "a_e*2,a_m,a_w")
+
+;; The "muls" and "mlas" instructions loop in the execute stage for
+;; four iterations in order to set the flags. The value result is
+;; available after three iterations.
+(define_insn_reservation "mult4" 3
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "muls,mlas"))
+ "a_e*4,a_m,a_w")
+
+;; Long multiply instructions that produce two registers of
+;; output (such as umull) make their results available in two cycles;
+;; the least significant word is available before the most significant
+;; word. That fact is not modeled; instead, the instructions are
+;; described.as if the entire result was available at the end of the
+;; cycle in which both words are available.
+
+;; The "umull", "umlal", "smull", and "smlal" instructions all take
+;; three iterations through the execute cycle, and make their results
+;; available after the memory cycle.
+(define_insn_reservation "mult5" 4
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "umull,umlal,smull,smlal"))
+ "a_e*3,a_m,a_w")
+
+;; The "umulls", "umlals", "smulls", and "smlals" instructions loop in
+;; the execute stage for five iterations in order to set the flags.
+;; The value result is available after four iterations.
+(define_insn_reservation "mult6" 4
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "insn" "umulls,umlals,smulls,smlals"))
+ "a_e*5,a_m,a_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load/Store Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The models for load/store instructions do not accurately describe
+;; the difference between operations with a base register writeback
+;; (such as "ldm!"). These models assume that all memory references
+;; hit in dcache.
+
+;; LSU instructions require six cycles to execute. They use the ALU
+;; pipeline in all but the 5th cycle, and the LSU pipeline in cycles
+;; three through six.
+;; Loads and stores which use a scaled register offset or scaled
+;; register pre-indexed addressing mode take three cycles EXCEPT for
+;; those that are base + offset with LSL of 0 or 2, or base - offset
+;; with LSL of zero. The remainder take 1 cycle to execute.
+;; For 4byte loads there is a bypass from the load stage
+
+(define_insn_reservation "load1_op" 2
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "load_byte,load1"))
+ "a_e+l_e,l_m,a_w+l_w")
+
+(define_insn_reservation "store1_op" 0
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "store1"))
+ "a_e+l_e,l_m,a_w+l_w")
+
+;; A load's result can be stored by an immediately following store
+(define_bypass 1 "load1_op" "store1_op" "arm_no_early_store_addr_dep")
+
+;; On a LDM/STM operation, the LSU pipeline iterates until all of the
+;; registers have been processed.
+;;
+;; The time it takes to load the data depends on whether or not the
+;; base address is 64-bit aligned; if it is not, an additional cycle
+;; is required. This model assumes that the address is always 64-bit
+;; aligned. Because the processor can load two registers per cycle,
+;; that assumption means that we use the same instruction reservations
+;; for loading 2k and 2k - 1 registers.
+;;
+;; The ALU pipeline is stalled until the completion of the last memory
+;; stage in the LSU pipeline. That is modeled by keeping the ALU
+;; execute stage busy until that point.
+;;
+;; As with ALU operations, if one of the destination registers is the
+;; PC, there are additional stalls; that is not modeled.
+
+(define_insn_reservation "load2_op" 2
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "load2"))
+ "a_e+l_e,l_m,a_w+l_w")
+
+(define_insn_reservation "store2_op" 0
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "store2"))
+ "a_e+l_e,l_m,a_w+l_w")
+
+(define_insn_reservation "load34_op" 3
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "load3,load4"))
+ "a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
+
+(define_insn_reservation "store34_op" 0
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "store3,store4"))
+ "a_e+l_e,a_e+l_e+l_m,a_e+l_m,a_w+l_w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Branch and Call Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Branch instructions are difficult to model accurately. The ARM
+;; core can predict most branches. If the branch is predicted
+;; correctly, and predicted early enough, the branch can be completely
+;; eliminated from the instruction stream. Some branches can
+;; therefore appear to require zero cycles to execute. We assume that
+;; all branches are predicted correctly, and that the latency is
+;; therefore the minimum value.
+
+(define_insn_reservation "branch_op" 0
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "branch"))
+ "nothing")
+
+;; The latency for a call is not predictable. Therefore, we use 32 as
+;; roughly equivalent to positive infinity.
+
+(define_insn_reservation "call_op" 32
+ (and (eq_attr "tune" "arm1026ejs")
+ (eq_attr "type" "call"))
+ "nothing")
diff --git a/contrib/gcc/config/arm/arm1136jfs.md b/contrib/gcc/config/arm/arm1136jfs.md
new file mode 100644
index 0000000..3086697
--- /dev/null
+++ b/contrib/gcc/config/arm/arm1136jfs.md
@@ -0,0 +1,377 @@
+;; ARM 1136J[F]-S Pipeline Description
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Written by CodeSourcery, LLC.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+;; These descriptions are based on the information contained in the
+;; ARM1136JF-S Technical Reference Manual, Copyright (c) 2003 ARM
+;; Limited.
+;;
+
+;; This automaton provides a pipeline description for the ARM
+;; 1136J-S and 1136JF-S cores.
+;;
+;; The model given here assumes that the condition for all conditional
+;; instructions is "true", i.e., that all of the instructions are
+;; actually executed.
+
+(define_automaton "arm1136jfs")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pipelines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; There are three distinct pipelines (page 1-26 and following):
+;;
+;; - A 4-stage decode pipeline, shared by all three. It has fetch (1),
+;; fetch (2), decode, and issue stages. Since this is always involved,
+;; we do not model it in the scheduler.
+;;
+;; - A 4-stage ALU pipeline. It has shifter, ALU (main integer operations),
+;; and saturation stages. The fourth stage is writeback; see below.
+;;
+;; - A 4-stage multiply-accumulate pipeline. It has three stages, called
+;; MAC1 through MAC3, and a fourth writeback stage.
+;;
+;; The 4th-stage writeback is shared between the ALU and MAC pipelines,
+;; which operate in lockstep. Results from either pipeline will be
+;; moved into the writeback stage. Because the two pipelines operate
+;; in lockstep, we schedule them as a single "execute" pipeline.
+;;
+;; - A 4-stage LSU pipeline. It has address generation, data cache (1),
+;; data cache (2), and writeback stages. (Note that this pipeline,
+;; including the writeback stage, is independent from the ALU & LSU pipes.)
+
+(define_cpu_unit "e_1,e_2,e_3,e_wb" "arm1136jfs") ; ALU and MAC
+; e_1 = Sh/Mac1, e_2 = ALU/Mac2, e_3 = SAT/Mac3
+(define_cpu_unit "l_a,l_dc1,l_dc2,l_wb" "arm1136jfs") ; Load/Store
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ALU Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ALU instructions require eight cycles to execute, and use the ALU
+;; pipeline in each of the eight stages. The results are available
+;; after the alu stage has finished.
+;;
+;; If the destination register is the PC, the pipelines are stalled
+;; for several cycles. That case is not modelled here.
+
+;; ALU operations with no shifted operand
+(define_insn_reservation "11_alu_op" 2
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "alu"))
+ "e_1,e_2,e_3,e_wb")
+
+;; ALU operations with a shift-by-constant operand
+(define_insn_reservation "11_alu_shift_op" 2
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "alu_shift"))
+ "e_1,e_2,e_3,e_wb")
+
+;; ALU operations with a shift-by-register operand
+;; These really stall in the decoder, in order to read
+;; the shift value in a second cycle. Pretend we take two cycles in
+;; the shift stage.
+(define_insn_reservation "11_alu_shift_reg_op" 3
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "alu_shift_reg"))
+ "e_1*2,e_2,e_3,e_wb")
+
+;; alu_ops can start sooner, if there is no shifter dependency
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_alu_op")
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_alu_op")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Multiplication Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Multiplication instructions loop in the first two execute stages until
+;; the instruction has been passed through the multiplier array enough
+;; times.
+
+;; Multiply and multiply-accumulate results are available after four stages.
+(define_insn_reservation "11_mult1" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "mul,mla"))
+ "e_1*2,e_2,e_3,e_wb")
+
+;; The *S variants set the condition flags, which requires three more cycles.
+(define_insn_reservation "11_mult2" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "muls,mlas"))
+ "e_1*2,e_2,e_3,e_wb")
+
+(define_bypass 3 "11_mult1,11_mult2"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 3 "11_mult1,11_mult2"
+ "11_alu_op")
+(define_bypass 3 "11_mult1,11_mult2"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 3 "11_mult1,11_mult2"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+(define_bypass 3 "11_mult1,11_mult2"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+
+;; Signed and unsigned multiply long results are available across two cycles;
+;; the less significant word is available one cycle before the more significant
+;; word. Here we conservatively wait until both are available, which is
+;; after three iterations and the memory cycle. The same is also true of
+;; the two multiply-accumulate instructions.
+(define_insn_reservation "11_mult3" 5
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "smull,umull,smlal,umlal"))
+ "e_1*3,e_2,e_3,e_wb*2")
+
+;; The *S variants set the condition flags, which requires three more cycles.
+(define_insn_reservation "11_mult4" 5
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "smulls,umulls,smlals,umlals"))
+ "e_1*3,e_2,e_3,e_wb*2")
+
+(define_bypass 4 "11_mult3,11_mult4"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 4 "11_mult3,11_mult4"
+ "11_alu_op")
+(define_bypass 4 "11_mult3,11_mult4"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 4 "11_mult3,11_mult4"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+(define_bypass 4 "11_mult3,11_mult4"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+
+;; Various 16x16->32 multiplies and multiply-accumulates, using combinations
+;; of high and low halves of the argument registers. They take a single
+;; pass through the pipeline and make the result available after three
+;; cycles.
+(define_insn_reservation "11_mult5" 3
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "smulxy,smlaxy,smulwy,smlawy,smuad,smuadx,smlad,smladx,smusd,smusdx,smlsd,smlsdx"))
+ "e_1,e_2,e_3,e_wb")
+
+(define_bypass 2 "11_mult5"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 2 "11_mult5"
+ "11_alu_op")
+(define_bypass 2 "11_mult5"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 2 "11_mult5"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+(define_bypass 2 "11_mult5"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+
+;; The same idea, then the 32-bit result is added to a 64-bit quantity.
+(define_insn_reservation "11_mult6" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "smlalxy"))
+ "e_1*2,e_2,e_3,e_wb*2")
+
+;; Signed 32x32 multiply, then the most significant 32 bits are extracted
+;; and are available after the memory stage.
+(define_insn_reservation "11_mult7" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "insn" "smmul,smmulr"))
+ "e_1*2,e_2,e_3,e_wb")
+
+(define_bypass 3 "11_mult6,11_mult7"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 3 "11_mult6,11_mult7"
+ "11_alu_op")
+(define_bypass 3 "11_mult6,11_mult7"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 3 "11_mult6,11_mult7"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+(define_bypass 3 "11_mult6,11_mult7"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Branch Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; These vary greatly depending on their arguments and the results of
+;; stat prediction. Cycle count ranges from zero (unconditional branch,
+;; folded dynamic prediction) to seven (incorrect predictions, etc). We
+;; assume an optimal case for now, because the cost of a cache miss
+;; overwhelms the cost of everything else anyhow.
+
+(define_insn_reservation "11_branches" 0
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "branch"))
+ "nothing")
+
+;; Call latencies are not predictable. A semi-arbitrary very large
+;; number is used as "positive infinity" so that everything should be
+;; finished by the time of return.
+(define_insn_reservation "11_call" 32
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "call"))
+ "nothing")
+
+;; Branches are predicted. A correctly predicted branch will be no
+;; cost, but we're conservative here, and use the timings a
+;; late-register would give us.
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_branches")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_branches")
+(define_bypass 2 "11_load1,11_load2"
+ "11_branches")
+(define_bypass 3 "11_load34"
+ "11_branches")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load/Store Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The models for load/store instructions do not accurately describe
+;; the difference between operations with a base register writeback.
+;; These models assume that all memory references hit in dcache. Also,
+;; if the PC is one of the registers involved, there are additional stalls
+;; not modelled here. Addressing modes are also not modelled.
+
+(define_insn_reservation "11_load1" 3
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "load1"))
+ "l_a+e_1,l_dc1,l_dc2,l_wb")
+
+;; Load byte results are not available until the writeback stage, where
+;; the correct byte is extracted.
+
+(define_insn_reservation "11_loadb" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "load_byte"))
+ "l_a+e_1,l_dc1,l_dc2,l_wb")
+
+(define_insn_reservation "11_store1" 0
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "store1"))
+ "l_a+e_1,l_dc1,l_dc2,l_wb")
+
+;; Load/store double words into adjacent registers. The timing and
+;; latencies are different depending on whether the address is 64-bit
+;; aligned. This model assumes that it is.
+(define_insn_reservation "11_load2" 3
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "load2"))
+ "l_a+e_1,l_dc1,l_dc2,l_wb")
+
+(define_insn_reservation "11_store2" 0
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "store2"))
+ "l_a+e_1,l_dc1,l_dc2,l_wb")
+
+;; Load/store multiple registers. Two registers are stored per cycle.
+;; Actual timing depends on how many registers are affected, so we
+;; optimistically schedule a low latency.
+(define_insn_reservation "11_load34" 4
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "load3,load4"))
+ "l_a+e_1,l_dc1*2,l_dc2,l_wb")
+
+(define_insn_reservation "11_store34" 0
+ (and (eq_attr "tune" "arm1136js,arm1136jfs")
+ (eq_attr "type" "store3,store4"))
+ "l_a+e_1,l_dc1*2,l_dc2,l_wb")
+
+;; A store can start immediately after an alu op, if that alu op does
+;; not provide part of the address to access.
+(define_bypass 1 "11_alu_op,11_alu_shift_op"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+(define_bypass 2 "11_alu_shift_reg_op"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+
+;; An alu op can start sooner after a load, if that alu op does not
+;; have an early register dependency on the load
+(define_bypass 2 "11_load1"
+ "11_alu_op")
+(define_bypass 2 "11_load1"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 2 "11_load1"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+
+(define_bypass 3 "11_loadb"
+ "11_alu_op")
+(define_bypass 3 "11_loadb"
+ "11_alu_shift_op"
+ "arm_no_early_alu_shift_value_dep")
+(define_bypass 3 "11_loadb"
+ "11_alu_shift_reg_op"
+ "arm_no_early_alu_shift_dep")
+
+;; A mul op can start sooner after a load, if that mul op does not
+;; have an early multiply dependency
+(define_bypass 2 "11_load1"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 3 "11_load34"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+(define_bypass 3 "11_loadb"
+ "11_mult1,11_mult2,11_mult3,11_mult4,11_mult5,11_mult6,11_mult7"
+ "arm_no_early_mul_dep")
+
+;; A store can start sooner after a load, if that load does not
+;; produce part of the address to access
+(define_bypass 2 "11_load1"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
+(define_bypass 3 "11_loadb"
+ "11_store1"
+ "arm_no_early_store_addr_dep")
diff --git a/contrib/gcc/config/arm/arm926ejs.md b/contrib/gcc/config/arm/arm926ejs.md
new file mode 100644
index 0000000..244e3a9
--- /dev/null
+++ b/contrib/gcc/config/arm/arm926ejs.md
@@ -0,0 +1,188 @@
+;; ARM 926EJ-S Pipeline Description
+;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Written by CodeSourcery, LLC.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+;; These descriptions are based on the information contained in the
+;; ARM926EJ-S Technical Reference Manual, Copyright (c) 2002 ARM
+;; Limited.
+;;
+
+;; This automaton provides a pipeline description for the ARM
+;; 926EJ-S core.
+;;
+;; The model given here assumes that the condition for all conditional
+;; instructions is "true", i.e., that all of the instructions are
+;; actually executed.
+
+(define_automaton "arm926ejs")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pipelines
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; There is a single pipeline
+;;
+;; The ALU pipeline has fetch, decode, execute, memory, and
+;; write stages. We only need to model the execute, memory and write
+;; stages.
+
+(define_cpu_unit "e,m,w" "arm926ejs")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; ALU Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; ALU instructions require three cycles to execute, and use the ALU
+;; pipeline in each of the three stages. The results are available
+;; after the execute stage stage has finished.
+;;
+;; If the destination register is the PC, the pipelines are stalled
+;; for several cycles. That case is not modeled here.
+
+;; ALU operations with no shifted operand
+(define_insn_reservation "9_alu_op" 1
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "alu,alu_shift"))
+ "e,m,w")
+
+;; ALU operations with a shift-by-register operand
+;; These really stall in the decoder, in order to read
+;; the shift value in a second cycle. Pretend we take two cycles in
+;; the execute stage.
+(define_insn_reservation "9_alu_shift_reg_op" 2
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "alu_shift_reg"))
+ "e*2,m,w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Multiplication Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Multiplication instructions loop in the execute stage until the
+;; instruction has been passed through the multiplier array enough
+;; times. Multiply operations occur in both the execute and memory
+;; stages of the pipeline
+
+(define_insn_reservation "9_mult1" 3
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "smlalxy,mul,mla"))
+ "e*2,m,w")
+
+(define_insn_reservation "9_mult2" 4
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "muls,mlas"))
+ "e*3,m,w")
+
+(define_insn_reservation "9_mult3" 4
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "umull,umlal,smull,smlal"))
+ "e*3,m,w")
+
+(define_insn_reservation "9_mult4" 5
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "umulls,umlals,smulls,smlals"))
+ "e*4,m,w")
+
+(define_insn_reservation "9_mult5" 2
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "smulxy,smlaxy,smlawx"))
+ "e,m,w")
+
+(define_insn_reservation "9_mult6" 3
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "insn" "smlalxy"))
+ "e*2,m,w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Load/Store Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The models for load/store instructions do not accurately describe
+;; the difference between operations with a base register writeback
+;; (such as "ldm!"). These models assume that all memory references
+;; hit in dcache.
+
+;; Loads with a shifted offset take 3 cycles, and are (a) probably the
+;; most common and (b) the pessimistic assumption will lead to fewer stalls.
+(define_insn_reservation "9_load1_op" 3
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "load1,load_byte"))
+ "e*2,m,w")
+
+(define_insn_reservation "9_store1_op" 0
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "store1"))
+ "e,m,w")
+
+;; multiple word loads and stores
+(define_insn_reservation "9_load2_op" 3
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "load2"))
+ "e,m*2,w")
+
+(define_insn_reservation "9_load3_op" 4
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "load3"))
+ "e,m*3,w")
+
+(define_insn_reservation "9_load4_op" 5
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "load4"))
+ "e,m*4,w")
+
+(define_insn_reservation "9_store2_op" 0
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "store2"))
+ "e,m*2,w")
+
+(define_insn_reservation "9_store3_op" 0
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "store3"))
+ "e,m*3,w")
+
+(define_insn_reservation "9_store4_op" 0
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "store4"))
+ "e,m*4,w")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Branch and Call Instructions
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Branch instructions are difficult to model accurately. The ARM
+;; core can predict most branches. If the branch is predicted
+;; correctly, and predicted early enough, the branch can be completely
+;; eliminated from the instruction stream. Some branches can
+;; therefore appear to require zero cycles to execute. We assume that
+;; all branches are predicted correctly, and that the latency is
+;; therefore the minimum value.
+
+(define_insn_reservation "9_branch_op" 0
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "branch"))
+ "nothing")
+
+;; The latency for a call is not predictable. Therefore, we use 32 as
+;; roughly equivalent to positive infinity.
+
+(define_insn_reservation "9_call_op" 32
+ (and (eq_attr "tune" "arm926ejs")
+ (eq_attr "type" "call"))
+ "nothing")
diff --git a/contrib/gcc/config/arm/bpabi.S b/contrib/gcc/config/arm/bpabi.S
new file mode 100644
index 0000000..e492d4b
--- /dev/null
+++ b/contrib/gcc/config/arm/bpabi.S
@@ -0,0 +1,95 @@
+/* Miscellaneous BPABI functions.
+
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifdef __ARMEB__
+#define xxh r0
+#define xxl r1
+#define yyh r2
+#define yyl r3
+#else
+#define xxh r1
+#define xxl r0
+#define yyh r3
+#define yyl r2
+#endif
+
+#ifdef L_aeabi_lcmp
+
+ARM_FUNC_START aeabi_lcmp
+ subs ip, xxl, yyl
+ sbcs ip, xxh, yyh
+ subeqs ip, xxl, yyl
+ mov r0, ip
+ RET
+ FUNC_END aeabi_lcmp
+
+#endif /* L_aeabi_lcmp */
+
+#ifdef L_aeabi_ulcmp
+
+ARM_FUNC_START aeabi_ulcmp
+ cmp xxh, yyh
+ movlo r0, #-1
+ movhi r0, #1
+ RETc(ne)
+ cmp xxl, yyl
+ movlo r0, #-1
+ movhi r0, #1
+ moveq r0, #0
+ RET
+ FUNC_END aeabi_ulcmp
+
+#endif /* L_aeabi_ulcmp */
+
+#ifdef L_aeabi_ldivmod
+
+ARM_FUNC_START aeabi_ldivmod
+ sub sp, sp, #8
+ stmfd sp!, {sp, lr}
+ bl SYM(__gnu_ldivmod_helper) __PLT__
+ ldr lr, [sp, #4]
+ add sp, sp, #8
+ ldmfd sp!, {r2, r3}
+ RET
+
+#endif /* L_aeabi_ldivmod */
+
+#ifdef L_aeabi_uldivmod
+
+ARM_FUNC_START aeabi_uldivmod
+ sub sp, sp, #8
+ stmfd sp!, {sp, lr}
+ bl SYM(__gnu_uldivmod_helper) __PLT__
+ ldr lr, [sp, #4]
+ add sp, sp, #8
+ ldmfd sp!, {r2, r3}
+ RET
+
+#endif /* L_aeabi_divmod */
+
diff --git a/contrib/gcc/config/arm/bpabi.c b/contrib/gcc/config/arm/bpabi.c
new file mode 100644
index 0000000..69f6e4e
--- /dev/null
+++ b/contrib/gcc/config/arm/bpabi.c
@@ -0,0 +1,61 @@
+/* Miscellaneous BPABI functions.
+
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+extern long long __divdi3 (long long, long long);
+extern unsigned long long __udivdi3 (unsigned long long,
+ unsigned long long);
+extern long long __gnu_ldivmod_helper (long long, long long, long long *);
+extern unsigned long long __gnu_uldivmod_helper (unsigned long long,
+ unsigned long long,
+ unsigned long long *);
+
+
+long long
+__gnu_ldivmod_helper (long long a,
+ long long b,
+ long long *remainder)
+{
+ long long quotient;
+
+ quotient = __divdi3 (a, b);
+ *remainder = a - b * quotient;
+ return quotient;
+}
+
+unsigned long long
+__gnu_uldivmod_helper (unsigned long long a,
+ unsigned long long b,
+ unsigned long long *remainder)
+{
+ unsigned long long quotient;
+
+ quotient = __udivdi3 (a, b);
+ *remainder = a - b * quotient;
+ return quotient;
+}
diff --git a/contrib/gcc/config/arm/bpabi.h b/contrib/gcc/config/arm/bpabi.h
new file mode 100644
index 0000000..4c73088
--- /dev/null
+++ b/contrib/gcc/config/arm/bpabi.h
@@ -0,0 +1,118 @@
+/* Configuration file for ARM BPABI targets.
+ Copyright (C) 2004, 2005
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* Use the AAPCS ABI by default. */
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS
+
+/* Assume that AAPCS ABIs should adhere to the full BPABI. */
+#define TARGET_BPABI (TARGET_AAPCS_BASED)
+
+/* BPABI targets use EABI frame unwinding tables. */
+#define TARGET_UNWIND_INFO 1
+
+/* Section 4.1 of the AAPCS requires the use of VFP format. */
+#undef FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT FPUTYPE_VFP
+
+/* EABI targets should enable interworking by default. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT MASK_INTERWORK
+
+/* The ARM BPABI functions return a boolean; they use no special
+ calling convention. */
+#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) TARGET_BPABI
+
+/* The BPABI integer comparison routines return { -1, 0, 1 }. */
+#define TARGET_LIB_INT_CMP_BIASED !TARGET_BPABI
+
+/* Tell the assembler to build BPABI binaries. */
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4}"
+
+/* The generic link spec in elf.h does not support shared libraries. */
+#undef LINK_SPEC
+#define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} " \
+ "%{static:-Bstatic} %{shared:-shared} %{symbolic:-Bsymbolic} " \
+ "-X"
+
+#if defined (__thumb__)
+#define RENAME_LIBRARY_SET ".thumb_set"
+#else
+#define RENAME_LIBRARY_SET ".set"
+#endif
+
+/* Make __aeabi_AEABI_NAME an alias for __GCC_NAME. */
+#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) \
+ __asm__ (".globl\t__aeabi_" #AEABI_NAME "\n" \
+ RENAME_LIBRARY_SET "\t__aeabi_" #AEABI_NAME \
+ ", __" #GCC_NAME "\n");
+
+/* Give some libgcc functions an additional __aeabi name. */
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_muldi3
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (muldi3, lmul)
+#endif
+#ifdef L_fixdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixdfdi, d2lz)
+#endif
+#ifdef L_fixunsdfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunsdfdi, d2ulz)
+#endif
+#ifdef L_fixsfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixsfdi, f2lz)
+#endif
+#ifdef L_fixunssfdi
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (fixunssfdi, f2ulz)
+#endif
+#ifdef L_floatdidf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdidf, l2d)
+#endif
+#ifdef L_floatdisf
+#define DECLARE_LIBRARY_RENAMES RENAME_LIBRARY (floatdisf, l2f)
+#endif
+
+/* The BPABI requires that we always use an out-of-line implementation
+ of RTTI comparison, even if the target supports weak symbols,
+ because the same object file might be used on a target that does
+ not support merging symbols across DLL boundaries. This macro is
+ broken out separately so that it can be used within
+ TARGET_OS_CPP_BUILTINS in configuration files for systems based on
+ the BPABI. */
+#define TARGET_BPABI_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__GXX_MERGED_TYPEINFO_NAMES=0"); \
+ } \
+ while (false)
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ TARGET_BPABI_CPP_BUILTINS()
+
+/* The BPABI specifies the use of .{init,fini}_array. Therefore, we
+ do not want GCC to put anything into the .{init,fini} sections. */
+#undef INIT_SECTION_ASM_OP
+#undef FINI_SECTION_ASM_OP
+#define INIT_ARRAY_SECTION_ASM_OP ARM_EABI_CTORS_SECTION_OP
+#define FINI_ARRAY_SECTION_ASM_OP ARM_EABI_DTORS_SECTION_OP
diff --git a/contrib/gcc/config/arm/cirrus.md b/contrib/gcc/config/arm/cirrus.md
index 0da8469..b857cbb 100644
--- a/contrib/gcc/config/arm/cirrus.md
+++ b/contrib/gcc/config/arm/cirrus.md
@@ -1,5 +1,5 @@
;; Cirrus EP9312 "Maverick" ARM floating point co-processor description.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Red Hat.
;; Written by Aldy Hernandez (aldyh@redhat.com)
@@ -17,8 +17,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
; Cirrus types for invalid insn combinations
@@ -34,7 +34,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(plus:DI (match_operand:DI 1 "cirrus_fp_register" "v")
(match_operand:DI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfadd64%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -44,7 +44,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(plus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfadd32%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -54,7 +54,7 @@
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(plus:SF (match_operand:SF 1 "cirrus_fp_register" "v")
(match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfadds%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -64,7 +64,7 @@
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(plus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
(match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfaddd%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -74,7 +74,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(minus:DI (match_operand:DI 1 "cirrus_fp_register" "v")
(match_operand:DI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfsub64%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -84,7 +84,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(minus:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfsub32%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -94,7 +94,7 @@
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(minus:SF (match_operand:SF 1 "cirrus_fp_register" "v")
(match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfsubs%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -104,7 +104,7 @@
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(minus:DF (match_operand:DF 1 "cirrus_fp_register" "v")
(match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfsubd%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -114,7 +114,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(mult:SI (match_operand:SI 2 "cirrus_fp_register" "v")
(match_operand:SI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfmul32%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -124,7 +124,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(mult:DI (match_operand:DI 2 "cirrus_fp_register" "v")
(match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmul64%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_dmult")
(set_attr "cirrus" "normal")]
@@ -136,7 +136,7 @@
(mult:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_fp_register" "v"))
(match_operand:SI 3 "cirrus_fp_register" "0")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfmac32%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -149,7 +149,7 @@
(match_operand:SI 1 "cirrus_fp_register" "0")
(mult:SI (match_operand:SI 2 "cirrus_fp_register" "v")
(match_operand:SI 3 "cirrus_fp_register" "v"))))]
- "0 && TARGET_ARM && TARGET_CIRRUS"
+ "0 && TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmsc32%?\\t%V0, %V2, %V3"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -159,7 +159,7 @@
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(mult:SF (match_operand:SF 1 "cirrus_fp_register" "v")
(match_operand:SF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmuls%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_farith")
(set_attr "cirrus" "normal")]
@@ -169,7 +169,7 @@
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(mult:DF (match_operand:DF 1 "cirrus_fp_register" "v")
(match_operand:DF 2 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmuld%?\\t%V0, %V1, %V2"
[(set_attr "type" "mav_dmult")
(set_attr "cirrus" "normal")]
@@ -179,7 +179,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(ashift:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfsh32%?\\t%V0, %V1, #%s2"
[(set_attr "cirrus" "normal")]
)
@@ -188,7 +188,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(ashiftrt:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfsh32%?\\t%V0, %V1, #-%s2"
[(set_attr "cirrus" "normal")]
)
@@ -197,7 +197,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(ashift:SI (match_operand:SI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "register_operand" "r")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfrshl32%?\\t%V1, %V0, %s2"
[(set_attr "cirrus" "normal")]
)
@@ -206,7 +206,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(ashift:DI (match_operand:DI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "register_operand" "r")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfrshl64%?\\t%V1, %V0, %s2"
[(set_attr "cirrus" "normal")]
)
@@ -215,7 +215,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(ashift:DI (match_operand:DI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfsh64%?\\t%V0, %V1, #%s2"
[(set_attr "cirrus" "normal")]
)
@@ -224,7 +224,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(ashiftrt:DI (match_operand:DI 1 "cirrus_fp_register" "v")
(match_operand:SI 2 "cirrus_shift_const" "")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfsh64%?\\t%V0, %V1, #-%s2"
[(set_attr "cirrus" "normal")]
)
@@ -232,7 +232,7 @@
(define_insn "*cirrus_absdi2"
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(abs:DI (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfabs64%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -242,7 +242,7 @@
[(set (match_operand:DI 0 "cirrus_fp_register" "=v")
(neg:DI (match_operand:DI 1 "cirrus_fp_register" "v")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfneg64%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -250,7 +250,7 @@
(define_insn "*cirrus_negsi2"
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(neg:SI (match_operand:SI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfneg32%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -258,7 +258,7 @@
(define_insn "*cirrus_negsf2"
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(neg:SF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfnegs%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -266,7 +266,7 @@
(define_insn "*cirrus_negdf2"
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(neg:DF (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfnegd%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -276,7 +276,7 @@
[(set (match_operand:SI 0 "cirrus_fp_register" "=v")
(abs:SI (match_operand:SI 1 "cirrus_fp_register" "v")))
(clobber (reg:CC CC_REGNUM))]
- "TARGET_ARM && TARGET_CIRRUS && 0"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0"
"cfabs32%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -284,7 +284,7 @@
(define_insn "*cirrus_abssf2"
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(abs:SF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfabss%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -292,7 +292,7 @@
(define_insn "*cirrus_absdf2"
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(abs:DF (match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfabsd%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -302,7 +302,7 @@
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(float:SF (match_operand:SI 1 "s_register_operand" "r")))
(clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmv64lr%?\\t%Z2, %1\;cfcvt32s%?\\t%V0, %Y2"
[(set_attr "length" "8")
(set_attr "cirrus" "move")]
@@ -312,7 +312,7 @@
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(float:DF (match_operand:SI 1 "s_register_operand" "r")))
(clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfmv64lr%?\\t%Z2, %1\;cfcvt32d%?\\t%V0, %Y2"
[(set_attr "length" "8")
(set_attr "cirrus" "move")]
@@ -321,14 +321,14 @@
(define_insn "floatdisf2"
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(float:SF (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcvt64s%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")])
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(float:DF (match_operand:DI 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcvt64d%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")])
@@ -336,7 +336,7 @@
[(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (fix:SF (match_operand:SF 1 "cirrus_fp_register" "v"))))
(clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cftruncs32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
[(set_attr "length" "8")
(set_attr "cirrus" "normal")]
@@ -346,7 +346,7 @@
[(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (fix:DF (match_operand:DF 1 "cirrus_fp_register" "v"))))
(clobber (match_scratch:DF 2 "=v"))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cftruncd32%?\\t%Y2, %V1\;cfmvr64l%?\\t%0, %Z2"
[(set_attr "length" "8")]
)
@@ -355,7 +355,7 @@
[(set (match_operand:SF 0 "cirrus_fp_register" "=v")
(float_truncate:SF
(match_operand:DF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcvtds%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
@@ -363,23 +363,24 @@
(define_insn "*cirrus_extendsfdf2"
[(set (match_operand:DF 0 "cirrus_fp_register" "=v")
(float_extend:DF (match_operand:SF 1 "cirrus_fp_register" "v")))]
- "TARGET_ARM && TARGET_CIRRUS"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"cfcvtsd%?\\t%V0, %V1"
[(set_attr "cirrus" "normal")]
)
(define_insn "*cirrus_arm_movdi"
[(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,o<>,v,r,v,m,v")
- (match_operand:DI 1 "di_operand" "rIK,mi,r,r,v,m,v,v"))]
- "TARGET_ARM && TARGET_CIRRUS"
+ (match_operand:DI 1 "di_operand" "rIK,mi,r,r,v,mi,v,v"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK"
"*
{
switch (which_alternative)
{
case 0:
+ return \"#\";
case 1:
case 2:
- return (output_move_double (operands));
+ return output_move_double (operands);
case 3: return \"cfmv64lr%?\\t%V0, %Q1\;cfmv64hr%?\\t%V0, %R1\";
case 4: return \"cfmvr64l%?\\t%Q0, %V1\;cfmvr64h%?\\t%R0, %V1\";
@@ -390,13 +391,13 @@
/* Shifting by 0 will just copy %1 into %0. */
case 7: return \"cfsh64%?\\t%V0, %V1, #0\";
- default: abort ();
+ default: gcc_unreachable ();
}
}"
[(set_attr "length" " 8, 8, 8, 8, 8, 4, 4, 4")
- (set_attr "type" " *,load,store2, *, *, load,store2, *")
- (set_attr "pool_range" " *,1020, *, *, *, *, *, *")
- (set_attr "neg_pool_range" " *,1012, *, *, *, *, *, *")
+ (set_attr "type" " *,load2,store2, *, *, load2,store2, *")
+ (set_attr "pool_range" " *,1020, *, *, *, 1020, *, *")
+ (set_attr "neg_pool_range" " *,1012, *, *, *, 1008, *, *")
(set_attr "cirrus" "not, not, not,move,normal,double,double,normal")]
)
@@ -406,7 +407,7 @@
(define_insn "*cirrus_arm_movsi_insn"
[(set (match_operand:SI 0 "general_operand" "=r,r,r,m,*v,r,*v,T,*v")
(match_operand:SI 1 "general_operand" "rI,K,mi,r,r,*v,T,*v,*v"))]
- "TARGET_ARM && TARGET_CIRRUS && 0
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK && 0
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
"@
@@ -419,7 +420,7 @@
cfldr32%?\\t%V0, %1
cfstr32%?\\t%V1, %0
cfsh32%?\\t%V0, %V1, #0"
- [(set_attr "type" "*, *, load,store1, *, *, load,store1, *")
+ [(set_attr "type" "*, *, load1,store1, *, *, load1,store1, *")
(set_attr "pool_range" "*, *, 4096, *, *, *, 1024, *, *")
(set_attr "neg_pool_range" "*, *, 4084, *, *, *, 1012, *, *")
(set_attr "cirrus" "not,not, not, not,move,normal,normal,normal,normal")]
@@ -427,8 +428,8 @@
(define_insn "*cirrus_movsf_hard_insn"
[(set (match_operand:SF 0 "nonimmediate_operand" "=v,v,v,r,m,r,r,m")
- (match_operand:SF 1 "general_operand" "v,m,r,v,v,r,mE,r"))]
- "TARGET_ARM && TARGET_CIRRUS
+ (match_operand:SF 1 "general_operand" "v,mE,r,v,v,r,mE,r"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_MAVERICK
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], SFmode))"
"@
@@ -441,17 +442,17 @@
ldr%?\\t%0, %1\\t%@ float
str%?\\t%1, %0\\t%@ float"
[(set_attr "length" " *, *, *, *, *, 4, 4, 4")
- (set_attr "type" " *, load, *, *,store1, *,load,store1")
- (set_attr "pool_range" " *, *, *, *, *, *,4096, *")
- (set_attr "neg_pool_range" " *, *, *, *, *, *,4084, *")
+ (set_attr "type" " *, load1, *, *,store1, *,load1,store1")
+ (set_attr "pool_range" " *, 1020, *, *, *, *,4096, *")
+ (set_attr "neg_pool_range" " *, 1008, *, *, *, *,4084, *")
(set_attr "cirrus" "normal,normal,move,normal,normal,not, not, not")]
)
(define_insn "*cirrus_movdf_hard_insn"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,Q,r,m,r,v,v,v,r,m")
- (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,v,m,r,v,v"))]
+ (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,v,mF,r,v,v"))]
"TARGET_ARM
- && TARGET_CIRRUS
+ && TARGET_HARD_FLOAT && TARGET_MAVERICK
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], DFmode))"
"*
@@ -460,19 +461,20 @@
{
case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
- case 2: case 3: case 4: return output_move_double (operands);
+ case 2: return \"#\";
+ case 3: case 4: return output_move_double (operands);
case 5: return \"cfcpyd%?\\t%V0, %V1\";
case 6: return \"cfldrd%?\\t%V0, %1\";
case 7: return \"cfmvdlr\\t%V0, %Q1\;cfmvdhr%?\\t%V0, %R1\";
case 8: return \"cfmvrdl%?\\t%Q0, %V1\;cfmvrdh%?\\t%R0, %V1\";
case 9: return \"cfstrd%?\\t%V1, %0\";
- default: abort ();
+ default: gcc_unreachable ();
}
}"
- [(set_attr "type" "load,store2, *,store2,load, *, load, *, *,store2")
+ [(set_attr "type" "load1,store2, *,store2,load1, *, load1, *, *,store2")
(set_attr "length" " 4, 4, 8, 8, 8, 4, 4, 8, 8, 4")
- (set_attr "pool_range" " *, *, *, *, 252, *, *, *, *, *")
- (set_attr "neg_pool_range" " *, *, *, *, 244, *, *, *, *, *")
+ (set_attr "pool_range" " *, *, *, *, 252, *, 1020, *, *, *")
+ (set_attr "neg_pool_range" " *, *, *, *, 244, *, 1008, *, *, *")
(set_attr "cirrus" " not, not,not, not, not,normal,double,move,normal,double")]
)
diff --git a/contrib/gcc/config/arm/coff.h b/contrib/gcc/config/arm/coff.h
index d6a6651..f4ad416 100644
--- a/contrib/gcc/config/arm/coff.h
+++ b/contrib/gcc/config/arm/coff.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
For ARM with COFF object format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Doug Evans (devans@cygnus.com).
@@ -18,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Note - it is important that this definition matches the one in tcoff.h. */
#undef USER_LABEL_PREFIX
@@ -30,12 +30,15 @@
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/coff)", stderr)
+#undef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_APCS_FRAME)
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
+ { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
#endif
/* This is COFF, but prefer stabs. */
diff --git a/contrib/gcc/config/arm/constraints.md b/contrib/gcc/config/arm/constraints.md
new file mode 100644
index 0000000..790b7de
--- /dev/null
+++ b/contrib/gcc/config/arm/constraints.md
@@ -0,0 +1,186 @@
+;; Constraint definitions for ARM and Thumb
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;; Contributed by ARM Ltd.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; The following register constraints have been used:
+;; - in ARM state: f, v, w, y, z
+;; - in Thumb state: h, k, b
+;; - in both states: l, c
+;; In ARM state, 'l' is an alias for 'r'
+
+;; The following normal constraints have been used:
+;; in ARM state: G, H, I, J, K, L, M
+;; in Thumb state: I, J, K, L, M, N, O
+
+;; The following multi-letter normal constraints have been used:
+;; in ARM state: Da, Db, Dc
+
+;; The following memory constraints have been used:
+;; in ARM state: Q, Uq, Uv, Uy
+
+
+(define_register_constraint "f" "TARGET_ARM ? FPA_REGS : NO_REGS"
+ "Legacy FPA registers @code{f0}-@code{f7}.")
+
+(define_register_constraint "v" "TARGET_ARM ? CIRRUS_REGS : NO_REGS"
+ "The Cirrus Maverick co-processor registers.")
+
+(define_register_constraint "w" "TARGET_ARM ? VFP_REGS : NO_REGS"
+ "The VFP registers @code{s0}-@code{s31}.")
+
+(define_register_constraint "y" "TARGET_REALLY_IWMMXT ? IWMMXT_REGS : NO_REGS"
+ "The Intel iWMMX co-processor registers.")
+
+(define_register_constraint "z"
+ "TARGET_REALLY_IWMMXT ? IWMMXT_GR_REGS : NO_REGS"
+ "The Intel iWMMX GR registers.")
+
+(define_register_constraint "l" "TARGET_THUMB ? LO_REGS : GENERAL_REGS"
+ "In Thumb state the core registers @code{r0}-@code{r7}.")
+
+(define_register_constraint "h" "TARGET_THUMB ? HI_REGS : NO_REGS"
+ "In Thumb state the core registers @code{r8}-@code{r15}.")
+
+(define_register_constraint "k" "TARGET_THUMB ? STACK_REG : NO_REGS"
+ "@internal
+ Thumb only. The stack register.")
+
+(define_register_constraint "b" "TARGET_THUMB ? BASE_REGS : NO_REGS"
+ "@internal
+ Thumb only. The union of the low registers and the stack register.")
+
+(define_register_constraint "c" "CC_REG"
+ "@internal The condition code register.")
+
+(define_constraint "I"
+ "In ARM state a constant that can be used as an immediate value in a Data
+ Processing instruction. In Thumb state a constant in the range 0-255."
+ (and (match_code "const_int")
+ (match_test "TARGET_ARM ? const_ok_for_arm (ival)
+ : ival >= 0 && ival <= 255")))
+
+(define_constraint "J"
+ "In ARM state a constant in the range @minus{}4095-4095. In Thumb state
+ a constant in the range @minus{}255-@minus{}1."
+ (and (match_code "const_int")
+ (match_test "TARGET_ARM ? (ival >= -4095 && ival <= 4095)
+ : (ival >= -255 && ival <= -1)")))
+
+(define_constraint "K"
+ "In ARM state a constant that satisfies the @code{I} constraint if inverted.
+ In Thumb state a constant that satisfies the @code{I} constraint multiplied
+ by any power of 2."
+ (and (match_code "const_int")
+ (match_test "TARGET_ARM ? const_ok_for_arm (~ival)
+ : thumb_shiftable_const (ival)")))
+
+(define_constraint "L"
+ "In ARM state a constant that satisfies the @code{I} constraint if negated.
+ In Thumb state a constant in the range @minus{}7-7."
+ (and (match_code "const_int")
+ (match_test "TARGET_ARM ? const_ok_for_arm (-ival)
+ : (ival >= -7 && ival <= 7)")))
+
+;; The ARM state version is internal...
+;; @internal In ARM state a constant in the range 0-32 or any power of 2.
+(define_constraint "M"
+ "In Thumb state a constant that is a multiple of 4 in the range 0-1020."
+ (and (match_code "const_int")
+ (match_test "TARGET_ARM ? ((ival >= 0 && ival <= 32)
+ || ((ival & (ival - 1)) == 0))
+ : ((ival >= 0 && ival <= 1020) && ((ival & 3) == 0))")))
+
+(define_constraint "N"
+ "In Thumb state a constant in the range 0-31."
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB && ival >= 0 && ival <= 31")))
+
+(define_constraint "O"
+ "In Thumb state a constant that is a multiple of 4 in the range
+ @minus{}508-508."
+ (and (match_code "const_int")
+ (match_test "TARGET_THUMB && ival >= -508 && ival <= 508
+ && ((ival & 3) == 0)")))
+
+(define_constraint "G"
+ "In ARM state a valid FPA immediate constant."
+ (and (match_code "const_double")
+ (match_test "TARGET_ARM && arm_const_double_rtx (op)")))
+
+(define_constraint "H"
+ "In ARM state a valid FPA immediate constant when negated."
+ (and (match_code "const_double")
+ (match_test "TARGET_ARM && neg_const_double_rtx_ok_for_fpa (op)")))
+
+(define_constraint "Da"
+ "@internal
+ In ARM state a const_int, const_double or const_vector that can
+ be generated with two Data Processing insns."
+ (and (match_code "const_double,const_int,const_vector")
+ (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 2")))
+
+(define_constraint "Db"
+ "@internal
+ In ARM state a const_int, const_double or const_vector that can
+ be generated with three Data Processing insns."
+ (and (match_code "const_double,const_int,const_vector")
+ (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 3")))
+
+(define_constraint "Dc"
+ "@internal
+ In ARM state a const_int, const_double or const_vector that can
+ be generated with four Data Processing insns. This pattern is disabled
+ if optimizing for space or when we have load-delay slots to fill."
+ (and (match_code "const_double,const_int,const_vector")
+ (match_test "TARGET_ARM && arm_const_double_inline_cost (op) == 4
+ && !(optimize_size || arm_ld_sched)")))
+
+(define_memory_constraint "Uv"
+ "@internal
+ In ARM state a valid VFP load/store address."
+ (and (match_code "mem")
+ (match_test "TARGET_ARM && arm_coproc_mem_operand (op, FALSE)")))
+
+(define_memory_constraint "Uy"
+ "@internal
+ In ARM state a valid iWMMX load/store address."
+ (and (match_code "mem")
+ (match_test "TARGET_ARM && arm_coproc_mem_operand (op, TRUE)")))
+
+(define_memory_constraint "Uq"
+ "@internal
+ In ARM state an address valid in ldrsb instructions."
+ (and (match_code "mem")
+ (match_test "TARGET_ARM
+ && arm_legitimate_address_p (GET_MODE (op), XEXP (op, 0),
+ SIGN_EXTEND, 0)")))
+
+(define_memory_constraint "Q"
+ "@internal
+ In ARM state an address that is a single base register."
+ (and (match_code "mem")
+ (match_test "REG_P (XEXP (op, 0))")))
+
+;; We used to have constraint letters for S and R in ARM state, but
+;; all uses of these now appear to have been removed.
+
+;; Additionally, we used to have a Q constraint in Thumb state, but
+;; this wasn't really a valid memory constraint. Again, all uses of
+;; this now seem to have been removed.
diff --git a/contrib/gcc/config/arm/crti.asm b/contrib/gcc/config/arm/crti.asm
index ac58e44..166a3ce 100644
--- a/contrib/gcc/config/arm/crti.asm
+++ b/contrib/gcc/config/arm/crti.asm
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
@@ -35,6 +35,12 @@
# .init sections. Users may put any desired instructions in those
# sections.
+#ifdef __ELF__
+#define TYPE(x) .type x,function
+#else
+#define TYPE(x)
+#endif
+
# Note - this macro is complemented by the FUNC_END macro
# in crtn.asm. If you change this macro you must also change
# that macro match.
@@ -42,12 +48,12 @@
#ifdef __thumb__
.thumb
- push {r4, r5, r6, r7, lr}
+ push {r3, r4, r5, r6, r7, lr}
#else
.arm
# Create a stack frame and save any call-preserved registers
mov ip, sp
- stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
+ stmdb sp!, {r3, r4, r5, r6, r7, r8, r9, sl, fp, ip, lr, pc}
sub fp, ip, #4
#endif
.endm
@@ -60,6 +66,7 @@
#ifdef __thumb__
.thumb_func
#endif
+ TYPE(_init)
_init:
FUNC_START
@@ -70,6 +77,7 @@ _init:
#ifdef __thumb__
.thumb_func
#endif
+ TYPE(_fini)
_fini:
FUNC_START
diff --git a/contrib/gcc/config/arm/crtn.asm b/contrib/gcc/config/arm/crtn.asm
index 9ad75e3..360afae 100644
--- a/contrib/gcc/config/arm/crtn.asm
+++ b/contrib/gcc/config/arm/crtn.asm
@@ -1,4 +1,4 @@
-# Copyright (C) 2001 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2004 Free Software Foundation, Inc.
# Written By Nick Clifton
#
# This file is free software; you can redistribute it and/or modify it
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
@@ -43,28 +43,26 @@
# sequences here, it is just not worth it. Instead keep things
# simple. Restore all the save resgisters, including the link
# register and then perform the correct function return instruction.
+ # We also save/restore r3 to ensure stack alignment.
.macro FUNC_END
#ifdef __thumb__
.thumb
- pop {r4, r5, r6, r7}
+ pop {r3, r4, r5, r6, r7}
pop {r3}
mov lr, r3
#else
.arm
- ldmdb fp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
+ sub sp, fp, #40
+ ldmfd sp, {r4, r5, r6, r7, r8, r9, sl, fp, sp, lr}
#endif
#if defined __THUMB_INTERWORK__ || defined __thumb__
bx lr
#else
-#ifdef __APCS_26__
- movs pc, lr
-#else
mov pc, lr
#endif
-#endif
.endm
diff --git a/contrib/gcc/config/arm/ecos-elf.h b/contrib/gcc/config/arm/ecos-elf.h
index d57fe8b..22eefe4 100644
--- a/contrib/gcc/config/arm/ecos-elf.h
+++ b/contrib/gcc/config/arm/ecos-elf.h
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#undef TARGET_VERSION
diff --git a/contrib/gcc/config/arm/elf.h b/contrib/gcc/config/arm/elf.h
index cb38264..ae3d533 100644
--- a/contrib/gcc/config/arm/elf.h
+++ b/contrib/gcc/config/arm/elf.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
For ARM with ELF obj format.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2004, 2005
Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org> and
Catherine Moore <clm@cygnus.com>
@@ -19,8 +19,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#ifndef OBJECT_FORMAT_ELF
#error elf.h included before elfos.h
@@ -46,7 +46,7 @@
#ifndef SUBTARGET_ASM_FLOAT_SPEC
#define SUBTARGET_ASM_FLOAT_SPEC "\
-%{mapcs-float:-mfloat} %{msoft-float:-mfpu=softfpa}"
+%{mapcs-float:-mfloat}"
#endif
#ifndef ASM_SPEC
@@ -58,6 +58,8 @@
%{mapcs-*:-mapcs-%*} \
%(subtarget_asm_float_spec) \
%{mthumb-interwork:-mthumb-interwork} \
+%{msoft-float:-mfloat-abi=soft} %{mhard-float:-mfloat-abi=hard} \
+%{mfloat-abi=*} %{mfpu=*} \
%(subtarget_extra_asm_spec)"
#endif
@@ -75,6 +77,7 @@
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
ASM_OUTPUT_LABEL(FILE, NAME); \
+ ARM_OUTPUT_FN_UNWIND (FILE, TRUE); \
} \
while (0)
@@ -83,6 +86,7 @@
#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
do \
{ \
+ ARM_OUTPUT_FN_UNWIND (FILE, FALSE); \
ARM_DECLARE_FUNCTION_SIZE (FILE, FNAME, DECL); \
if (!flag_inhibit_size_directive) \
ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
@@ -106,20 +110,21 @@
#endif
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_APCS_FRAME)
#endif
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork", "fno-leading-underscore" }
+ { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork", "fno-leading-underscore" }
#endif
#define TARGET_ASM_FILE_START_APP_OFF true
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
-#undef TARGET_ASM_NAMED_SECTION
-#define TARGET_ASM_NAMED_SECTION arm_elf_asm_named_section
-
+
+/* Output an element in the static constructor array. */
+#undef TARGET_ASM_CONSTRUCTOR
+#define TARGET_ASM_CONSTRUCTOR arm_elf_asm_constructor
/* For PIC code we need to explicitly specify (PLT) and (GOT) relocs. */
#define NEED_PLT_RELOC flag_pic
@@ -144,4 +149,5 @@
} \
while (0)
-#define SUPPORTS_INIT_PRIORITY 1
+/* The EABI doesn't provide a way of implementing init_priority. */
+#define SUPPORTS_INIT_PRIORITY (!TARGET_AAPCS_BASED)
diff --git a/contrib/gcc/config/arm/fpa.md b/contrib/gcc/config/arm/fpa.md
index 3b6efbf..b801f5a 100644
--- a/contrib/gcc/config/arm/fpa.md
+++ b/contrib/gcc/config/arm/fpa.md
@@ -1,6 +1,6 @@
;;- Machine description for FPA co-processor for ARM cpus.
;; Copyright 1991, 1993, 1994, 1995, 1996, 1996, 1997, 1998, 1999, 2000,
-;; 2001, 2002, 2003 Free Software Foundation, Inc.
+;; 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
;; and Martin Simmons (@harleqn.co.uk).
;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
@@ -19,8 +19,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; FPA automaton.
(define_automaton "armfp")
@@ -100,8 +100,8 @@
(define_insn "*addsf3_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f,f")
(plus:SF (match_operand:SF 1 "s_register_operand" "%f,f")
- (match_operand:SF 2 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
adf%?s\\t%0, %1, %2
suf%?s\\t%0, %1, #%N2"
@@ -112,8 +112,8 @@
(define_insn "*adddf3_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f,f")
(plus:DF (match_operand:DF 1 "s_register_operand" "%f,f")
- (match_operand:DF 2 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
adf%?d\\t%0, %1, %2
suf%?d\\t%0, %1, #%N2"
@@ -125,8 +125,8 @@
[(set (match_operand:DF 0 "s_register_operand" "=f,f")
(plus:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f,f"))
- (match_operand:DF 2 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
adf%?d\\t%0, %1, %2
suf%?d\\t%0, %1, #%N2"
@@ -139,7 +139,7 @@
(plus:DF (match_operand:DF 1 "s_register_operand" "f")
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"adf%?d\\t%0, %1, %2"
[(set_attr "type" "farith")
(set_attr "predicable" "yes")]
@@ -151,7 +151,7 @@
(match_operand:SF 1 "s_register_operand" "f"))
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"adf%?d\\t%0, %1, %2"
[(set_attr "type" "farith")
(set_attr "predicable" "yes")]
@@ -159,9 +159,9 @@
(define_insn "*subsf3_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (minus:SF (match_operand:SF 1 "fpa_rhs_operand" "f,G")
- (match_operand:SF 2 "fpa_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (minus:SF (match_operand:SF 1 "arm_float_rhs_operand" "f,G")
+ (match_operand:SF 2 "arm_float_rhs_operand" "fG,f")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
suf%?s\\t%0, %1, %2
rsf%?s\\t%0, %2, %1"
@@ -170,9 +170,9 @@
(define_insn "*subdf3_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
- (match_operand:DF 2 "fpa_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG,f")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
suf%?d\\t%0, %1, %2
rsf%?d\\t%0, %2, %1"
@@ -184,8 +184,8 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(minus:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"suf%?d\\t%0, %1, %2"
[(set_attr "type" "farith")
(set_attr "predicable" "yes")]
@@ -193,10 +193,10 @@
(define_insn "*subdf_df_esfdf_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (minus:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
+ (minus:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f,f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
suf%?d\\t%0, %1, %2
rsf%?d\\t%0, %2, %1"
@@ -210,7 +210,7 @@
(match_operand:SF 1 "s_register_operand" "f"))
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"suf%?d\\t%0, %1, %2"
[(set_attr "type" "farith")
(set_attr "predicable" "yes")]
@@ -219,8 +219,8 @@
(define_insn "*mulsf3_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(mult:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"fml%?s\\t%0, %1, %2"
[(set_attr "type" "ffmul")
(set_attr "predicable" "yes")]
@@ -229,8 +229,8 @@
(define_insn "*muldf3_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(mult:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"muf%?d\\t%0, %1, %2"
[(set_attr "type" "fmul")
(set_attr "predicable" "yes")]
@@ -240,8 +240,8 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(mult:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"muf%?d\\t%0, %1, %2"
[(set_attr "type" "fmul")
(set_attr "predicable" "yes")]
@@ -252,7 +252,7 @@
(mult:DF (match_operand:DF 1 "s_register_operand" "f")
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"muf%?d\\t%0, %1, %2"
[(set_attr "type" "fmul")
(set_attr "predicable" "yes")]
@@ -263,7 +263,7 @@
(mult:DF
(float_extend:DF (match_operand:SF 1 "s_register_operand" "f"))
(float_extend:DF (match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"muf%?d\\t%0, %1, %2"
[(set_attr "type" "fmul")
(set_attr "predicable" "yes")]
@@ -273,9 +273,9 @@
(define_insn "*divsf3_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "fpa_rhs_operand" "f,G")
- (match_operand:SF 2 "fpa_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (div:SF (match_operand:SF 1 "arm_float_rhs_operand" "f,G")
+ (match_operand:SF 2 "arm_float_rhs_operand" "fG,f")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
fdv%?s\\t%0, %1, %2
frd%?s\\t%0, %2, %1"
@@ -285,9 +285,9 @@
(define_insn "*divdf3_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "fpa_rhs_operand" "f,G")
- (match_operand:DF 2 "fpa_rhs_operand" "fG,f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "f,G")
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG,f")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
dvf%?d\\t%0, %1, %2
rdf%?d\\t%0, %2, %1"
@@ -299,8 +299,8 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(div:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"dvf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -308,10 +308,10 @@
(define_insn "*divdf_df_esfdf_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
- (div:DF (match_operand:DF 1 "fpa_rhs_operand" "fG")
+ (div:DF (match_operand:DF 1 "arm_float_rhs_operand" "fG")
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rdf%?d\\t%0, %2, %1"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -323,7 +323,7 @@
(match_operand:SF 1 "s_register_operand" "f"))
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"dvf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -332,8 +332,8 @@
(define_insn "*modsf3_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(mod:SF (match_operand:SF 1 "s_register_operand" "f")
- (match_operand:SF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rmf%?s\\t%0, %1, %2"
[(set_attr "type" "fdivs")
(set_attr "predicable" "yes")]
@@ -342,8 +342,8 @@
(define_insn "*moddf3_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(mod:DF (match_operand:DF 1 "s_register_operand" "f")
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rmf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -353,8 +353,8 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(mod:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))
- (match_operand:DF 2 "fpa_rhs_operand" "fG")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 2 "arm_float_rhs_operand" "fG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rmf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -365,7 +365,7 @@
(mod:DF (match_operand:DF 1 "s_register_operand" "f")
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rmf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -377,7 +377,7 @@
(match_operand:SF 1 "s_register_operand" "f"))
(float_extend:DF
(match_operand:SF 2 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"rmf%?d\\t%0, %1, %2"
[(set_attr "type" "fdivd")
(set_attr "predicable" "yes")]
@@ -386,7 +386,7 @@
(define_insn "*negsf2_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"mnf%?s\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -395,7 +395,7 @@
(define_insn "*negdf2_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"mnf%?d\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -405,7 +405,7 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(neg:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"mnf%?d\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -414,7 +414,7 @@
(define_insn "*abssf2_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"abs%?s\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -423,7 +423,7 @@
(define_insn "*absdf2_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"abs%?d\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -433,7 +433,7 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(abs:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"abs%?d\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -442,7 +442,7 @@
(define_insn "*sqrtsf2_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"sqt%?s\\t%0, %1"
[(set_attr "type" "float_em")
(set_attr "predicable" "yes")]
@@ -451,7 +451,7 @@
(define_insn "*sqrtdf2_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"sqt%?d\\t%0, %1"
[(set_attr "type" "float_em")
(set_attr "predicable" "yes")]
@@ -461,7 +461,7 @@
[(set (match_operand:DF 0 "s_register_operand" "=f")
(sqrt:DF (float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"sqt%?d\\t%0, %1"
[(set_attr "type" "float_em")
(set_attr "predicable" "yes")]
@@ -470,7 +470,7 @@
(define_insn "*floatsisf2_fpa"
[(set (match_operand:SF 0 "s_register_operand" "=f")
(float:SF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"flt%?s\\t%0, %1"
[(set_attr "type" "r_2_f")
(set_attr "predicable" "yes")]
@@ -479,7 +479,7 @@
(define_insn "*floatsidf2_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(float:DF (match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"flt%?d\\t%0, %1"
[(set_attr "type" "r_2_f")
(set_attr "predicable" "yes")]
@@ -488,7 +488,7 @@
(define_insn "*fix_truncsfsi2_fpa"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"fix%?z\\t%0, %1"
[(set_attr "type" "f_2_r")
(set_attr "predicable" "yes")]
@@ -497,7 +497,7 @@
(define_insn "*fix_truncdfsi2_fpa"
[(set (match_operand:SI 0 "s_register_operand" "=r")
(fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"fix%?z\\t%0, %1"
[(set_attr "type" "f_2_r")
(set_attr "predicable" "yes")]
@@ -507,7 +507,7 @@
[(set (match_operand:SF 0 "s_register_operand" "=f")
(float_truncate:SF
(match_operand:DF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"mvf%?s\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -516,7 +516,7 @@
(define_insn "*extendsfdf2_fpa"
[(set (match_operand:DF 0 "s_register_operand" "=f")
(float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"mvf%?d\\t%0, %1"
[(set_attr "type" "ffarith")
(set_attr "predicable" "yes")]
@@ -526,7 +526,7 @@
[(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f, m,f,r,r,r, m")
(match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
"TARGET_ARM
- && TARGET_HARD_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPA
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], SFmode))"
"@
@@ -542,7 +542,7 @@
[(set_attr "length" "4,4,4,4,8,8,4,4,4")
(set_attr "predicable" "yes")
(set_attr "type"
- "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
+ "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load1,store1")
(set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
(set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
)
@@ -553,7 +553,7 @@
(match_operand:DF 1 "general_operand"
"Q, r,r,r,mF,fG,H,mF,f,r, f"))]
"TARGET_ARM
- && TARGET_HARD_FLOAT
+ && TARGET_HARD_FLOAT && TARGET_FPA
&& (GET_CODE (operands[0]) != MEM
|| register_operand (operands[1], DFmode))"
"*
@@ -563,7 +563,8 @@
default:
case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
- case 2: case 3: case 4: return output_move_double (operands);
+ case 2: return \"#\";
+ case 3: case 4: return output_move_double (operands);
case 5: return \"mvf%?d\\t%0, %1\";
case 6: return \"mnf%?d\\t%0, #%N1\";
case 7: return \"ldf%?d\\t%0, %1\";
@@ -576,45 +577,43 @@
[(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
(set_attr "predicable" "yes")
(set_attr "type"
- "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
+ "load1,store2,*,store2,load1,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
(set_attr "pool_range" "*,*,*,*,1020,*,*,1024,*,*,*")
(set_attr "neg_pool_range" "*,*,*,*,1008,*,*,1008,*,*,*")]
)
-;; Saving and restoring the floating point registers in the prologue should
-;; be done in XFmode, even though we don't support that for anything else
-;; (Well, strictly it's 'internal representation', but that's effectively
-;; XFmode).
-
+;; We treat XFmode as meaning 'internal format'. It's the right size and we
+;; don't use it for anything else. We only support moving between FPA
+;; registers and moving an FPA register to/from memory.
(define_insn "*movxf_fpa"
- [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
- (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
- "TARGET_ARM && TARGET_HARD_FLOAT && reload_completed"
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,m")
+ (match_operand:XF 1 "general_operand" "f,m,f"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA
+ && (register_operand (operands[0], XFmode)
+ || register_operand (operands[1], XFmode))"
"*
switch (which_alternative)
{
default:
case 0: return \"mvf%?e\\t%0, %1\";
- case 1: return \"mnf%?e\\t%0, #%N1\";
- case 2: return \"ldf%?e\\t%0, %1\";
- case 3: return \"stf%?e\\t%1, %0\";
- case 4: return output_mov_long_double_fpa_from_arm (operands);
- case 5: return output_mov_long_double_arm_from_fpa (operands);
- case 6: return output_mov_long_double_arm_from_arm (operands);
+ case 1: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
+ return \"ldf%?e\\t%0, %1\";
+ return \"lfm%?\\t%0, 1, %1\";
+ case 2: if (arm_fpu_arch == FPUTYPE_FPA_EMU2)
+ return \"stf%?e\\t%1, %0\";
+ return \"sfm%?\\t%1, 1, %0\";
}
"
- [(set_attr "length" "4,4,4,4,8,8,12")
+ [(set_attr "length" "4,4,4")
(set_attr "predicable" "yes")
- (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
- (set_attr "pool_range" "*,*,1024,*,*,*,*")
- (set_attr "neg_pool_range" "*,*,1004,*,*,*,*")]
+ (set_attr "type" "ffarith,f_load,f_store")]
)
(define_insn "*cmpsf_fpa"
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?\\t%0, %1
cnf%?\\t%0, #%N1"
@@ -625,8 +624,8 @@
(define_insn "*cmpdf_fpa"
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?\\t%0, %1
cnf%?\\t%0, #%N1"
@@ -638,8 +637,8 @@
[(set (reg:CCFP CC_REGNUM)
(compare:CCFP (float_extend:DF
(match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?\\t%0, %1
cnf%?\\t%0, #%N1"
@@ -652,7 +651,7 @@
(compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
(float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"cmf%?\\t%0, %1"
[(set_attr "conds" "set")
(set_attr "type" "f_2_r")]
@@ -661,8 +660,8 @@
(define_insn "*cmpsf_trap_fpa"
[(set (reg:CCFPE CC_REGNUM)
(compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
- (match_operand:SF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?e\\t%0, %1
cnf%?e\\t%0, #%N1"
@@ -673,8 +672,8 @@
(define_insn "*cmpdf_trap_fpa"
[(set (reg:CCFPE CC_REGNUM)
(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
- (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?e\\t%0, %1
cnf%?e\\t%0, #%N1"
@@ -686,8 +685,8 @@
[(set (reg:CCFPE CC_REGNUM)
(compare:CCFPE (float_extend:DF
(match_operand:SF 0 "s_register_operand" "f,f"))
- (match_operand:DF 1 "fpa_add_operand" "fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_add_operand" "fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
cmf%?e\\t%0, %1
cnf%?e\\t%0, #%N1"
@@ -700,7 +699,7 @@
(compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
(float_extend:DF
(match_operand:SF 1 "s_register_operand" "f"))))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"cmf%?e\\t%0, %1"
[(set_attr "conds" "set")
(set_attr "type" "f_2_r")]
@@ -711,9 +710,9 @@
(if_then_else:SF
(match_operator 3 "arm_comparison_operator"
[(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:SF 1 "fpa_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:SF 2 "fpa_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:SF 1 "arm_float_add_operand" "0,0,fG,H,fG,fG,H,H")
+ (match_operand:SF 2 "arm_float_add_operand" "fG,H,0,0,fG,H,fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
mvf%D3s\\t%0, %2
mnf%D3s\\t%0, #%N2
@@ -733,9 +732,9 @@
(if_then_else:DF
(match_operator 3 "arm_comparison_operator"
[(match_operand 4 "cc_register" "") (const_int 0)])
- (match_operand:DF 1 "fpa_add_operand" "0,0,fG,H,fG,fG,H,H")
- (match_operand:DF 2 "fpa_add_operand" "fG,H,0,0,fG,H,fG,H")))]
- "TARGET_ARM && TARGET_HARD_FLOAT"
+ (match_operand:DF 1 "arm_float_add_operand" "0,0,fG,H,fG,fG,H,H")
+ (match_operand:DF 2 "arm_float_add_operand" "fG,H,0,0,fG,H,fG,H")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_FPA"
"@
mvf%D3d\\t%0, %2
mnf%D3d\\t%0, #%N2
@@ -749,4 +748,3 @@
(set_attr "type" "ffarith")
(set_attr "conds" "use")]
)
-
diff --git a/contrib/gcc/config/arm/freebsd.h b/contrib/gcc/config/arm/freebsd.h
index cc3f727..6bae83d 100644
--- a/contrib/gcc/config/arm/freebsd.h
+++ b/contrib/gcc/config/arm/freebsd.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#undef SUBTARGET_EXTRA_SPECS
@@ -30,7 +30,6 @@
#undef LINK_SPEC
#define LINK_SPEC " \
%{p:%nconsider using `-pg' instead of `-p' with gprof(1) } \
- %{Wl,*:%*} \
%{v:-V} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
%{shared:-Bshareable %{h*} %{soname*}} \
diff --git a/contrib/gcc/config/arm/gentune.sh b/contrib/gcc/config/arm/gentune.sh
new file mode 100755
index 0000000..40c0541
--- /dev/null
+++ b/contrib/gcc/config/arm/gentune.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+# Generate arm-tune.md, a file containing the tune attribute from the list of
+# CPUs in arm-cores.def
+
+echo ";; -*- buffer-read-only: t -*-"
+echo ";; Generated automatically by gentune.sh from arm-cores.def"
+
+allcores=`awk -F'[(, ]+' '/^ARM_CORE/ { cores = cores$3"," } END { print cores } ' $1`
+
+echo "(define_attr \"tune\""
+echo " \"$allcores\"" | sed -e 's/,"$/"/'
+echo " (const (symbol_ref \"arm_tune\")))"
diff --git a/contrib/gcc/config/arm/ieee754-df.S b/contrib/gcc/config/arm/ieee754-df.S
index 6a7aab8..74d9f0d 100644
--- a/contrib/gcc/config/arm/ieee754-df.S
+++ b/contrib/gcc/config/arm/ieee754-df.S
@@ -1,6 +1,6 @@
/* ieee754-df.S double-precision floating point support for ARM
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Nicolas Pitre (nico@cam.org)
This file is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/*
* Notes:
@@ -59,55 +59,52 @@
#ifdef L_negdf2
ARM_FUNC_START negdf2
+ARM_FUNC_ALIAS aeabi_dneg negdf2
+
@ flip sign bit
eor xh, xh, #0x80000000
RET
+ FUNC_END aeabi_dneg
FUNC_END negdf2
#endif
#ifdef L_addsubdf3
+ARM_FUNC_START aeabi_drsub
+
+ eor xh, xh, #0x80000000 @ flip sign bit of first arg
+ b 1f
+
ARM_FUNC_START subdf3
- @ flip sign bit of second arg
- eor yh, yh, #0x80000000
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+ARM_FUNC_ALIAS aeabi_dsub subdf3
+
+ eor yh, yh, #0x80000000 @ flip sign bit of second arg
+#if defined(__INTERWORKING_STUBS__)
b 1f @ Skip Thumb-code prologue
#endif
ARM_FUNC_START adddf3
+ARM_FUNC_ALIAS aeabi_dadd adddf3
-1: @ Compare both args, return zero if equal but the sign.
- teq xl, yl
- eoreq ip, xh, yh
- teqeq ip, #0x80000000
- beq LSYM(Lad_z)
-
- @ If first arg is 0 or -0, return second arg.
- @ If second arg is 0 or -0, return first arg.
- orrs ip, xl, xh, lsl #1
- moveq xl, yl
- moveq xh, yh
- orrnes ip, yl, yh, lsl #1
- RETc(eq)
-
- stmfd sp!, {r4, r5, lr}
-
- @ Mask out exponents.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r4, xh, ip
- and r5, yh, ip
+1: stmfd sp!, {r4, r5, lr}
- @ If either of them is 0x7ff, result will be INF or NAN
- teq r4, ip
- teqne r5, ip
- beq LSYM(Lad_i)
+ @ Look for zeroes, equal values, INF, or NAN.
+ mov r4, xh, lsl #1
+ mov r5, yh, lsl #1
+ teq r4, r5
+ teqeq xl, yl
+ orrnes ip, r4, xl
+ orrnes ip, r5, yl
+ mvnnes ip, r4, asr #21
+ mvnnes ip, r5, asr #21
+ beq LSYM(Lad_s)
@ Compute exponent difference. Make largest exponent in r4,
@ corresponding arg in xh-xl, and positive exponent difference in r5.
- subs r5, r5, r4
+ mov r4, r4, lsr #21
+ rsbs r5, r4, r5, lsr #21
rsblt r5, r5, #0
ble 1f
add r4, r4, r5
@@ -118,24 +115,24 @@ ARM_FUNC_START adddf3
eor yl, xl, yl
eor yh, xh, yh
1:
-
@ If exponent difference is too large, return largest argument
@ already in xh-xl. We need up to 54 bit to handle proper rounding
@ of 0x1p54 - 1.1.
- cmp r5, #(54 << 20)
+ cmp r5, #54
RETLDM "r4, r5" hi
@ Convert mantissa to signed integer.
tst xh, #0x80000000
- bic xh, xh, ip, lsl #1
- orr xh, xh, #0x00100000
+ mov xh, xh, lsl #12
+ mov ip, #0x00100000
+ orr xh, ip, xh, lsr #12
beq 1f
rsbs xl, xl, #0
rsc xh, xh, #0
1:
tst yh, #0x80000000
- bic yh, yh, ip, lsl #1
- orr yh, yh, #0x00100000
+ mov yh, yh, lsl #12
+ orr yh, ip, yh, lsr #12
beq 1f
rsbs yl, yl, #0
rsc yh, yh, #0
@@ -145,42 +142,30 @@ ARM_FUNC_START adddf3
teq r4, r5
beq LSYM(Lad_d)
LSYM(Lad_x):
- @ Scale down second arg with exponent difference.
- @ Apply shift one bit left to first arg and the rest to second arg
- @ to simplify things later, but only if exponent does not become 0.
- mov ip, #0
- movs r5, r5, lsr #20
- beq 3f
- teq r4, #(1 << 20)
- beq 1f
- movs xl, xl, lsl #1
- adc xh, ip, xh, lsl #1
- sub r4, r4, #(1 << 20)
- subs r5, r5, #1
- beq 3f
- @ Shift yh-yl right per r5, keep leftover bits into ip.
-1: rsbs lr, r5, #32
- blt 2f
+ @ Compensate for the exponent overlapping the mantissa MSB added later
+ sub r4, r4, #1
+
+ @ Shift yh-yl right per r5, add to xh-xl, keep leftover bits into ip.
+ rsbs lr, r5, #32
+ blt 1f
mov ip, yl, lsl lr
- mov yl, yl, lsr r5
- orr yl, yl, yh, lsl lr
- mov yh, yh, asr r5
- b 3f
-2: sub r5, r5, #32
+ adds xl, xl, yl, lsr r5
+ adc xh, xh, #0
+ adds xl, xl, yh, lsl lr
+ adcs xh, xh, yh, asr r5
+ b 2f
+1: sub r5, r5, #32
add lr, lr, #32
cmp yl, #1
- adc ip, ip, yh, lsl lr
- mov yl, yh, asr r5
- mov yh, yh, asr #32
-3:
- @ the actual addition
- adds xl, xl, yl
- adc xh, xh, yh
-
+ mov ip, yh, lsl lr
+ orrcs ip, ip, #2 @ 2 not 1, to allow lsr #1 later
+ adds xl, xl, yh, asr r5
+ adcs xh, xh, yh, asr #31
+2:
@ We now have a result in xh-xl-ip.
- @ Keep absolute value in xh-xl-ip, sign in r5.
- ands r5, xh, #0x80000000
+ @ Keep absolute value in xh-xl-ip, sign in r5 (the n bit was set above)
+ and r5, xh, #0x80000000
bpl LSYM(Lad_p)
rsbs ip, ip, #0
rscs xl, xl, #0
@@ -189,75 +174,66 @@ LSYM(Lad_x):
@ Determine how to normalize the result.
LSYM(Lad_p):
cmp xh, #0x00100000
- bcc LSYM(Lad_l)
+ bcc LSYM(Lad_a)
cmp xh, #0x00200000
- bcc LSYM(Lad_r0)
- cmp xh, #0x00400000
- bcc LSYM(Lad_r1)
+ bcc LSYM(Lad_e)
@ Result needs to be shifted right.
movs xh, xh, lsr #1
movs xl, xl, rrx
- movs ip, ip, rrx
- orrcs ip, ip, #1
- add r4, r4, #(1 << 20)
-LSYM(Lad_r1):
- movs xh, xh, lsr #1
- movs xl, xl, rrx
- movs ip, ip, rrx
- orrcs ip, ip, #1
- add r4, r4, #(1 << 20)
+ mov ip, ip, rrx
+ add r4, r4, #1
+
+ @ Make sure we did not bust our exponent.
+ mov r2, r4, lsl #21
+ cmn r2, #(2 << 21)
+ bcs LSYM(Lad_o)
@ Our result is now properly aligned into xh-xl, remaining bits in ip.
@ Round with MSB of ip. If halfway between two numbers, round towards
@ LSB of xl = 0.
-LSYM(Lad_r0):
- adds xl, xl, ip, lsr #31
- adc xh, xh, #0
- teq ip, #0x80000000
- biceq xl, xl, #1
-
- @ One extreme rounding case may add a new MSB. Adjust exponent.
- @ That MSB will be cleared when exponent is merged below.
- tst xh, #0x00200000
- addne r4, r4, #(1 << 20)
-
- @ Make sure we did not bust our exponent.
- adds ip, r4, #(1 << 20)
- bmi LSYM(Lad_o)
-
@ Pack final result together.
LSYM(Lad_e):
- bic xh, xh, #0x00300000
- orr xh, xh, r4
+ cmp ip, #0x80000000
+ moveqs ip, xl, lsr #1
+ adcs xl, xl, #0
+ adc xh, xh, r4, lsl #20
orr xh, xh, r5
RETLDM "r4, r5"
-LSYM(Lad_l):
@ Result must be shifted left and exponent adjusted.
- @ No rounding necessary since ip will always be 0.
+LSYM(Lad_a):
+ movs ip, ip, lsl #1
+ adcs xl, xl, xl
+ adc xh, xh, xh
+ tst xh, #0x00100000
+ sub r4, r4, #1
+ bne LSYM(Lad_e)
+
+ @ No rounding necessary since ip will always be 0 at this point.
+LSYM(Lad_l):
+
#if __ARM_ARCH__ < 5
teq xh, #0
- movne r3, #-11
- moveq r3, #21
+ movne r3, #20
+ moveq r3, #52
moveq xh, xl
moveq xl, #0
mov r2, xh
- movs ip, xh, lsr #16
- moveq r2, r2, lsl #16
- addeq r3, r3, #16
- tst r2, #0xff000000
- moveq r2, r2, lsl #8
- addeq r3, r3, #8
- tst r2, #0xf0000000
- moveq r2, r2, lsl #4
- addeq r3, r3, #4
- tst r2, #0xc0000000
- moveq r2, r2, lsl #2
- addeq r3, r3, #2
- tst r2, #0x80000000
- addeq r3, r3, #1
+ cmp r2, #(1 << 16)
+ movhs r2, r2, lsr #16
+ subhs r3, r3, #16
+ cmp r2, #(1 << 8)
+ movhs r2, r2, lsr #8
+ subhs r3, r3, #8
+ cmp r2, #(1 << 4)
+ movhs r2, r2, lsr #4
+ subhs r3, r3, #4
+ cmp r2, #(1 << 2)
+ subhs r3, r3, #2
+ sublo r3, r3, r2, lsr #1
+ sub r3, r3, r2, lsr #3
#else
@@ -293,13 +269,15 @@ LSYM(Lad_l):
movle xl, xl, lsl r2
@ adjust exponent accordingly.
-3: subs r4, r4, r3, lsl #20
- bgt LSYM(Lad_e)
+3: subs r4, r4, r3
+ addge xh, xh, r4, lsl #20
+ orrge xh, xh, r5
+ RETLDM "r4, r5" ge
@ Exponent too small, denormalize result.
@ Find out proper shift value.
- mvn r4, r4, asr #20
- subs r4, r4, #30
+ mvn r4, r4
+ subs r4, r4, #31
bge 2f
adds r4, r4, #12
bgt 1f
@@ -328,23 +306,49 @@ LSYM(Lad_l):
RETLDM "r4, r5"
@ Adjust exponents for denormalized arguments.
+ @ Note that r4 must not remain equal to 0.
LSYM(Lad_d):
teq r4, #0
- eoreq xh, xh, #0x00100000
- addeq r4, r4, #(1 << 20)
eor yh, yh, #0x00100000
- subne r5, r5, #(1 << 20)
+ eoreq xh, xh, #0x00100000
+ addeq r4, r4, #1
+ subne r5, r5, #1
b LSYM(Lad_x)
- @ Result is x - x = 0, unless x = INF or NAN.
-LSYM(Lad_z):
- sub ip, ip, #0x00100000 @ ip becomes 0x7ff00000
- and r2, xh, ip
- teq r2, ip
- orreq xh, ip, #0x00080000
+
+LSYM(Lad_s):
+ mvns ip, r4, asr #21
+ mvnnes ip, r5, asr #21
+ beq LSYM(Lad_i)
+
+ teq r4, r5
+ teqeq xl, yl
+ beq 1f
+
+ @ Result is x + 0.0 = x or 0.0 + y = y.
+ orrs ip, r4, xl
+ moveq xh, yh
+ moveq xl, yl
+ RETLDM "r4, r5"
+
+1: teq xh, yh
+
+ @ Result is x - x = 0.
movne xh, #0
- mov xl, #0
- RET
+ movne xl, #0
+ RETLDM "r4, r5" ne
+
+ @ Result is x + x = 2x.
+ movs ip, r4, lsr #21
+ bne 2f
+ movs xl, xl, lsl #1
+ adcs xh, xh, xh
+ orrcs xh, xh, #0x80000000
+ RETLDM "r4, r5"
+2: adds r4, r4, #(2 << 21)
+ addcc xh, xh, #(1 << 20)
+ RETLDM "r4, r5" cc
+ and r5, xh, #0x80000000
@ Overflow: return INF.
LSYM(Lad_o):
@@ -358,127 +362,221 @@ LSYM(Lad_o):
@ if yh-yl != INF/NAN: return xh-xl (which is INF/NAN)
@ if either is NAN: return NAN
@ if opposite sign: return NAN
- @ return xh-xl (which is INF or -INF)
+ @ otherwise return xh-xl (which is INF or -INF)
LSYM(Lad_i):
- teq r4, ip
+ mvns ip, r4, asr #21
movne xh, yh
movne xl, yl
- teqeq r5, ip
- RETLDM "r4, r5" ne
-
+ mvneqs ip, r5, asr #21
+ movne yh, xh
+ movne yl, xl
orrs r4, xl, xh, lsl #12
- orreqs r4, yl, yh, lsl #12
+ orreqs r5, yl, yh, lsl #12
teqeq xh, yh
- orrne xh, r5, #0x00080000
- movne xl, #0
+ orrne xh, xh, #0x00080000 @ quiet NAN
RETLDM "r4, r5"
+ FUNC_END aeabi_dsub
FUNC_END subdf3
+ FUNC_END aeabi_dadd
FUNC_END adddf3
ARM_FUNC_START floatunsidf
+ARM_FUNC_ALIAS aeabi_ui2d floatunsidf
+
teq r0, #0
moveq r1, #0
RETc(eq)
stmfd sp!, {r4, r5, lr}
- mov r4, #(0x400 << 20) @ initial exponent
- add r4, r4, #((52-1) << 20)
+ mov r4, #0x400 @ initial exponent
+ add r4, r4, #(52-1 - 1)
mov r5, #0 @ sign bit is 0
+ .ifnc xl, r0
mov xl, r0
+ .endif
mov xh, #0
b LSYM(Lad_l)
+ FUNC_END aeabi_ui2d
FUNC_END floatunsidf
ARM_FUNC_START floatsidf
+ARM_FUNC_ALIAS aeabi_i2d floatsidf
+
teq r0, #0
moveq r1, #0
RETc(eq)
stmfd sp!, {r4, r5, lr}
- mov r4, #(0x400 << 20) @ initial exponent
- add r4, r4, #((52-1) << 20)
+ mov r4, #0x400 @ initial exponent
+ add r4, r4, #(52-1 - 1)
ands r5, r0, #0x80000000 @ sign bit in r5
rsbmi r0, r0, #0 @ absolute value
+ .ifnc xl, r0
mov xl, r0
+ .endif
mov xh, #0
b LSYM(Lad_l)
+ FUNC_END aeabi_i2d
FUNC_END floatsidf
ARM_FUNC_START extendsfdf2
- movs r2, r0, lsl #1
- beq 1f @ value is 0.0 or -0.0
+ARM_FUNC_ALIAS aeabi_f2d extendsfdf2
+
+ movs r2, r0, lsl #1 @ toss sign bit
mov xh, r2, asr #3 @ stretch exponent
mov xh, xh, rrx @ retrieve sign bit
mov xl, r2, lsl #28 @ retrieve remaining bits
- ands r2, r2, #0xff000000 @ isolate exponent
- beq 2f @ exponent was 0 but not mantissa
- teq r2, #0xff000000 @ check if INF or NAN
+ andnes r3, r2, #0xff000000 @ isolate exponent
+ teqne r3, #0xff000000 @ if not 0, check if INF or NAN
eorne xh, xh, #0x38000000 @ fixup exponent otherwise.
- RET
+ RETc(ne) @ and return it.
-1: mov xh, r0
- mov xl, #0
- RET
+ teq r2, #0 @ if actually 0
+ teqne r3, #0xff000000 @ or INF or NAN
+ RETc(eq) @ we are done already.
-2: @ value was denormalized. We can normalize it now.
+ @ value was denormalized. We can normalize it now.
stmfd sp!, {r4, r5, lr}
- mov r4, #(0x380 << 20) @ setup corresponding exponent
- add r4, r4, #(1 << 20)
+ mov r4, #0x380 @ setup corresponding exponent
and r5, xh, #0x80000000 @ move sign bit in r5
bic xh, xh, #0x80000000
b LSYM(Lad_l)
+ FUNC_END aeabi_f2d
FUNC_END extendsfdf2
+ARM_FUNC_START floatundidf
+ARM_FUNC_ALIAS aeabi_ul2d floatundidf
+
+ orrs r2, r0, r1
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ mvfeqd f0, #0.0
+#endif
+ RETc(eq)
+
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ @ For hard FPA code we want to return via the tail below so that
+ @ we can return the result in f0 as well as in r0/r1 for backwards
+ @ compatibility.
+ adr ip, LSYM(f0_ret)
+ stmfd sp!, {r4, r5, ip, lr}
+#else
+ stmfd sp!, {r4, r5, lr}
+#endif
+
+ mov r5, #0
+ b 2f
+
+ARM_FUNC_START floatdidf
+ARM_FUNC_ALIAS aeabi_l2d floatdidf
+
+ orrs r2, r0, r1
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ mvfeqd f0, #0.0
+#endif
+ RETc(eq)
+
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ @ For hard FPA code we want to return via the tail below so that
+ @ we can return the result in f0 as well as in r0/r1 for backwards
+ @ compatibility.
+ adr ip, LSYM(f0_ret)
+ stmfd sp!, {r4, r5, ip, lr}
+#else
+ stmfd sp!, {r4, r5, lr}
+#endif
+
+ ands r5, ah, #0x80000000 @ sign bit in r5
+ bpl 2f
+ rsbs al, al, #0
+ rsc ah, ah, #0
+2:
+ mov r4, #0x400 @ initial exponent
+ add r4, r4, #(52-1 - 1)
+
+ @ FPA little-endian: must swap the word order.
+ .ifnc xh, ah
+ mov ip, al
+ mov xh, ah
+ mov xl, ip
+ .endif
+
+ movs ip, xh, lsr #22
+ beq LSYM(Lad_p)
+
+ @ The value is too big. Scale it down a bit...
+ mov r2, #3
+ movs ip, ip, lsr #3
+ addne r2, r2, #3
+ movs ip, ip, lsr #3
+ addne r2, r2, #3
+ add r2, r2, ip, lsr #3
+
+ rsb r3, r2, #32
+ mov ip, xl, lsl r3
+ mov xl, xl, lsr r2
+ orr xl, xl, xh, lsl r3
+ mov xh, xh, lsr r2
+ add r4, r4, r2
+ b LSYM(Lad_p)
+
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+
+ @ Legacy code expects the result to be returned in f0. Copy it
+ @ there as well.
+LSYM(f0_ret):
+ stmfd sp!, {r0, r1}
+ ldfd f0, [sp], #8
+ RETLDM
+
+#endif
+
+ FUNC_END floatdidf
+ FUNC_END aeabi_l2d
+ FUNC_END floatundidf
+ FUNC_END aeabi_ul2d
+
#endif /* L_addsubdf3 */
#ifdef L_muldivdf3
ARM_FUNC_START muldf3
-
+ARM_FUNC_ALIAS aeabi_dmul muldf3
stmfd sp!, {r4, r5, r6, lr}
- @ Mask out exponents.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r4, xh, ip
- and r5, yh, ip
-
- @ Trap any INF/NAN.
- teq r4, ip
+ @ Mask out exponents, trap any zero/denormal/INF/NAN.
+ mov ip, #0xff
+ orr ip, ip, #0x700
+ ands r4, ip, xh, lsr #20
+ andnes r5, ip, yh, lsr #20
+ teqne r4, ip
teqne r5, ip
- beq LSYM(Lml_s)
+ bleq LSYM(Lml_s)
- @ Trap any multiplication by 0.
- orrs r6, xl, xh, lsl #1
- orrnes r6, yl, yh, lsl #1
- beq LSYM(Lml_z)
-
- @ Shift exponents right one bit to make room for overflow bit.
- @ If either of them is 0, scale denormalized arguments off line.
- @ Then add both exponents together.
- movs r4, r4, lsr #1
- teqne r5, #0
- beq LSYM(Lml_d)
-LSYM(Lml_x):
- add r4, r4, r5, asr #1
-
- @ Preserve final sign in r4 along with exponent for now.
- teq xh, yh
- orrmi r4, r4, #0x8000
+ @ Add exponents together
+ add r4, r4, r5
+
+ @ Determine final sign.
+ eor r6, xh, yh
@ Convert mantissa to unsigned integer.
- bic xh, xh, ip, lsl #1
- bic yh, yh, ip, lsl #1
+ @ If power of two, branch to a separate path.
+ bic xh, xh, ip, lsl #21
+ bic yh, yh, ip, lsl #21
+ orrs r5, xl, xh, lsl #12
+ orrnes r5, yl, yh, lsl #12
orr xh, xh, #0x00100000
orr yh, yh, #0x00100000
+ beq LSYM(Lml_1)
#if __ARM_ARCH__ < 4
+ @ Put sign bit in r6, which will be restored in yl later.
+ and r6, r6, #0x80000000
+
@ Well, no way to make it shorter without the umull instruction.
- @ We must perform that 53 x 53 bit multiplication by hand.
- stmfd sp!, {r7, r8, r9, sl, fp}
+ stmfd sp!, {r6, r7, r8, r9, sl, fp}
mov r7, xl, lsr #16
mov r8, yl, lsr #16
mov r9, xh, lsr #16
@@ -530,92 +628,83 @@ LSYM(Lml_x):
mul fp, xh, yh
adcs r5, r5, fp
adc r6, r6, #0
- ldmfd sp!, {r7, r8, r9, sl, fp}
+ ldmfd sp!, {yl, r7, r8, r9, sl, fp}
#else
- @ Here is the actual multiplication: 53 bits * 53 bits -> 106 bits.
+ @ Here is the actual multiplication.
umull ip, lr, xl, yl
mov r5, #0
- umlal lr, r5, xl, yh
umlal lr, r5, xh, yl
+ and yl, r6, #0x80000000
+ umlal lr, r5, xl, yh
mov r6, #0
umlal r5, r6, xh, yh
#endif
@ The LSBs in ip are only significant for the final rounding.
- @ Fold them into one bit of lr.
+ @ Fold them into lr.
teq ip, #0
orrne lr, lr, #1
- @ Put final sign in xh.
- mov xh, r4, lsl #16
- bic r4, r4, #0x8000
-
- @ Adjust result if one extra MSB appeared (one of four times).
- tst r6, #(1 << 9)
- beq 1f
- add r4, r4, #(1 << 19)
- movs r6, r6, lsr #1
- movs r5, r5, rrx
- movs lr, lr, rrx
- orrcs lr, lr, #1
-1:
- @ Scale back to 53 bits.
- @ xh contains sign bit already.
- orr xh, xh, r6, lsl #12
- orr xh, xh, r5, lsr #20
- mov xl, r5, lsl #12
- orr xl, xl, lr, lsr #20
-
- @ Apply exponent bias, check range for underflow.
- sub r4, r4, #0x00f80000
- subs r4, r4, #0x1f000000
- ble LSYM(Lml_u)
-
- @ Round the result.
- movs lr, lr, lsl #12
- bpl 1f
- adds xl, xl, #1
- adc xh, xh, #0
- teq lr, #0x80000000
- biceq xl, xl, #1
-
- @ Rounding may have produced an extra MSB here.
- @ The extra bit is cleared before merging the exponent below.
- tst xh, #0x00200000
- addne r4, r4, #(1 << 19)
+ @ Adjust result upon the MSB position.
+ sub r4, r4, #0xff
+ cmp r6, #(1 << (20-11))
+ sbc r4, r4, #0x300
+ bcs 1f
+ movs lr, lr, lsl #1
+ adcs r5, r5, r5
+ adc r6, r6, r6
1:
- @ Check exponent for overflow.
- adds ip, r4, #(1 << 19)
- tst ip, #(1 << 30)
- bne LSYM(Lml_o)
-
- @ Add final exponent.
- bic xh, xh, #0x00300000
- orr xh, xh, r4, lsl #1
+ @ Shift to final position, add sign to result.
+ orr xh, yl, r6, lsl #11
+ orr xh, xh, r5, lsr #21
+ mov xl, r5, lsl #11
+ orr xl, xl, lr, lsr #21
+ mov lr, lr, lsl #11
+
+ @ Check exponent range for under/overflow.
+ subs ip, r4, #(254 - 1)
+ cmphi ip, #0x700
+ bhi LSYM(Lml_u)
+
+ @ Round the result, merge final exponent.
+ cmp lr, #0x80000000
+ moveqs lr, xl, lsr #1
+ adcs xl, xl, #0
+ adc xh, xh, r4, lsl #20
RETLDM "r4, r5, r6"
- @ Result is 0, but determine sign anyway.
-LSYM(Lml_z):
+ @ Multiplication by 0x1p*: let''s shortcut a lot of code.
+LSYM(Lml_1):
+ and r6, r6, #0x80000000
+ orr xh, r6, xh
+ orr xl, xl, yl
eor xh, xh, yh
-LSYM(Ldv_z):
- bic xh, xh, #0x7fffffff
- mov xl, #0
- RETLDM "r4, r5, r6"
+ subs r4, r4, ip, lsr #1
+ rsbgts r5, r4, ip
+ orrgt xh, xh, r4, lsl #20
+ RETLDM "r4, r5, r6" gt
+
+ @ Under/overflow: fix things up for the code below.
+ orr xh, xh, #0x00100000
+ mov lr, #0
+ subs r4, r4, #1
- @ Check if denormalized result is possible, otherwise return signed 0.
LSYM(Lml_u):
- cmn r4, #(53 << 19)
+ @ Overflow?
+ bgt LSYM(Lml_o)
+
+ @ Check if denormalized result is possible, otherwise return signed 0.
+ cmn r4, #(53 + 1)
movle xl, #0
bicle xh, xh, #0x7fffffff
RETLDM "r4, r5, r6" le
@ Find out proper shift value.
-LSYM(Lml_r):
- mvn r4, r4, asr #19
- subs r4, r4, #30
+ rsb r4, r4, #0
+ subs r4, r4, #32
bge 2f
adds r4, r4, #12
bgt 1f
@@ -626,14 +715,12 @@ LSYM(Lml_r):
mov r3, xl, lsl r5
mov xl, xl, lsr r4
orr xl, xl, xh, lsl r5
- movs xh, xh, lsl #1
- mov xh, xh, lsr r4
- mov xh, xh, rrx
+ and r2, xh, #0x80000000
+ bic xh, xh, #0x80000000
adds xl, xl, r3, lsr #31
- adc xh, xh, #0
- teq lr, #0
- teqeq r3, #0x80000000
- biceq xl, xl, #1
+ adc xh, r2, xh, lsr r4
+ orrs lr, lr, r3, lsl #1
+ biceq xl, xl, r3, lsr #31
RETLDM "r4, r5, r6"
@ shift result right of 21 to 31 bits, or left 11 to 1 bits after
@@ -646,53 +733,70 @@ LSYM(Lml_r):
bic xh, xh, #0x7fffffff
adds xl, xl, r3, lsr #31
adc xh, xh, #0
- teq lr, #0
- teqeq r3, #0x80000000
- biceq xl, xl, #1
+ orrs lr, lr, r3, lsl #1
+ biceq xl, xl, r3, lsr #31
RETLDM "r4, r5, r6"
@ Shift value right of 32 to 64 bits, or 0 to 32 bits after a switch
@ from xh to xl. Leftover bits are in r3-r6-lr for rounding.
2: rsb r5, r4, #32
- mov r6, xl, lsl r5
+ orr lr, lr, xl, lsl r5
mov r3, xl, lsr r4
orr r3, r3, xh, lsl r5
mov xl, xh, lsr r4
bic xh, xh, #0x7fffffff
bic xl, xl, xh, lsr r4
add xl, xl, r3, lsr #31
- orrs r6, r6, lr
- teqeq r3, #0x80000000
- biceq xl, xl, #1
+ orrs lr, lr, r3, lsl #1
+ biceq xl, xl, r3, lsr #31
RETLDM "r4, r5, r6"
@ One or both arguments are denormalized.
@ Scale them leftwards and preserve sign bit.
LSYM(Lml_d):
- mov lr, #0
teq r4, #0
bne 2f
and r6, xh, #0x80000000
1: movs xl, xl, lsl #1
- adc xh, lr, xh, lsl #1
+ adc xh, xh, xh
tst xh, #0x00100000
- subeq r4, r4, #(1 << 19)
+ subeq r4, r4, #1
beq 1b
orr xh, xh, r6
teq r5, #0
- bne LSYM(Lml_x)
+ movne pc, lr
2: and r6, yh, #0x80000000
3: movs yl, yl, lsl #1
- adc yh, lr, yh, lsl #1
+ adc yh, yh, yh
tst yh, #0x00100000
- subeq r5, r5, #(1 << 20)
+ subeq r5, r5, #1
beq 3b
orr yh, yh, r6
- b LSYM(Lml_x)
+ mov pc, lr
- @ One or both args are INF or NAN.
LSYM(Lml_s):
+ @ Isolate the INF and NAN cases away
+ teq r4, ip
+ and r5, ip, yh, lsr #20
+ teqne r5, ip
+ beq 1f
+
+ @ Here, one or more arguments are either denormalized or zero.
+ orrs r6, xl, xh, lsl #1
+ orrnes r6, yl, yh, lsl #1
+ bne LSYM(Lml_d)
+
+ @ Result is 0, but determine sign anyway.
+LSYM(Lml_z):
+ eor xh, xh, yh
+ bic xh, xh, #0x7fffffff
+ mov xl, #0
+ RETLDM "r4, r5, r6"
+
+1: @ One or both args are INF or NAN.
orrs r6, xl, xh, lsl #1
+ moveq xl, yl
+ moveq xh, yh
orrnes r6, yl, yh, lsl #1
beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
teq r4, ip
@@ -702,6 +806,8 @@ LSYM(Lml_s):
1: teq r5, ip
bne LSYM(Lml_i)
orrs r6, yl, yh, lsl #12
+ movne xl, yl
+ movne xh, yh
bne LSYM(Lml_n) @ <anything> * NAN -> NAN
@ Result is INF, but we need to determine its sign.
@@ -716,53 +822,45 @@ LSYM(Lml_o):
mov xl, #0
RETLDM "r4, r5, r6"
- @ Return NAN.
+ @ Return a quiet NAN.
LSYM(Lml_n):
- mov xh, #0x7f000000
+ orr xh, xh, #0x7f000000
orr xh, xh, #0x00f80000
RETLDM "r4, r5, r6"
+ FUNC_END aeabi_dmul
FUNC_END muldf3
ARM_FUNC_START divdf3
-
+ARM_FUNC_ALIAS aeabi_ddiv divdf3
+
stmfd sp!, {r4, r5, r6, lr}
- @ Mask out exponents.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r4, xh, ip
- and r5, yh, ip
-
- @ Trap any INF/NAN or zeroes.
- teq r4, ip
+ @ Mask out exponents, trap any zero/denormal/INF/NAN.
+ mov ip, #0xff
+ orr ip, ip, #0x700
+ ands r4, ip, xh, lsr #20
+ andnes r5, ip, yh, lsr #20
+ teqne r4, ip
teqne r5, ip
- orrnes r6, xl, xh, lsl #1
- orrnes r6, yl, yh, lsl #1
- beq LSYM(Ldv_s)
+ bleq LSYM(Ldv_s)
- @ Shift exponents right one bit to make room for overflow bit.
- @ If either of them is 0, scale denormalized arguments off line.
- @ Then substract divisor exponent from dividend''s.
- movs r4, r4, lsr #1
- teqne r5, #0
- beq LSYM(Ldv_d)
-LSYM(Ldv_x):
- sub r4, r4, r5, asr #1
+ @ Substract divisor exponent from dividend''s.
+ sub r4, r4, r5
@ Preserve final sign into lr.
eor lr, xh, yh
@ Convert mantissa to unsigned integer.
@ Dividend -> r5-r6, divisor -> yh-yl.
- mov r5, #0x10000000
+ orrs r5, yl, yh, lsl #12
+ mov xh, xh, lsl #12
+ beq LSYM(Ldv_1)
mov yh, yh, lsl #12
+ mov r5, #0x10000000
orr yh, r5, yh, lsr #4
orr yh, yh, yl, lsr #24
- movs yl, yl, lsl #8
- mov xh, xh, lsl #12
- teqeq yh, r5
- beq LSYM(Ldv_1)
+ mov yl, yl, lsl #8
orr r5, r5, xh, lsr #4
orr r5, r5, xl, lsr #24
mov r6, xl, lsl #8
@@ -771,21 +869,15 @@ LSYM(Ldv_x):
and xh, lr, #0x80000000
@ Ensure result will land to known bit position.
+ @ Apply exponent bias accordingly.
cmp r5, yh
cmpeq r6, yl
+ adc r4, r4, #(255 - 2)
+ add r4, r4, #0x300
bcs 1f
- sub r4, r4, #(1 << 19)
movs yh, yh, lsr #1
mov yl, yl, rrx
1:
- @ Apply exponent bias, check range for over/underflow.
- add r4, r4, #0x1f000000
- add r4, r4, #0x00f80000
- cmn r4, #(53 << 19)
- ble LSYM(Ldv_z)
- cmp r4, ip, lsr #1
- bge LSYM(Lml_o)
-
@ Perform first substraction to align result to a nibble.
subs r6, r6, yl
sbc r5, r5, yh
@@ -847,73 +939,42 @@ LSYM(Ldv_x):
orreq xh, xh, xl
moveq xl, #0
3:
- @ Check if denormalized result is needed.
- cmp r4, #0
- ble LSYM(Ldv_u)
+ @ Check exponent range for under/overflow.
+ subs ip, r4, #(254 - 1)
+ cmphi ip, #0x700
+ bhi LSYM(Lml_u)
- @ Apply proper rounding.
+ @ Round the result, merge final exponent.
subs ip, r5, yh
subeqs ip, r6, yl
+ moveqs ip, xl, lsr #1
adcs xl, xl, #0
- adc xh, xh, #0
- teq ip, #0
- biceq xl, xl, #1
-
- @ Add exponent to result.
- bic xh, xh, #0x00100000
- orr xh, xh, r4, lsl #1
+ adc xh, xh, r4, lsl #20
RETLDM "r4, r5, r6"
@ Division by 0x1p*: shortcut a lot of code.
LSYM(Ldv_1):
and lr, lr, #0x80000000
orr xh, lr, xh, lsr #12
- add r4, r4, #0x1f000000
- add r4, r4, #0x00f80000
- cmp r4, ip, lsr #1
- bge LSYM(Lml_o)
- cmp r4, #0
- orrgt xh, xh, r4, lsl #1
+ adds r4, r4, ip, lsr #1
+ rsbgts r5, r4, ip
+ orrgt xh, xh, r4, lsl #20
RETLDM "r4, r5, r6" gt
- cmn r4, #(53 << 19)
- ble LSYM(Ldv_z)
orr xh, xh, #0x00100000
mov lr, #0
- b LSYM(Lml_r)
+ subs r4, r4, #1
+ b LSYM(Lml_u)
- @ Result must be denormalized: put remainder in lr for
- @ rounding considerations.
+ @ Result mightt need to be denormalized: put remainder bits
+ @ in lr for rounding considerations.
LSYM(Ldv_u):
orr lr, r5, r6
- b LSYM(Lml_r)
-
- @ One or both arguments are denormalized.
- @ Scale them leftwards and preserve sign bit.
-LSYM(Ldv_d):
- mov lr, #0
- teq r4, #0
- bne 2f
- and r6, xh, #0x80000000
-1: movs xl, xl, lsl #1
- adc xh, lr, xh, lsl #1
- tst xh, #0x00100000
- subeq r4, r4, #(1 << 19)
- beq 1b
- orr xh, xh, r6
- teq r5, #0
- bne LSYM(Ldv_x)
-2: and r6, yh, #0x80000000
-3: movs yl, yl, lsl #1
- adc yh, lr, yh, lsl #1
- tst yh, #0x00100000
- subeq r5, r5, #(1 << 20)
- beq 3b
- orr yh, yh, r6
- b LSYM(Ldv_x)
+ b LSYM(Lml_u)
@ One or both arguments is either INF, NAN or zero.
LSYM(Ldv_s):
+ and r5, ip, yh, lsr #20
teq r4, ip
teqeq r5, ip
beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
@@ -921,25 +982,38 @@ LSYM(Ldv_s):
bne 1f
orrs r4, xl, xh, lsl #12
bne LSYM(Lml_n) @ NAN / <anything> -> NAN
- b LSYM(Lml_i) @ INF / <anything> -> INF
+ teq r5, ip
+ bne LSYM(Lml_i) @ INF / <anything> -> INF
+ mov xl, yl
+ mov xh, yh
+ b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
1: teq r5, ip
bne 2f
orrs r5, yl, yh, lsl #12
- bne LSYM(Lml_n) @ <anything> / NAN -> NAN
- b LSYM(Lml_z) @ <anything> / INF -> 0
-2: @ One or both arguments are 0.
+ beq LSYM(Lml_z) @ <anything> / INF -> 0
+ mov xl, yl
+ mov xh, yh
+ b LSYM(Lml_n) @ <anything> / NAN -> NAN
+2: @ If both are nonzero, we need to normalize and resume above.
+ orrs r6, xl, xh, lsl #1
+ orrnes r6, yl, yh, lsl #1
+ bne LSYM(Lml_d)
+ @ One or both arguments are 0.
orrs r4, xl, xh, lsl #1
bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
orrs r5, yl, yh, lsl #1
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN
+ FUNC_END aeabi_ddiv
FUNC_END divdf3
#endif /* L_muldivdf3 */
#ifdef L_cmpdf2
+@ Note: only r0 (return value) and ip are clobbered here.
+
ARM_FUNC_START gtdf2
ARM_FUNC_ALIAS gedf2 gtdf2
mov ip, #-1
@@ -955,15 +1029,13 @@ ARM_FUNC_ALIAS nedf2 cmpdf2
ARM_FUNC_ALIAS eqdf2 cmpdf2
mov ip, #1 @ how should we specify unordered here?
-1: stmfd sp!, {r4, r5, lr}
+1: str ip, [sp, #-4]
@ Trap any INF/NAN first.
- mov lr, #0x7f000000
- orr lr, lr, #0x00f00000
- and r4, xh, lr
- and r5, yh, lr
- teq r4, lr
- teqne r5, lr
+ mov ip, xh, lsl #1
+ mvns ip, ip, asr #21
+ mov ip, yh, lsl #1
+ mvnnes ip, ip, asr #21
beq 3f
@ Test for equality.
@@ -973,37 +1045,37 @@ ARM_FUNC_ALIAS eqdf2 cmpdf2
teqne xh, yh @ or xh == yh
teqeq xl, yl @ and xl == yl
moveq r0, #0 @ then equal.
- RETLDM "r4, r5" eq
+ RETc(eq)
- @ Check for sign difference.
- teq xh, yh
- movmi r0, xh, asr #31
- orrmi r0, r0, #1
- RETLDM "r4, r5" mi
+ @ Clear C flag
+ cmn r0, #0
- @ Compare exponents.
- cmp r4, r5
+ @ Compare sign,
+ teq xh, yh
- @ Compare mantissa if exponents are equal.
- moveq xh, xh, lsl #12
- cmpeq xh, yh, lsl #12
+ @ Compare values if same sign
+ cmppl xh, yh
cmpeq xl, yl
+
+ @ Result:
movcs r0, yh, asr #31
mvncc r0, yh, asr #31
orr r0, r0, #1
- RETLDM "r4, r5"
+ RET
@ Look for a NAN.
-3: teq r4, lr
+3: mov ip, xh, lsl #1
+ mvns ip, ip, asr #21
bne 4f
- orrs xl, xl, xh, lsl #12
+ orrs ip, xl, xh, lsl #12
bne 5f @ x is NAN
-4: teq r5, lr
+4: mov ip, yh, lsl #1
+ mvns ip, ip, asr #21
bne 2b
- orrs yl, yl, yh, lsl #12
+ orrs ip, yl, yh, lsl #12
beq 2b @ y is not NAN
-5: mov r0, ip @ return unordered code from ip
- RETLDM "r4, r5"
+5: ldr r0, [sp, #-4] @ unordered return code
+ RET
FUNC_END gedf2
FUNC_END gtdf2
@@ -1013,30 +1085,109 @@ ARM_FUNC_ALIAS eqdf2 cmpdf2
FUNC_END eqdf2
FUNC_END cmpdf2
+ARM_FUNC_START aeabi_cdrcmple
+
+ mov ip, r0
+ mov r0, r2
+ mov r2, ip
+ mov ip, r1
+ mov r1, r3
+ mov r3, ip
+ b 6f
+
+ARM_FUNC_START aeabi_cdcmpeq
+ARM_FUNC_ALIAS aeabi_cdcmple aeabi_cdcmpeq
+
+ @ The status-returning routines are required to preserve all
+ @ registers except ip, lr, and cpsr.
+6: stmfd sp!, {r0, lr}
+ ARM_CALL cmpdf2
+ @ Set the Z flag correctly, and the C flag unconditionally.
+ cmp r0, #0
+ @ Clear the C flag if the return value was -1, indicating
+ @ that the first operand was smaller than the second.
+ cmnmi r0, #0
+ RETLDM "r0"
+
+ FUNC_END aeabi_cdcmple
+ FUNC_END aeabi_cdcmpeq
+ FUNC_END aeabi_cdrcmple
+
+ARM_FUNC_START aeabi_dcmpeq
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cdcmple
+ moveq r0, #1 @ Equal to.
+ movne r0, #0 @ Less than, greater than, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_dcmpeq
+
+ARM_FUNC_START aeabi_dcmplt
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cdcmple
+ movcc r0, #1 @ Less than.
+ movcs r0, #0 @ Equal to, greater than, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_dcmplt
+
+ARM_FUNC_START aeabi_dcmple
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cdcmple
+ movls r0, #1 @ Less than or equal to.
+ movhi r0, #0 @ Greater than or unordered.
+ RETLDM
+
+ FUNC_END aeabi_dcmple
+
+ARM_FUNC_START aeabi_dcmpge
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cdrcmple
+ movls r0, #1 @ Operand 2 is less than or equal to operand 1.
+ movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_dcmpge
+
+ARM_FUNC_START aeabi_dcmpgt
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cdrcmple
+ movcc r0, #1 @ Operand 2 is less than operand 1.
+ movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
+ @ or they are unordered.
+ RETLDM
+
+ FUNC_END aeabi_dcmpgt
+
#endif /* L_cmpdf2 */
#ifdef L_unorddf2
ARM_FUNC_START unorddf2
- str lr, [sp, #-4]!
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and lr, xh, ip
- teq lr, ip
+ARM_FUNC_ALIAS aeabi_dcmpun unorddf2
+
+ mov ip, xh, lsl #1
+ mvns ip, ip, asr #21
bne 1f
- orrs xl, xl, xh, lsl #12
+ orrs ip, xl, xh, lsl #12
bne 3f @ x is NAN
-1: and lr, yh, ip
- teq lr, ip
+1: mov ip, yh, lsl #1
+ mvns ip, ip, asr #21
bne 2f
- orrs yl, yl, yh, lsl #12
+ orrs ip, yl, yh, lsl #12
bne 3f @ y is NAN
2: mov r0, #0 @ arguments are ordered.
- RETLDM
+ RET
3: mov r0, #1 @ arguments are unordered.
- RETLDM
+ RET
+ FUNC_END aeabi_dcmpun
FUNC_END unorddf2
#endif /* L_unorddf2 */
@@ -1044,31 +1195,23 @@ ARM_FUNC_START unorddf2
#ifdef L_fixdfsi
ARM_FUNC_START fixdfsi
- orrs ip, xl, xh, lsl #1
- beq 1f @ value is 0.
-
- mov r3, r3, rrx @ preserve C flag (the actual sign)
+ARM_FUNC_ALIAS aeabi_d2iz fixdfsi
@ check exponent range.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r2, xh, ip
- teq r2, ip
- beq 2f @ value is INF or NAN
- bic ip, ip, #0x40000000
- cmp r2, ip
- bcc 1f @ value is too small
- add ip, ip, #(31 << 20)
- cmp r2, ip
- bcs 3f @ value is too large
-
- rsb r2, r2, ip
- mov ip, xh, lsl #11
- orr ip, ip, #0x80000000
- orr ip, ip, xl, lsr #21
- mov r2, r2, lsr #20
- tst r3, #0x80000000 @ the sign bit
- mov r0, ip, lsr r2
+ mov r2, xh, lsl #1
+ adds r2, r2, #(1 << 21)
+ bcs 2f @ value is INF or NAN
+ bpl 1f @ value is too small
+ mov r3, #(0xfffffc00 + 31)
+ subs r2, r3, r2, asr #21
+ bls 3f @ value is too large
+
+ @ scale value
+ mov r3, xh, lsl #11
+ orr r3, r3, #0x80000000
+ orr r3, r3, xl, lsr #21
+ tst xh, #0x80000000 @ the sign bit
+ mov r0, r3, lsr r2
rsbne r0, r0, #0
RET
@@ -1076,14 +1219,15 @@ ARM_FUNC_START fixdfsi
RET
2: orrs xl, xl, xh, lsl #12
- bne 4f @ r0 is NAN.
-3: ands r0, r3, #0x80000000 @ the sign bit
+ bne 4f @ x is NAN.
+3: ands r0, xh, #0x80000000 @ the sign bit
moveq r0, #0x7fffffff @ maximum signed positive si
RET
4: mov r0, #0 @ How should we convert NAN?
RET
+ FUNC_END aeabi_d2iz
FUNC_END fixdfsi
#endif /* L_fixdfsi */
@@ -1091,29 +1235,23 @@ ARM_FUNC_START fixdfsi
#ifdef L_fixunsdfsi
ARM_FUNC_START fixunsdfsi
- orrs ip, xl, xh, lsl #1
- movcss r0, #0 @ value is negative
- RETc(eq) @ or 0 (xl, xh overlap r0)
+ARM_FUNC_ALIAS aeabi_d2uiz fixunsdfsi
@ check exponent range.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r2, xh, ip
- teq r2, ip
- beq 2f @ value is INF or NAN
- bic ip, ip, #0x40000000
- cmp r2, ip
- bcc 1f @ value is too small
- add ip, ip, #(31 << 20)
- cmp r2, ip
- bhi 3f @ value is too large
-
- rsb r2, r2, ip
- mov ip, xh, lsl #11
- orr ip, ip, #0x80000000
- orr ip, ip, xl, lsr #21
- mov r2, r2, lsr #20
- mov r0, ip, lsr r2
+ movs r2, xh, lsl #1
+ bcs 1f @ value is negative
+ adds r2, r2, #(1 << 21)
+ bcs 2f @ value is INF or NAN
+ bpl 1f @ value is too small
+ mov r3, #(0xfffffc00 + 31)
+ subs r2, r3, r2, asr #21
+ bmi 3f @ value is too large
+
+ @ scale value
+ mov r3, xh, lsl #11
+ orr r3, r3, #0x80000000
+ orr r3, r3, xl, lsr #21
+ mov r0, r3, lsr r2
RET
1: mov r0, #0
@@ -1127,6 +1265,7 @@ ARM_FUNC_START fixunsdfsi
4: mov r0, #0 @ How should we convert NAN?
RET
+ FUNC_END aeabi_d2uiz
FUNC_END fixunsdfsi
#endif /* L_fixunsdfsi */
@@ -1134,91 +1273,63 @@ ARM_FUNC_START fixunsdfsi
#ifdef L_truncdfsf2
ARM_FUNC_START truncdfsf2
- orrs r2, xl, xh, lsl #1
- moveq r0, r2, rrx
- RETc(eq) @ value is 0.0 or -0.0
-
+ARM_FUNC_ALIAS aeabi_d2f truncdfsf2
+
@ check exponent range.
- mov ip, #0x7f000000
- orr ip, ip, #0x00f00000
- and r2, ip, xh
- teq r2, ip
- beq 2f @ value is INF or NAN
- bic xh, xh, ip
- cmp r2, #(0x380 << 20)
- bls 4f @ value is too small
-
- @ shift and round mantissa
-1: movs r3, xl, lsr #29
- adc r3, r3, xh, lsl #3
-
- @ if halfway between two numbers, round towards LSB = 0.
- mov xl, xl, lsl #3
- teq xl, #0x80000000
- biceq r3, r3, #1
-
- @ rounding might have created an extra MSB. If so adjust exponent.
- tst r3, #0x00800000
- addne r2, r2, #(1 << 20)
- bicne r3, r3, #0x00800000
-
- @ check exponent for overflow
- mov ip, #(0x400 << 20)
- orr ip, ip, #(0x07f << 20)
- cmp r2, ip
- bcs 3f @ overflow
-
- @ adjust exponent, merge with sign bit and mantissa.
- movs xh, xh, lsl #1
- mov r2, r2, lsl #4
- orr r0, r3, r2, rrx
- eor r0, r0, #0x40000000
+ mov r2, xh, lsl #1
+ subs r3, r2, #((1023 - 127) << 21)
+ subcss ip, r3, #(1 << 21)
+ rsbcss ip, ip, #(254 << 21)
+ bls 2f @ value is out of range
+
+1: @ shift and round mantissa
+ and ip, xh, #0x80000000
+ mov r2, xl, lsl #3
+ orr xl, ip, xl, lsr #29
+ cmp r2, #0x80000000
+ adc r0, xl, r3, lsl #2
+ biceq r0, r0, #1
RET
-2: @ chech for NAN
- orrs xl, xl, xh, lsl #12
- movne r0, #0x7f000000
- orrne r0, r0, #0x00c00000
- RETc(ne) @ return NAN
+2: @ either overflow or underflow
+ tst xh, #0x40000000
+ bne 3f @ overflow
-3: @ return INF with sign
- and r0, xh, #0x80000000
- orr r0, r0, #0x7f000000
- orr r0, r0, #0x00800000
- RET
+ @ check if denormalized value is possible
+ adds r2, r3, #(23 << 21)
+ andlt r0, xh, #0x80000000 @ too small, return signed 0.
+ RETc(lt)
-4: @ check if denormalized value is possible
- subs r2, r2, #((0x380 - 24) << 20)
- andle r0, xh, #0x80000000 @ too small, return signed 0.
- RETc(le)
-
@ denormalize value so we can resume with the code above afterwards.
orr xh, xh, #0x00100000
- mov r2, r2, lsr #20
- rsb r2, r2, #25
- cmp r2, #20
- bgt 6f
-
+ mov r2, r2, lsr #21
+ rsb r2, r2, #24
rsb ip, r2, #32
- mov r3, xl, lsl ip
+ movs r3, xl, lsl ip
mov xl, xl, lsr r2
- orr xl, xl, xh, lsl ip
- movs xh, xh, lsl #1
- mov xh, xh, lsr r2
- mov xh, xh, rrx
-5: teq r3, #0 @ fold r3 bits into the LSB
- orrne xl, xl, #1 @ for rounding considerations.
- mov r2, #(0x380 << 20) @ equivalent to the 0 float exponent
+ orrne xl, xl, #1 @ fold r3 for rounding considerations.
+ mov r3, xh, lsl #11
+ mov r3, r3, lsr #11
+ orr xl, xl, r3, lsl ip
+ mov r3, r3, lsr r2
+ mov r3, r3, lsl #1
b 1b
-6: rsb r2, r2, #(12 + 20)
- rsb ip, r2, #32
- mov r3, xl, lsl r2
- mov xl, xl, lsr ip
- orr xl, xl, xh, lsl r2
- and xh, xh, #0x80000000
- b 5b
+3: @ chech for NAN
+ mvns r3, r2, asr #21
+ bne 5f @ simple overflow
+ orrs r3, xl, xh, lsl #12
+ movne r0, #0x7f000000
+ orrne r0, r0, #0x00c00000
+ RETc(ne) @ return NAN
+
+5: @ return INF with sign
+ and r0, xh, #0x80000000
+ orr r0, r0, #0x7f000000
+ orr r0, r0, #0x00800000
+ RET
+ FUNC_END aeabi_d2f
FUNC_END truncdfsf2
#endif /* L_truncdfsf2 */
diff --git a/contrib/gcc/config/arm/ieee754-sf.S b/contrib/gcc/config/arm/ieee754-sf.S
index 5c97245..f74f458 100644
--- a/contrib/gcc/config/arm/ieee754-sf.S
+++ b/contrib/gcc/config/arm/ieee754-sf.S
@@ -1,6 +1,6 @@
/* ieee754-sf.S single-precision floating point support for ARM
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Nicolas Pitre (nico@cam.org)
This file is free software; you can redistribute it and/or modify it
@@ -24,8 +24,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/*
* Notes:
@@ -41,48 +41,46 @@
#ifdef L_negsf2
ARM_FUNC_START negsf2
+ARM_FUNC_ALIAS aeabi_fneg negsf2
+
eor r0, r0, #0x80000000 @ flip sign bit
RET
+ FUNC_END aeabi_fneg
FUNC_END negsf2
#endif
#ifdef L_addsubsf3
+ARM_FUNC_START aeabi_frsub
+
+ eor r0, r0, #0x80000000 @ flip sign bit of first arg
+ b 1f
+
ARM_FUNC_START subsf3
+ARM_FUNC_ALIAS aeabi_fsub subsf3
+
eor r1, r1, #0x80000000 @ flip sign bit of second arg
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+#if defined(__INTERWORKING_STUBS__)
b 1f @ Skip Thumb-code prologue
#endif
ARM_FUNC_START addsf3
+ARM_FUNC_ALIAS aeabi_fadd addsf3
-1: @ Compare both args, return zero if equal but the sign.
- eor r2, r0, r1
- teq r2, #0x80000000
- beq LSYM(Lad_z)
-
- @ If first arg is 0 or -0, return second arg.
- @ If second arg is 0 or -0, return first arg.
- bics r2, r0, #0x80000000
- moveq r0, r1
- bicnes r2, r1, #0x80000000
- RETc(eq)
-
- @ Mask out exponents.
- mov ip, #0xff000000
- and r2, r0, ip, lsr #1
- and r3, r1, ip, lsr #1
-
- @ If either of them is 255, result will be INF or NAN
- teq r2, ip, lsr #1
- teqne r3, ip, lsr #1
- beq LSYM(Lad_i)
+1: @ Look for zeroes, equal values, INF, or NAN.
+ movs r2, r0, lsl #1
+ movnes r3, r1, lsl #1
+ teqne r2, r3
+ mvnnes ip, r2, asr #24
+ mvnnes ip, r3, asr #24
+ beq LSYM(Lad_s)
@ Compute exponent difference. Make largest exponent in r2,
@ corresponding arg in r0, and positive exponent difference in r3.
- subs r3, r3, r2
+ mov r2, r2, lsr #24
+ rsbs r3, r2, r3, lsr #24
addgt r2, r2, r3
eorgt r1, r0, r1
eorgt r0, r1, r0
@@ -92,7 +90,7 @@ ARM_FUNC_START addsf3
@ If exponent difference is too large, return largest argument
@ already in r0. We need up to 25 bit to handle proper rounding
@ of 0x1p25 - 1.1.
- cmp r3, #(25 << 23)
+ cmp r3, #25
RETc(hi)
@ Convert mantissa to signed integer.
@@ -111,25 +109,17 @@ ARM_FUNC_START addsf3
beq LSYM(Lad_d)
LSYM(Lad_x):
- @ Scale down second arg with exponent difference.
- @ Apply shift one bit left to first arg and the rest to second arg
- @ to simplify things later, but only if exponent does not become 0.
- movs r3, r3, lsr #23
- teqne r2, #(1 << 23)
- movne r0, r0, lsl #1
- subne r2, r2, #(1 << 23)
- subne r3, r3, #1
+ @ Compensate for the exponent overlapping the mantissa MSB added later
+ sub r2, r2, #1
- @ Shift second arg into ip, keep leftover bits into r1.
- mov ip, r1, asr r3
+ @ Shift and add second arg to first arg in r0.
+ @ Keep leftover bits into r1.
+ adds r0, r0, r1, asr r3
rsb r3, r3, #32
mov r1, r1, lsl r3
- add r0, r0, ip @ the actual addition
-
- @ We now have a 64 bit result in r0-r1.
- @ Keep absolute value in r0-r1, sign in r3.
- ands r3, r0, #0x80000000
+ @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above)
+ and r3, r0, #0x80000000
bpl LSYM(Lad_p)
rsbs r1, r1, #0
rsc r0, r0, #0
@@ -137,103 +127,117 @@ LSYM(Lad_x):
@ Determine how to normalize the result.
LSYM(Lad_p):
cmp r0, #0x00800000
- bcc LSYM(Lad_l)
+ bcc LSYM(Lad_a)
cmp r0, #0x01000000
- bcc LSYM(Lad_r0)
- cmp r0, #0x02000000
- bcc LSYM(Lad_r1)
+ bcc LSYM(Lad_e)
@ Result needs to be shifted right.
movs r0, r0, lsr #1
mov r1, r1, rrx
- add r2, r2, #(1 << 23)
-LSYM(Lad_r1):
- movs r0, r0, lsr #1
- mov r1, r1, rrx
- add r2, r2, #(1 << 23)
-
- @ Our result is now properly aligned into r0, remaining bits in r1.
- @ Round with MSB of r1. If halfway between two numbers, round towards
- @ LSB of r0 = 0.
-LSYM(Lad_r0):
- add r0, r0, r1, lsr #31
- teq r1, #0x80000000
- biceq r0, r0, #1
-
- @ Rounding may have added a new MSB. Adjust exponent.
- @ That MSB will be cleared when exponent is merged below.
- tst r0, #0x01000000
- addne r2, r2, #(1 << 23)
+ add r2, r2, #1
@ Make sure we did not bust our exponent.
- cmp r2, #(254 << 23)
- bhi LSYM(Lad_o)
+ cmp r2, #254
+ bhs LSYM(Lad_o)
+ @ Our result is now properly aligned into r0, remaining bits in r1.
@ Pack final result together.
+ @ Round with MSB of r1. If halfway between two numbers, round towards
+ @ LSB of r0 = 0.
LSYM(Lad_e):
- bic r0, r0, #0x01800000
- orr r0, r0, r2
+ cmp r1, #0x80000000
+ adc r0, r0, r2, lsl #23
+ biceq r0, r0, #1
orr r0, r0, r3
RET
- @ Result must be shifted left.
- @ No rounding necessary since r1 will always be 0.
+ @ Result must be shifted left and exponent adjusted.
+LSYM(Lad_a):
+ movs r1, r1, lsl #1
+ adc r0, r0, r0
+ tst r0, #0x00800000
+ sub r2, r2, #1
+ bne LSYM(Lad_e)
+
+ @ No rounding necessary since r1 will always be 0 at this point.
LSYM(Lad_l):
#if __ARM_ARCH__ < 5
movs ip, r0, lsr #12
moveq r0, r0, lsl #12
- subeq r2, r2, #(12 << 23)
+ subeq r2, r2, #12
tst r0, #0x00ff0000
moveq r0, r0, lsl #8
- subeq r2, r2, #(8 << 23)
+ subeq r2, r2, #8
tst r0, #0x00f00000
moveq r0, r0, lsl #4
- subeq r2, r2, #(4 << 23)
+ subeq r2, r2, #4
tst r0, #0x00c00000
moveq r0, r0, lsl #2
- subeq r2, r2, #(2 << 23)
- tst r0, #0x00800000
- moveq r0, r0, lsl #1
- subeq r2, r2, #(1 << 23)
- cmp r2, #0
- bgt LSYM(Lad_e)
+ subeq r2, r2, #2
+ cmp r0, #0x00800000
+ movcc r0, r0, lsl #1
+ sbcs r2, r2, #0
#else
clz ip, r0
sub ip, ip, #8
+ subs r2, r2, ip
mov r0, r0, lsl ip
- subs r2, r2, ip, lsl #23
- bgt LSYM(Lad_e)
#endif
- @ Exponent too small, denormalize result.
- mvn r2, r2, asr #23
- add r2, r2, #2
- orr r0, r3, r0, lsr r2
+ @ Final result with sign
+ @ If exponent negative, denormalize result.
+ addge r0, r0, r2, lsl #23
+ rsblt r2, r2, #0
+ orrge r0, r0, r3
+ orrlt r0, r3, r0, lsr r2
RET
@ Fixup and adjust bit position for denormalized arguments.
@ Note that r2 must not remain equal to 0.
LSYM(Lad_d):
teq r2, #0
- eoreq r0, r0, #0x00800000
- addeq r2, r2, #(1 << 23)
eor r1, r1, #0x00800000
- subne r3, r3, #(1 << 23)
+ eoreq r0, r0, #0x00800000
+ addeq r2, r2, #1
+ subne r3, r3, #1
b LSYM(Lad_x)
- @ Result is x - x = 0, unless x is INF or NAN.
-LSYM(Lad_z):
- mov ip, #0xff000000
- and r2, r0, ip, lsr #1
- teq r2, ip, lsr #1
- moveq r0, ip, asr #2
+LSYM(Lad_s):
+ mov r3, r1, lsl #1
+
+ mvns ip, r2, asr #24
+ mvnnes ip, r3, asr #24
+ beq LSYM(Lad_i)
+
+ teq r2, r3
+ beq 1f
+
+ @ Result is x + 0.0 = x or 0.0 + y = y.
+ teq r2, #0
+ moveq r0, r1
+ RET
+
+1: teq r0, r1
+
+ @ Result is x - x = 0.
movne r0, #0
+ RETc(ne)
+
+ @ Result is x + x = 2x.
+ tst r2, #0xff000000
+ bne 2f
+ movs r0, r0, lsl #1
+ orrcs r0, r0, #0x80000000
RET
+2: adds r2, r2, #(2 << 24)
+ addcc r0, r0, #(1 << 23)
+ RETc(cc)
+ and r3, r0, #0x80000000
@ Overflow: return INF.
LSYM(Lad_o):
@@ -246,191 +250,271 @@ LSYM(Lad_o):
@ if r1 != INF/NAN: return r0 (which is INF/NAN)
@ if r0 or r1 is NAN: return NAN
@ if opposite sign: return NAN
- @ return r0 (which is INF or -INF)
+ @ otherwise return r0 (which is INF or -INF)
LSYM(Lad_i):
- teq r2, ip, lsr #1
+ mvns r2, r2, asr #24
movne r0, r1
- teqeq r3, ip, lsr #1
- RETc(ne)
+ mvneqs r3, r3, asr #24
+ movne r1, r0
movs r2, r0, lsl #9
- moveqs r2, r1, lsl #9
+ moveqs r3, r1, lsl #9
teqeq r0, r1
- orrne r0, r3, #0x00400000 @ NAN
+ orrne r0, r0, #0x00400000 @ quiet NAN
RET
+ FUNC_END aeabi_frsub
+ FUNC_END aeabi_fadd
FUNC_END addsf3
+ FUNC_END aeabi_fsub
FUNC_END subsf3
ARM_FUNC_START floatunsisf
+ARM_FUNC_ALIAS aeabi_ui2f floatunsisf
+
mov r3, #0
b 1f
ARM_FUNC_START floatsisf
+ARM_FUNC_ALIAS aeabi_i2f floatsisf
+
ands r3, r0, #0x80000000
rsbmi r0, r0, #0
-1: teq r0, #0
+1: movs ip, r0
RETc(eq)
- mov r1, #0
- mov r2, #((127 + 23) << 23)
- tst r0, #0xfc000000
- beq LSYM(Lad_p)
-
- @ We need to scale the value a little before branching to code above.
- tst r0, #0xf0000000
- movne r1, r0, lsl #28
- movne r0, r0, lsr #4
- addne r2, r2, #(4 << 23)
- tst r0, #0x0c000000
- beq LSYM(Lad_p)
- mov r1, r1, lsr #2
- orr r1, r1, r0, lsl #30
- mov r0, r0, lsr #2
- add r2, r2, #(2 << 23)
- b LSYM(Lad_p)
+ @ Add initial exponent to sign
+ orr r3, r3, #((127 + 23) << 23)
+ .ifnc ah, r0
+ mov ah, r0
+ .endif
+ mov al, #0
+ b 2f
+
+ FUNC_END aeabi_i2f
FUNC_END floatsisf
+ FUNC_END aeabi_ui2f
FUNC_END floatunsisf
+ARM_FUNC_START floatundisf
+ARM_FUNC_ALIAS aeabi_ul2f floatundisf
+
+ orrs r2, r0, r1
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ mvfeqs f0, #0.0
+#endif
+ RETc(eq)
+
+ mov r3, #0
+ b 1f
+
+ARM_FUNC_START floatdisf
+ARM_FUNC_ALIAS aeabi_l2f floatdisf
+
+ orrs r2, r0, r1
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ mvfeqs f0, #0.0
+#endif
+ RETc(eq)
+
+ ands r3, ah, #0x80000000 @ sign bit in r3
+ bpl 1f
+ rsbs al, al, #0
+ rsc ah, ah, #0
+1:
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+ @ For hard FPA code we want to return via the tail below so that
+ @ we can return the result in f0 as well as in r0 for backwards
+ @ compatibility.
+ str lr, [sp, #-8]!
+ adr lr, LSYM(f0_ret)
+#endif
+
+ movs ip, ah
+ moveq ip, al
+ moveq ah, al
+ moveq al, #0
+
+ @ Add initial exponent to sign
+ orr r3, r3, #((127 + 23 + 32) << 23)
+ subeq r3, r3, #(32 << 23)
+2: sub r3, r3, #(1 << 23)
+
+#if __ARM_ARCH__ < 5
+
+ mov r2, #23
+ cmp ip, #(1 << 16)
+ movhs ip, ip, lsr #16
+ subhs r2, r2, #16
+ cmp ip, #(1 << 8)
+ movhs ip, ip, lsr #8
+ subhs r2, r2, #8
+ cmp ip, #(1 << 4)
+ movhs ip, ip, lsr #4
+ subhs r2, r2, #4
+ cmp ip, #(1 << 2)
+ subhs r2, r2, #2
+ sublo r2, r2, ip, lsr #1
+ subs r2, r2, ip, lsr #3
+
+#else
+
+ clz r2, ip
+ subs r2, r2, #8
+
+#endif
+
+ sub r3, r3, r2, lsl #23
+ blt 3f
+
+ add r3, r3, ah, lsl r2
+ mov ip, al, lsl r2
+ rsb r2, r2, #32
+ cmp ip, #0x80000000
+ adc r0, r3, al, lsr r2
+ biceq r0, r0, #1
+ RET
+
+3: add r2, r2, #32
+ mov ip, ah, lsl r2
+ rsb r2, r2, #32
+ orrs al, al, ip, lsl #1
+ adc r0, r3, ah, lsr r2
+ biceq r0, r0, ip, lsr #31
+ RET
+
+#if !defined (__VFP_FP__) && !defined(__SOFTFP__)
+
+LSYM(f0_ret):
+ str r0, [sp, #-4]!
+ ldfs f0, [sp], #4
+ RETLDM
+
+#endif
+
+ FUNC_END floatdisf
+ FUNC_END aeabi_l2f
+ FUNC_END floatundisf
+ FUNC_END aeabi_ul2f
+
#endif /* L_addsubsf3 */
#ifdef L_muldivsf3
ARM_FUNC_START mulsf3
-
- @ Mask out exponents.
- mov ip, #0xff000000
- and r2, r0, ip, lsr #1
- and r3, r1, ip, lsr #1
-
- @ Trap any INF/NAN.
- teq r2, ip, lsr #1
- teqne r3, ip, lsr #1
+ARM_FUNC_ALIAS aeabi_fmul mulsf3
+
+ @ Mask out exponents, trap any zero/denormal/INF/NAN.
+ mov ip, #0xff
+ ands r2, ip, r0, lsr #23
+ andnes r3, ip, r1, lsr #23
+ teqne r2, ip
+ teqne r3, ip
beq LSYM(Lml_s)
-
- @ Trap any multiplication by 0.
- bics ip, r0, #0x80000000
- bicnes ip, r1, #0x80000000
- beq LSYM(Lml_z)
-
- @ Shift exponents right one bit to make room for overflow bit.
- @ If either of them is 0, scale denormalized arguments off line.
- @ Then add both exponents together.
- movs r2, r2, lsr #1
- teqne r3, #0
- beq LSYM(Lml_d)
LSYM(Lml_x):
- add r2, r2, r3, asr #1
- @ Preserve final sign in r2 along with exponent for now.
- teq r0, r1
- orrmi r2, r2, #0x8000
+ @ Add exponents together
+ add r2, r2, r3
+
+ @ Determine final sign.
+ eor ip, r0, r1
@ Convert mantissa to unsigned integer.
- bic r0, r0, #0xff000000
- bic r1, r1, #0xff000000
- orr r0, r0, #0x00800000
- orr r1, r1, #0x00800000
+ @ If power of two, branch to a separate path.
+ @ Make up for final alignment.
+ movs r0, r0, lsl #9
+ movnes r1, r1, lsl #9
+ beq LSYM(Lml_1)
+ mov r3, #0x08000000
+ orr r0, r3, r0, lsr #5
+ orr r1, r3, r1, lsr #5
#if __ARM_ARCH__ < 4
+ @ Put sign bit in r3, which will be restored into r0 later.
+ and r3, ip, #0x80000000
+
@ Well, no way to make it shorter without the umull instruction.
- @ We must perform that 24 x 24 -> 48 bit multiplication by hand.
- stmfd sp!, {r4, r5}
+ stmfd sp!, {r3, r4, r5}
mov r4, r0, lsr #16
mov r5, r1, lsr #16
- bic r0, r0, #0x00ff0000
- bic r1, r1, #0x00ff0000
+ bic r0, r0, r4, lsl #16
+ bic r1, r1, r5, lsl #16
mul ip, r4, r5
mul r3, r0, r1
mul r0, r5, r0
mla r0, r4, r1, r0
adds r3, r3, r0, lsl #16
- adc ip, ip, r0, lsr #16
- ldmfd sp!, {r4, r5}
+ adc r1, ip, r0, lsr #16
+ ldmfd sp!, {r0, r4, r5}
#else
- umull r3, ip, r0, r1 @ The actual multiplication.
+ @ The actual multiplication.
+ umull r3, r1, r0, r1
+
+ @ Put final sign in r0.
+ and r0, ip, #0x80000000
#endif
- @ Put final sign in r0.
- mov r0, r2, lsl #16
- bic r2, r2, #0x8000
-
- @ Adjust result if one extra MSB appeared.
- @ The LSB may be lost but this never changes the result in this case.
- tst ip, #(1 << 15)
- addne r2, r2, #(1 << 22)
- movnes ip, ip, lsr #1
- movne r3, r3, rrx
-
- @ Apply exponent bias, check range for underflow.
- subs r2, r2, #(127 << 22)
- ble LSYM(Lml_u)
-
- @ Scale back to 24 bits with rounding.
- @ r0 contains sign bit already.
- orrs r0, r0, r3, lsr #23
- adc r0, r0, ip, lsl #9
-
- @ If halfway between two numbers, rounding should be towards LSB = 0.
- mov r3, r3, lsl #9
- teq r3, #0x80000000
- biceq r0, r0, #1
+ @ Adjust result upon the MSB position.
+ cmp r1, #(1 << 23)
+ movcc r1, r1, lsl #1
+ orrcc r1, r1, r3, lsr #31
+ movcc r3, r3, lsl #1
- @ Note: rounding may have produced an extra MSB here.
- @ The extra bit is cleared before merging the exponent below.
- tst r0, #0x01000000
- addne r2, r2, #(1 << 22)
+ @ Add sign to result.
+ orr r0, r0, r1
- @ Check for exponent overflow
- cmp r2, #(255 << 22)
- bge LSYM(Lml_o)
+ @ Apply exponent bias, check for under/overflow.
+ sbc r2, r2, #127
+ cmp r2, #(254 - 1)
+ bhi LSYM(Lml_u)
- @ Add final exponent.
- bic r0, r0, #0x01800000
- orr r0, r0, r2, lsl #1
+ @ Round the result, merge final exponent.
+ cmp r3, #0x80000000
+ adc r0, r0, r2, lsl #23
+ biceq r0, r0, #1
RET
- @ Result is 0, but determine sign anyway.
-LSYM(Lml_z):
- eor r0, r0, r1
- bic r0, r0, #0x7fffffff
- RET
+ @ Multiplication by 0x1p*: let''s shortcut a lot of code.
+LSYM(Lml_1):
+ teq r0, #0
+ and ip, ip, #0x80000000
+ moveq r1, r1, lsl #9
+ orr r0, ip, r0, lsr #9
+ orr r0, r0, r1, lsr #9
+ subs r2, r2, #127
+ rsbgts r3, r2, #255
+ orrgt r0, r0, r2, lsl #23
+ RETc(gt)
+
+ @ Under/overflow: fix things up for the code below.
+ orr r0, r0, #0x00800000
+ mov r3, #0
+ subs r2, r2, #1
- @ Check if denormalized result is possible, otherwise return signed 0.
LSYM(Lml_u):
- cmn r2, #(24 << 22)
- RETc(le)
+ @ Overflow?
+ bgt LSYM(Lml_o)
- @ Find out proper shift value.
- mvn r1, r2, asr #22
- subs r1, r1, #7
- bgt LSYM(Lml_ur)
-
- @ Shift value left, round, etc.
- add r1, r1, #32
- orrs r0, r0, r3, lsr r1
- rsb r1, r1, #32
- adc r0, r0, ip, lsl r1
- mov ip, r3, lsl r1
- teq ip, #0x80000000
- biceq r0, r0, #1
- RET
+ @ Check if denormalized result is possible, otherwise return signed 0.
+ cmn r2, #(24 + 1)
+ bicle r0, r0, #0x7fffffff
+ RETc(le)
@ Shift value right, round, etc.
- @ Note: r1 must not be 0 otherwise carry does not get set.
-LSYM(Lml_ur):
- orrs r0, r0, ip, lsr r1
+ rsb r2, r2, #0
+ movs r1, r0, lsl #1
+ mov r1, r1, lsr r2
+ rsb r2, r2, #32
+ mov ip, r0, lsl r2
+ movs r0, r1, rrx
adc r0, r0, #0
- rsb r1, r1, #32
- mov ip, ip, lsl r1
- teq r3, #0
- teqeq ip, #0x80000000
- biceq r0, r0, #1
+ orrs r3, r3, ip, lsl #1
+ biceq r0, r0, ip, lsr #31
RET
@ One or both arguments are denormalized.
@@ -440,32 +524,51 @@ LSYM(Lml_d):
and ip, r0, #0x80000000
1: moveq r0, r0, lsl #1
tsteq r0, #0x00800000
- subeq r2, r2, #(1 << 22)
+ subeq r2, r2, #1
beq 1b
orr r0, r0, ip
teq r3, #0
and ip, r1, #0x80000000
2: moveq r1, r1, lsl #1
tsteq r1, #0x00800000
- subeq r3, r3, #(1 << 23)
+ subeq r3, r3, #1
beq 2b
orr r1, r1, ip
b LSYM(Lml_x)
- @ One or both args are INF or NAN.
LSYM(Lml_s):
+ @ Isolate the INF and NAN cases away
+ and r3, ip, r1, lsr #23
+ teq r2, ip
+ teqne r3, ip
+ beq 1f
+
+ @ Here, one or more arguments are either denormalized or zero.
+ bics ip, r0, #0x80000000
+ bicnes ip, r1, #0x80000000
+ bne LSYM(Lml_d)
+
+ @ Result is 0, but determine sign anyway.
+LSYM(Lml_z):
+ eor r0, r0, r1
+ bic r0, r0, #0x7fffffff
+ RET
+
+1: @ One or both args are INF or NAN.
teq r0, #0x0
- teqne r1, #0x0
teqne r0, #0x80000000
+ moveq r0, r1
+ teqne r1, #0x0
teqne r1, #0x80000000
beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN
- teq r2, ip, lsr #1
+ teq r2, ip
bne 1f
movs r2, r0, lsl #9
bne LSYM(Lml_n) @ NAN * <anything> -> NAN
-1: teq r3, ip, lsr #1
+1: teq r3, ip
bne LSYM(Lml_i)
movs r3, r1, lsl #9
+ movne r0, r1
bne LSYM(Lml_n) @ <anything> * NAN -> NAN
@ Result is INF, but we need to determine its sign.
@@ -479,46 +582,39 @@ LSYM(Lml_o):
orr r0, r0, #0x00800000
RET
- @ Return NAN.
+ @ Return a quiet NAN.
LSYM(Lml_n):
- mov r0, #0x7f000000
+ orr r0, r0, #0x7f000000
orr r0, r0, #0x00c00000
RET
+ FUNC_END aeabi_fmul
FUNC_END mulsf3
ARM_FUNC_START divsf3
-
- @ Mask out exponents.
- mov ip, #0xff000000
- and r2, r0, ip, lsr #1
- and r3, r1, ip, lsr #1
-
- @ Trap any INF/NAN or zeroes.
- teq r2, ip, lsr #1
- teqne r3, ip, lsr #1
- bicnes ip, r0, #0x80000000
- bicnes ip, r1, #0x80000000
+ARM_FUNC_ALIAS aeabi_fdiv divsf3
+
+ @ Mask out exponents, trap any zero/denormal/INF/NAN.
+ mov ip, #0xff
+ ands r2, ip, r0, lsr #23
+ andnes r3, ip, r1, lsr #23
+ teqne r2, ip
+ teqne r3, ip
beq LSYM(Ldv_s)
-
- @ Shift exponents right one bit to make room for overflow bit.
- @ If either of them is 0, scale denormalized arguments off line.
- @ Then substract divisor exponent from dividend''s.
- movs r2, r2, lsr #1
- teqne r3, #0
- beq LSYM(Ldv_d)
LSYM(Ldv_x):
- sub r2, r2, r3, asr #1
+
+ @ Substract divisor exponent from dividend''s
+ sub r2, r2, r3
@ Preserve final sign into ip.
eor ip, r0, r1
@ Convert mantissa to unsigned integer.
@ Dividend -> r3, divisor -> r1.
- mov r3, #0x10000000
movs r1, r1, lsl #9
mov r0, r0, lsl #9
beq LSYM(Ldv_1)
+ mov r3, #0x10000000
orr r1, r3, r1, lsr #4
orr r3, r3, r0, lsr #4
@@ -526,16 +622,10 @@ LSYM(Ldv_x):
and r0, ip, #0x80000000
@ Ensure result will land to known bit position.
+ @ Apply exponent bias accordingly.
cmp r3, r1
- subcc r2, r2, #(1 << 22)
movcc r3, r3, lsl #1
-
- @ Apply exponent bias, check range for over/underflow.
- add r2, r2, #(127 << 22)
- cmn r2, #(24 << 22)
- RETc(le)
- cmp r2, #(255 << 22)
- bge LSYM(Lml_o)
+ adc r2, r2, #(127 - 2)
@ The actual division loop.
mov ip, #0x00800000
@@ -555,44 +645,29 @@ LSYM(Ldv_x):
movnes ip, ip, lsr #4
bne 1b
- @ Check if denormalized result is needed.
- cmp r2, #0
- ble LSYM(Ldv_u)
+ @ Check exponent for under/overflow.
+ cmp r2, #(254 - 1)
+ bhi LSYM(Lml_u)
- @ Apply proper rounding.
+ @ Round the result, merge final exponent.
cmp r3, r1
- addcs r0, r0, #1
+ adc r0, r0, r2, lsl #23
biceq r0, r0, #1
-
- @ Add exponent to result.
- bic r0, r0, #0x00800000
- orr r0, r0, r2, lsl #1
RET
@ Division by 0x1p*: let''s shortcut a lot of code.
LSYM(Ldv_1):
and ip, ip, #0x80000000
orr r0, ip, r0, lsr #9
- add r2, r2, #(127 << 22)
- cmp r2, #(255 << 22)
- bge LSYM(Lml_o)
- cmp r2, #0
- orrgt r0, r0, r2, lsl #1
+ adds r2, r2, #127
+ rsbgts r3, r2, #255
+ orrgt r0, r0, r2, lsl #23
RETc(gt)
- cmn r2, #(24 << 22)
- movle r0, ip
- RETc(le)
+
orr r0, r0, #0x00800000
mov r3, #0
-
- @ Result must be denormalized: prepare parameters to use code above.
- @ r3 already contains remainder for rounding considerations.
-LSYM(Ldv_u):
- bic ip, r0, #0x80000000
- and r0, r0, #0x80000000
- mvn r1, r2, asr #22
- add r1, r1, #2
- b LSYM(Lml_ur)
+ subs r2, r2, #1
+ b LSYM(Lml_u)
@ One or both arguments are denormalized.
@ Scale them leftwards and preserve sign bit.
@@ -601,108 +676,114 @@ LSYM(Ldv_d):
and ip, r0, #0x80000000
1: moveq r0, r0, lsl #1
tsteq r0, #0x00800000
- subeq r2, r2, #(1 << 22)
+ subeq r2, r2, #1
beq 1b
orr r0, r0, ip
teq r3, #0
and ip, r1, #0x80000000
2: moveq r1, r1, lsl #1
tsteq r1, #0x00800000
- subeq r3, r3, #(1 << 23)
+ subeq r3, r3, #1
beq 2b
orr r1, r1, ip
b LSYM(Ldv_x)
- @ One or both arguments is either INF, NAN or zero.
+ @ One or both arguments are either INF, NAN, zero or denormalized.
LSYM(Ldv_s):
- mov ip, #0xff000000
- teq r2, ip, lsr #1
- teqeq r3, ip, lsr #1
- beq LSYM(Lml_n) @ INF/NAN / INF/NAN -> NAN
- teq r2, ip, lsr #1
+ and r3, ip, r1, lsr #23
+ teq r2, ip
bne 1f
movs r2, r0, lsl #9
bne LSYM(Lml_n) @ NAN / <anything> -> NAN
- b LSYM(Lml_i) @ INF / <anything> -> INF
-1: teq r3, ip, lsr #1
+ teq r3, ip
+ bne LSYM(Lml_i) @ INF / <anything> -> INF
+ mov r0, r1
+ b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN
+1: teq r3, ip
bne 2f
movs r3, r1, lsl #9
- bne LSYM(Lml_n) @ <anything> / NAN -> NAN
- b LSYM(Lml_z) @ <anything> / INF -> 0
-2: @ One or both arguments are 0.
+ beq LSYM(Lml_z) @ <anything> / INF -> 0
+ mov r0, r1
+ b LSYM(Lml_n) @ <anything> / NAN -> NAN
+2: @ If both are nonzero, we need to normalize and resume above.
+ bics ip, r0, #0x80000000
+ bicnes ip, r1, #0x80000000
+ bne LSYM(Ldv_d)
+ @ One or both arguments are zero.
bics r2, r0, #0x80000000
bne LSYM(Lml_i) @ <non_zero> / 0 -> INF
bics r3, r1, #0x80000000
bne LSYM(Lml_z) @ 0 / <non_zero> -> 0
b LSYM(Lml_n) @ 0 / 0 -> NAN
+ FUNC_END aeabi_fdiv
FUNC_END divsf3
#endif /* L_muldivsf3 */
#ifdef L_cmpsf2
+ @ The return value in r0 is
+ @
+ @ 0 if the operands are equal
+ @ 1 if the first operand is greater than the second, or
+ @ the operands are unordered and the operation is
+ @ CMP, LT, LE, NE, or EQ.
+ @ -1 if the first operand is less than the second, or
+ @ the operands are unordered and the operation is GT
+ @ or GE.
+ @
+ @ The Z flag will be set iff the operands are equal.
+ @
+ @ The following registers are clobbered by this function:
+ @ ip, r0, r1, r2, r3
+
ARM_FUNC_START gtsf2
ARM_FUNC_ALIAS gesf2 gtsf2
- mov r3, #-1
+ mov ip, #-1
b 1f
ARM_FUNC_START ltsf2
ARM_FUNC_ALIAS lesf2 ltsf2
- mov r3, #1
+ mov ip, #1
b 1f
ARM_FUNC_START cmpsf2
ARM_FUNC_ALIAS nesf2 cmpsf2
ARM_FUNC_ALIAS eqsf2 cmpsf2
- mov r3, #1 @ how should we specify unordered here?
-
-1: @ Trap any INF/NAN first.
- mov ip, #0xff000000
- and r2, r1, ip, lsr #1
- teq r2, ip, lsr #1
- and r2, r0, ip, lsr #1
- teqne r2, ip, lsr #1
+ mov ip, #1 @ how should we specify unordered here?
+
+1: str ip, [sp, #-4]
+
+ @ Trap any INF/NAN first.
+ mov r2, r0, lsl #1
+ mov r3, r1, lsl #1
+ mvns ip, r2, asr #24
+ mvnnes ip, r3, asr #24
beq 3f
- @ Test for equality.
+ @ Compare values.
@ Note that 0.0 is equal to -0.0.
-2: orr r3, r0, r1
- bics r3, r3, #0x80000000 @ either 0.0 or -0.0
- teqne r0, r1 @ or both the same
- moveq r0, #0
- RETc(eq)
-
- @ Check for sign difference. The N flag is set if it is the case.
- @ If so, return sign of r0.
- movmi r0, r0, asr #31
- orrmi r0, r0, #1
- RETc(mi)
-
- @ Compare exponents.
- and r3, r1, ip, lsr #1
- cmp r2, r3
-
- @ Compare mantissa if exponents are equal
- moveq r0, r0, lsl #9
- cmpeq r0, r1, lsl #9
- movcs r0, r1, asr #31
- mvncc r0, r1, asr #31
- orr r0, r0, #1
+2: orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag
+ teqne r0, r1 @ if not 0 compare sign
+ subpls r0, r2, r3 @ if same sign compare values, set r0
+
+ @ Result:
+ movhi r0, r1, asr #31
+ mvnlo r0, r1, asr #31
+ orrne r0, r0, #1
RET
@ Look for a NAN.
-3: and r2, r1, ip, lsr #1
- teq r2, ip, lsr #1
+3: mvns ip, r2, asr #24
bne 4f
- movs r2, r1, lsl #9
- bne 5f @ r1 is NAN
-4: and r2, r0, ip, lsr #1
- teq r2, ip, lsr #1
- bne 2b
movs ip, r0, lsl #9
- beq 2b @ r0 is not NAN
-5: mov r0, r3 @ return unordered code from r3.
+ bne 5f @ r0 is NAN
+4: mvns ip, r3, asr #24
+ bne 2b
+ movs ip, r1, lsl #9
+ beq 2b @ r1 is not NAN
+5: ldr r0, [sp, #-4] @ return unordered code.
RET
FUNC_END gesf2
@@ -713,27 +794,105 @@ ARM_FUNC_ALIAS eqsf2 cmpsf2
FUNC_END eqsf2
FUNC_END cmpsf2
+ARM_FUNC_START aeabi_cfrcmple
+
+ mov ip, r0
+ mov r0, r1
+ mov r1, ip
+ b 6f
+
+ARM_FUNC_START aeabi_cfcmpeq
+ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq
+
+ @ The status-returning routines are required to preserve all
+ @ registers except ip, lr, and cpsr.
+6: stmfd sp!, {r0, r1, r2, r3, lr}
+ ARM_CALL cmpsf2
+ @ Set the Z flag correctly, and the C flag unconditionally.
+ cmp r0, #0
+ @ Clear the C flag if the return value was -1, indicating
+ @ that the first operand was smaller than the second.
+ cmnmi r0, #0
+ RETLDM "r0, r1, r2, r3"
+
+ FUNC_END aeabi_cfcmple
+ FUNC_END aeabi_cfcmpeq
+ FUNC_END aeabi_cfrcmple
+
+ARM_FUNC_START aeabi_fcmpeq
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cfcmple
+ moveq r0, #1 @ Equal to.
+ movne r0, #0 @ Less than, greater than, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_fcmpeq
+
+ARM_FUNC_START aeabi_fcmplt
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cfcmple
+ movcc r0, #1 @ Less than.
+ movcs r0, #0 @ Equal to, greater than, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_fcmplt
+
+ARM_FUNC_START aeabi_fcmple
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cfcmple
+ movls r0, #1 @ Less than or equal to.
+ movhi r0, #0 @ Greater than or unordered.
+ RETLDM
+
+ FUNC_END aeabi_fcmple
+
+ARM_FUNC_START aeabi_fcmpge
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cfrcmple
+ movls r0, #1 @ Operand 2 is less than or equal to operand 1.
+ movhi r0, #0 @ Operand 2 greater than operand 1, or unordered.
+ RETLDM
+
+ FUNC_END aeabi_fcmpge
+
+ARM_FUNC_START aeabi_fcmpgt
+
+ str lr, [sp, #-8]!
+ ARM_CALL aeabi_cfrcmple
+ movcc r0, #1 @ Operand 2 is less than operand 1.
+ movcs r0, #0 @ Operand 2 is greater than or equal to operand 1,
+ @ or they are unordered.
+ RETLDM
+
+ FUNC_END aeabi_fcmpgt
+
#endif /* L_cmpsf2 */
#ifdef L_unordsf2
ARM_FUNC_START unordsf2
- mov ip, #0xff000000
- and r2, r1, ip, lsr #1
- teq r2, ip, lsr #1
+ARM_FUNC_ALIAS aeabi_fcmpun unordsf2
+
+ mov r2, r0, lsl #1
+ mov r3, r1, lsl #1
+ mvns ip, r2, asr #24
bne 1f
- movs r2, r1, lsl #9
- bne 3f @ r1 is NAN
-1: and r2, r0, ip, lsr #1
- teq r2, ip, lsr #1
- bne 2f
- movs r2, r0, lsl #9
+ movs ip, r0, lsl #9
bne 3f @ r0 is NAN
+1: mvns ip, r3, asr #24
+ bne 2f
+ movs ip, r1, lsl #9
+ bne 3f @ r1 is NAN
2: mov r0, #0 @ arguments are ordered.
RET
3: mov r0, #1 @ arguments are unordered.
RET
+ FUNC_END aeabi_fcmpun
FUNC_END unordsf2
#endif /* L_unordsf2 */
@@ -741,39 +900,39 @@ ARM_FUNC_START unordsf2
#ifdef L_fixsfsi
ARM_FUNC_START fixsfsi
- movs r0, r0, lsl #1
- RETc(eq) @ value is 0.
-
- mov r1, r1, rrx @ preserve C flag (the actual sign)
+ARM_FUNC_ALIAS aeabi_f2iz fixsfsi
@ check exponent range.
- and r2, r0, #0xff000000
+ mov r2, r0, lsl #1
cmp r2, #(127 << 24)
- movcc r0, #0 @ value is too small
- RETc(cc)
- cmp r2, #((127 + 31) << 24)
- bcs 1f @ value is too large
-
- mov r0, r0, lsl #7
- orr r0, r0, #0x80000000
- mov r2, r2, lsr #24
- rsb r2, r2, #(127 + 31)
- tst r1, #0x80000000 @ the sign bit
- mov r0, r0, lsr r2
+ bcc 1f @ value is too small
+ mov r3, #(127 + 31)
+ subs r2, r3, r2, lsr #24
+ bls 2f @ value is too large
+
+ @ scale value
+ mov r3, r0, lsl #8
+ orr r3, r3, #0x80000000
+ tst r0, #0x80000000 @ the sign bit
+ mov r0, r3, lsr r2
rsbne r0, r0, #0
RET
-1: teq r2, #0xff000000
- bne 2f
- movs r0, r0, lsl #8
- bne 3f @ r0 is NAN.
-2: ands r0, r1, #0x80000000 @ the sign bit
+1: mov r0, #0
+ RET
+
+2: cmp r2, #(127 + 31 - 0xff)
+ bne 3f
+ movs r2, r0, lsl #9
+ bne 4f @ r0 is NAN.
+3: ands r0, r0, #0x80000000 @ the sign bit
moveq r0, #0x7fffffff @ the maximum signed positive si
RET
-3: mov r0, #0 @ What should we convert NAN to?
+4: mov r0, #0 @ What should we convert NAN to?
RET
+ FUNC_END aeabi_f2iz
FUNC_END fixsfsi
#endif /* L_fixsfsi */
@@ -781,36 +940,37 @@ ARM_FUNC_START fixsfsi
#ifdef L_fixunssfsi
ARM_FUNC_START fixunssfsi
- movs r0, r0, lsl #1
- movcss r0, #0 @ value is negative...
- RETc(eq) @ ... or 0.
-
+ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi
@ check exponent range.
- and r2, r0, #0xff000000
+ movs r2, r0, lsl #1
+ bcs 1f @ value is negative
cmp r2, #(127 << 24)
- movcc r0, #0 @ value is too small
- RETc(cc)
- cmp r2, #((127 + 32) << 24)
- bcs 1f @ value is too large
+ bcc 1f @ value is too small
+ mov r3, #(127 + 31)
+ subs r2, r3, r2, lsr #24
+ bmi 2f @ value is too large
+
+ @ scale the value
+ mov r3, r0, lsl #8
+ orr r3, r3, #0x80000000
+ mov r0, r3, lsr r2
+ RET
- mov r0, r0, lsl #7
- orr r0, r0, #0x80000000
- mov r2, r2, lsr #24
- rsb r2, r2, #(127 + 31)
- mov r0, r0, lsr r2
+1: mov r0, #0
RET
-1: teq r2, #0xff000000
- bne 2f
- movs r0, r0, lsl #8
- bne 3f @ r0 is NAN.
-2: mov r0, #0xffffffff @ maximum unsigned si
+2: cmp r2, #(127 + 31 - 0xff)
+ bne 3f
+ movs r2, r0, lsl #9
+ bne 4f @ r0 is NAN.
+3: mov r0, #0xffffffff @ maximum unsigned si
RET
-3: mov r0, #0 @ What should we convert NAN to?
+4: mov r0, #0 @ What should we convert NAN to?
RET
+ FUNC_END aeabi_f2uiz
FUNC_END fixunssfsi
#endif /* L_fixunssfsi */
diff --git a/contrib/gcc/config/arm/iwmmxt.md b/contrib/gcc/config/arm/iwmmxt.md
index f8070a8..380d4b9 100644
--- a/contrib/gcc/config/arm/iwmmxt.md
+++ b/contrib/gcc/config/arm/iwmmxt.md
@@ -1,5 +1,5 @@
;; Patterns for the Intel Wireless MMX technology architecture.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Red Hat.
;; This file is part of GCC.
@@ -16,8 +16,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
(define_insn "iwmmxt_iordi3"
[(set (match_operand:DI 0 "register_operand" "=y,?&r,?&r")
@@ -64,15 +64,19 @@
[(set_attr "predicable" "yes")])
(define_insn "*iwmmxt_arm_movdi"
- [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, o<>,y,y,yr,y,yrm")
- (match_operand:DI 1 "di_operand" "rIK,mi,r ,y,yr,y,yrm,y"))]
- "TARGET_REALLY_IWMMXT"
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r, m,y,y,yr,y,yrUy")
+ (match_operand:DI 1 "di_operand" "rIK,mi,r,y,yr,y,yrUy,y"))]
+ "TARGET_REALLY_IWMMXT
+ && ( register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
"*
{
switch (which_alternative)
{
default:
return output_move_double (operands);
+ case 0:
+ return \"#\";
case 3:
return \"wmov%?\\t%0,%1\";
case 4:
@@ -86,14 +90,14 @@
}
}"
[(set_attr "length" "8,8,8,4,4,4,4,4")
- (set_attr "type" "*,load,store2,*,*,*,*,*")
+ (set_attr "type" "*,load1,store2,*,*,*,*,*")
(set_attr "pool_range" "*,1020,*,*,*,*,*,*")
(set_attr "neg_pool_range" "*,1012,*,*,*,*,*,*")]
)
(define_insn "*iwmmxt_movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,m,z")
- (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,m,z,z"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r, m,z,r,?z,Uy,z")
+ (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,z,Uy,z,z"))]
"TARGET_REALLY_IWMMXT
&& ( register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode))"
@@ -110,7 +114,7 @@
case 7: return \"wstrw\\t%1, %0\";
default:return \"wstrw\\t%1, [sp, #-4]!\;wldrw\\t%0, [sp], #4\\t@move CG reg\";
}"
- [(set_attr "type" "*,*,load,store1,*,*,load,store1,*")
+ [(set_attr "type" "*,*,load1,store1,*,*,load1,store1,*")
(set_attr "length" "*,*,*, *,*,*, 16, *,8")
(set_attr "pool_range" "*,*,4096, *,*,*,1024, *,*")
(set_attr "neg_pool_range" "*,*,4084, *,*,*, *, 1012,*")
@@ -148,14 +152,14 @@
case 4: return \"tmcr%?\\t%0, %1\";
default: return \"tmrc%?\\t%0, %1\";
}"
- [(set_attr "type" "*,*,load,store1,*,*")
+ [(set_attr "type" "*,*,load1,store1,*,*")
(set_attr "pool_range" "*,*,4096, *,*,*")
(set_attr "neg_pool_range" "*,*,4084, *,*,*")]
)
(define_insn "movv8qi_internal"
[(set (match_operand:V8QI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V8QI 1 "general_operand" "y,y,m,y,r,i"))]
+ (match_operand:V8QI 1 "general_operand" "y,y,mi,y,r,mi"))]
"TARGET_REALLY_IWMMXT"
"*
switch (which_alternative)
@@ -169,13 +173,13 @@
}"
[(set_attr "predicable" "yes")
(set_attr "length" "4, 4, 4,4,4, 8")
- (set_attr "type" "*,store1,load,*,*,load")
+ (set_attr "type" "*,store1,load1,*,*,load1")
(set_attr "pool_range" "*, *, 256,*,*, 256")
(set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
(define_insn "movv4hi_internal"
[(set (match_operand:V4HI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V4HI 1 "general_operand" "y,y,m,y,r,i"))]
+ (match_operand:V4HI 1 "general_operand" "y,y,mi,y,r,mi"))]
"TARGET_REALLY_IWMMXT"
"*
switch (which_alternative)
@@ -189,13 +193,13 @@
}"
[(set_attr "predicable" "yes")
(set_attr "length" "4, 4, 4,4,4, 8")
- (set_attr "type" "*,store1,load,*,*,load")
+ (set_attr "type" "*,store1,load1,*,*,load1")
(set_attr "pool_range" "*, *, 256,*,*, 256")
(set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
(define_insn "movv2si_internal"
[(set (match_operand:V2SI 0 "nonimmediate_operand" "=y,m,y,?r,?y,?r")
- (match_operand:V2SI 1 "general_operand" "y,y,m,y,r,i"))]
+ (match_operand:V2SI 1 "general_operand" "y,y,mi,y,r,mi"))]
"TARGET_REALLY_IWMMXT"
"*
switch (which_alternative)
@@ -209,7 +213,7 @@
}"
[(set_attr "predicable" "yes")
(set_attr "length" "4, 4, 4,4,4, 24")
- (set_attr "type" "*,store1,load,*,*,load")
+ (set_attr "type" "*,store1,load1,*,*,load1")
(set_attr "pool_range" "*, *, 256,*,*, 256")
(set_attr "neg_pool_range" "*, *, 244,*,*, 244")])
@@ -220,12 +224,12 @@
;; deliberately omitted.
(define_insn "movv2si_internal_2"
[(set (match_operand:V2SI 0 "nonimmediate_operand" "=?r")
- (match_operand 1 "immediate_operand" "i"))]
+ (match_operand 1 "immediate_operand" "mi"))]
"TARGET_REALLY_IWMMXT"
"* return output_move_double (operands);"
[(set_attr "predicable" "yes")
(set_attr "length" "8")
- (set_attr "type" "load")
+ (set_attr "type" "load1")
(set_attr "pool_range" "256")
(set_attr "neg_pool_range" "244")])
@@ -1149,7 +1153,7 @@
"wsrawg%?\\t%0, %1, %2"
[(set_attr "predicable" "yes")])
-(define_insn "ashrdi3"
+(define_insn "ashrdi3_iwmmxt"
[(set (match_operand:DI 0 "register_operand" "=y")
(ashiftrt:DI (match_operand:DI 1 "register_operand" "y")
(match_operand:SI 2 "register_operand" "z")))]
@@ -1173,7 +1177,7 @@
"wsrlwg%?\\t%0, %1, %2"
[(set_attr "predicable" "yes")])
-(define_insn "lshrdi3"
+(define_insn "lshrdi3_iwmmxt"
[(set (match_operand:DI 0 "register_operand" "=y")
(lshiftrt:DI (match_operand:DI 1 "register_operand" "y")
(match_operand:SI 2 "register_operand" "z")))]
diff --git a/contrib/gcc/config/arm/kaos-arm.h b/contrib/gcc/config/arm/kaos-arm.h
index 0d3bf2d..b575489 100644
--- a/contrib/gcc/config/arm/kaos-arm.h
+++ b/contrib/gcc/config/arm/kaos-arm.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM/kaOS[ELF])", stderr);
diff --git a/contrib/gcc/config/arm/kaos-strongarm.h b/contrib/gcc/config/arm/kaos-strongarm.h
index 8eb9473..7be2151 100644
--- a/contrib/gcc/config/arm/kaos-strongarm.h
+++ b/contrib/gcc/config/arm/kaos-strongarm.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (StrongARM/kaOS[ELF])", stderr);
diff --git a/contrib/gcc/config/arm/lib1funcs.asm b/contrib/gcc/config/arm/lib1funcs.asm
index e72af6c..9245b3c 100644
--- a/contrib/gcc/config/arm/lib1funcs.asm
+++ b/contrib/gcc/config/arm/lib1funcs.asm
@@ -1,7 +1,7 @@
@ libgcc routines for ARM cpu.
@ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
-/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004
+/* Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
@@ -25,8 +25,8 @@ General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* ------------------------------------------------------------------------ */
/* We need to know what prefix to add to function names. */
@@ -60,7 +60,7 @@ Boston, MA 02111-1307, USA. */
#define LSYM(x) x
#endif
-/* Function end macros. Variants for 26 bit APCS and interworking. */
+/* Function end macros. Variants for interworking. */
@ This selects the minimum architecture level required.
#define __ARM_ARCH__ 3
@@ -74,27 +74,44 @@ Boston, MA 02111-1307, USA. */
#endif
#if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
- || defined(__ARM_ARCH_5TE__)
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
+ || defined(__ARM_ARCH_5TEJ__)
# undef __ARM_ARCH__
# define __ARM_ARCH__ 5
#endif
-/* How to return from a function call depends on the architecture variant. */
+#if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
+ || defined(__ARM_ARCH_6ZK__)
+# undef __ARM_ARCH__
+# define __ARM_ARCH__ 6
+#endif
-#ifdef __APCS_26__
+#ifndef __ARM_ARCH__
+#error Unable to determine architecture.
+#endif
-# define RET movs pc, lr
-# define RETc(x) mov##x##s pc, lr
+/* How to return from a function call depends on the architecture variant. */
-#elif (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
+#if (__ARM_ARCH__ > 4) || defined(__ARM_ARCH_4T__)
# define RET bx lr
# define RETc(x) bx##x lr
-# if (__ARM_ARCH__ == 4) \
- && (defined(__thumb__) || defined(__THUMB_INTERWORK__))
-# define __INTERWORKING__
-# endif
+/* Special precautions for interworking on armv4t. */
+# if (__ARM_ARCH__ == 4)
+
+/* Always use bx, not ldr pc. */
+# if (defined(__thumb__) || defined(__THUMB_INTERWORK__))
+# define __INTERWORKING__
+# endif /* __THUMB__ || __THUMB_INTERWORK__ */
+
+/* Include thumb stub before arm mode code. */
+# if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+# define __INTERWORKING_STUBS__
+# endif /* __thumb__ && !__THUMB_INTERWORK__ */
+
+#endif /* __ARM_ARCH == 4 */
#else
@@ -103,25 +120,82 @@ Boston, MA 02111-1307, USA. */
#endif
+.macro cfi_pop advance, reg, cfa_offset
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .4byte \advance
+ .byte (0xc0 | \reg) /* DW_CFA_restore */
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .uleb128 \cfa_offset
+ .popsection
+#endif
+.endm
+.macro cfi_push advance, reg, offset, cfa_offset
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .byte 0x4 /* DW_CFA_advance_loc4 */
+ .4byte \advance
+ .byte (0x80 | \reg) /* DW_CFA_offset */
+ .uleb128 (\offset / -4)
+ .byte 0xe /* DW_CFA_def_cfa_offset */
+ .uleb128 \cfa_offset
+ .popsection
+#endif
+.endm
+.macro cfi_start start_label, end_label
+#ifdef __ELF__
+ .pushsection .debug_frame
+LSYM(Lstart_frame):
+ .4byte LSYM(Lend_cie) - LSYM(Lstart_cie) @ Length of CIE
+LSYM(Lstart_cie):
+ .4byte 0xffffffff @ CIE Identifier Tag
+ .byte 0x1 @ CIE Version
+ .ascii "\0" @ CIE Augmentation
+ .uleb128 0x1 @ CIE Code Alignment Factor
+ .sleb128 -4 @ CIE Data Alignment Factor
+ .byte 0xe @ CIE RA Column
+ .byte 0xc @ DW_CFA_def_cfa
+ .uleb128 0xd
+ .uleb128 0x0
+
+ .align 2
+LSYM(Lend_cie):
+ .4byte LSYM(Lend_fde)-LSYM(Lstart_fde) @ FDE Length
+LSYM(Lstart_fde):
+ .4byte LSYM(Lstart_frame) @ FDE CIE offset
+ .4byte \start_label @ FDE initial location
+ .4byte \end_label-\start_label @ FDE address range
+ .popsection
+#endif
+.endm
+.macro cfi_end end_label
+#ifdef __ELF__
+ .pushsection .debug_frame
+ .align 2
+LSYM(Lend_fde):
+ .popsection
+\end_label:
+#endif
+.endm
+
/* Don't pass dirn, it's there just to get token pasting right. */
-.macro RETLDM regs=, cond=, dirn=ia
-#ifdef __APCS_26__
- .ifc "\regs",""
- ldm\cond\dirn sp!, {pc}^
- .else
- ldm\cond\dirn sp!, {\regs, pc}^
- .endif
-#elif defined (__INTERWORKING__)
+.macro RETLDM regs=, cond=, unwind=, dirn=ia
+#if defined (__INTERWORKING__)
.ifc "\regs",""
- ldr\cond lr, [sp], #4
+ ldr\cond lr, [sp], #8
.else
ldm\cond\dirn sp!, {\regs, lr}
.endif
+ .ifnc "\unwind", ""
+ /* Mark LR as restored. */
+97: cfi_pop 97b - \unwind, 0xe, 0x0
+ .endif
bx\cond lr
#else
.ifc "\regs",""
- ldr\cond pc, [sp], #4
+ ldr\cond pc, [sp], #8
.else
ldm\cond\dirn sp!, {\regs, pc}
.endif
@@ -129,25 +203,25 @@ Boston, MA 02111-1307, USA. */
.endm
-.macro ARM_LDIV0
-LSYM(Ldiv0):
- str lr, [sp, #-4]!
+.macro ARM_LDIV0 name
+ str lr, [sp, #-8]!
+98: cfi_push 98b - __\name, 0xe, -0x8, 0x8
bl SYM (__div0) __PLT__
mov r0, #0 @ About as wrong as it could be.
- RETLDM
+ RETLDM unwind=98b
.endm
-.macro THUMB_LDIV0
-LSYM(Ldiv0):
- push { lr }
+.macro THUMB_LDIV0 name
+ push { r1, lr }
+98: cfi_push 98b - __\name, 0xe, -0x4, 0x8
bl SYM (__div0)
mov r0, #0 @ About as wrong as it could be.
#if defined (__INTERWORKING__)
- pop { r1 }
- bx r1
+ pop { r1, r2 }
+ bx r2
#else
- pop { pc }
+ pop { r1, pc }
#endif
.endm
@@ -156,12 +230,14 @@ LSYM(Ldiv0):
.endm
.macro DIV_FUNC_END name
+ cfi_start __\name, LSYM(Lend_div0)
LSYM(Ldiv0):
#ifdef __thumb__
- THUMB_LDIV0
+ THUMB_LDIV0 \name
#else
- ARM_LDIV0
+ ARM_LDIV0 \name
#endif
+ cfi_end LSYM(Lend_div0)
FUNC_END \name
.endm
@@ -195,15 +271,22 @@ SYM (__\name):
/* Special function that will always be coded in ARM assembly, even if
in Thumb-only compilation. */
-#if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
+#if defined(__INTERWORKING_STUBS__)
.macro ARM_FUNC_START name
FUNC_START \name
bx pc
nop
.arm
-_L__\name: /* A hook to tell gdb that we've switched to ARM */
+/* A hook to tell gdb that we've switched to ARM mode. Also used to call
+ directly from other local arm routines. */
+_L__\name:
.endm
#define EQUIV .thumb_set
+/* Branch directly to a function declared with ARM_FUNC_START.
+ Must be called in arm mode. */
+.macro ARM_CALL name
+ bl _L__\name
+.endm
#else
.macro ARM_FUNC_START name
.text
@@ -214,11 +297,26 @@ _L__\name: /* A hook to tell gdb that we've switched to ARM */
SYM (__\name):
.endm
#define EQUIV .set
+.macro ARM_CALL name
+ bl __\name
+.endm
#endif
+.macro FUNC_ALIAS new old
+ .globl SYM (__\new)
+#if defined (__thumb__)
+ .thumb_set SYM (__\new), SYM (__\old)
+#else
+ .set SYM (__\new), SYM (__\old)
+#endif
+.endm
+
.macro ARM_FUNC_ALIAS new old
.globl SYM (__\new)
EQUIV SYM (__\new), SYM (__\old)
+#if defined(__INTERWORKING_STUBS__)
+ .set SYM (_L__\new), SYM (_L__\old)
+#endif
.endm
#ifdef __thumb__
@@ -243,6 +341,25 @@ pc .req r15
/* ------------------------------------------------------------------------ */
.macro ARM_DIV_BODY dividend, divisor, result, curbit
+#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
+
+ clz \curbit, \dividend
+ clz \result, \divisor
+ sub \curbit, \result, \curbit
+ rsbs \curbit, \curbit, #31
+ addne \curbit, \curbit, \curbit, lsl #1
+ mov \result, #0
+ addne pc, pc, \curbit, lsl #2
+ nop
+ .set shift, 32
+ .rept 32
+ .set shift, shift - 1
+ cmp \dividend, \divisor, lsl #shift
+ adc \result, \result, \result
+ subcs \dividend, \dividend, \divisor, lsl #shift
+ .endr
+
+#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
#if __ARM_ARCH__ >= 5
clz \curbit, \divisor
@@ -253,7 +370,7 @@ pc .req r15
mov \curbit, \curbit, lsl \result
mov \result, #0
-#else
+#else /* __ARM_ARCH__ < 5 */
@ Initially shift the divisor left 3 bits if possible,
@ set curbit accordingly. This allows for curbit to be located
@@ -284,7 +401,7 @@ pc .req r15
mov \result, #0
-#endif
+#endif /* __ARM_ARCH__ < 5 */
@ Division loop
1: cmp \dividend, \divisor
@@ -304,6 +421,8 @@ pc .req r15
movne \divisor, \divisor, lsr #4
bne 1b
+#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+
.endm
/* ------------------------------------------------------------------------ */
.macro ARM_DIV2_ORDER divisor, order
@@ -338,6 +457,22 @@ pc .req r15
/* ------------------------------------------------------------------------ */
.macro ARM_MOD_BODY dividend, divisor, order, spare
+#if __ARM_ARCH__ >= 5 && ! defined (__OPTIMIZE_SIZE__)
+
+ clz \order, \divisor
+ clz \spare, \dividend
+ sub \order, \order, \spare
+ rsbs \order, \order, #31
+ addne pc, pc, \order, lsl #3
+ nop
+ .set shift, 32
+ .rept 32
+ .set shift, shift - 1
+ cmp \dividend, \divisor, lsl #shift
+ subcs \dividend, \dividend, \divisor, lsl #shift
+ .endr
+
+#else /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
#if __ARM_ARCH__ >= 5
clz \order, \divisor
@@ -345,7 +480,7 @@ pc .req r15
sub \order, \order, \spare
mov \divisor, \divisor, lsl \order
-#else
+#else /* __ARM_ARCH__ < 5 */
mov \order, #0
@@ -367,7 +502,7 @@ pc .req r15
addlo \order, \order, #1
blo 1b
-#endif
+#endif /* __ARM_ARCH__ < 5 */
@ Perform all needed substractions to keep only the reminder.
@ Do comparisons in batch of 4 first.
@@ -404,6 +539,9 @@ pc .req r15
4: cmp \dividend, \divisor
subhs \dividend, \dividend, \divisor
5:
+
+#endif /* __ARM_ARCH__ < 5 || defined (__OPTIMIZE_SIZE__) */
+
.endm
/* ------------------------------------------------------------------------ */
.macro THUMB_DIV_MOD_BODY modulo
@@ -568,6 +706,7 @@ LSYM(Lgot_result):
#ifdef L_udivsi3
FUNC_START udivsi3
+ FUNC_ALIAS aeabi_uidiv udivsi3
#ifdef __thumb__
@@ -614,6 +753,24 @@ LSYM(Lgot_result):
DIV_FUNC_END udivsi3
+FUNC_START aeabi_uidivmod
+#ifdef __thumb__
+ push {r0, r1, lr}
+ bl SYM(__udivsi3)
+ POP {r1, r2, r3}
+ mul r2, r0
+ sub r1, r1, r2
+ bx r3
+#else
+ stmfd sp!, { r0, r1, lr }
+ bl SYM(__udivsi3)
+ ldmfd sp!, { r1, r2, lr }
+ mul r3, r2, r0
+ sub r1, r1, r3
+ RET
+#endif
+ FUNC_END aeabi_uidivmod
+
#endif /* L_udivsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_umodsi3
@@ -660,6 +817,7 @@ LSYM(Lover10):
#ifdef L_divsi3
FUNC_START divsi3
+ FUNC_ALIAS aeabi_idiv divsi3
#ifdef __thumb__
cmp divisor, #0
@@ -734,6 +892,24 @@ LSYM(Lover12):
DIV_FUNC_END divsi3
+FUNC_START aeabi_idivmod
+#ifdef __thumb__
+ push {r0, r1, lr}
+ bl SYM(__divsi3)
+ POP {r1, r2, r3}
+ mul r2, r0
+ sub r1, r1, r2
+ bx r3
+#else
+ stmfd sp!, { r0, r1, lr }
+ bl SYM(__divsi3)
+ ldmfd sp!, { r1, r2, lr }
+ mul r3, r2, r0
+ sub r1, r1, r3
+ RET
+#endif
+ FUNC_END aeabi_idivmod
+
#endif /* L_divsi3 */
/* ------------------------------------------------------------------------ */
#ifdef L_modsi3
@@ -799,9 +975,13 @@ LSYM(Lover12):
#ifdef L_dvmd_tls
FUNC_START div0
+ FUNC_ALIAS aeabi_idiv0 div0
+ FUNC_ALIAS aeabi_ldiv0 div0
RET
+ FUNC_END aeabi_ldiv0
+ FUNC_END aeabi_idiv0
FUNC_END div0
#endif /* L_divmodsi_tools */
@@ -809,34 +989,155 @@ LSYM(Lover12):
#ifdef L_dvmd_lnx
@ GNU/Linux division-by zero handler. Used in place of L_dvmd_tls
-/* Constants taken from <asm/unistd.h> and <asm/signal.h> */
+/* Constant taken from <asm/signal.h>. */
#define SIGFPE 8
-#define __NR_SYSCALL_BASE 0x900000
-#define __NR_getpid (__NR_SYSCALL_BASE+ 20)
-#define __NR_kill (__NR_SYSCALL_BASE+ 37)
.code 32
FUNC_START div0
stmfd sp!, {r1, lr}
- swi __NR_getpid
- cmn r0, #1000
- RETLDM r1 hs
- mov r1, #SIGFPE
- swi __NR_kill
+ mov r0, #SIGFPE
+ bl SYM(raise) __PLT__
RETLDM r1
FUNC_END div0
#endif /* L_dvmd_lnx */
/* ------------------------------------------------------------------------ */
+/* Dword shift operations. */
+/* All the following Dword shift variants rely on the fact that
+ shft xxx, Reg
+ is in fact done as
+ shft xxx, (Reg & 255)
+ so for Reg value in (32...63) and (-1...-31) we will get zero (in the
+ case of logical shifts) or the sign (for asr). */
+
+#ifdef __ARMEB__
+#define al r1
+#define ah r0
+#else
+#define al r0
+#define ah r1
+#endif
+
+/* Prevent __aeabi double-word shifts from being produced on SymbianOS. */
+#ifndef __symbian__
+
+#ifdef L_lshrdi3
+
+ FUNC_START lshrdi3
+ FUNC_ALIAS aeabi_llsr lshrdi3
+
+#ifdef __thumb__
+ lsr al, r2
+ mov r3, ah
+ lsr ah, r2
+ mov ip, r3
+ sub r2, #32
+ lsr r3, r2
+ orr al, r3
+ neg r2, r2
+ mov r3, ip
+ lsl r3, r2
+ orr al, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi al, al, lsr r2
+ movpl al, ah, lsr r3
+ orrmi al, al, ah, lsl ip
+ mov ah, ah, lsr r2
+ RET
+#endif
+ FUNC_END aeabi_llsr
+ FUNC_END lshrdi3
+
+#endif
+
+#ifdef L_ashrdi3
+
+ FUNC_START ashrdi3
+ FUNC_ALIAS aeabi_lasr ashrdi3
+
+#ifdef __thumb__
+ lsr al, r2
+ mov r3, ah
+ asr ah, r2
+ sub r2, #32
+ @ If r2 is negative at this point the following step would OR
+ @ the sign bit into all of AL. That's not what we want...
+ bmi 1f
+ mov ip, r3
+ asr r3, r2
+ orr al, r3
+ mov r3, ip
+1:
+ neg r2, r2
+ lsl r3, r2
+ orr al, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi al, al, lsr r2
+ movpl al, ah, asr r3
+ orrmi al, al, ah, lsl ip
+ mov ah, ah, asr r2
+ RET
+#endif
+
+ FUNC_END aeabi_lasr
+ FUNC_END ashrdi3
+
+#endif
+
+#ifdef L_ashldi3
+
+ FUNC_START ashldi3
+ FUNC_ALIAS aeabi_llsl ashldi3
+
+#ifdef __thumb__
+ lsl ah, r2
+ mov r3, al
+ lsl al, r2
+ mov ip, r3
+ sub r2, #32
+ lsl r3, r2
+ orr ah, r3
+ neg r2, r2
+ mov r3, ip
+ lsr r3, r2
+ orr ah, r3
+ RET
+#else
+ subs r3, r2, #32
+ rsb ip, r2, #32
+ movmi ah, ah, lsl r2
+ movpl ah, al, lsl r3
+ orrmi ah, ah, al, lsr ip
+ mov al, al, lsl r2
+ RET
+#endif
+ FUNC_END aeabi_llsl
+ FUNC_END ashldi3
+
+#endif
+
+#endif /* __symbian__ */
+
+/* ------------------------------------------------------------------------ */
/* These next two sections are here despite the fact that they contain Thumb
assembler because their presence allows interworked code to be linked even
when the GCC library is this one. */
/* Do not build the interworking functions when the target architecture does
not support Thumb instructions. (This can be a multilib option). */
-#if defined L_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
+#if defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__\
+ || defined __ARM_ARCH_5TE__ || defined __ARM_ARCH_5TEJ__ \
+ || __ARM_ARCH__ >= 6
+
+#if defined L_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code.
The address of function to be called is loaded into a register and then
@@ -874,10 +1175,8 @@ LSYM(Lover12):
call_via lr
#endif /* L_call_via_rX */
-/* ------------------------------------------------------------------------ */
-/* Do not build the interworking functions when the target architecture does
- not support Thumb instructions. (This can be a multilib option). */
-#if defined L_interwork_call_via_rX && (defined __ARM_ARCH_4T__ || defined __ARM_ARCH_5T__ || defined __ARM_ARCH_5TE__)
+
+#if defined L_interwork_call_via_rX
/* These labels & instructions are used by the Arm/Thumb interworking code,
when the target address is in an unknown instruction set. The address
@@ -888,16 +1187,61 @@ LSYM(Lover12):
the target code cannot be relied upon to return via a BX instruction, so
instead we have to store the resturn address on the stack and allow the
called function to return here instead. Upon return we recover the real
- return address and use a BX to get back to Thumb mode. */
+ return address and use a BX to get back to Thumb mode.
+
+ There are three variations of this code. The first,
+ _interwork_call_via_rN(), will push the return address onto the
+ stack and pop it in _arm_return(). It should only be used if all
+ arguments are passed in registers.
+
+ The second, _interwork_r7_call_via_rN(), instead stores the return
+ address at [r7, #-4]. It is the caller's responsibility to ensure
+ that this address is valid and contains no useful data.
+
+ The third, _interwork_r11_call_via_rN(), works in the same way but
+ uses r11 instead of r7. It is useful if the caller does not really
+ need a frame pointer. */
.text
.align 0
.code 32
.globl _arm_return
+LSYM(Lstart_arm_return):
+ cfi_start LSYM(Lstart_arm_return) LSYM(Lend_arm_return)
+ cfi_push 0, 0xe, -0x8, 0x8
+ nop @ This nop is for the benefit of debuggers, so that
+ @ backtraces will use the correct unwind information.
_arm_return:
- RETLDM
- .code 16
+ RETLDM unwind=LSYM(Lstart_arm_return)
+ cfi_end LSYM(Lend_arm_return)
+
+ .globl _arm_return_r7
+_arm_return_r7:
+ ldr lr, [r7, #-4]
+ bx lr
+
+ .globl _arm_return_r11
+_arm_return_r11:
+ ldr lr, [r11, #-4]
+ bx lr
+
+.macro interwork_with_frame frame, register, name, return
+ .code 16
+
+ THUMB_FUNC_START \name
+
+ bx pc
+ nop
+
+ .code 32
+ tst \register, #1
+ streq lr, [\frame, #-4]
+ adreq lr, _arm_return_\frame
+ bx \register
+
+ SIZE (\name)
+.endm
.macro interwork register
.code 16
@@ -911,11 +1255,14 @@ _arm_return:
.globl LSYM(Lchange_\register)
LSYM(Lchange_\register):
tst \register, #1
- streq lr, [sp, #-4]!
+ streq lr, [sp, #-8]!
adreq lr, _arm_return
bx \register
SIZE (_interwork_call_via_\register)
+
+ interwork_with_frame r7,\register,_interwork_r7_call_via_\register
+ interwork_with_frame r11,\register,_interwork_r11_call_via_\register
.endm
interwork r0
@@ -945,7 +1292,7 @@ LSYM(Lchange_\register):
.globl .Lchange_lr
.Lchange_lr:
tst lr, #1
- stmeqdb r13!, {lr}
+ stmeqdb r13!, {lr, pc}
mov ip, lr
adreq lr, _arm_return
bx ip
@@ -953,7 +1300,10 @@ LSYM(Lchange_\register):
SIZE (_interwork_call_via_lr)
#endif /* L_interwork_call_via_rX */
+#endif /* Arch supports thumb. */
+#ifndef __symbian__
#include "ieee754-df.S"
#include "ieee754-sf.S"
-
+#include "bpabi.S"
+#endif /* __symbian__ */
diff --git a/contrib/gcc/config/arm/libgcc-bpabi.ver b/contrib/gcc/config/arm/libgcc-bpabi.ver
new file mode 100644
index 0000000..2f259eb
--- /dev/null
+++ b/contrib/gcc/config/arm/libgcc-bpabi.ver
@@ -0,0 +1,83 @@
+GCC_3.5 {
+ # BPABI symbols
+ __aeabi_cdcmpeq
+ __aeabi_cdcmple
+ __aeabi_cdrcmple
+ __aeabi_cfcmpeq
+ __aeabi_cfcmple
+ __aeabi_cfrcmple
+ __aeabi_d2f
+ __aeabi_d2iz
+ __aeabi_d2lz
+ __aeabi_d2uiz
+ __aeabi_d2ulz
+ __aeabi_dadd
+ __aeabi_dcmpeq
+ __aeabi_dcmpge
+ __aeabi_dcmpgt
+ __aeabi_dcmple
+ __aeabi_dcmplt
+ __aeabi_dcmpun
+ __aeabi_ddiv
+ __aeabi_dmul
+ __aeabi_dneg
+ __aeabi_drsub
+ __aeabi_dsub
+ __aeabi_f2d
+ __aeabi_f2iz
+ __aeabi_f2lz
+ __aeabi_f2uiz
+ __aeabi_f2ulz
+ __aeabi_fadd
+ __aeabi_fcmpeq
+ __aeabi_fcmpge
+ __aeabi_fcmpgt
+ __aeabi_fcmple
+ __aeabi_fcmplt
+ __aeabi_fcmpun
+ __aeabi_fdiv
+ __aeabi_fmul
+ __aeabi_fneg
+ __aeabi_frsub
+ __aeabi_fsub
+ __aeabi_i2d
+ __aeabi_i2f
+ __aeabi_idiv
+ __aeabi_idiv0
+ __aeabi_idivmod
+ __aeabi_l2d
+ __aeabi_l2f
+ __aeabi_lasr
+ __aeabi_lcmp
+ __aeabi_ldiv0
+ __aeabi_ldivmod
+ __aeabi_llsl
+ __aeabi_llsr
+ __aeabi_lmul
+ __aeabi_ui2d
+ __aeabi_ui2f
+ __aeabi_uidiv
+ __aeabi_uidivmod
+ __aeabi_uldivmod
+ __aeabi_ulcmp
+ __aeabi_ul2d
+ __aeabi_ul2f
+ __aeabi_uread4
+ __aeabi_uread8
+ __aeabi_uwrite4
+ __aeabi_uwrite8
+
+ # Exception-Handling
+ # \S 7.5
+ _Unwind_Complete
+ _Unwind_VRS_Get
+ _Unwind_VRS_Set
+ _Unwind_VRS_Pop
+ # \S 9.2
+ __aeabi_unwind_cpp_pr0
+ __aeabi_unwind_cpp_pr1
+ __aeabi_unwind_cpp_pr2
+ # The libstdc++ exception-handling personality routine uses this
+ # GNU-specific entry point.
+ __gnu_unwind_frame
+}
diff --git a/contrib/gcc/config/arm/libunwind.S b/contrib/gcc/config/arm/libunwind.S
new file mode 100644
index 0000000..06e1310
--- /dev/null
+++ b/contrib/gcc/config/arm/libunwind.S
@@ -0,0 +1,120 @@
+/* Support functions for the unwinder.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Contributed by Paul Brook
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+#ifndef __symbian__
+
+#include "lib1funcs.asm"
+
+.macro UNPREFIX name
+ .global SYM (\name)
+ EQUIV SYM (\name), SYM (__\name)
+.endm
+
+/* r0 points to a 16-word block. Upload these values to the actual core
+ state. */
+ARM_FUNC_START restore_core_regs
+ /* We must use sp as the base register when restoring sp. Push the
+ last 3 registers onto the top of the current stack to achieve
+ this. */
+ add r1, r0, #52
+ ldmia r1, {r3, r4, r5} /* {sp, lr, pc}. */
+#ifdef __INTERWORKING__
+ /* Restore pc into ip. */
+ mov r2, r5
+ stmfd sp!, {r2, r3, r4}
+#else
+ stmfd sp!, {r3, r4, r5}
+#endif
+ /* Don't bother restoring ip. */
+ ldmia r0, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp}
+ /* Pop the three registers we pushed earlier. */
+#ifdef __INTERWORKING__
+ ldmfd sp, {ip, sp, lr}
+ bx ip
+#else
+ ldmfd sp, {sp, lr, pc}
+#endif
+ FUNC_END restore_core_regs
+ UNPREFIX restore_core_regs
+
+/* Load VFP registers d0-d15 from the address in r0. */
+ARM_FUNC_START gnu_Unwind_Restore_VFP
+ /* Use the generic coprocessor form so that gas doesn't complain
+ on soft-float targets. */
+ ldc p11,cr0,[r0],{0x21} /* fldmiax r0, {d0-d15} */
+ RET
+
+/* Store VFR regsters d0-d15 to the address in r0. */
+ARM_FUNC_START gnu_Unwind_Save_VFP
+ /* Use the generic coprocessor form so that gas doesn't complain
+ on soft-float targets. */
+ stc p11,cr0,[r0],{0x21} /* fstmiax r0, {d0-d15} */
+ RET
+
+/* Wrappers to save core registers, then call the real routine. */
+
+.macro UNWIND_WRAPPER name nargs
+ ARM_FUNC_START \name
+ /* Create a phase2_vrs structure. */
+ /* Split reg push in two to ensure the correct value for sp. */
+ stmfd sp!, {sp, lr, pc}
+ stmfd sp!, {r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, sl, fp, ip}
+
+ /* Demand-save flags, plus an extra word for alignment. */
+ mov r3, #0
+ stmfd sp!, {r2, r3}
+
+ /* Point r1 at the block. Pass r[0..nargs) unchanged. */
+ add r\nargs, sp, #4
+#if defined(__thumb__)
+ /* Switch back to thumb mode to avoid interworking hassle. */
+ adr ip, .L1_\name
+ orr ip, ip, #1
+ bx ip
+ .thumb
+.L1_\name:
+ bl SYM (__gnu\name) __PLT__
+ ldr r3, [sp, #64]
+ add sp, #72
+ bx r3
+#else
+ bl SYM (__gnu\name) __PLT__
+ ldr lr, [sp, #64]
+ add sp, sp, #72
+ RET
+#endif
+ FUNC_END \name
+ UNPREFIX \name
+.endm
+
+UNWIND_WRAPPER _Unwind_RaiseException 1
+UNWIND_WRAPPER _Unwind_Resume 1
+UNWIND_WRAPPER _Unwind_Resume_or_Rethrow 1
+UNWIND_WRAPPER _Unwind_ForcedUnwind 3
+
+#endif /* __symbian__ */
diff --git a/contrib/gcc/config/arm/linux-eabi.h b/contrib/gcc/config/arm/linux-eabi.h
new file mode 100644
index 0000000..6612f74
--- /dev/null
+++ b/contrib/gcc/config/arm/linux-eabi.h
@@ -0,0 +1,85 @@
+/* Configuration file for ARM GNU/Linux EABI targets.
+ Copyright (C) 2004, 2005, 2006
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* On EABI GNU/Linux, we want both the BPABI builtins and the
+ GNU/Linux builtins. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ TARGET_BPABI_CPP_BUILTINS(); \
+ LINUX_TARGET_OS_CPP_BUILTINS(); \
+ } \
+ while (false)
+
+/* We default to a soft-float ABI so that binaries can run on all
+ target hardware. */
+#undef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+
+/* We default to the "aapcs-linux" ABI so that enums are int-sized by
+ default. */
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
+/* Default to armv5t so that thumb shared libraries work.
+ The ARM10TDMI core is the default for armv5t, so set
+ SUBTARGET_CPU_DEFAULT to achieve this. */
+#undef SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
+
+#undef SUBTARGET_EXTRA_LINK_SPEC
+#define SUBTARGET_EXTRA_LINK_SPEC " -m armelf_linux_eabi"
+
+/* Use ld-linux.so.3 so that it will be possible to run "classic"
+ GNU/Linux binaries on an EABI system. */
+#undef GLIBC_DYNAMIC_LINKER
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.3"
+
+/* At this point, bpabi.h will have clobbered LINK_SPEC. We want to
+ use the GNU/Linux version, not the generic BPABI version. */
+#undef LINK_SPEC
+#define LINK_SPEC LINUX_TARGET_LINK_SPEC
+
+/* Use the default LIBGCC_SPEC, not the version in linux-elf.h, as we
+ do not use -lfloat. */
+#undef LIBGCC_SPEC
+
+/* Use the AAPCS type for wchar_t, or the previous Linux default for
+ non-AAPCS. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_AAPCS_BASED ? "unsigned int" : "long int")
+
+/* Clear the instruction cache from `beg' to `end'. This makes an
+ inline system call to SYS_cacheflush. It is modified to work with
+ both the original and EABI-only syscall interfaces. */
+#undef CLEAR_INSN_CACHE
+#define CLEAR_INSN_CACHE(BEG, END) \
+{ \
+ register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
+ register unsigned long _end __asm ("a2") = (unsigned long) (END); \
+ register unsigned long _flg __asm ("a3") = 0; \
+ register unsigned long _scno __asm ("r7") = 0xf0002; \
+ __asm __volatile ("swi 0x9f0002 @ sys_cacheflush" \
+ : "=r" (_beg) \
+ : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \
+}
diff --git a/contrib/gcc/config/arm/linux-elf.h b/contrib/gcc/config/arm/linux-elf.h
index 9f291c0..acb13cd 100644
--- a/contrib/gcc/config/arm/linux-elf.h
+++ b/contrib/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, 2001, 2002, 2003, 2004
+ Copyright (C) 1993, 1994, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006
Free Software Foundation, Inc.
Contributed by Philip Blundell <philb@gnu.org>
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* elfos.h should have already been included. Now just override
any conflicting definitions and add any extras. */
@@ -27,12 +28,11 @@
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (ARM GNU/Linux with ELF)", stderr);
-/* Do not assume anything about header files. */
-#define NO_IMPLICIT_EXTERN_C
+#undef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
-/* Default is to use APCS-32 mode. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (0)
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
@@ -40,13 +40,7 @@
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "mhard-float", "mapcs-32", "mno-thumb-interwork" }
-
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
-
-/* The GNU C++ standard library requires that these macros be defined. */
-#undef CPLUSPLUS_CPP_SPEC
-#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
+ { "marm", "mlittle-endian", "mhard-float", "mno-thumb-interwork" }
/* Now we define the strings used to build the spec file. */
#undef LIB_SPEC
@@ -55,44 +49,30 @@
%{shared:-lc} \
%{!shared:%{profile:-lc_p}%{!profile:-lc}}"
-#define LIBGCC_SPEC "%{msoft-float:-lfloat} -lgcc"
-
-/* 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
- object constructed before entering `main'. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
- %{!p:%{profile:gcrt1.o%s} \
- %{!profile:crt1.o%s}}}} \
- crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-
-/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
- the GNU/Linux magical crtend.o file (see crtstuff.c) which
- provides part of the support for getting C++ file-scope static
- object constructed before entering `main', followed by a normal
- GNU/Linux "finalizer" file, `crtn.o'. */
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+#define LIBGCC_SPEC "%{msoft-float:-lfloat} %{mfloat-abi=soft*:-lfloat} -lgcc"
-#undef LINK_SPEC
-#define LINK_SPEC "%{h*} %{version:-v} \
- %{b} %{Wl,*:%*} \
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+
+#define LINUX_TARGET_LINK_SPEC "%{h*} %{version:-v} \
+ %{b} \
%{static:-Bstatic} \
%{shared:-shared} \
%{symbolic:-Bsymbolic} \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "} \
-X \
%{mbig-endian:-EB}" \
SUBTARGET_EXTRA_LINK_SPEC
-#define TARGET_OS_CPP_BUILTINS() LINUX_TARGET_OS_CPP_BUILTINS()
+#undef LINK_SPEC
+#define LINK_SPEC LINUX_TARGET_LINK_SPEC
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ LINUX_TARGET_OS_CPP_BUILTINS(); \
+ } \
+ while (0)
/* This is how we tell the assembler that two symbols have the same value. */
#define ASM_OUTPUT_DEF(FILE, NAME1, NAME2) \
@@ -113,16 +93,14 @@
#undef ARM_FUNCTION_PROFILER
#define ARM_FUNCTION_PROFILER(STREAM, LABELNO) \
{ \
- fprintf (STREAM, "\tbl\tmcount%s\n", NEED_PLT_RELOC ? "(PLT)" : ""); \
+ fprintf (STREAM, "\tbl\tmcount%s\n", \
+ (TARGET_ARM && NEED_PLT_RELOC) ? "(PLT)" : ""); \
}
-/* The linux profiler clobbers the link register. Make sure the
+/* The GNU/Linux profiler clobbers the link register. Make sure the
prologue knows to save it. */
#define PROFILE_HOOK(X) \
emit_insn (gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, LR_REGNUM)))
-#undef CC1_SPEC
-#define CC1_SPEC "%{profile:-p}"
-
-#define LINK_GCC_C_SEQUENCE_SPEC \
- "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+/* The GNU/Linux profiler needs a frame pointer. */
+#define SUBTARGET_FRAME_POINTER_REQUIRED current_function_profile
diff --git a/contrib/gcc/config/arm/linux-gas.h b/contrib/gcc/config/arm/linux-gas.h
index 6911284..a04e050 100644
--- a/contrib/gcc/config/arm/linux-gas.h
+++ b/contrib/gcc/config/arm/linux-gas.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler.
ARM Linux-based GNU systems version.
- Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2004
+ Free Software Foundation, Inc.
Contributed by Russell King <rmk92@ecs.soton.ac.uk>.
This file is part of GCC.
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* This is how we tell the assembler that a symbol is weak.
GAS always supports weak symbols. */
@@ -27,7 +28,7 @@
#define DEFAULT_SIGNED_CHAR 0
#undef SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{fPIC|fPIE:-D__PIC__ -D__pic__} %{fpic|fpie:-D__PIC__ -D__pic__}"
+#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -41,19 +42,6 @@
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-/* Emit code to set up a trampoline and synchronize the caches. */
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
- (CXT)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
- (FNADDR)); \
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
- 0, VOIDmode, 2, TRAMP, Pmode, \
- plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
-}
-
/* Clear the instruction cache from `beg' to `end'. This makes an
inline system call to SYS_cacheflush. */
#define CLEAR_INSN_CACHE(BEG, END) \
diff --git a/contrib/gcc/config/arm/mmintrin.h b/contrib/gcc/config/arm/mmintrin.h
index 4dc1d45..bed6204 100644
--- a/contrib/gcc/config/arm/mmintrin.h
+++ b/contrib/gcc/config/arm/mmintrin.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +14,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 59 Temple Place - Suite 330, Boston, MA
- 02111-1307, USA. */
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -31,9 +31,9 @@
typedef unsigned long long __m64, __int64;
/* Internal data types for implementing the intrinsics. */
-typedef int __v2si __attribute__ ((__mode__ (__V2SI__)));
-typedef int __v4hi __attribute__ ((__mode__ (__V4HI__)));
-typedef int __v8qi __attribute__ ((__mode__ (__V8QI__)));
+typedef int __v2si __attribute__ ((vector_size (8)));
+typedef short __v4hi __attribute__ ((vector_size (8)));
+typedef char __v8qi __attribute__ ((vector_size (8)));
/* "Convert" __m64 and __int64 into each other. */
static __inline __m64
@@ -419,7 +419,7 @@ _mm_madd_pu16 (__m64 __m1, __m64 __m2)
static __inline __m64
_mm_mulhi_pi16 (__m64 __m1, __m64 __m2)
{
- return (__m64) __builtin_arm_wmulsh ((__v4hi)__m1, (__v4hi)__m2);
+ return (__m64) __builtin_arm_wmulsm ((__v4hi)__m1, (__v4hi)__m2);
}
/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in
@@ -427,7 +427,7 @@ _mm_mulhi_pi16 (__m64 __m1, __m64 __m2)
static __inline __m64
_mm_mulhi_pu16 (__m64 __m1, __m64 __m2)
{
- return (__m64) __builtin_arm_wmuluh ((__v4hi)__m1, (__v4hi)__m2);
+ return (__m64) __builtin_arm_wmulum ((__v4hi)__m1, (__v4hi)__m2);
}
/* Multiply four 16-bit values in M1 by four 16-bit values in M2 and produce
@@ -986,18 +986,18 @@ _mm_setzero_si64 (void)
the rest are reserved. */
static __inline void
-_mm_setwcx (const int __regno, const int __value)
+_mm_setwcx (const int __value, const int __regno)
{
switch (__regno)
{
- case 0: __builtin_arm_setwcx (0, __value); break;
- case 1: __builtin_arm_setwcx (1, __value); break;
- case 2: __builtin_arm_setwcx (2, __value); break;
- case 3: __builtin_arm_setwcx (3, __value); break;
- case 8: __builtin_arm_setwcx (8, __value); break;
- case 9: __builtin_arm_setwcx (9, __value); break;
- case 10: __builtin_arm_setwcx (10, __value); break;
- case 11: __builtin_arm_setwcx (11, __value); break;
+ case 0: __builtin_arm_setwcx (__value, 0); break;
+ case 1: __builtin_arm_setwcx (__value, 1); break;
+ case 2: __builtin_arm_setwcx (__value, 2); break;
+ case 3: __builtin_arm_setwcx (__value, 3); break;
+ case 8: __builtin_arm_setwcx (__value, 8); break;
+ case 9: __builtin_arm_setwcx (__value, 9); break;
+ case 10: __builtin_arm_setwcx (__value, 10); break;
+ case 11: __builtin_arm_setwcx (__value, 11); break;
default: break;
}
}
diff --git a/contrib/gcc/config/arm/netbsd-elf.h b/contrib/gcc/config/arm/netbsd-elf.h
index a8b43f6..8a01b0f 100644
--- a/contrib/gcc/config/arm/netbsd-elf.h
+++ b/contrib/gcc/config/arm/netbsd-elf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, NetBSD/arm ELF version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Wasabi Systems, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#undef TARGET_VERSION
@@ -35,14 +35,12 @@
/* Default it to use ATPCS with soft-VFP. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (ARM_FLAG_APCS_32 \
- | ARM_FLAG_SOFT_FLOAT \
- | ARM_FLAG_APCS_FRAME \
- | ARM_FLAG_ATPCS \
- | ARM_FLAG_VFP \
- | ARM_FLAG_MMU_TRAPS \
+ (MASK_APCS_FRAME \
| TARGET_ENDIAN_DEFAULT)
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_ATPCS
+
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
@@ -57,14 +55,11 @@
#define SUBTARGET_EXTRA_ASM_SPEC \
"-matpcs %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
-/* Default floating point model is soft-VFP.
- FIXME: -mhard-float currently implies FPA. */
+/* Default to full VFP if -mhard-float is specified. */
#undef SUBTARGET_ASM_FLOAT_SPEC
#define SUBTARGET_ASM_FLOAT_SPEC \
- "%{mhard-float:-mfpu=fpa} \
- %{msoft-float:-mfpu=softvfp} \
- %{!mhard-float: \
- %{!msoft-float:-mfpu=softvfp}}"
+ "%{mhard-float:{!mfpu=*:-mfpu=vfp}} \
+ %{mfloat-abi=hard:{!mfpu=*:-mfpu=vfp}}"
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
@@ -102,7 +97,8 @@
{ \
asm_fprintf (STREAM, "\tmov\t%Rip, %Rlr\n"); \
asm_fprintf (STREAM, "\tbl\t__mcount%s\n", \
- NEED_PLT_RELOC ? "(PLT)" : ""); \
+ (TARGET_ARM && NEED_PLT_RELOC) \
+ ? "(PLT)" : ""); \
}
/* VERY BIG NOTE: Change of structure alignment for NetBSD/arm.
@@ -140,21 +136,6 @@
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-/* Emit code to set up a trampoline and synchronize the caches. */
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-do \
- { \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
- (CXT)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
- (FNADDR)); \
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
- 0, VOIDmode, 2, TRAMP, Pmode, \
- plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
- } \
-while (0)
-
/* Clear the instruction cache from `BEG' to `END'. This makes a
call to the ARM_SYNC_ICACHE architecture specific syscall. */
#define CLEAR_INSN_CACHE(BEG, END) \
@@ -171,3 +152,7 @@ do \
(void) sysarch (0, &s); \
} \
while (0)
+
+#undef FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT FPUTYPE_VFP
+
diff --git a/contrib/gcc/config/arm/netbsd.h b/contrib/gcc/config/arm/netbsd.h
index 71763e6..4d14744 100644
--- a/contrib/gcc/config/arm/netbsd.h
+++ b/contrib/gcc/config/arm/netbsd.h
@@ -1,5 +1,6 @@
/* NetBSD/arm a.out version.
- Copyright (C) 1993, 1994, 1997, 1998, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1993, 1994, 1997, 1998, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Mark Brinicombe (amb@physig.ph.kcl.ac.uk)
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#undef TARGET_VERSION
@@ -34,9 +35,8 @@
/* ARM6 family default cpu. */
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-/* Default is to use APCS-32 mode. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_APCS_FRAME)
/* Some defines for CPP.
arm32 is the NetBSD port name, so we always define arm32 and __arm32__. */
@@ -55,14 +55,10 @@
#undef CPP_SPEC
#define CPP_SPEC "\
-%(cpp_cpu_arch) %(cpp_apcs_pc) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
+%(cpp_cpu_arch) %(cpp_float) %(cpp_endian) %(netbsd_cpp_spec) \
"
-/* Because TARGET_DEFAULT sets ARM_FLAG_APCS_32 */
-#undef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
-
-/* Because TARGET_DEFAULT sets ARM_FLAG_SOFT_FLOAT */
+/* Because TARGET_DEFAULT sets MASK_SOFT_FLOAT */
#undef CPP_FLOAT_DEFAULT_SPEC
#define CPP_FLOAT_DEFAULT_SPEC "-D__SOFTFP__"
@@ -142,19 +138,6 @@
#undef DEFAULT_STRUCTURE_SIZE_BOUNDARY
#define DEFAULT_STRUCTURE_SIZE_BOUNDARY 8
-/* Emit code to set up a trampoline and synchronize the caches. */
-#undef INITIALIZE_TRAMPOLINE
-#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
-{ \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 8)), \
- (CXT)); \
- emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 12)), \
- (FNADDR)); \
- emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__clear_cache"), \
- 0, VOIDmode, 2, TRAMP, Pmode, \
- plus_constant (TRAMP, TRAMPOLINE_SIZE), Pmode); \
-}
-
/* Clear the instruction cache from `BEG' to `END'. This makes a
call to the ARM32_SYNC_ICACHE architecture specific syscall. */
#define CLEAR_INSN_CACHE(BEG, END) \
diff --git a/contrib/gcc/config/arm/pe.c b/contrib/gcc/config/arm/pe.c
index d25fd0d..f2f67d5 100644
--- a/contrib/gcc/config/arm/pe.c
+++ b/contrib/gcc/config/arm/pe.c
@@ -1,5 +1,6 @@
/* Routines for GCC for ARM/pe.
- Copyright (C) 1995, 1996, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2001, 2002, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -95,7 +96,7 @@ arm_dllimport_name_p (symbol)
}
/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (eg: dllimport). */
+ Note that we override the previous setting (e.g.: dllimport). */
void
arm_mark_dllexport (decl)
@@ -107,13 +108,11 @@ arm_mark_dllexport (decl)
tree idp;
rtlname = XEXP (DECL_RTL (decl), 0);
- if (GET_CODE (rtlname) == SYMBOL_REF)
- oldname = XSTR (rtlname, 0);
- else if (GET_CODE (rtlname) == MEM
- && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
- oldname = XSTR (XEXP (rtlname, 0), 0);
- else
- abort ();
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
+
if (arm_dllimport_name_p (oldname))
oldname += 9;
else if (arm_dllexport_name_p (oldname))
@@ -130,7 +129,7 @@ arm_mark_dllexport (decl)
idp = get_identifier (newname);
XEXP (DECL_RTL (decl), 0) =
- gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
+ gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
}
/* Mark a DECL as being dllimport'd. */
@@ -146,17 +145,13 @@ arm_mark_dllimport (decl)
rtlname = XEXP (DECL_RTL (decl), 0);
- if (GET_CODE (rtlname) == SYMBOL_REF)
- oldname = XSTR (rtlname, 0);
- else if (GET_CODE (rtlname) == MEM
- && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
- oldname = XSTR (XEXP (rtlname, 0), 0);
- else
- abort ();
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
- if (arm_dllexport_name_p (oldname))
- abort (); /* this shouldn't happen */
- else if (arm_dllimport_name_p (oldname))
+ gcc_assert (!arm_dllexport_name_p (oldname));
+ if (arm_dllimport_name_p (oldname))
return; /* already done */
/* ??? One can well ask why we're making these checks here,
@@ -167,7 +162,7 @@ arm_mark_dllimport (decl)
&& !DECL_VIRTUAL_P (decl)
&& DECL_INITIAL (decl))
{
- error ("%Jinitialized variable '%D' is marked dllimport", decl, decl);
+ error ("initialized variable %q+D is marked dllimport", decl);
return;
}
/* Nor can they be static. */
@@ -176,7 +171,7 @@ arm_mark_dllimport (decl)
&& !DECL_VIRTUAL_P (decl)
&& 0 /*???*/)
{
- error ("%Jstatic variable '%D' is marked dllimport", decl, decl);
+ error ("static variable %q+D is marked dllimport", decl);
return;
}
@@ -200,9 +195,9 @@ arm_mark_dllimport (decl)
/* ??? At least I think that's why we do this. */
idp = get_identifier (newname);
- newrtl = gen_rtx (MEM, Pmode,
- gen_rtx (SYMBOL_REF, Pmode,
- IDENTIFIER_POINTER (idp)));
+ newrtl = gen_rtx_MEM (Pmode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ IDENTIFIER_POINTER (idp)));
XEXP (DECL_RTL (decl), 0) = newrtl;
}
@@ -213,8 +208,7 @@ arm_pe_encode_section_info (decl, rtl, first)
int first ATTRIBUTE_UNUSED;
{
/* This bit is copied from arm_encode_section_info. */
- if (optimize > 0 && TREE_CONSTANT (decl)
- && (!flag_writable_strings || TREE_CODE (decl) != STRING_CST))
+ if (optimize > 0 && TREE_CONSTANT (decl))
SYMBOL_REF_FLAG (XEXP (rtl, 0)) = 1;
/* Mark the decl so we can tell from the rtl whether the object is
@@ -236,7 +230,7 @@ arm_pe_encode_section_info (decl, rtl, first)
{
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));
+ rtx newrtl = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
XEXP (DECL_RTL (decl), 0) = newrtl;
diff --git a/contrib/gcc/config/arm/pe.h b/contrib/gcc/config/arm/pe.h
index e83f97b..f96cd66 100644
--- a/contrib/gcc/config/arm/pe.h
+++ b/contrib/gcc/config/arm/pe.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for ARM with PE obj format.
- Copyright (C) 1995, 1996, 1999, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1999, 2000, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Doug Evans (dje@cygnus.com).
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Enable PE specific code. */
#define ARM_PE 1
@@ -39,44 +40,17 @@
/* Get tree.c to declare a target-specific specialization of
merge_decl_attributes. */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES
-
-/* Support the __declspec keyword by turning them into attributes.
- We currently only support: naked, 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 SUBTARGET_CPP_SPEC
-#define SUBTARGET_CPP_SPEC "-D__pe__ -D__declspec(x)=__attribute__((x))"
-
-
-/* Experimental addition for pr 7885.
- Ignore dllimport for functions. */
-#define TARGET_FLAG_NOP_FUN (1 << 24)
-
-#undef TARGET_NOP_FUN_DLLIMPORT
-#define TARGET_NOP_FUN_DLLIMPORT (target_flags & TARGET_FLAG_NOP_FUN)
-
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{ "nop-fun-dllimport", TARGET_FLAG_NOP_FUN, \
- N_("Ignore dllimport attribute for functions") }, \
-{ "no-nop-fun-dllimport", - TARGET_FLAG_NOP_FUN, "" },
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-/* Defaulting to APCS-26 support is a legacy issue. It has been done
- that way for a long time, so changing it will probably break some
- people's worlds. Support for APCS-32 is now enabled as a multilib,
- and at some point in the future APCS-32 may become the default.
- Possibly when chips that support APCS-26 are no longer made. */
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "-D__pe__"
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | TARGET_FLAG_NOP_FUN | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_NOP_FUN_DLLIMPORT)
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mapcs-26", "mno-thumb-interwork" }
+ { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
#undef WCHAR_TYPE
#define WCHAR_TYPE "short unsigned int"
@@ -90,13 +64,11 @@
call_used_regs [11] = 1;
-/* Define this macro if in some cases global symbols from one translation
- unit may not be bound to undefined symbols in another translation unit
- without user intervention. For instance, under Microsoft Windows
- symbols must be explicitly imported from shared libraries (DLLs). */
-#define MULTIPLE_SYMBOL_SPACES
+/* PE/COFF uses explicit import from shared libraries. */
+#define MULTIPLE_SYMBOL_SPACES 1
#define TARGET_ASM_UNIQUE_SECTION arm_pe_unique_section
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
#define SUPPORTS_ONE_ONLY 1
@@ -121,7 +93,7 @@
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n", \
arm_strip_name_encoding (NAME)); \
- function_section (DECL); \
+ switch_to_section (function_section (DECL)); \
} \
ARM_DECLARE_FUNCTION_NAME (STREAM, NAME, DECL); \
if (TARGET_THUMB) \
@@ -158,11 +130,11 @@
{ \
if (arm_dllexport_name_p (NAME)) \
{ \
- enum in_section save_section = in_section; \
+ section *save_section = in_section; \
drectve_section (); \
fprintf (STREAM, "\t.ascii \" -export:%s\"\n",\
arm_strip_name_encoding (NAME)); \
- switch_to_section (save_section, (DECL)); \
+ switch_to_section (save_section); \
} \
ASM_OUTPUT_LABEL ((STREAM), (NAME)); \
} \
@@ -172,50 +144,6 @@
#define DRECTVE_SECTION_ASM_OP "\t.section .drectve"
-/* A list of other sections which the compiler might be "in" at any
- given time. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_drectve
-
-/* A list of extra section function definitions. */
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- DRECTVE_SECTION_FUNCTION \
- SWITCH_TO_SECTION_FUNCTION
-
-#define DRECTVE_SECTION_FUNCTION \
-void \
-drectve_section (void) \
-{ \
- if (in_section != in_drectve) \
- { \
- fprintf (asm_out_file, "%s\n", DRECTVE_SECTION_ASM_OP); \
- in_section = in_drectve; \
- } \
-}
-
-/* Switch to SECTION (an `enum in_section').
-
- ??? This facility should be provided by GCC proper.
- The problem is that we want to temporarily switch sections in
- ASM_DECLARE_OBJECT_NAME and then switch back to the original section
- afterwards. */
-#define SWITCH_TO_SECTION_FUNCTION \
-static void \
-switch_to_section (enum in_section section, tree decl) \
-{ \
- switch (section) \
- { \
- case in_text: text_section (); break; \
- case in_data: data_section (); break; \
- case in_named: named_section (decl, NULL, 0); break; \
- case in_readonly_data: readonly_data_section (); break; \
- case in_ctors: ctors_section (); break; \
- case in_dtors: dtors_section (); break; \
- case in_drectve: drectve_section (); break; \
- default: abort (); break; \
- } \
-}
-
+#define drectve_section() \
+ (fprintf (asm_out_file, "%s\n", DRECTVE_SECTION_ASM_OP), \
+ in_section = NULL)
diff --git a/contrib/gcc/config/arm/pe.opt b/contrib/gcc/config/arm/pe.opt
new file mode 100644
index 0000000..f3d6d8b
--- /dev/null
+++ b/contrib/gcc/config/arm/pe.opt
@@ -0,0 +1,24 @@
+; PE-specific options for the ARM port
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mnop-fun-dllimport
+Target Report Mask(NOP_FUN_DLLIMPORT)
+Ignore dllimport attribute for functions
diff --git a/contrib/gcc/config/arm/pr-support.c b/contrib/gcc/config/arm/pr-support.c
new file mode 100644
index 0000000..0e750bf
--- /dev/null
+++ b/contrib/gcc/config/arm/pr-support.c
@@ -0,0 +1,381 @@
+/* ARM EABI compliant unwinding routines
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by Paul Brook
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+#include "unwind.h"
+
+/* We add a prototype for abort here to avoid creating a dependency on
+ target headers. */
+extern void abort (void);
+
+typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
+
+/* Misc constants. */
+#define R_IP 12
+#define R_SP 13
+#define R_LR 14
+#define R_PC 15
+
+#define uint32_highbit (((_uw) 1) << 31)
+
+void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
+
+/* Unwind descriptors. */
+
+typedef struct
+{
+ _uw16 length;
+ _uw16 offset;
+} EHT16;
+
+typedef struct
+{
+ _uw length;
+ _uw offset;
+} EHT32;
+
+/* Calculate the address encoded by a 31-bit self-relative offset at address
+ P. Copy of routine in unwind-arm.c. */
+
+static inline _uw
+selfrel_offset31 (const _uw *p)
+{
+ _uw offset;
+
+ offset = *p;
+ /* Sign extend to 32 bits. */
+ if (offset & (1 << 30))
+ offset |= 1u << 31;
+
+ return offset + (_uw) p;
+}
+
+
+/* Personality routine helper functions. */
+
+#define CODE_FINISH (0xb0)
+
+/* Return the next byte of unwinding information, or CODE_FINISH if there is
+ no data remaining. */
+static inline _uw8
+next_unwind_byte (__gnu_unwind_state * uws)
+{
+ _uw8 b;
+
+ if (uws->bytes_left == 0)
+ {
+ /* Load another word */
+ if (uws->words_left == 0)
+ return CODE_FINISH; /* Nothing left. */
+ uws->words_left--;
+ uws->data = *(uws->next++);
+ uws->bytes_left = 3;
+ }
+ else
+ uws->bytes_left--;
+
+ /* Extract the most significant byte. */
+ b = (uws->data >> 24) & 0xff;
+ uws->data <<= 8;
+ return b;
+}
+
+/* Execute the unwinding instructions described by UWS. */
+_Unwind_Reason_Code
+__gnu_unwind_execute (_Unwind_Context * context, __gnu_unwind_state * uws)
+{
+ _uw op;
+ int set_pc;
+ _uw reg;
+
+ set_pc = 0;
+ for (;;)
+ {
+ op = next_unwind_byte (uws);
+ if (op == CODE_FINISH)
+ {
+ /* If we haven't already set pc then copy it from lr. */
+ if (!set_pc)
+ {
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_LR, _UVRSD_UINT32,
+ &reg);
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_PC, _UVRSD_UINT32,
+ &reg);
+ set_pc = 1;
+ }
+ /* Drop out of the loop. */
+ break;
+ }
+ if ((op & 0x80) == 0)
+ {
+ /* vsp = vsp +- (imm6 << 2 + 4). */
+ _uw offset;
+
+ offset = ((op & 0x3f) << 2) + 4;
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ if (op & 0x40)
+ reg -= offset;
+ else
+ reg += offset;
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ continue;
+ }
+
+ if ((op & 0xf0) == 0x80)
+ {
+ op = (op << 8) | next_unwind_byte (uws);
+ if (op == 0x8000)
+ {
+ /* Refuse to unwind. */
+ return _URC_FAILURE;
+ }
+ /* Pop r4-r15 under mask. */
+ op = (op << 4) & 0xfff0;
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ if (op & (1 << R_PC))
+ set_pc = 1;
+ continue;
+ }
+ if ((op & 0xf0) == 0x90)
+ {
+ op &= 0xf;
+ if (op == 13 || op == 15)
+ /* Reserved. */
+ return _URC_FAILURE;
+ /* vsp = r[nnnn]. */
+ _Unwind_VRS_Get (context, _UVRSC_CORE, op, _UVRSD_UINT32, &reg);
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32, &reg);
+ continue;
+ }
+ if ((op & 0xf0) == 0xa0)
+ {
+ /* Pop r4-r[4+nnn], [lr]. */
+ _uw mask;
+
+ mask = (0xff0 >> (7 - (op & 7))) & 0xff0;
+ if (op & 8)
+ mask |= (1 << R_LR);
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, mask, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf0) == 0xb0)
+ {
+ /* op == 0xb0 already handled. */
+ if (op == 0xb1)
+ {
+ op = next_unwind_byte (uws);
+ if (op == 0 || ((op & 0xf0) != 0))
+ /* Spare. */
+ return _URC_FAILURE;
+ /* Pop r0-r4 under mask. */
+ if (_Unwind_VRS_Pop (context, _UVRSC_CORE, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xb2)
+ {
+ /* vsp = vsp + 0x204 + (uleb128 << 2). */
+ int shift;
+
+ _Unwind_VRS_Get (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+ &reg);
+ op = next_unwind_byte (uws);
+ shift = 2;
+ while (op & 0x80)
+ {
+ reg += ((op & 0x7f) << shift);
+ shift += 7;
+ op = next_unwind_byte (uws);
+ }
+ reg += ((op & 0x7f) << shift) + 0x204;
+ _Unwind_VRS_Set (context, _UVRSC_CORE, R_SP, _UVRSD_UINT32,
+ &reg);
+ continue;
+ }
+ if (op == 0xb3)
+ {
+ /* Pop VFP registers with fldmx. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xfc) == 0xb4)
+ {
+ /* Pop FPA E[4]-E[4+nn]. */
+ op = 0x40000 | ((op & 3) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* op & 0xf8 == 0xb8. */
+ /* Pop VFP D[8]-D[8+nnn] with fldmx. */
+ op = 0x80000 | ((op & 7) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_VFPX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf0) == 0xc0)
+ {
+ if (op == 0xc6)
+ {
+ /* Pop iWMMXt D registers. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc7)
+ {
+ op = next_unwind_byte (uws);
+ if (op == 0 || (op & 0xf0) != 0)
+ /* Spare. */
+ return _URC_FAILURE;
+ /* Pop iWMMXt wCGR{3,2,1,0} under mask. */
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXC, op, _UVRSD_UINT32)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if ((op & 0xf8) == 0xc0)
+ {
+ /* Pop iWMMXt wR[10]-wR[10+nnn]. */
+ op = 0xa0000 | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_WMMXD, op, _UVRSD_UINT64)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc8)
+ {
+ /* Pop FPA registers. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_FPA, op, _UVRSD_FPAX)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ if (op == 0xc9)
+ {
+ /* Pop VFP registers with fldmd. */
+ op = next_unwind_byte (uws);
+ op = ((op & 0xf0) << 12) | ((op & 0xf) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* Spare. */
+ return _URC_FAILURE;
+ }
+ if ((op & 0xf8) == 0xd0)
+ {
+ /* Pop VFP D[8]-D[8+nnn] with fldmd. */
+ op = 0x80000 | ((op & 7) + 1);
+ if (_Unwind_VRS_Pop (context, _UVRSC_VFP, op, _UVRSD_DOUBLE)
+ != _UVRSR_OK)
+ return _URC_FAILURE;
+ continue;
+ }
+ /* Spare. */
+ return _URC_FAILURE;
+ }
+ return _URC_OK;
+}
+
+
+/* Execute the unwinding instructions associated with a frame. UCBP and
+ CONTEXT are the current exception object and virtual CPU state
+ respectively. */
+
+_Unwind_Reason_Code
+__gnu_unwind_frame (_Unwind_Control_Block * ucbp, _Unwind_Context * context)
+{
+ _uw *ptr;
+ __gnu_unwind_state uws;
+
+ ptr = (_uw *) ucbp->pr_cache.ehtp;
+ /* Skip over the personality routine address. */
+ ptr++;
+ /* Setup the unwinder state. */
+ uws.data = (*ptr) << 8;
+ uws.next = ptr + 1;
+ uws.bytes_left = 3;
+ uws.words_left = ((*ptr) >> 24) & 0xff;
+
+ return __gnu_unwind_execute (context, &uws);
+}
+
+/* Get the _Unwind_Control_Block from an _Unwind_Context. */
+
+static inline _Unwind_Control_Block *
+unwind_UCB_from_context (_Unwind_Context * context)
+{
+ return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
+}
+
+/* Get the start address of the function being unwound. */
+
+_Unwind_Ptr
+_Unwind_GetRegionStart (_Unwind_Context * context)
+{
+ _Unwind_Control_Block *ucbp;
+
+ ucbp = unwind_UCB_from_context (context);
+ return (_Unwind_Ptr) ucbp->pr_cache.fnstart;
+}
+
+/* Find the Language specific exception data. */
+
+void *
+_Unwind_GetLanguageSpecificData (_Unwind_Context * context)
+{
+ _Unwind_Control_Block *ucbp;
+ _uw *ptr;
+
+ /* Get a pointer to the exception table entry. */
+ ucbp = unwind_UCB_from_context (context);
+ ptr = (_uw *) ucbp->pr_cache.ehtp;
+ /* Skip the personality routine address. */
+ ptr++;
+ /* Skip the unwind opcodes. */
+ ptr += (((*ptr) >> 24) & 0xff) + 1;
+
+ return ptr;
+}
+
diff --git a/contrib/gcc/config/arm/predicates.md b/contrib/gcc/config/arm/predicates.md
new file mode 100644
index 0000000..4a08204
--- /dev/null
+++ b/contrib/gcc/config/arm/predicates.md
@@ -0,0 +1,458 @@
+;; Predicate definitions for ARM and Thumb
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;; Contributed by ARM Ltd.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_predicate "s_register_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ /* We don't consider registers whose class is NO_REGS
+ to be a register operand. */
+ /* XXX might have to check for lo regs only for thumb ??? */
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) != NO_REGS));
+})
+
+;; Any hard register.
+(define_predicate "arm_hard_register_operand"
+ (match_code "reg")
+{
+ return REGNO (op) < FIRST_PSEUDO_REGISTER;
+})
+
+;; Any core register, or any pseudo. */
+(define_predicate "arm_general_register_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) <= LAST_ARM_REGNUM
+ || REGNO (op) >= FIRST_PSEUDO_REGISTER));
+})
+
+(define_predicate "f_register_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ /* We don't consider registers whose class is NO_REGS
+ to be a register operand. */
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == FPA_REGS));
+})
+
+;; Reg, subreg(reg) or const_int.
+(define_predicate "reg_or_int_operand"
+ (ior (match_code "const_int")
+ (match_operand 0 "s_register_operand")))
+
+(define_predicate "arm_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "const_ok_for_arm (INTVAL (op))")))
+
+(define_predicate "arm_neg_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "const_ok_for_arm (-INTVAL (op))")))
+
+(define_predicate "arm_not_immediate_operand"
+ (and (match_code "const_int")
+ (match_test "const_ok_for_arm (~INTVAL (op))")))
+
+;; Something valid on the RHS of an ARM data-processing instruction
+(define_predicate "arm_rhs_operand"
+ (ior (match_operand 0 "s_register_operand")
+ (match_operand 0 "arm_immediate_operand")))
+
+(define_predicate "arm_rhsm_operand"
+ (ior (match_operand 0 "arm_rhs_operand")
+ (match_operand 0 "memory_operand")))
+
+(define_predicate "arm_add_operand"
+ (ior (match_operand 0 "arm_rhs_operand")
+ (match_operand 0 "arm_neg_immediate_operand")))
+
+(define_predicate "arm_addimm_operand"
+ (ior (match_operand 0 "arm_immediate_operand")
+ (match_operand 0 "arm_neg_immediate_operand")))
+
+(define_predicate "arm_not_operand"
+ (ior (match_operand 0 "arm_rhs_operand")
+ (match_operand 0 "arm_not_immediate_operand")))
+
+;; True if the operand is a memory reference which contains an
+;; offsettable address.
+(define_predicate "offsettable_memory_operand"
+ (and (match_code "mem")
+ (match_test
+ "offsettable_address_p (reload_completed | reload_in_progress,
+ mode, XEXP (op, 0))")))
+
+;; True if the operand is a memory operand that does not have an
+;; automodified base register (and thus will not generate output reloads).
+(define_predicate "call_memory_operand"
+ (and (match_code "mem")
+ (and (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0)))
+ != RTX_AUTOINC")
+ (match_operand 0 "memory_operand"))))
+
+(define_predicate "arm_reload_memory_operand"
+ (and (match_code "mem,reg,subreg")
+ (match_test "(!CONSTANT_P (op)
+ && (true_regnum(op) == -1
+ || (GET_CODE (op) == REG
+ && REGNO (op) >= FIRST_PSEUDO_REGISTER)))")))
+
+;; True for valid operands for the rhs of an floating point insns.
+;; Allows regs or certain consts on FPA, just regs for everything else.
+(define_predicate "arm_float_rhs_operand"
+ (ior (match_operand 0 "s_register_operand")
+ (and (match_code "const_double")
+ (match_test "TARGET_FPA && arm_const_double_rtx (op)"))))
+
+(define_predicate "arm_float_add_operand"
+ (ior (match_operand 0 "arm_float_rhs_operand")
+ (and (match_code "const_double")
+ (match_test "TARGET_FPA && neg_const_double_rtx_ok_for_fpa (op)"))))
+
+(define_predicate "vfp_compare_operand"
+ (ior (match_operand 0 "s_register_operand")
+ (and (match_code "const_double")
+ (match_test "arm_const_double_rtx (op)"))))
+
+(define_predicate "arm_float_compare_operand"
+ (if_then_else (match_test "TARGET_VFP")
+ (match_operand 0 "vfp_compare_operand")
+ (match_operand 0 "arm_float_rhs_operand")))
+
+;; True for valid index operands.
+(define_predicate "index_operand"
+ (ior (match_operand 0 "s_register_operand")
+ (and (match_operand 0 "immediate_operand")
+ (match_test "(GET_CODE (op) != CONST_INT
+ || (INTVAL (op) < 4096 && INTVAL (op) > -4096))"))))
+
+;; True for operators that can be combined with a shift in ARM state.
+(define_special_predicate "shiftable_operator"
+ (and (match_code "plus,minus,ior,xor,and")
+ (match_test "mode == GET_MODE (op)")))
+
+;; True for logical binary operators.
+(define_special_predicate "logical_binary_operator"
+ (and (match_code "ior,xor,and")
+ (match_test "mode == GET_MODE (op)")))
+
+;; True for shift operators.
+(define_special_predicate "shift_operator"
+ (and (ior (ior (and (match_code "mult")
+ (match_test "power_of_two_operand (XEXP (op, 1), mode)"))
+ (and (match_code "rotate")
+ (match_test "GET_CODE (XEXP (op, 1)) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (op, 1))) < 32")))
+ (match_code "ashift,ashiftrt,lshiftrt,rotatert"))
+ (match_test "mode == GET_MODE (op)")))
+
+;; True for EQ & NE
+(define_special_predicate "equality_operator"
+ (match_code "eq,ne"))
+
+;; True for comparisons other than LTGT or UNEQ.
+(define_special_predicate "arm_comparison_operator"
+ (match_code "eq,ne,le,lt,ge,gt,geu,gtu,leu,ltu,unordered,ordered,unlt,unle,unge,ungt"))
+
+(define_special_predicate "minmax_operator"
+ (and (match_code "smin,smax,umin,umax")
+ (match_test "mode == GET_MODE (op)")))
+
+(define_special_predicate "cc_register"
+ (and (match_code "reg")
+ (and (match_test "REGNO (op) == CC_REGNUM")
+ (ior (match_test "mode == GET_MODE (op)")
+ (match_test "mode == VOIDmode && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))))
+
+(define_special_predicate "dominant_cc_register"
+ (match_code "reg")
+{
+ if (mode == VOIDmode)
+ {
+ mode = GET_MODE (op);
+
+ if (GET_MODE_CLASS (mode) != MODE_CC)
+ return false;
+ }
+
+ return (cc_register (op, mode)
+ && (mode == CC_DNEmode
+ || mode == CC_DEQmode
+ || mode == CC_DLEmode
+ || mode == CC_DLTmode
+ || mode == CC_DGEmode
+ || mode == CC_DGTmode
+ || mode == CC_DLEUmode
+ || mode == CC_DLTUmode
+ || mode == CC_DGEUmode
+ || mode == CC_DGTUmode));
+})
+
+(define_special_predicate "arm_extendqisi_mem_op"
+ (and (match_operand 0 "memory_operand")
+ (match_test "arm_legitimate_address_p (mode, XEXP (op, 0), SIGN_EXTEND,
+ 0)")))
+
+(define_predicate "power_of_two_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT value = INTVAL (op);
+
+ return value != 0 && (value & (value - 1)) == 0;
+})
+
+(define_predicate "nonimmediate_di_operand"
+ (match_code "reg,subreg,mem")
+{
+ if (s_register_operand (op, mode))
+ return true;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return GET_CODE (op) == MEM && memory_address_p (DImode, XEXP (op, 0));
+})
+
+(define_predicate "di_operand"
+ (ior (match_code "const_int,const_double")
+ (and (match_code "reg,subreg,mem")
+ (match_operand 0 "nonimmediate_di_operand"))))
+
+(define_predicate "nonimmediate_soft_df_operand"
+ (match_code "reg,subreg,mem")
+{
+ if (s_register_operand (op, mode))
+ return true;
+
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return GET_CODE (op) == MEM && memory_address_p (DFmode, XEXP (op, 0));
+})
+
+(define_predicate "soft_df_operand"
+ (ior (match_code "const_double")
+ (and (match_code "reg,subreg,mem")
+ (match_operand 0 "nonimmediate_soft_df_operand"))))
+
+(define_predicate "const_shift_operand"
+ (and (match_code "const_int")
+ (ior (match_operand 0 "power_of_two_operand")
+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 32"))))
+
+
+(define_special_predicate "load_multiple_operation"
+ (match_code "parallel")
+{
+ HOST_WIDE_INT count = XVECLEN (op, 0);
+ int dest_regno;
+ rtx src_addr;
+ HOST_WIDE_INT i = 1, base = 0;
+ rtx elt;
+
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET)
+ return false;
+
+ /* Check to see if this might be a write-back. */
+ if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
+ {
+ i++;
+ base = 1;
+
+ /* Now check it more carefully. */
+ if (GET_CODE (SET_DEST (elt)) != REG
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
+ || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
+ || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
+ return false;
+ }
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= i
+ || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != REG
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != MEM)
+ return false;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, i - 1)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, i - 1)), 0);
+
+ for (; i < count; i++)
+ {
+ elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != (unsigned int)(dest_regno + i - base)
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || 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 - base) * 4)
+ return false;
+ }
+
+ return true;
+})
+
+(define_special_predicate "store_multiple_operation"
+ (match_code "parallel")
+{
+ HOST_WIDE_INT count = XVECLEN (op, 0);
+ int src_regno;
+ rtx dest_addr;
+ HOST_WIDE_INT i = 1, base = 0;
+ rtx elt;
+
+ if (count <= 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET)
+ return false;
+
+ /* Check to see if this might be a write-back. */
+ if (GET_CODE (SET_SRC (elt = XVECEXP (op, 0, 0))) == PLUS)
+ {
+ i++;
+ base = 1;
+
+ /* Now check it more carefully. */
+ if (GET_CODE (SET_DEST (elt)) != REG
+ || GET_CODE (XEXP (SET_SRC (elt), 0)) != REG
+ || GET_CODE (XEXP (SET_SRC (elt), 1)) != CONST_INT
+ || INTVAL (XEXP (SET_SRC (elt), 1)) != (count - 1) * 4)
+ return false;
+ }
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count <= i
+ || GET_CODE (XVECEXP (op, 0, i - 1)) != SET
+ || GET_CODE (SET_DEST (XVECEXP (op, 0, i - 1))) != MEM
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, i - 1))) != REG)
+ return false;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, i - 1)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, i - 1)), 0);
+
+ for (; i < count; i++)
+ {
+ elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != (unsigned int)(src_regno + i - base)
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || 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 - base) * 4)
+ return false;
+ }
+
+ return true;
+})
+
+(define_special_predicate "multi_register_push"
+ (match_code "parallel")
+{
+ if ((GET_CODE (XVECEXP (op, 0, 0)) != SET)
+ || (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC)
+ || (XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPEC_PUSH_MULT))
+ return false;
+
+ return true;
+})
+
+;;-------------------------------------------------------------------------
+;;
+;; Thumb predicates
+;;
+
+(define_predicate "thumb_cmp_operand"
+ (ior (and (match_code "reg,subreg")
+ (match_operand 0 "s_register_operand"))
+ (and (match_code "const_int")
+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 256"))))
+
+(define_predicate "thumb_cmpneg_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) < 0 && INTVAL (op) > -256")))
+
+;; Return TRUE if a result can be stored in OP without clobbering the
+;; condition code register. Prior to reload we only accept a
+;; register. After reload we have to be able to handle memory as
+;; well, since a pseudo may not get a hard reg and reload cannot
+;; handle output-reloads on jump insns.
+
+;; We could possibly handle mem before reload as well, but that might
+;; complicate things with the need to handle increment
+;; side-effects.
+(define_predicate "thumb_cbrch_target_operand"
+ (and (match_code "reg,subreg,mem")
+ (ior (match_operand 0 "s_register_operand")
+ (and (match_test "reload_in_progress || reload_completed")
+ (match_operand 0 "memory_operand")))))
+
+;;-------------------------------------------------------------------------
+;;
+;; MAVERICK predicates
+;;
+
+(define_predicate "cirrus_register_operand"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return (GET_CODE (op) == REG
+ && (REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS
+ || REGNO_REG_CLASS (REGNO (op)) == GENERAL_REGS));
+})
+
+(define_predicate "cirrus_fp_register"
+ (match_code "reg,subreg")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ return (GET_CODE (op) == REG
+ && (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (op)) == CIRRUS_REGS));
+})
+
+(define_predicate "cirrus_shift_const"
+ (and (match_code "const_int")
+ (match_test "((unsigned HOST_WIDE_INT) INTVAL (op)) < 64")))
+
+
diff --git a/contrib/gcc/config/arm/rtems-elf.h b/contrib/gcc/config/arm/rtems-elf.h
index a736ee1..f71e582 100644
--- a/contrib/gcc/config/arm/rtems-elf.h
+++ b/contrib/gcc/config/arm/rtems-elf.h
@@ -1,5 +1,5 @@
/* Definitions for RTEMS based ARM systems using ELF
- Copyright (C) 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#undef TARGET_VERSION
@@ -29,3 +29,18 @@
builtin_define ("__rtems__"); \
builtin_assert ("system=rtems"); \
} while (0)
+
+/*
+ * The default in gcc now is soft-float, but gcc misses it to
+ * pass it to the assembler.
+ */
+#undef SUBTARGET_EXTRA_ASM_SPEC
+#define SUBTARGET_EXTRA_ASM_SPEC "\
+ %{!mhard-float: %{!msoft-float:-mfpu=softfpa}}"
+
+/*
+ * The default includes --start-group and --end-group which conflicts
+ * with how this used to be defined.
+ */
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC "%G %L"
diff --git a/contrib/gcc/config/arm/semi.h b/contrib/gcc/config/arm/semi.h
index 2ab06cb..0de57d6 100644
--- a/contrib/gcc/config/arm/semi.h
+++ b/contrib/gcc/config/arm/semi.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
- Copyright (C) 1994, 1995, 1996, 1997, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997, 2001, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Richard Earnshaw (richard.earnshaw@arm.com)
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#define STARTFILE_SPEC "crt0.o%s"
@@ -37,8 +38,12 @@
#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
#endif
+#ifndef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
+#endif
+
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_APCS_FRAME)
#endif
#ifndef SUBTARGET_EXTRA_SPECS
@@ -64,10 +69,8 @@
%{mcpu=*:-mcpu=%*} \
%{march=*:-march=%*} \
%{mapcs-float:-mfloat} \
-%{msoft-float:-mfpu=softfpa} \
+%{msoft-float:-mfloat-abi=soft} %{mhard-float:-mfloat-abi=hard} \
+%{mfloat-abi=*} %{mfpu=*} \
%{mthumb-interwork:-mthumb-interwork} \
%(subtarget_extra_asm_spec)"
#endif
-
-#undef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
diff --git a/contrib/gcc/config/arm/semiaof.h b/contrib/gcc/config/arm/semiaof.h
index 19a6cf8..9038f0d 100644
--- a/contrib/gcc/config/arm/semiaof.h
+++ b/contrib/gcc/config/arm/semiaof.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler. ARM on semi-hosted platform
AOF Syntax assembler.
- Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 1997, 2004 Free Software Foundation, Inc.
Contributed by Richard Earnshaw (richard.earnshaw@armltd.co.uk)
This file is part of GCC.
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do { \
@@ -26,17 +26,15 @@
builtin_define_std ("semi"); \
} while (0)
-#define ASM_SPEC "%{g -g} -arch 4 \
--apcs 3%{mapcs-32:/32bit}%{mapcs-26:/26bit}%{!mapcs-26:%{!macps-32:/32bit}}"
+#define ASM_SPEC "%{g -g} -arch 4 -apcs 3/32bit"
#define LIB_SPEC "%{Eb: armlib_h.32b%s}%{!Eb: armlib_h.32l%s}"
#define TARGET_VERSION fputs (" (ARM/semi-hosted)", stderr);
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_HARD
+
+#define TARGET_DEFAULT (0)
/* The Norcroft C library defines size_t as "unsigned int". */
#define SIZE_TYPE "unsigned int"
-
-#undef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
diff --git a/contrib/gcc/config/arm/strongarm-coff.h b/contrib/gcc/config/arm/strongarm-coff.h
index 77dab37..0ba32ce 100644
--- a/contrib/gcc/config/arm/strongarm-coff.h
+++ b/contrib/gcc/config/arm/strongarm-coff.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#ifndef SUBTARGET_CPU_DEFAULT
diff --git a/contrib/gcc/config/arm/strongarm-elf.h b/contrib/gcc/config/arm/strongarm-elf.h
index 476b2e4..84c2099 100644
--- a/contrib/gcc/config/arm/strongarm-elf.h
+++ b/contrib/gcc/config/arm/strongarm-elf.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#ifndef TARGET_VERSION
diff --git a/contrib/gcc/config/arm/strongarm-pe.h b/contrib/gcc/config/arm/strongarm-pe.h
index bb123e5..f1a13c0 100644
--- a/contrib/gcc/config/arm/strongarm-pe.h
+++ b/contrib/gcc/config/arm/strongarm-pe.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (StrongARM/PE)", stderr);
diff --git a/contrib/gcc/config/arm/symbian.h b/contrib/gcc/config/arm/symbian.h
new file mode 100644
index 0000000..af1ba9a
--- /dev/null
+++ b/contrib/gcc/config/arm/symbian.h
@@ -0,0 +1,101 @@
+/* Configuration file for Symbian OS on ARM processors.
+ Copyright (C) 2004, 2005
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* Do not expand builtin functions (unless explicitly prefixed with
+ "__builtin"). Symbian OS code relies on properties of the standard
+ library that go beyond those guaranteed by the ANSI/ISO standard.
+ For example, "memcpy" works even with overlapping memory, like
+ "memmove". We cannot simply set flag_no_builtin in arm.c because
+ (a) flag_no_builtin is not declared in language-independent code,
+ and (b) that would prevent users from explicitly overriding the
+ default with -fbuiltin, which may sometimes be useful.
+
+ Make all symbols hidden by default. Symbian OS expects that all
+ exported symbols will be explicitly marked with
+ "__declspec(dllexport)".
+
+ Enumeration types use 4 bytes, even if the enumerals are small,
+ unless explicitly overridden.
+
+ The wchar_t type is a 2-byte type, unless explicitly
+ overridden. */
+#define CC1_SPEC \
+ "%{!fbuiltin:%{!fno-builtin:-fno-builtin}} " \
+ "%{!fvisibility=*:-fvisibility=hidden} " \
+ "%{!fshort-enums:%{!fno-short-enums:-fno-short-enums}} " \
+ "%{!fshort-wchar:%{!fno-short-wchar:-fshort-wchar}} "
+#define CC1PLUS_SPEC CC1_SPEC
+
+/* Symbian OS does not use crt*.o, unlike the generic unknown-elf
+ configuration. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC ""
+
+/* Do not link with any libraries by default. On Symbian OS, the user
+ must supply all required libraries on the command line. */
+#undef LIB_SPEC
+#define LIB_SPEC ""
+
+/* Support the "dllimport" attribute. */
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
+
+/* Symbian OS assumes ARM V5 or above. Since -march=armv5 is
+ equivalent to making the ARM 10TDMI core the default, we can set
+ SUBTARGET_CPU_DEFAULT and get an equivalent effect. */
+#undef SUBTARGET_CPU_DEFAULT
+#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
+
+/* The assembler should assume VFP FPU format, and armv5t. */
+#undef SUBTARGET_ASM_FLOAT_SPEC
+#define SUBTARGET_ASM_FLOAT_SPEC \
+ "%{!mfpu=*:-mfpu=vfp} %{!mcpu=*:%{!march=*:-march=armv5t}}"
+
+/* SymbianOS provides the BPABI routines in a separate library.
+ Therefore, we do not need to define any of them in libgcc. */
+#undef RENAME_LIBRARY
+#define RENAME_LIBRARY(GCC_NAME, AEABI_NAME) /* empty */
+
+/* Define the __symbian__ macro. */
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ /* Include the default BPABI stuff. */ \
+ TARGET_BPABI_CPP_BUILTINS (); \
+ builtin_define ("__symbian__"); \
+ } \
+ while (false)
+
+/* On SymbianOS, these sections are not writable, so we use "a",
+ rather than "aw", for the section attributes. */
+#undef ARM_EABI_CTORS_SECTION_OP
+#define ARM_EABI_CTORS_SECTION_OP \
+ "\t.section\t.init_array,\"a\",%init_array"
+#undef ARM_EABI_DTORS_SECTION_OP
+#define ARM_EABI_DTORS_SECTION_OP \
+ "\t.section\t.fini_array,\"a\",%fini_array"
+
+/* SymbianOS cannot merge entities with vague linkage at runtime. */
+#define TARGET_ARM_DYNAMIC_VAGUE_LINKAGE_P false
diff --git a/contrib/gcc/config/arm/t-arm b/contrib/gcc/config/arm/t-arm
new file mode 100644
index 0000000..9fcd187
--- /dev/null
+++ b/contrib/gcc/config/arm/t-arm
@@ -0,0 +1,22 @@
+# Rules common to all arm targets
+
+MD_INCLUDES= $(srcdir)/config/arm/arm-tune.md \
+ $(srcdir)/config/arm/predicates.md \
+ $(srcdir)/config/arm/arm-generic.md \
+ $(srcdir)/config/arm/arm1020e.md \
+ $(srcdir)/config/arm/arm1026ejs.md \
+ $(srcdir)/config/arm/arm1136jfs.md \
+ $(srcdir)/config/arm/arm926ejs.md \
+ $(srcdir)/config/arm/cirrus.md \
+ $(srcdir)/config/arm/fpa.md \
+ $(srcdir)/config/arm/iwmmxt.md \
+ $(srcdir)/config/arm/vfp.md
+
+s-config s-conditions s-flags s-codes s-constants s-emit s-recog s-preds \
+ s-opinit s-extract s-peep s-attr s-attrtab s-output: $(MD_INCLUDES)
+
+$(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/gentune.sh \
+ $(srcdir)/config/arm/arm-cores.def
+ $(SHELL) $(srcdir)/config/arm/gentune.sh \
+ $(srcdir)/config/arm/arm-cores.def > \
+ $(srcdir)/config/arm/arm-tune.md
diff --git a/contrib/gcc/config/arm/t-arm-coff b/contrib/gcc/config/arm/t-arm-coff
index 8eef976..763add3 100644
--- a/contrib/gcc/config/arm/t-arm-coff
+++ b/contrib/gcc/config/arm/t-arm-coff
@@ -31,4 +31,4 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/contrib/gcc/config/arm/t-arm-elf b/contrib/gcc/config/arm/t-arm-elf
index 3f48f8b..bee4051 100644
--- a/contrib/gcc/config/arm/t-arm-elf
+++ b/contrib/gcc/config/arm/t-arm-elf
@@ -1,9 +1,10 @@
LIB1ASMSRC = arm/lib1funcs.asm
LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func \
_call_via_rX _interwork_call_via_rX \
+ _lshrdi3 _ashrdi3 _ashldi3 \
_negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
- _fixsfsi _fixunssfsi
+ _fixsfsi _fixunssfsi _floatdidf _floatdisf _floatundidf _floatundisf
MULTILIB_OPTIONS = marm/mthumb
MULTILIB_DIRNAMES = arm thumb
@@ -13,7 +14,7 @@ MULTILIB_MATCHES =
# MULTILIB_OPTIONS += mcpu=ep9312
# MULTILIB_DIRNAMES += ep9312
# MULTILIB_EXCEPTIONS += *mthumb/*mcpu=ep9312*
-
+#
# MULTILIB_OPTIONS += mlittle-endian/mbig-endian
# MULTILIB_DIRNAMES += le be
# MULTILIB_MATCHES += mbig-endian=mbe mlittle-endian=mle
@@ -22,13 +23,8 @@ MULTILIB_MATCHES =
# MULTILIB_DIRNAMES += fpu soft
# MULTILIB_EXCEPTIONS += *mthumb/*mhard-float*
#
-# MULTILIB_OPTIONS += mapcs-32/mapcs-26
-# MULTILIB_DIRNAMES += 32bit 26bit
-# MULTILIB_EXCEPTIONS += *mthumb/*mapcs-26*
-#
# MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
# MULTILIB_DIRNAMES += normal interwork
-# MULTILIB_EXCEPTIONS += *mapcs-26/*mthumb-interwork*
#
# MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
# MULTILIB_DIRNAMES += elf under
@@ -71,7 +67,7 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
# Assemble startup files.
$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
diff --git a/contrib/gcc/config/arm/t-bpabi b/contrib/gcc/config/arm/t-bpabi
new file mode 100644
index 0000000..b5c6a0b
--- /dev/null
+++ b/contrib/gcc/config/arm/t-bpabi
@@ -0,0 +1,16 @@
+# Add the bpabi.S functions.
+LIB1ASMFUNCS += _aeabi_lcmp _aeabi_ulcmp _aeabi_ldivmod _aeabi_uldivmod
+
+# Add the BPABI C functions.
+LIB2FUNCS_EXTRA = $(srcdir)/config/arm/bpabi.c \
+ $(srcdir)/config/arm/unaligned-funcs.c
+
+UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
+LIB2ADDEH = $(srcdir)/config/arm/unwind-arm.c \
+ $(srcdir)/config/arm/libunwind.S \
+ $(srcdir)/config/arm/pr-support.c $(srcdir)/unwind-c.c
+LIB2ADDEHDEP = $(UNWIND_H) $(srcdir)/config/$(LIB1ASMSRC)
+
+# Add the BPABI names.
+SHLIB_MAPFILES += $(srcdir)/config/arm/libgcc-bpabi.ver
+
diff --git a/contrib/gcc/config/arm/t-linux b/contrib/gcc/config/arm/t-linux
index 1c5f48a..b2697e6 100644
--- a/contrib/gcc/config/arm/t-linux
+++ b/contrib/gcc/config/arm/t-linux
@@ -9,11 +9,6 @@ LIB1ASMFUNCS = _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_lnx
# MULTILIB_OPTIONS = mhard-float/msoft-float
# MULTILIB_DIRNAMES = hard-float soft-float
-# If you want to build both APCS variants as multilib options this is how
-# to do it.
-# MULTILIB_OPTIONS += mapcs-32/mapcs-26
-# MULTILIB_DIRNAMES += apcs-32 apcs-26
-
# EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
# LIBGCC = stmp-multilib
diff --git a/contrib/gcc/config/arm/t-linux-eabi b/contrib/gcc/config/arm/t-linux-eabi
new file mode 100644
index 0000000..5e8d94d
--- /dev/null
+++ b/contrib/gcc/config/arm/t-linux-eabi
@@ -0,0 +1,14 @@
+# These functions are included in shared libraries.
+TARGET_LIBGCC2_CFLAGS = -fPIC
+
+# We do not build a Thumb multilib for Linux because the definition of
+# CLEAR_INSN_CACHE in linux-gas.h does not work in Thumb mode.
+MULTILIB_OPTIONS =
+MULTILIB_DIRNAMES =
+
+# Use a version of div0 which raises SIGFPE.
+LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx
+
+# Multilib the standard Linux files. Don't include crti.o or crtn.o,
+# which are provided by glibc.
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
diff --git a/contrib/gcc/config/arm/t-netbsd b/contrib/gcc/config/arm/t-netbsd
index 533fab9..7d0724c 100644
--- a/contrib/gcc/config/arm/t-netbsd
+++ b/contrib/gcc/config/arm/t-netbsd
@@ -2,6 +2,7 @@
# difference. It is then pointless adding debugging.
TARGET_LIBGCC2_CFLAGS = -fomit-frame-pointer -fpic
LIBGCC2_DEBUG_CFLAGS = -g0
+LIB2FUNCS_EXTRA = $(srcdir)/config/floatunsidf.c $(srcdir)/config/floatunsisf.c
# Build a shared libgcc library.
SHLIB_EXT = .so
@@ -20,6 +21,8 @@ SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
$(LN_S) $(SHLIB_NAME) $(SHLIB_SONAME)
# $(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_NAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME); \
+SHLIB_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir); \
+ $(INSTALL_DATA) $(SHLIB_NAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME); \
rm -f $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME); \
$(LN_S) $(SHLIB_SONAME) $$(DESTDIR)$$(slibdir)/$(SHLIB_NAME)
diff --git a/contrib/gcc/config/arm/t-pe b/contrib/gcc/config/arm/t-pe
index 4c20b31..741e2b8 100644
--- a/contrib/gcc/config/arm/t-pe
+++ b/contrib/gcc/config/arm/t-pe
@@ -24,9 +24,9 @@ pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
-MULTILIB_OPTIONS = mhard-float mthumb mapcs-32
-MULTILIB_DIRNAMES = fpu thumb apcs32
+MULTILIB_OPTIONS = mhard-float mthumb
+MULTILIB_DIRNAMES = fpu thumb
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc
+TARGET_LIBGCC2_CFLAGS = \ No newline at end of file
diff --git a/contrib/gcc/config/arm/t-semi b/contrib/gcc/config/arm/t-semi
index abd642c..f5d8f1a 100644
--- a/contrib/gcc/config/arm/t-semi
+++ b/contrib/gcc/config/arm/t-semi
@@ -29,9 +29,9 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
echo '#endif' >> dp-bit.c
-MULTILIB_OPTIONS = msoft-float mapcs-26 mbig-endian mwords-little-endian
-MULTILIB_DIRNAMES = soft apcs26 big wlittle
-MULTILIB_EXCEPTIONS = *mapcs-26/*mbig-endian* mwords-little-endian *mapcs-26/mwords-little-endian msoft-float/mwords-little-endian
+MULTILIB_OPTIONS = msoft-float mbig-endian mwords-little-endian
+MULTILIB_DIRNAMES = soft big wlittle
+MULTILIB_EXCEPTIONS = mwords-little-endian msoft-float/mwords-little-endian
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/arm/t-strongarm-elf b/contrib/gcc/config/arm/t-strongarm-elf
index 46e2ac4..c819354 100644
--- a/contrib/gcc/config/arm/t-strongarm-elf
+++ b/contrib/gcc/config/arm/t-strongarm-elf
@@ -32,7 +32,7 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
# Assemble startup files.
$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
diff --git a/contrib/gcc/config/arm/t-strongarm-pe b/contrib/gcc/config/arm/t-strongarm-pe
index e401666..2e4732f 100644
--- a/contrib/gcc/config/arm/t-strongarm-pe
+++ b/contrib/gcc/config/arm/t-strongarm-pe
@@ -35,4 +35,4 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/contrib/gcc/config/arm/t-symbian b/contrib/gcc/config/arm/t-symbian
new file mode 100644
index 0000000..db89138
--- /dev/null
+++ b/contrib/gcc/config/arm/t-symbian
@@ -0,0 +1,32 @@
+LIB1ASMFUNCS = _bb_init_func _call_via_rX _interwork_call_via_rX
+
+# These functions have __aeabi equivalents and will never be called by GCC.
+# By putting them in LIB1ASMFUNCS, we avoid the standard libgcc2.c code being
+# used -- and we make sure that definitions are not available in lib1funcs.asm,
+# either, so they end up undefined.
+LIB1ASMFUNCS += \
+ _ashldi3 _ashrdi3 _divdi3 _floatdidf _udivmoddi4 _umoddi3 \
+ _udivdi3 _lshrdi3 _moddi3 _muldi3 _negdi2 _cmpdi2 \
+ _fixdfdi _fixsfdi _fixunsdfdi _fixunssfdi _floatdisf \
+ _negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
+ _truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
+ _fixsfsi _fixunssfsi
+
+# Include the gcc personality routine
+UNWIND_H = $(srcdir)/config/arm/unwind-arm.h
+LIB2ADDEH = $(srcdir)/unwind-c.c $(srcdir)/config/arm/pr-support.c
+LIB2ADDEHDEP = $(UNWIND_H)
+
+# Create a multilib for processors with VFP floating-point, and a
+# multilib for those without -- using the soft-float ABI in both
+# cases. Symbian OS object should be compiled with interworking
+# enabled, so there are no separate thumb-mode libraries.
+MULTILIB_OPTIONS = mfloat-abi=softfp
+MULTILIB_DIRNAMES = softfp
+
+# There is no C library to link against on Symbian OS -- at least when
+# building GCC.
+SHLIB_LC =
+
+# Symbian OS provides its own startup code.
+EXTRA_MULTILIB_PARTS=
diff --git a/contrib/gcc/config/arm/t-wince-pe b/contrib/gcc/config/arm/t-wince-pe
index 9537a7f..fca9853 100644
--- a/contrib/gcc/config/arm/t-wince-pe
+++ b/contrib/gcc/config/arm/t-wince-pe
@@ -24,9 +24,9 @@ pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
-MULTILIB_OPTIONS = mhard-float mapcs-26
-MULTILIB_DIRNAMES = fpu apcs26
-# Note - Thumb multilib omitted because Thumb apcs32 support for
+MULTILIB_OPTIONS = mhard-float
+MULTILIB_DIRNAMES = fpu
+# Note - Thumb multilib omitted because Thumb support for
# arm-wince-pe target does not appear to be working in binutils
# yet...
# MULTILIB_OPTIONS += thumb
@@ -34,4 +34,4 @@ MULTILIB_DIRNAMES = fpu apcs26
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc
+TARGET_LIBGCC2_CFLAGS =
diff --git a/contrib/gcc/config/arm/t-xscale-coff b/contrib/gcc/config/arm/t-xscale-coff
index 89f371f..e2331a0 100644
--- a/contrib/gcc/config/arm/t-xscale-coff
+++ b/contrib/gcc/config/arm/t-xscale-coff
@@ -20,19 +20,18 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-MULTILIB_OPTIONS = mlittle-endian/mbig-endian
-MULTILIB_DIRNAMES = le be
+MULTILIB_OPTIONS = mbig-endian
+MULTILIB_DIRNAMES = be
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-# Note XScale does not support 26 bit APCS.
# Note XScale does not support hard FP
-MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
-MULTILIB_DIRNAMES += normal interwork
+MULTILIB_OPTIONS += mthumb-interwork
+MULTILIB_DIRNAMES += interwork
-MULTILIB_OPTIONS += marm/mthumb
-MULTILIB_DIRNAMES += arm thumb
+MULTILIB_OPTIONS += mthumb
+MULTILIB_DIRNAMES += thumb
MULTILIB_EXCEPTIONS += *mhard-float/*mthumb*
MULTILIB_REDUNDANT_DIRS = interwork/thumb=thumb
@@ -43,4 +42,4 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
diff --git a/contrib/gcc/config/arm/t-xscale-elf b/contrib/gcc/config/arm/t-xscale-elf
index b72c21c..d7a8124 100644
--- a/contrib/gcc/config/arm/t-xscale-elf
+++ b/contrib/gcc/config/arm/t-xscale-elf
@@ -20,26 +20,31 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
echo '#endif' >> dp-bit.c
cat $(srcdir)/config/fp-bit.c >> dp-bit.c
-MULTILIB_OPTIONS = mlittle-endian/mbig-endian
-MULTILIB_DIRNAMES = le be
+MULTILIB_OPTIONS = mbig-endian
+MULTILIB_DIRNAMES = be
MULTILIB_EXCEPTIONS =
MULTILIB_MATCHES = mbig-endian=mbe mlittle-endian=mle
-# Note XScale does not support 26 bit APCS.
# Note XScale does not support hard FP
-MULTILIB_OPTIONS += mno-thumb-interwork/mthumb-interwork
-MULTILIB_DIRNAMES += normal interwork
+MULTILIB_OPTIONS += mthumb-interwork
+MULTILIB_DIRNAMES += interwork
-MULTILIB_OPTIONS += marm/mthumb
-MULTILIB_DIRNAMES += arm thumb
+MULTILIB_OPTIONS += mthumb
+MULTILIB_DIRNAMES += thumb
MULTILIB_EXCEPTIONS += *mhard-float/*mthumb*
MULTILIB_REDUNDANT_DIRS = interwork/thumb=thumb
-MULTILIB_OPTIONS += mcpu=iwmmxt
-MULTILIB_DIRNAMES += iwmmxt
-MULTILIB_REDUNDANT_DIRS += interwork/thumb/iwmmxt=thumb
+# The iWMMXt multilibs are suppressed for now because gcc only
+# supports generating them with the IWMMXT or AAPCS ABIs, neither of
+# which is the default. Until GCC can generate code for an iWMMXt
+# which will work with the default ABI it is not possible to safely
+# generate these multilibs.
+#
+# MULTILIB_OPTIONS += mcpu=iwmmxt
+# MULTILIB_DIRNAMES += iwmmxt
+# MULTILIB_REDUNDANT_DIRS += interwork/thumb/iwmmxt=thumb
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
@@ -49,7 +54,7 @@ INSTALL_LIBGCC = install-multilib
# Currently there is a bug somewhere in GCC's alias analysis
# or scheduling code that is breaking _fpmul_parts in fp-bit.c.
# Disabling function inlining is a workaround for this problem.
-TARGET_LIBGCC2_CFLAGS = -Dinhibit_libc -fno-inline
+TARGET_LIBGCC2_CFLAGS = -fno-inline
# Assemble startup files.
$(T)crti.o: $(srcdir)/config/arm/crti.asm $(GCC_PASSES)
diff --git a/contrib/gcc/config/arm/uclinux-elf.h b/contrib/gcc/config/arm/uclinux-elf.h
index e3cd48d..9f112cd 100644
--- a/contrib/gcc/config/arm/uclinux-elf.h
+++ b/contrib/gcc/config/arm/uclinux-elf.h
@@ -1,5 +1,5 @@
/* Definitions for ARM running ucLinux using ELF
- Copyright (C) 1999, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2001, 2004, 2005 Free Software Foundation, Inc.
Contributed by Philip Blundell <pb@nexus.co.uk>
This file is part of GCC.
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* We don't want a PLT. */
#undef NEED_PLT_RELOC
@@ -27,4 +27,48 @@
#define TARGET_VERSION fputs (" (ARM/ELF ucLinux)", stderr);
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_MMU_TRAPS | ARM_FLAG_SINGLE_PIC_BASE)
+#define TARGET_DEFAULT (MASK_SINGLE_PIC_BASE)
+
+/* NOTE: The remaining definitions in this file are needed because uclinux
+ does not use config/linux.h. */
+
+/* Do not assume anything about header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* The GNU C++ standard library requires that these macros be defined. */
+#undef CPLUSPLUS_CPP_SPEC
+#define CPLUSPLUS_CPP_SPEC "-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
+ object constructed before entering `main'. */
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
+ %{!p:%{profile:gcrt1.o%s} \
+ %{!profile:crt1.o%s}}}} \
+ crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
+
+/* Provide a ENDFILE_SPEC appropriate for GNU/Linux. Here we tack on
+ the GNU/Linux magical crtend.o file (see crtstuff.c) which
+ provides part of the support for getting C++ file-scope static
+ object constructed before entering `main', followed by a normal
+ GNU/Linux "finalizer" file, `crtn.o'. */
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+
+#undef CC1_SPEC
+#define CC1_SPEC "%{profile:-p}"
+
+#define LINK_GCC_C_SEQUENCE_SPEC \
+ "%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
diff --git a/contrib/gcc/config/arm/unaligned-funcs.c b/contrib/gcc/config/arm/unaligned-funcs.c
new file mode 100644
index 0000000..66cfd3b
--- /dev/null
+++ b/contrib/gcc/config/arm/unaligned-funcs.c
@@ -0,0 +1,62 @@
+/* EABI unaligned read/write functions.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+int __aeabi_uread4 (void *);
+int __aeabi_uwrite4 (int, void *);
+long long __aeabi_uread8 (void *);
+long long __aeabi_uwrite8 (long long, void *);
+
+struct __attribute__((packed)) u4 { int data; };
+struct __attribute__((packed)) u8 { long long data; };
+
+int
+__aeabi_uread4 (void *ptr)
+{
+ return ((struct u4 *) ptr)->data;
+}
+
+int
+__aeabi_uwrite4 (int data, void *ptr)
+{
+ ((struct u4 *) ptr)->data = data;
+ return data;
+}
+
+long long
+__aeabi_uread8 (void *ptr)
+{
+ return ((struct u8 *) ptr)->data;
+}
+
+long long
+__aeabi_uwrite8 (long long data, void *ptr)
+{
+ ((struct u8 *) ptr)->data = data;
+ return data;
+}
diff --git a/contrib/gcc/config/arm/unknown-elf.h b/contrib/gcc/config/arm/unknown-elf.h
index 1af7994..c9ad990 100644
--- a/contrib/gcc/config/arm/unknown-elf.h
+++ b/contrib/gcc/config/arm/unknown-elf.h
@@ -1,5 +1,5 @@
/* Definitions for non-Linux based ARM systems using ELF
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by Catherine Moore <clm@cygnus.com>
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* elfos.h should have already been included. Now just override
any conflicting definitions and add any extras. */
@@ -28,9 +28,9 @@
#define TARGET_VERSION fputs (" (ARM/ELF)", stderr);
#endif
-/* Default to using APCS-32 and software floating point. */
+/* Default to using software floating point. */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_SOFT_FLOAT | ARM_FLAG_APCS_32 | ARM_FLAG_APCS_FRAME | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (0)
#endif
/* Now we define the strings used to build the spec file. */
@@ -58,9 +58,9 @@
do \
{ \
if (IN_NAMED_SECTION (DECL)) \
- named_section (DECL, NULL, 0); \
+ switch_to_section (get_named_section (DECL, NULL, 0)); \
else \
- bss_section (); \
+ switch_to_section (bss_section); \
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
\
@@ -75,9 +75,9 @@
do \
{ \
if ((DECL) != NULL && IN_NAMED_SECTION (DECL)) \
- named_section (DECL, NULL, 0); \
+ switch_to_section (get_named_section (DECL, NULL, 0)); \
else \
- bss_section (); \
+ switch_to_section (bss_section); \
\
ASM_OUTPUT_ALIGN (FILE, floor_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (FILE, NAME); \
@@ -85,11 +85,13 @@
} \
while (0)
-#ifndef CPP_APCS_PC_DEFAULT_SPEC
-#define CPP_APCS_PC_DEFAULT_SPEC "-D__APCS_32__"
-#endif
-
#ifndef SUBTARGET_CPU_DEFAULT
#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm7tdmi
#endif
+/* The libgcc udivmod functions may throw exceptions. If newlib is
+ configured to support long longs in I/O, then printf will depend on
+ udivmoddi4, which will depend on the exception unwind routines,
+ which will depend on abort, which is defined in libc. */
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC "--start-group %G %L --end-group"
diff --git a/contrib/gcc/config/arm/unwind-arm.c b/contrib/gcc/config/arm/unwind-arm.c
new file mode 100644
index 0000000..9d2513b
--- /dev/null
+++ b/contrib/gcc/config/arm/unwind-arm.c
@@ -0,0 +1,1016 @@
+/* ARM EABI compliant unwinding routines.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by Paul Brook
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+#include "unwind.h"
+
+/* We add a prototype for abort here to avoid creating a dependency on
+ target headers. */
+extern void abort (void);
+
+/* Definitions for C++ runtime support routines. We make these weak
+ declarations to avoid pulling in libsupc++ unnecessarily. */
+typedef unsigned char bool;
+
+typedef struct _ZSt9type_info type_info; /* This names C++ type_info type */
+
+void __attribute__((weak)) __cxa_call_unexpected(_Unwind_Control_Block *ucbp);
+bool __attribute__((weak)) __cxa_begin_cleanup(_Unwind_Control_Block *ucbp);
+bool __attribute__((weak)) __cxa_type_match(_Unwind_Control_Block *ucbp,
+ const type_info *rttip,
+ void **matched_object);
+
+_Unwind_Ptr __attribute__((weak))
+__gnu_Unwind_Find_exidx (_Unwind_Ptr, int *);
+
+/* Misc constants. */
+#define R_IP 12
+#define R_SP 13
+#define R_LR 14
+#define R_PC 15
+
+#define EXIDX_CANTUNWIND 1
+#define uint32_highbit (((_uw) 1) << 31)
+
+#define UCB_FORCED_STOP_FN(ucbp) ((ucbp)->unwinder_cache.reserved1)
+#define UCB_PR_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved2)
+#define UCB_SAVED_CALLSITE_ADDR(ucbp) ((ucbp)->unwinder_cache.reserved3)
+#define UCB_FORCED_STOP_ARG(ucbp) ((ucbp)->unwinder_cache.reserved4)
+
+struct core_regs
+{
+ _uw r[16];
+};
+
+/* We use normal integer types here to avoid the compiler generating
+ coprocessor instructions. */
+struct vfp_regs
+{
+ _uw64 d[16];
+ _uw pad;
+};
+
+struct fpa_reg
+{
+ _uw w[3];
+};
+
+struct fpa_regs
+{
+ struct fpa_reg f[8];
+};
+
+/* Unwind descriptors. */
+
+typedef struct
+{
+ _uw16 length;
+ _uw16 offset;
+} EHT16;
+
+typedef struct
+{
+ _uw length;
+ _uw offset;
+} EHT32;
+
+/* The ABI specifies that the unwind routines may only use core registers,
+ except when actually manipulating coprocessor state. This allows
+ us to write one implementation that works on all platforms by
+ demand-saving coprocessor registers.
+
+ During unwinding we hold the coprocessor state in the actual hardware
+ registers and allocate demand-save areas for use during phase1
+ unwinding. */
+
+typedef struct
+{
+ /* The first fields must be the same as a phase2_vrs. */
+ _uw demand_save_flags;
+ struct core_regs core;
+ _uw prev_sp; /* Only valid during forced unwinding. */
+ struct vfp_regs vfp;
+ struct fpa_regs fpa;
+} phase1_vrs;
+
+#define DEMAND_SAVE_VFP 1
+
+/* This must match the structure created by the assembly wrappers. */
+typedef struct
+{
+ _uw demand_save_flags;
+ struct core_regs core;
+} phase2_vrs;
+
+
+/* An exception index table entry. */
+
+typedef struct __EIT_entry
+{
+ _uw fnoffset;
+ _uw content;
+} __EIT_entry;
+
+/* Assembly helper functions. */
+
+/* Restore core register state. Never returns. */
+void __attribute__((noreturn)) restore_core_regs (struct core_regs *);
+
+
+/* Coprocessor register state manipulation functions. */
+
+void __gnu_Unwind_Save_VFP (struct vfp_regs * p);
+void __gnu_Unwind_Restore_VFP (struct vfp_regs * p);
+
+/* Restore coprocessor state after phase1 unwinding. */
+static void
+restore_non_core_regs (phase1_vrs * vrs)
+{
+ if ((vrs->demand_save_flags & DEMAND_SAVE_VFP) == 0)
+ __gnu_Unwind_Restore_VFP (&vrs->vfp);
+}
+
+/* A better way to do this would probably be to compare the absolute address
+ with a segment relative relocation of the same symbol. */
+
+extern int __text_start;
+extern int __data_start;
+
+/* The exception index table location. */
+extern __EIT_entry __exidx_start;
+extern __EIT_entry __exidx_end;
+
+/* ABI defined personality routines. */
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr0 (_Unwind_State,
+ _Unwind_Control_Block *, _Unwind_Context *);// __attribute__((weak));
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr1 (_Unwind_State,
+ _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
+extern _Unwind_Reason_Code __aeabi_unwind_cpp_pr2 (_Unwind_State,
+ _Unwind_Control_Block *, _Unwind_Context *) __attribute__((weak));
+
+/* ABI defined routine to store a virtual register to memory. */
+
+_Unwind_VRS_Result _Unwind_VRS_Get (_Unwind_Context *context,
+ _Unwind_VRS_RegClass regclass,
+ _uw regno,
+ _Unwind_VRS_DataRepresentation representation,
+ void *valuep)
+{
+ phase1_vrs *vrs = (phase1_vrs *) context;
+
+ switch (regclass)
+ {
+ case _UVRSC_CORE:
+ if (representation != _UVRSD_UINT32
+ || regno > 15)
+ return _UVRSR_FAILED;
+ *(_uw *) valuep = vrs->core.r[regno];
+ return _UVRSR_OK;
+
+ case _UVRSC_VFP:
+ case _UVRSC_FPA:
+ case _UVRSC_WMMXD:
+ case _UVRSC_WMMXC:
+ return _UVRSR_NOT_IMPLEMENTED;
+
+ default:
+ return _UVRSR_FAILED;
+ }
+}
+
+
+/* ABI defined function to load a virtual register from memory. */
+
+_Unwind_VRS_Result _Unwind_VRS_Set (_Unwind_Context *context,
+ _Unwind_VRS_RegClass regclass,
+ _uw regno,
+ _Unwind_VRS_DataRepresentation representation,
+ void *valuep)
+{
+ phase1_vrs *vrs = (phase1_vrs *) context;
+
+ switch (regclass)
+ {
+ case _UVRSC_CORE:
+ if (representation != _UVRSD_UINT32
+ || regno > 15)
+ return _UVRSR_FAILED;
+
+ vrs->core.r[regno] = *(_uw *) valuep;
+ return _UVRSR_OK;
+
+ case _UVRSC_VFP:
+ case _UVRSC_FPA:
+ case _UVRSC_WMMXD:
+ case _UVRSC_WMMXC:
+ return _UVRSR_NOT_IMPLEMENTED;
+
+ default:
+ return _UVRSR_FAILED;
+ }
+}
+
+
+/* ABI defined function to pop registers off the stack. */
+
+_Unwind_VRS_Result _Unwind_VRS_Pop (_Unwind_Context *context,
+ _Unwind_VRS_RegClass regclass,
+ _uw discriminator,
+ _Unwind_VRS_DataRepresentation representation)
+{
+ phase1_vrs *vrs = (phase1_vrs *) context;
+
+ switch (regclass)
+ {
+ case _UVRSC_CORE:
+ {
+ _uw *ptr;
+ _uw mask;
+ int i;
+
+ if (representation != _UVRSD_UINT32)
+ return _UVRSR_FAILED;
+
+ mask = discriminator & 0xffff;
+ ptr = (_uw *) vrs->core.r[R_SP];
+ /* Pop the requested registers. */
+ for (i = 0; i < 16; i++)
+ {
+ if (mask & (1 << i))
+ vrs->core.r[i] = *(ptr++);
+ }
+ /* Writeback the stack pointer value if it wasn't restored. */
+ if ((mask & (1 << R_SP)) == 0)
+ vrs->core.r[R_SP] = (_uw) ptr;
+ }
+ return _UVRSR_OK;
+
+ case _UVRSC_VFP:
+ {
+ _uw start = discriminator >> 16;
+ _uw count = discriminator & 0xffff;
+ struct vfp_regs tmp;
+ _uw *sp;
+ _uw *dest;
+
+ if ((representation != _UVRSD_VFPX && representation != _UVRSD_DOUBLE)
+ || start + count > 16)
+ return _UVRSR_FAILED;
+
+ if (vrs->demand_save_flags & DEMAND_SAVE_VFP)
+ {
+ /* Demand-save resisters for stage1. */
+ vrs->demand_save_flags &= ~DEMAND_SAVE_VFP;
+ __gnu_Unwind_Save_VFP (&vrs->vfp);
+ }
+
+ /* Restore the registers from the stack. Do this by saving the
+ current VFP registers to a memory area, moving the in-memory
+ values into that area, and restoring from the whole area.
+ For _UVRSD_VFPX we assume FSTMX standard format 1. */
+ __gnu_Unwind_Save_VFP (&tmp);
+
+ /* The stack address is only guaranteed to be word aligned, so
+ we can't use doubleword copies. */
+ sp = (_uw *) vrs->core.r[R_SP];
+ dest = (_uw *) &tmp.d[start];
+ count *= 2;
+ while (count--)
+ *(dest++) = *(sp++);
+
+ /* Skip the pad word */
+ if (representation == _UVRSD_VFPX)
+ sp++;
+
+ /* Set the new stack pointer. */
+ vrs->core.r[R_SP] = (_uw) sp;
+
+ /* Reload the registers. */
+ __gnu_Unwind_Restore_VFP (&tmp);
+ }
+ return _UVRSR_OK;
+
+ case _UVRSC_FPA:
+ case _UVRSC_WMMXD:
+ case _UVRSC_WMMXC:
+ return _UVRSR_NOT_IMPLEMENTED;
+
+ default:
+ return _UVRSR_FAILED;
+ }
+}
+
+
+/* Core unwinding functions. */
+
+/* Calculate the address encoded by a 31-bit self-relative offset at address
+ P. */
+static inline _uw
+selfrel_offset31 (const _uw *p)
+{
+ _uw offset;
+
+ offset = *p;
+ /* Sign extend to 32 bits. */
+ if (offset & (1 << 30))
+ offset |= 1u << 31;
+ else
+ offset &= ~(1u << 31);
+
+ return offset + (_uw) p;
+}
+
+
+/* Perform a binary search for RETURN_ADDRESS in TABLE. The table contains
+ NREC entries. */
+
+static const __EIT_entry *
+search_EIT_table (const __EIT_entry * table, int nrec, _uw return_address)
+{
+ _uw next_fn;
+ _uw this_fn;
+ int n, left, right;
+
+ if (nrec == 0)
+ return (__EIT_entry *) 0;
+
+ left = 0;
+ right = nrec - 1;
+
+ while (1)
+ {
+ n = (left + right) / 2;
+ this_fn = selfrel_offset31 (&table[n].fnoffset);
+ if (n != nrec - 1)
+ next_fn = selfrel_offset31 (&table[n + 1].fnoffset) - 1;
+ else
+ next_fn = (_uw)0 - 1;
+
+ if (return_address < this_fn)
+ {
+ if (n == left)
+ return (__EIT_entry *) 0;
+ right = n - 1;
+ }
+ else if (return_address <= next_fn)
+ return &table[n];
+ else
+ left = n + 1;
+ }
+}
+
+/* Find the exception index table eintry for the given address.
+ Fill in the relevant fields of the UCB.
+ Returns _URC_FAILURE if an error occurred, _URC_OK on success. */
+
+static _Unwind_Reason_Code
+get_eit_entry (_Unwind_Control_Block *ucbp, _uw return_address)
+{
+ const __EIT_entry * eitp;
+ int nrec;
+
+ /* The return address is the address of the instruction following the
+ call instruction (plus one in thumb mode). If this was the last
+ instruction in the function the address will lie in the following
+ function. Subtract 2 from the address so that it points within the call
+ instruction itself. */
+ return_address -= 2;
+
+ if (__gnu_Unwind_Find_exidx)
+ {
+ eitp = (const __EIT_entry *) __gnu_Unwind_Find_exidx (return_address,
+ &nrec);
+ if (!eitp)
+ {
+ UCB_PR_ADDR (ucbp) = 0;
+ return _URC_FAILURE;
+ }
+ }
+ else
+ {
+ eitp = &__exidx_start;
+ nrec = &__exidx_end - &__exidx_start;
+ }
+
+ eitp = search_EIT_table (eitp, nrec, return_address);
+
+ if (!eitp)
+ {
+ UCB_PR_ADDR (ucbp) = 0;
+ return _URC_FAILURE;
+ }
+ ucbp->pr_cache.fnstart = selfrel_offset31 (&eitp->fnoffset);
+
+ /* Can this frame be unwound at all? */
+ if (eitp->content == EXIDX_CANTUNWIND)
+ {
+ UCB_PR_ADDR (ucbp) = 0;
+ return _URC_END_OF_STACK;
+ }
+
+ /* Obtain the address of the "real" __EHT_Header word. */
+
+ if (eitp->content & uint32_highbit)
+ {
+ /* It is immediate data. */
+ ucbp->pr_cache.ehtp = (_Unwind_EHT_Header *)&eitp->content;
+ ucbp->pr_cache.additional = 1;
+ }
+ else
+ {
+ /* The low 31 bits of the content field are a self-relative
+ offset to an _Unwind_EHT_Entry structure. */
+ ucbp->pr_cache.ehtp =
+ (_Unwind_EHT_Header *) selfrel_offset31 (&eitp->content);
+ ucbp->pr_cache.additional = 0;
+ }
+
+ /* Discover the personality routine address. */
+ if (*ucbp->pr_cache.ehtp & (1u << 31))
+ {
+ /* One of the predefined standard routines. */
+ _uw idx = (*(_uw *) ucbp->pr_cache.ehtp >> 24) & 0xf;
+ if (idx == 0)
+ UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr0;
+ else if (idx == 1)
+ UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr1;
+ else if (idx == 2)
+ UCB_PR_ADDR (ucbp) = (_uw) &__aeabi_unwind_cpp_pr2;
+ else
+ { /* Failed */
+ UCB_PR_ADDR (ucbp) = 0;
+ return _URC_FAILURE;
+ }
+ }
+ else
+ {
+ /* Execute region offset to PR */
+ UCB_PR_ADDR (ucbp) = selfrel_offset31 (ucbp->pr_cache.ehtp);
+ }
+ return _URC_OK;
+}
+
+
+/* Perform phase2 unwinding. VRS is the initial virtual register state. */
+
+static void __attribute__((noreturn))
+unwind_phase2 (_Unwind_Control_Block * ucbp, phase2_vrs * vrs)
+{
+ _Unwind_Reason_Code pr_result;
+
+ do
+ {
+ /* Find the entry for this routine. */
+ if (get_eit_entry (ucbp, vrs->core.r[R_PC]) != _URC_OK)
+ abort ();
+
+ UCB_SAVED_CALLSITE_ADDR (ucbp) = vrs->core.r[R_PC];
+
+ /* Call the pr to decide what to do. */
+ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+ (_US_UNWIND_FRAME_STARTING, ucbp, (_Unwind_Context *) vrs);
+ }
+ while (pr_result == _URC_CONTINUE_UNWIND);
+
+ if (pr_result != _URC_INSTALL_CONTEXT)
+ abort();
+
+ restore_core_regs (&vrs->core);
+}
+
+/* Perform phase2 forced unwinding. */
+
+static _Unwind_Reason_Code
+unwind_phase2_forced (_Unwind_Control_Block *ucbp, phase2_vrs *entry_vrs,
+ int resuming)
+{
+ _Unwind_Stop_Fn stop_fn = (_Unwind_Stop_Fn) UCB_FORCED_STOP_FN (ucbp);
+ void *stop_arg = (void *)UCB_FORCED_STOP_ARG (ucbp);
+ _Unwind_Reason_Code pr_result = 0;
+ /* We use phase1_vrs here even though we do not demand save, for the
+ prev_sp field. */
+ phase1_vrs saved_vrs, next_vrs;
+
+ /* Save the core registers. */
+ saved_vrs.core = entry_vrs->core;
+ /* We don't need to demand-save the non-core registers, because we
+ unwind in a single pass. */
+ saved_vrs.demand_save_flags = 0;
+
+ /* Unwind until we reach a propagation barrier. */
+ do
+ {
+ _Unwind_State action;
+ _Unwind_Reason_Code entry_code;
+ _Unwind_Reason_Code stop_code;
+
+ /* Find the entry for this routine. */
+ entry_code = get_eit_entry (ucbp, saved_vrs.core.r[R_PC]);
+
+ if (resuming)
+ {
+ action = _US_UNWIND_FRAME_RESUME | _US_FORCE_UNWIND;
+ resuming = 0;
+ }
+ else
+ action = _US_UNWIND_FRAME_STARTING | _US_FORCE_UNWIND;
+
+ if (entry_code == _URC_OK)
+ {
+ UCB_SAVED_CALLSITE_ADDR (ucbp) = saved_vrs.core.r[R_PC];
+
+ next_vrs = saved_vrs;
+
+ /* Call the pr to decide what to do. */
+ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+ (action, ucbp, (void *) &next_vrs);
+
+ saved_vrs.prev_sp = next_vrs.core.r[R_SP];
+ }
+ else
+ {
+ /* Treat any failure as the end of unwinding, to cope more
+ gracefully with missing EH information. Mixed EH and
+ non-EH within one object will usually result in failure,
+ because the .ARM.exidx tables do not indicate the end
+ of the code to which they apply; but mixed EH and non-EH
+ shared objects should return an unwind failure at the
+ entry of a non-EH shared object. */
+ action |= _US_END_OF_STACK;
+
+ saved_vrs.prev_sp = saved_vrs.core.r[R_SP];
+ }
+
+ stop_code = stop_fn (1, action, ucbp->exception_class, ucbp,
+ (void *)&saved_vrs, stop_arg);
+ if (stop_code != _URC_NO_REASON)
+ return _URC_FAILURE;
+
+ if (entry_code != _URC_OK)
+ return entry_code;
+
+ saved_vrs = next_vrs;
+ }
+ while (pr_result == _URC_CONTINUE_UNWIND);
+
+ if (pr_result != _URC_INSTALL_CONTEXT)
+ {
+ /* Some sort of failure has occurred in the pr and probably the
+ pr returned _URC_FAILURE. */
+ return _URC_FAILURE;
+ }
+
+ restore_core_regs (&saved_vrs.core);
+}
+
+/* This is a very limited implementation of _Unwind_GetCFA. It returns
+ the stack pointer as it is about to be unwound, and is only valid
+ while calling the stop function during forced unwinding. If the
+ current personality routine result is going to run a cleanup, this
+ will not be the CFA; but when the frame is really unwound, it will
+ be. */
+
+_Unwind_Word
+_Unwind_GetCFA (_Unwind_Context *context)
+{
+ return ((phase1_vrs *) context)->prev_sp;
+}
+
+/* Perform phase1 unwinding. UCBP is the exception being thrown, and
+ entry_VRS is the register state on entry to _Unwind_RaiseException. */
+
+_Unwind_Reason_Code
+__gnu_Unwind_RaiseException (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_RaiseException (_Unwind_Control_Block * ucbp,
+ phase2_vrs * entry_vrs)
+{
+ phase1_vrs saved_vrs;
+ _Unwind_Reason_Code pr_result;
+
+ /* Set the pc to the call site. */
+ entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+
+ /* Save the core registers. */
+ saved_vrs.core = entry_vrs->core;
+ /* Set demand-save flags. */
+ saved_vrs.demand_save_flags = ~(_uw) 0;
+
+ /* Unwind until we reach a propagation barrier. */
+ do
+ {
+ /* Find the entry for this routine. */
+ if (get_eit_entry (ucbp, saved_vrs.core.r[R_PC]) != _URC_OK)
+ return _URC_FAILURE;
+
+ /* Call the pr to decide what to do. */
+ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+ (_US_VIRTUAL_UNWIND_FRAME, ucbp, (void *) &saved_vrs);
+ }
+ while (pr_result == _URC_CONTINUE_UNWIND);
+
+ /* We've unwound as far as we want to go, so restore the original
+ register state. */
+ restore_non_core_regs (&saved_vrs);
+ if (pr_result != _URC_HANDLER_FOUND)
+ {
+ /* Some sort of failure has occurred in the pr and probably the
+ pr returned _URC_FAILURE. */
+ return _URC_FAILURE;
+ }
+
+ unwind_phase2 (ucbp, entry_vrs);
+}
+
+/* Resume unwinding after a cleanup has been run. UCBP is the exception
+ being thrown and ENTRY_VRS is the register state on entry to
+ _Unwind_Resume. */
+_Unwind_Reason_Code
+__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *,
+ _Unwind_Stop_Fn, void *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_ForcedUnwind (_Unwind_Control_Block *ucbp,
+ _Unwind_Stop_Fn stop_fn, void *stop_arg,
+ phase2_vrs *entry_vrs)
+{
+ UCB_FORCED_STOP_FN (ucbp) = (_uw) stop_fn;
+ UCB_FORCED_STOP_ARG (ucbp) = (_uw) stop_arg;
+
+ /* Set the pc to the call site. */
+ entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+
+ return unwind_phase2_forced (ucbp, entry_vrs, 0);
+}
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume (_Unwind_Control_Block * ucbp, phase2_vrs * entry_vrs)
+{
+ _Unwind_Reason_Code pr_result;
+
+ /* Recover the saved address. */
+ entry_vrs->core.r[R_PC] = UCB_SAVED_CALLSITE_ADDR (ucbp);
+
+ if (UCB_FORCED_STOP_FN (ucbp))
+ {
+ unwind_phase2_forced (ucbp, entry_vrs, 1);
+
+ /* We can't return failure at this point. */
+ abort ();
+ }
+
+ /* Call the cached PR. */
+ pr_result = ((personality_routine) UCB_PR_ADDR (ucbp))
+ (_US_UNWIND_FRAME_RESUME, ucbp, (_Unwind_Context *) entry_vrs);
+
+ switch (pr_result)
+ {
+ case _URC_INSTALL_CONTEXT:
+ /* Upload the registers to enter the landing pad. */
+ restore_core_regs (&entry_vrs->core);
+
+ case _URC_CONTINUE_UNWIND:
+ /* Continue unwinding the next frame. */
+ unwind_phase2 (ucbp, entry_vrs);
+
+ default:
+ abort ();
+ }
+}
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block *, phase2_vrs *);
+
+_Unwind_Reason_Code
+__gnu_Unwind_Resume_or_Rethrow (_Unwind_Control_Block * ucbp,
+ phase2_vrs * entry_vrs)
+{
+ if (!UCB_FORCED_STOP_FN (ucbp))
+ return __gnu_Unwind_RaiseException (ucbp, entry_vrs);
+
+ /* Set the pc to the call site. */
+ entry_vrs->core.r[R_PC] = entry_vrs->core.r[R_LR];
+ /* Continue unwinding the next frame. */
+ return unwind_phase2_forced (ucbp, entry_vrs, 0);
+}
+
+/* Clean up an exception object when unwinding is complete. */
+void
+_Unwind_Complete (_Unwind_Control_Block * ucbp __attribute__((unused)))
+{
+}
+
+
+/* Get the _Unwind_Control_Block from an _Unwind_Context. */
+
+static inline _Unwind_Control_Block *
+unwind_UCB_from_context (_Unwind_Context * context)
+{
+ return (_Unwind_Control_Block *) _Unwind_GetGR (context, R_IP);
+}
+
+
+/* Free an exception. */
+
+void
+_Unwind_DeleteException (_Unwind_Exception * exc)
+{
+ if (exc->exception_cleanup)
+ (*exc->exception_cleanup) (_URC_FOREIGN_EXCEPTION_CAUGHT, exc);
+}
+
+
+/* Common implementation for ARM ABI defined personality routines.
+ ID is the index of the personality routine, other arguments are as defined
+ by __aeabi_unwind_cpp_pr{0,1,2}. */
+
+static _Unwind_Reason_Code
+__gnu_unwind_pr_common (_Unwind_State state,
+ _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context,
+ int id)
+{
+ __gnu_unwind_state uws;
+ _uw *data;
+ _uw offset;
+ _uw len;
+ _uw rtti_count;
+ int phase2_call_unexpected_after_unwind = 0;
+ int in_range = 0;
+ int forced_unwind = state & _US_FORCE_UNWIND;
+
+ state &= _US_ACTION_MASK;
+
+ data = (_uw *) ucbp->pr_cache.ehtp;
+ uws.data = *(data++);
+ uws.next = data;
+ if (id == 0)
+ {
+ uws.data <<= 8;
+ uws.words_left = 0;
+ uws.bytes_left = 3;
+ }
+ else
+ {
+ uws.words_left = (uws.data >> 16) & 0xff;
+ uws.data <<= 16;
+ uws.bytes_left = 2;
+ data += uws.words_left;
+ }
+
+ /* Restore the saved pointer. */
+ if (state == _US_UNWIND_FRAME_RESUME)
+ data = (_uw *) ucbp->cleanup_cache.bitpattern[0];
+
+ if ((ucbp->pr_cache.additional & 1) == 0)
+ {
+ /* Process descriptors. */
+ while (*data)
+ {
+ _uw addr;
+ _uw fnstart;
+
+ if (id == 2)
+ {
+ len = ((EHT32 *) data)->length;
+ offset = ((EHT32 *) data)->offset;
+ data += 2;
+ }
+ else
+ {
+ len = ((EHT16 *) data)->length;
+ offset = ((EHT16 *) data)->offset;
+ data++;
+ }
+
+ fnstart = ucbp->pr_cache.fnstart + (offset & ~1);
+ addr = _Unwind_GetGR (context, R_PC);
+ in_range = (fnstart <= addr && addr < fnstart + (len & ~1));
+
+ switch (((offset & 1) << 1) | (len & 1))
+ {
+ case 0:
+ /* Cleanup. */
+ if (state != _US_VIRTUAL_UNWIND_FRAME
+ && in_range)
+ {
+ /* Cleanup in range, and we are running cleanups. */
+ _uw lp;
+
+ /* Landing pad address is 31-bit pc-relative offset. */
+ lp = selfrel_offset31 (data);
+ data++;
+ /* Save the exception data pointer. */
+ ucbp->cleanup_cache.bitpattern[0] = (_uw) data;
+ if (!__cxa_begin_cleanup (ucbp))
+ return _URC_FAILURE;
+ /* Setup the VRS to enter the landing pad. */
+ _Unwind_SetGR (context, R_PC, lp);
+ return _URC_INSTALL_CONTEXT;
+ }
+ /* Cleanup not in range, or we are in stage 1. */
+ data++;
+ break;
+
+ case 1:
+ /* Catch handler. */
+ if (state == _US_VIRTUAL_UNWIND_FRAME)
+ {
+ if (in_range)
+ {
+ /* Check for a barrier. */
+ _uw rtti;
+ void *matched;
+
+ /* Check for no-throw areas. */
+ if (data[1] == (_uw) -2)
+ return _URC_FAILURE;
+
+ /* The thrown object immediately follows the ECB. */
+ matched = (void *)(ucbp + 1);
+ if (data[1] != (_uw) -1)
+ {
+ /* Match a catch specification. */
+ rtti = _Unwind_decode_target2 ((_uw) &data[1]);
+ if (!__cxa_type_match (ucbp, (type_info *) rtti,
+ &matched))
+ matched = (void *)0;
+ }
+
+ if (matched)
+ {
+ ucbp->barrier_cache.sp =
+ _Unwind_GetGR (context, R_SP);
+ ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
+ ucbp->barrier_cache.bitpattern[1] = (_uw) data;
+ return _URC_HANDLER_FOUND;
+ }
+ }
+ /* Handler out of range, or not matched. */
+ }
+ else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
+ && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
+ {
+ /* Matched a previous propagation barrier. */
+ _uw lp;
+
+ /* Setup for entry to the handler. */
+ lp = selfrel_offset31 (data);
+ _Unwind_SetGR (context, R_PC, lp);
+ _Unwind_SetGR (context, 0, (_uw) ucbp);
+ return _URC_INSTALL_CONTEXT;
+ }
+ /* Catch handler not matched. Advance to the next descriptor. */
+ data += 2;
+ break;
+
+ case 2:
+ rtti_count = data[0] & 0x7fffffff;
+ /* Exception specification. */
+ if (state == _US_VIRTUAL_UNWIND_FRAME)
+ {
+ if (in_range && (!forced_unwind || !rtti_count))
+ {
+ /* Match against the exception specification. */
+ _uw i;
+ _uw rtti;
+ void *matched;
+
+ for (i = 0; i < rtti_count; i++)
+ {
+ matched = (void *)(ucbp + 1);
+ rtti = _Unwind_decode_target2 ((_uw) &data[i + 1]);
+ if (__cxa_type_match (ucbp, (type_info *) rtti,
+ &matched))
+ break;
+ }
+
+ if (i == rtti_count)
+ {
+ /* Exception does not match the spec. */
+ ucbp->barrier_cache.sp =
+ _Unwind_GetGR (context, R_SP);
+ ucbp->barrier_cache.bitpattern[0] = (_uw) matched;
+ ucbp->barrier_cache.bitpattern[1] = (_uw) data;
+ return _URC_HANDLER_FOUND;
+ }
+ }
+ /* Handler out of range, or exception is permitted. */
+ }
+ else if (ucbp->barrier_cache.sp == _Unwind_GetGR (context, R_SP)
+ && ucbp->barrier_cache.bitpattern[1] == (_uw) data)
+ {
+ /* Matched a previous propagation barrier. */
+ _uw lp;
+ /* Record the RTTI list for __cxa_call_unexpected. */
+ ucbp->barrier_cache.bitpattern[1] = rtti_count;
+ ucbp->barrier_cache.bitpattern[2] = 0;
+ ucbp->barrier_cache.bitpattern[3] = 4;
+ ucbp->barrier_cache.bitpattern[4] = (_uw) &data[1];
+
+ if (data[0] & uint32_highbit)
+ phase2_call_unexpected_after_unwind = 1;
+ else
+ {
+ data += rtti_count + 1;
+ /* Setup for entry to the handler. */
+ lp = selfrel_offset31 (data);
+ data++;
+ _Unwind_SetGR (context, R_PC, lp);
+ _Unwind_SetGR (context, 0, (_uw) ucbp);
+ return _URC_INSTALL_CONTEXT;
+ }
+ }
+ if (data[0] & uint32_highbit)
+ data++;
+ data += rtti_count + 1;
+ break;
+
+ default:
+ /* Should never happen. */
+ return _URC_FAILURE;
+ }
+ /* Finished processing this descriptor. */
+ }
+ }
+
+ if (__gnu_unwind_execute (context, &uws) != _URC_OK)
+ return _URC_FAILURE;
+
+ if (phase2_call_unexpected_after_unwind)
+ {
+ /* Enter __cxa_unexpected as if called from the call site. */
+ _Unwind_SetGR (context, R_LR, _Unwind_GetGR (context, R_PC));
+ _Unwind_SetGR (context, R_PC, (_uw) &__cxa_call_unexpected);
+ return _URC_INSTALL_CONTEXT;
+ }
+
+ return _URC_CONTINUE_UNWIND;
+}
+
+
+/* ABI defined personality routine entry points. */
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr0 (_Unwind_State state,
+ _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context)
+{
+ return __gnu_unwind_pr_common (state, ucbp, context, 0);
+}
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr1 (_Unwind_State state,
+ _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context)
+{
+ return __gnu_unwind_pr_common (state, ucbp, context, 1);
+}
+
+_Unwind_Reason_Code
+__aeabi_unwind_cpp_pr2 (_Unwind_State state,
+ _Unwind_Control_Block *ucbp,
+ _Unwind_Context *context)
+{
+ return __gnu_unwind_pr_common (state, ucbp, context, 2);
+}
+
+/* These two should never be used. */
+_Unwind_Ptr
+_Unwind_GetDataRelBase (_Unwind_Context *context __attribute__ ((unused)))
+{
+ abort ();
+}
+
+_Unwind_Ptr
+_Unwind_GetTextRelBase (_Unwind_Context *context __attribute__ ((unused)))
+{
+ abort ();
+}
diff --git a/contrib/gcc/config/arm/unwind-arm.h b/contrib/gcc/config/arm/unwind-arm.h
new file mode 100644
index 0000000..a3040d7
--- /dev/null
+++ b/contrib/gcc/config/arm/unwind-arm.h
@@ -0,0 +1,271 @@
+/* Header file for the ARM EABI unwinder
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+ Contributed by Paul Brook
+
+ This file is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by the
+ Free Software Foundation; either version 2, or (at your option) any
+ later version.
+
+ In addition to the permissions in the GNU General Public License, the
+ Free Software Foundation gives you unlimited permission to link the
+ compiled version of this file into combinations with other programs,
+ and to distribute those combinations without any restriction coming
+ from the use of this file. (The General Public License restrictions
+ do apply in other respects; for example, they cover modification of
+ the file, and distribution when not linked into a combine
+ executable.)
+
+ This file is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* Language-independent unwinder header public defines. This contains both
+ ABI defined objects, and GNU support routines. */
+
+#ifndef UNWIND_ARM_H
+#define UNWIND_ARM_H
+
+#define __ARM_EABI_UNWINDER__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ typedef unsigned _Unwind_Word __attribute__((__mode__(__word__)));
+ typedef signed _Unwind_Sword __attribute__((__mode__(__word__)));
+ typedef unsigned _Unwind_Ptr __attribute__((__mode__(__pointer__)));
+ typedef unsigned _Unwind_Internal_Ptr __attribute__((__mode__(__pointer__)));
+ typedef _Unwind_Word _uw;
+ typedef unsigned _uw64 __attribute__((mode(__DI__)));
+ typedef unsigned _uw16 __attribute__((mode(__HI__)));
+ typedef unsigned _uw8 __attribute__((mode(__QI__)));
+
+ typedef enum
+ {
+ _URC_OK = 0, /* operation completed successfully */
+ _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+ _URC_END_OF_STACK = 5,
+ _URC_HANDLER_FOUND = 6,
+ _URC_INSTALL_CONTEXT = 7,
+ _URC_CONTINUE_UNWIND = 8,
+ _URC_FAILURE = 9 /* unspecified failure of some kind */
+ }
+ _Unwind_Reason_Code;
+
+ typedef enum
+ {
+ _US_VIRTUAL_UNWIND_FRAME = 0,
+ _US_UNWIND_FRAME_STARTING = 1,
+ _US_UNWIND_FRAME_RESUME = 2,
+ _US_ACTION_MASK = 3,
+ _US_FORCE_UNWIND = 8,
+ _US_END_OF_STACK = 16
+ }
+ _Unwind_State;
+
+ /* Provided only for for compatibility with existing code. */
+ typedef int _Unwind_Action;
+#define _UA_SEARCH_PHASE 1
+#define _UA_CLEANUP_PHASE 2
+#define _UA_HANDLER_FRAME 4
+#define _UA_FORCE_UNWIND 8
+#define _UA_END_OF_STACK 16
+#define _URC_NO_REASON _URC_OK
+
+ typedef struct _Unwind_Control_Block _Unwind_Control_Block;
+ typedef struct _Unwind_Context _Unwind_Context;
+ typedef _uw _Unwind_EHT_Header;
+
+
+ /* UCB: */
+
+ struct _Unwind_Control_Block
+ {
+ char exception_class[8];
+ void (*exception_cleanup)(_Unwind_Reason_Code, _Unwind_Control_Block *);
+ /* Unwinder cache, private fields for the unwinder's use */
+ struct
+ {
+ _uw reserved1; /* Forced unwind stop fn, 0 if not forced */
+ _uw reserved2; /* Personality routine address */
+ _uw reserved3; /* Saved callsite address */
+ _uw reserved4; /* Forced unwind stop arg */
+ _uw reserved5;
+ }
+ unwinder_cache;
+ /* Propagation barrier cache (valid after phase 1): */
+ struct
+ {
+ _uw sp;
+ _uw bitpattern[5];
+ }
+ barrier_cache;
+ /* Cleanup cache (preserved over cleanup): */
+ struct
+ {
+ _uw bitpattern[4];
+ }
+ cleanup_cache;
+ /* Pr cache (for pr's benefit): */
+ struct
+ {
+ _uw fnstart; /* function start address */
+ _Unwind_EHT_Header *ehtp; /* pointer to EHT entry header word */
+ _uw additional; /* additional data */
+ _uw reserved1;
+ }
+ pr_cache;
+ long long int :0; /* Force alignment to 8-byte boundary */
+ };
+
+ /* Virtual Register Set*/
+
+ typedef enum
+ {
+ _UVRSC_CORE = 0, /* integer register */
+ _UVRSC_VFP = 1, /* vfp */
+ _UVRSC_FPA = 2, /* fpa */
+ _UVRSC_WMMXD = 3, /* Intel WMMX data register */
+ _UVRSC_WMMXC = 4 /* Intel WMMX control register */
+ }
+ _Unwind_VRS_RegClass;
+
+ typedef enum
+ {
+ _UVRSD_UINT32 = 0,
+ _UVRSD_VFPX = 1,
+ _UVRSD_FPAX = 2,
+ _UVRSD_UINT64 = 3,
+ _UVRSD_FLOAT = 4,
+ _UVRSD_DOUBLE = 5
+ }
+ _Unwind_VRS_DataRepresentation;
+
+ typedef enum
+ {
+ _UVRSR_OK = 0,
+ _UVRSR_NOT_IMPLEMENTED = 1,
+ _UVRSR_FAILED = 2
+ }
+ _Unwind_VRS_Result;
+
+ /* Frame unwinding state. */
+ typedef struct
+ {
+ /* The current word (bytes packed msb first). */
+ _uw data;
+ /* Pointer to the next word of data. */
+ _uw *next;
+ /* The number of bytes left in this word. */
+ _uw8 bytes_left;
+ /* The number of words pointed to by ptr. */
+ _uw8 words_left;
+ }
+ __gnu_unwind_state;
+
+ typedef _Unwind_Reason_Code (*personality_routine) (_Unwind_State,
+ _Unwind_Control_Block *, _Unwind_Context *);
+
+ _Unwind_VRS_Result _Unwind_VRS_Set(_Unwind_Context *, _Unwind_VRS_RegClass,
+ _uw, _Unwind_VRS_DataRepresentation,
+ void *);
+
+ _Unwind_VRS_Result _Unwind_VRS_Get(_Unwind_Context *, _Unwind_VRS_RegClass,
+ _uw, _Unwind_VRS_DataRepresentation,
+ void *);
+
+ _Unwind_VRS_Result _Unwind_VRS_Pop(_Unwind_Context *, _Unwind_VRS_RegClass,
+ _uw, _Unwind_VRS_DataRepresentation);
+
+
+ /* Support functions for the PR. */
+#define _Unwind_Exception _Unwind_Control_Block
+ typedef char _Unwind_Exception_Class[8];
+
+ void * _Unwind_GetLanguageSpecificData (_Unwind_Context *);
+ _Unwind_Ptr _Unwind_GetRegionStart (_Unwind_Context *);
+
+ /* These two should never be used. */
+ _Unwind_Ptr _Unwind_GetDataRelBase (_Unwind_Context *);
+ _Unwind_Ptr _Unwind_GetTextRelBase (_Unwind_Context *);
+
+ /* Interface functions: */
+ _Unwind_Reason_Code _Unwind_RaiseException(_Unwind_Control_Block *ucbp);
+ void __attribute__((noreturn)) _Unwind_Resume(_Unwind_Control_Block *ucbp);
+ _Unwind_Reason_Code _Unwind_Resume_or_Rethrow (_Unwind_Control_Block *ucbp);
+
+ typedef _Unwind_Reason_Code (*_Unwind_Stop_Fn)
+ (int, _Unwind_Action, _Unwind_Exception_Class,
+ _Unwind_Control_Block *, struct _Unwind_Context *, void *);
+ _Unwind_Reason_Code _Unwind_ForcedUnwind (_Unwind_Control_Block *,
+ _Unwind_Stop_Fn, void *);
+ _Unwind_Word _Unwind_GetCFA (struct _Unwind_Context *);
+ void _Unwind_Complete(_Unwind_Control_Block *ucbp);
+ void _Unwind_DeleteException (_Unwind_Exception *);
+
+ _Unwind_Reason_Code __gnu_unwind_frame (_Unwind_Control_Block *,
+ _Unwind_Context *);
+ _Unwind_Reason_Code __gnu_unwind_execute (_Unwind_Context *,
+ __gnu_unwind_state *);
+
+ /* Decode an R_ARM_TARGET2 relocation. */
+ static inline _Unwind_Word
+ _Unwind_decode_target2 (_Unwind_Word ptr)
+ {
+ _Unwind_Word tmp;
+
+ tmp = *(_Unwind_Word *) ptr;
+ /* Zero values are always NULL. */
+ if (!tmp)
+ return 0;
+
+#if defined(linux) || defined(__NetBSD__)
+ /* Pc-relative indirect. */
+ tmp += ptr;
+ tmp = *(_Unwind_Word *) tmp;
+#elif defined(__symbian__)
+ /* Absolute pointer. Nothing more to do. */
+#else
+ /* Pc-relative pointer. */
+ tmp += ptr;
+#endif
+ return tmp;
+ }
+
+ static inline _Unwind_Word
+ _Unwind_GetGR (_Unwind_Context *context, int regno)
+ {
+ _uw val;
+ _Unwind_VRS_Get (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+ return val;
+ }
+
+ /* Return the address of the instruction, not the actual IP value. */
+#define _Unwind_GetIP(context) \
+ (_Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
+#define _Unwind_GetIPInfo(context, ip_before_insn) \
+ (*ip_before_insn = 0, _Unwind_GetGR (context, 15) & ~(_Unwind_Word)1)
+
+ static inline void
+ _Unwind_SetGR (_Unwind_Context *context, int regno, _Unwind_Word val)
+ {
+ _Unwind_VRS_Set (context, _UVRSC_CORE, regno, _UVRSD_UINT32, &val);
+ }
+
+ /* The dwarf unwinder doesn't understand arm/thumb state. We assume the
+ landing pad uses the same instruction set as the call site. */
+#define _Unwind_SetIP(context, val) \
+ _Unwind_SetGR (context, 15, val | (_Unwind_GetGR (context, 15) & 1))
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* defined UNWIND_ARM_H */
diff --git a/contrib/gcc/config/arm/vfp.md b/contrib/gcc/config/arm/vfp.md
new file mode 100644
index 0000000..2380c83
--- /dev/null
+++ b/contrib/gcc/config/arm/vfp.md
@@ -0,0 +1,841 @@
+;; ARM VFP coprocessor Machine Description
+;; Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+;; Written by CodeSourcery, LLC.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful, but
+;; WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+;; General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA. */
+
+;; Additional register numbers
+(define_constants
+ [(VFPCC_REGNUM 95)]
+)
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Pipeline description
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_automaton "vfp11")
+
+;; There are 3 pipelines in the VFP11 unit.
+;;
+;; - A 8-stage FMAC pipeline (7 execute + writeback) with forward from
+;; fourth stage for simple operations.
+;;
+;; - A 5-stage DS pipeline (4 execute + writeback) for divide/sqrt insns.
+;; These insns also uses first execute stage of FMAC pipeline.
+;;
+;; - A 4-stage LS pipeline (execute + 2 memory + writeback) with forward from
+;; second memory stage for loads.
+
+;; We do not model Write-After-Read hazards.
+;; We do not do write scheduling with the arm core, so it is only necessary
+;; to model the first stage of each pipeline
+;; ??? Need to model LS pipeline properly for load/store multiple?
+;; We do not model fmstat properly. This could be done by modeling pipelines
+;; properly and defining an absence set between a dummy fmstat unit and all
+;; other vfp units.
+
+(define_cpu_unit "fmac" "vfp11")
+
+(define_cpu_unit "ds" "vfp11")
+
+(define_cpu_unit "vfp_ls" "vfp11")
+
+(define_cpu_unit "fmstat" "vfp11")
+
+(exclusion_set "fmac,ds" "fmstat")
+
+;; The VFP "type" attributes differ from those used in the FPA model.
+;; ffarith Fast floating point insns, e.g. abs, neg, cpy, cmp.
+;; farith Most arithmetic insns.
+;; fmul Double precision multiply.
+;; fdivs Single precision sqrt or division.
+;; fdivd Double precision sqrt or division.
+;; f_flag fmstat operation
+;; f_load[sd] Floating point load from memory.
+;; f_store[sd] Floating point store to memory.
+;; f_2_r Transfer vfp to arm reg.
+;; r_2_f Transfer arm to vfp reg.
+;; f_cvt Convert floating<->integral
+
+(define_insn_reservation "vfp_ffarith" 4
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "ffarith"))
+ "fmac")
+
+(define_insn_reservation "vfp_farith" 8
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "farith,f_cvt"))
+ "fmac")
+
+(define_insn_reservation "vfp_fmul" 9
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "fmul"))
+ "fmac*2")
+
+(define_insn_reservation "vfp_fdivs" 19
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "fdivs"))
+ "ds*15")
+
+(define_insn_reservation "vfp_fdivd" 33
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "fdivd"))
+ "fmac+ds*29")
+
+;; Moves to/from arm regs also use the load/store pipeline.
+(define_insn_reservation "vfp_fload" 4
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "f_loads,f_loadd,r_2_f"))
+ "vfp_ls")
+
+(define_insn_reservation "vfp_fstore" 4
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "f_stores,f_stored,f_2_r"))
+ "vfp_ls")
+
+(define_insn_reservation "vfp_to_cpsr" 4
+ (and (eq_attr "generic_vfp" "yes")
+ (eq_attr "type" "f_flag"))
+ "fmstat,vfp_ls*3")
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Insn pattern
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; SImode moves
+;; ??? For now do not allow loading constants into vfp regs. This causes
+;; problems because small constants get converted into adds.
+(define_insn "*arm_movsi_vfp"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r ,m,*w,r,*w,*w, *Uv")
+ (match_operand:SI 1 "general_operand" "rI,K,mi,r,r,*w,*w,*Uvi,*w"))]
+ "TARGET_ARM && TARGET_VFP && TARGET_HARD_FLOAT
+ && ( s_register_operand (operands[0], SImode)
+ || s_register_operand (operands[1], SImode))"
+ "@
+ mov%?\\t%0, %1
+ mvn%?\\t%0, #%B1
+ ldr%?\\t%0, %1
+ str%?\\t%1, %0
+ fmsr%?\\t%0, %1\\t%@ int
+ fmrs%?\\t%0, %1\\t%@ int
+ fcpys%?\\t%0, %1\\t%@ int
+ flds%?\\t%0, %1\\t%@ int
+ fsts%?\\t%1, %0\\t%@ int"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "*,*,load1,store1,r_2_f,f_2_r,ffarith,f_loads,f_stores")
+ (set_attr "pool_range" "*,*,4096,*,*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,*,4084,*,*,*,*,1008,*")]
+)
+
+
+;; DImode moves
+
+(define_insn "*arm_movdi_vfp"
+ [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r, r,m,w,r,w,w, Uv")
+ (match_operand:DI 1 "di_operand" "rIK,mi,r,r,w,w,Uvi,w"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
+ && ( register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
+ "*
+ switch (which_alternative)
+ {
+ case 0:
+ return \"#\";
+ case 1:
+ case 2:
+ return output_move_double (operands);
+ case 3:
+ return \"fmdrr%?\\t%P0, %Q1, %R1\\t%@ int\";
+ case 4:
+ return \"fmrrd%?\\t%Q0, %R0, %P1\\t%@ int\";
+ case 5:
+ return \"fcpyd%?\\t%P0, %P1\\t%@ int\";
+ case 6:
+ return \"fldd%?\\t%P0, %1\\t%@ int\";
+ case 7:
+ return \"fstd%?\\t%P1, %0\\t%@ int\";
+ default:
+ gcc_unreachable ();
+ }
+ "
+ [(set_attr "type" "*,load2,store2,r_2_f,f_2_r,ffarith,f_loadd,f_stored")
+ (set_attr "length" "8,8,8,4,4,4,4,4")
+ (set_attr "pool_range" "*,1020,*,*,*,*,1020,*")
+ (set_attr "neg_pool_range" "*,1008,*,*,*,*,1008,*")]
+)
+
+
+;; SFmode moves
+;; Disparage the w<->r cases because reloading an invalid address is
+;; preferable to loading the value via integer registers.
+
+(define_insn "*movsf_vfp"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=w,?r,w ,Uv,r ,m,w,r")
+ (match_operand:SF 1 "general_operand" " ?r,w,UvE,w, mE,r,w,r"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
+ && ( s_register_operand (operands[0], SFmode)
+ || s_register_operand (operands[1], SFmode))"
+ "@
+ fmsr%?\\t%0, %1
+ fmrs%?\\t%0, %1
+ flds%?\\t%0, %1
+ fsts%?\\t%1, %0
+ ldr%?\\t%0, %1\\t%@ float
+ str%?\\t%1, %0\\t%@ float
+ fcpys%?\\t%0, %1
+ mov%?\\t%0, %1\\t%@ float"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "r_2_f,f_2_r,ffarith,*,f_loads,f_stores,load1,store1")
+ (set_attr "pool_range" "*,*,1020,*,4096,*,*,*")
+ (set_attr "neg_pool_range" "*,*,1008,*,4080,*,*,*")]
+)
+
+
+;; DFmode moves
+
+(define_insn "*movdf_vfp"
+ [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=w,?r,r, m,w ,Uv,w,r")
+ (match_operand:DF 1 "soft_df_operand" " ?r,w,mF,r,UvF,w, w,r"))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP
+ && ( register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ "*
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return \"fmdrr%?\\t%P0, %Q1, %R1\";
+ case 1:
+ return \"fmrrd%?\\t%Q0, %R0, %P1\";
+ case 2: case 3:
+ return output_move_double (operands);
+ case 4:
+ return \"fldd%?\\t%P0, %1\";
+ case 5:
+ return \"fstd%?\\t%P1, %0\";
+ case 6:
+ return \"fcpyd%?\\t%P0, %P1\";
+ case 7:
+ return \"#\";
+ default:
+ gcc_unreachable ();
+ }
+ }
+ "
+ [(set_attr "type" "r_2_f,f_2_r,ffarith,*,load2,store2,f_loadd,f_stored")
+ (set_attr "length" "4,4,8,8,4,4,4,8")
+ (set_attr "pool_range" "*,*,1020,*,1020,*,*,*")
+ (set_attr "neg_pool_range" "*,*,1008,*,1008,*,*,*")]
+)
+
+
+;; Conditional move patterns
+
+(define_insn "*movsfcc_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
+ (if_then_else:SF
+ (match_operator 3 "arm_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:SF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
+ (match_operand:SF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcpys%D3\\t%0, %2
+ fcpys%d3\\t%0, %1
+ fcpys%D3\\t%0, %2\;fcpys%d3\\t%0, %1
+ fmsr%D3\\t%0, %2
+ fmsr%d3\\t%0, %1
+ fmsr%D3\\t%0, %2\;fmsr%d3\\t%0, %1
+ fmrs%D3\\t%0, %2
+ fmrs%d3\\t%0, %1
+ fmrs%D3\\t%0, %2\;fmrs%d3\\t%0, %1"
+ [(set_attr "conds" "use")
+ (set_attr "length" "4,4,8,4,4,8,4,4,8")
+ (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
+)
+
+(define_insn "*movdfcc_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w,w,w,w,w,w,?r,?r,?r")
+ (if_then_else:DF
+ (match_operator 3 "arm_comparison_operator"
+ [(match_operand 4 "cc_register" "") (const_int 0)])
+ (match_operand:DF 1 "s_register_operand" "0,w,w,0,?r,?r,0,w,w")
+ (match_operand:DF 2 "s_register_operand" "w,0,w,?r,0,?r,w,0,w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcpyd%D3\\t%P0, %P2
+ fcpyd%d3\\t%P0, %P1
+ fcpyd%D3\\t%P0, %P2\;fcpyd%d3\\t%P0, %P1
+ fmdrr%D3\\t%P0, %Q2, %R2
+ fmdrr%d3\\t%P0, %Q1, %R1
+ fmdrr%D3\\t%P0, %Q2, %R2\;fmdrr%d3\\t%P0, %Q1, %R1
+ fmrrd%D3\\t%Q0, %R0, %P2
+ fmrrd%d3\\t%Q0, %R0, %P1
+ fmrrd%D3\\t%Q0, %R0, %P2\;fmrrd%d3\\t%Q0, %R0, %P1"
+ [(set_attr "conds" "use")
+ (set_attr "length" "4,4,8,4,4,8,4,4,8")
+ (set_attr "type" "ffarith,ffarith,ffarith,r_2_f,r_2_f,r_2_f,f_2_r,f_2_r,f_2_r")]
+)
+
+
+;; Sign manipulation functions
+
+(define_insn "*abssf2_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (abs:SF (match_operand:SF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fabss%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn "*absdf2_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (abs:DF (match_operand:DF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fabsd%?\\t%P0, %P1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn "*negsf2_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w,?r")
+ (neg:SF (match_operand:SF 1 "s_register_operand" "w,r")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fnegs%?\\t%0, %1
+ eor%?\\t%0, %1, #-2147483648"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn_and_split "*negdf2_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w,?r,?r")
+ (neg:DF (match_operand:DF 1 "s_register_operand" "w,0,r")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fnegd%?\\t%P0, %P1
+ #
+ #"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP && reload_completed
+ && arm_general_register_operand (operands[0], DFmode)"
+ [(set (match_dup 0) (match_dup 1))]
+ "
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ operands[0] = gen_highpart (SImode, operands[0]);
+ operands[1] = gen_rtx_XOR (SImode, operands[0], GEN_INT (0x80000000));
+ }
+ else
+ {
+ rtx in_hi, in_lo, out_hi, out_lo;
+
+ in_hi = gen_rtx_XOR (SImode, gen_highpart (SImode, operands[1]),
+ GEN_INT (0x80000000));
+ in_lo = gen_lowpart (SImode, operands[1]);
+ out_hi = gen_highpart (SImode, operands[0]);
+ out_lo = gen_lowpart (SImode, operands[0]);
+
+ if (REGNO (in_lo) == REGNO (out_hi))
+ {
+ emit_insn (gen_rtx_SET (SImode, out_lo, in_lo));
+ operands[0] = out_hi;
+ operands[1] = in_hi;
+ }
+ else
+ {
+ emit_insn (gen_rtx_SET (SImode, out_hi, in_hi));
+ operands[0] = out_lo;
+ operands[1] = in_lo;
+ }
+ }
+ "
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "4,4,8")
+ (set_attr "type" "ffarith")]
+)
+
+
+;; Arithmetic insns
+
+(define_insn "*addsf3_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (plus:SF (match_operand:SF 1 "s_register_operand" "w")
+ (match_operand:SF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fadds%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*adddf3_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (plus:DF (match_operand:DF 1 "s_register_operand" "w")
+ (match_operand:DF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "faddd%?\\t%P0, %P1, %P2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+
+(define_insn "*subsf3_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (minus:SF (match_operand:SF 1 "s_register_operand" "w")
+ (match_operand:SF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsubs%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*subdf3_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (minus:DF (match_operand:DF 1 "s_register_operand" "w")
+ (match_operand:DF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsubd%?\\t%P0, %P1, %P2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+
+;; Division insns
+
+(define_insn "*divsf3_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "+w")
+ (div:SF (match_operand:SF 1 "s_register_operand" "w")
+ (match_operand:SF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fdivs%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fdivs")]
+)
+
+(define_insn "*divdf3_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "+w")
+ (div:DF (match_operand:DF 1 "s_register_operand" "w")
+ (match_operand:DF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fdivd%?\\t%P0, %P1, %P2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fdivd")]
+)
+
+
+;; Multiplication insns
+
+(define_insn "*mulsf3_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "+w")
+ (mult:SF (match_operand:SF 1 "s_register_operand" "w")
+ (match_operand:SF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmuls%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*muldf3_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "+w")
+ (mult:DF (match_operand:DF 1 "s_register_operand" "w")
+ (match_operand:DF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmuld%?\\t%P0, %P1, %P2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+
+(define_insn "*mulsf3negsf_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "+w")
+ (mult:SF (neg:SF (match_operand:SF 1 "s_register_operand" "w"))
+ (match_operand:SF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmuls%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*muldf3negdf_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "+w")
+ (mult:DF (neg:DF (match_operand:DF 1 "s_register_operand" "w"))
+ (match_operand:DF 2 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmuld%?\\t%P0, %P1, %P2"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+
+;; Multiply-accumulate insns
+
+;; 0 = 1 * 2 + 0
+(define_insn "*mulsf3addsf_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (plus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
+ (match_operand:SF 3 "s_register_operand" "w"))
+ (match_operand:SF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmacs%?\\t%0, %2, %3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*muldf3adddf_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (plus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
+ (match_operand:DF 3 "s_register_operand" "w"))
+ (match_operand:DF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmacd%?\\t%P0, %P2, %P3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+;; 0 = 1 * 2 - 0
+(define_insn "*mulsf3subsf_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (minus:SF (mult:SF (match_operand:SF 2 "s_register_operand" "w")
+ (match_operand:SF 3 "s_register_operand" "w"))
+ (match_operand:SF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmscs%?\\t%0, %2, %3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*muldf3subdf_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (minus:DF (mult:DF (match_operand:DF 2 "s_register_operand" "w")
+ (match_operand:DF 3 "s_register_operand" "w"))
+ (match_operand:DF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmscd%?\\t%P0, %P2, %P3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+;; 0 = -(1 * 2) + 0
+(define_insn "*mulsf3negsfaddsf_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (minus:SF (match_operand:SF 1 "s_register_operand" "0")
+ (mult:SF (match_operand:SF 2 "s_register_operand" "w")
+ (match_operand:SF 3 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmacs%?\\t%0, %2, %3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*fmuldf3negdfadddf_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (minus:DF (match_operand:DF 1 "s_register_operand" "0")
+ (mult:DF (match_operand:DF 2 "s_register_operand" "w")
+ (match_operand:DF 3 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmacd%?\\t%P0, %P2, %P3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+
+;; 0 = -(1 * 2) - 0
+(define_insn "*mulsf3negsfsubsf_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (minus:SF (mult:SF
+ (neg:SF (match_operand:SF 2 "s_register_operand" "w"))
+ (match_operand:SF 3 "s_register_operand" "w"))
+ (match_operand:SF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmscs%?\\t%0, %2, %3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "farith")]
+)
+
+(define_insn "*muldf3negdfsubdf_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (minus:DF (mult:DF
+ (neg:DF (match_operand:DF 2 "s_register_operand" "w"))
+ (match_operand:DF 3 "s_register_operand" "w"))
+ (match_operand:DF 1 "s_register_operand" "0")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fnmscd%?\\t%P0, %P2, %P3"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fmul")]
+)
+
+
+;; Conversion routines
+
+(define_insn "*extendsfdf2_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (float_extend:DF (match_operand:SF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fcvtds%?\\t%P0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "*truncdfsf2_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (float_truncate:SF (match_operand:DF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fcvtsd%?\\t%0, %P1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "*truncsisf2_vfp"
+ [(set (match_operand:SI 0 "s_register_operand" "=w")
+ (fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "ftosizs%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "*truncsidf2_vfp"
+ [(set (match_operand:SI 0 "s_register_operand" "=w")
+ (fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "ftosizd%?\\t%0, %P1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+
+(define_insn "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=w")
+ (unsigned_fix:SI (fix:SF (match_operand:SF 1 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "ftouizs%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "s_register_operand" "=w")
+ (unsigned_fix:SI (fix:DF (match_operand:DF 1 "s_register_operand" "w"))))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "ftouizd%?\\t%0, %P1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+
+(define_insn "*floatsisf2_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (float:SF (match_operand:SI 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsitos%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "*floatsidf2_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (float:DF (match_operand:SI 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsitod%?\\t%P0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+
+(define_insn "floatunssisf2"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (unsigned_float:SF (match_operand:SI 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fuitos%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+(define_insn "floatunssidf2"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (unsigned_float:DF (match_operand:SI 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fuitod%?\\t%P0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "f_cvt")]
+)
+
+
+;; Sqrt insns.
+
+(define_insn "*sqrtsf2_vfp"
+ [(set (match_operand:SF 0 "s_register_operand" "=w")
+ (sqrt:SF (match_operand:SF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsqrts%?\\t%0, %1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fdivs")]
+)
+
+(define_insn "*sqrtdf2_vfp"
+ [(set (match_operand:DF 0 "s_register_operand" "=w")
+ (sqrt:DF (match_operand:DF 1 "s_register_operand" "w")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fsqrtd%?\\t%P0, %P1"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "fdivd")]
+)
+
+
+;; Patterns to split/copy vfp condition flags.
+
+(define_insn "*movcc_vfp"
+ [(set (reg CC_REGNUM)
+ (reg VFPCC_REGNUM))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "fmstat%?"
+ [(set_attr "conds" "set")
+ (set_attr "type" "f_flag")]
+)
+
+(define_insn_and_split "*cmpsf_split_vfp"
+ [(set (reg:CCFP CC_REGNUM)
+ (compare:CCFP (match_operand:SF 0 "s_register_operand" "w")
+ (match_operand:SF 1 "vfp_compare_operand" "wG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "#"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ [(set (reg:CCFP VFPCC_REGNUM)
+ (compare:CCFP (match_dup 0)
+ (match_dup 1)))
+ (set (reg:CCFP CC_REGNUM)
+ (reg:CCFP VFPCC_REGNUM))]
+ ""
+)
+
+(define_insn_and_split "*cmpsf_trap_split_vfp"
+ [(set (reg:CCFPE CC_REGNUM)
+ (compare:CCFPE (match_operand:SF 0 "s_register_operand" "w")
+ (match_operand:SF 1 "vfp_compare_operand" "wG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "#"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ [(set (reg:CCFPE VFPCC_REGNUM)
+ (compare:CCFPE (match_dup 0)
+ (match_dup 1)))
+ (set (reg:CCFPE CC_REGNUM)
+ (reg:CCFPE VFPCC_REGNUM))]
+ ""
+)
+
+(define_insn_and_split "*cmpdf_split_vfp"
+ [(set (reg:CCFP CC_REGNUM)
+ (compare:CCFP (match_operand:DF 0 "s_register_operand" "w")
+ (match_operand:DF 1 "vfp_compare_operand" "wG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "#"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ [(set (reg:CCFP VFPCC_REGNUM)
+ (compare:CCFP (match_dup 0)
+ (match_dup 1)))
+ (set (reg:CCFP CC_REGNUM)
+ (reg:CCFPE VFPCC_REGNUM))]
+ ""
+)
+
+(define_insn_and_split "*cmpdf_trap_split_vfp"
+ [(set (reg:CCFPE CC_REGNUM)
+ (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w")
+ (match_operand:DF 1 "vfp_compare_operand" "wG")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "#"
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ [(set (reg:CCFPE VFPCC_REGNUM)
+ (compare:CCFPE (match_dup 0)
+ (match_dup 1)))
+ (set (reg:CCFPE CC_REGNUM)
+ (reg:CCFPE VFPCC_REGNUM))]
+ ""
+)
+
+
+;; Comparison patterns
+
+(define_insn "*cmpsf_vfp"
+ [(set (reg:CCFP VFPCC_REGNUM)
+ (compare:CCFP (match_operand:SF 0 "s_register_operand" "w,w")
+ (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcmps%?\\t%0, %1
+ fcmpzs%?\\t%0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn "*cmpsf_trap_vfp"
+ [(set (reg:CCFPE VFPCC_REGNUM)
+ (compare:CCFPE (match_operand:SF 0 "s_register_operand" "w,w")
+ (match_operand:SF 1 "vfp_compare_operand" "w,G")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcmpes%?\\t%0, %1
+ fcmpezs%?\\t%0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn "*cmpdf_vfp"
+ [(set (reg:CCFP VFPCC_REGNUM)
+ (compare:CCFP (match_operand:DF 0 "s_register_operand" "w,w")
+ (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcmpd%?\\t%P0, %P1
+ fcmpzd%?\\t%P0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+(define_insn "*cmpdf_trap_vfp"
+ [(set (reg:CCFPE VFPCC_REGNUM)
+ (compare:CCFPE (match_operand:DF 0 "s_register_operand" "w,w")
+ (match_operand:DF 1 "vfp_compare_operand" "w,G")))]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "@
+ fcmped%?\\t%P0, %P1
+ fcmpezd%?\\t%P0"
+ [(set_attr "predicable" "yes")
+ (set_attr "type" "ffarith")]
+)
+
+
+;; Store multiple insn used in function prologue.
+
+(define_insn "*push_multi_vfp"
+ [(match_parallel 2 "multi_register_push"
+ [(set (match_operand:BLK 0 "memory_operand" "=m")
+ (unspec:BLK [(match_operand:DF 1 "s_register_operand" "w")]
+ UNSPEC_PUSH_MULT))])]
+ "TARGET_ARM && TARGET_HARD_FLOAT && TARGET_VFP"
+ "* return vfp_output_fstmx (operands);"
+ [(set_attr "type" "f_stored")]
+)
+
+
+;; Unimplemented insns:
+;; fldm*
+;; fstm*
+;; fmdhr et al (VFPv1)
+;; Support for xD (single precision only) variants.
+;; fmrrs, fmsrr
diff --git a/contrib/gcc/config/arm/vxworks.h b/contrib/gcc/config/arm/vxworks.h
index afe6b70..319c1e8 100644
--- a/contrib/gcc/config/arm/vxworks.h
+++ b/contrib/gcc/config/arm/vxworks.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GCC,
for ARM with targetting the VXWorks run time environment.
- Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc.
Contributed by: Mike Stump <mrs@wrs.com>
Brought up to date by CodeSourcery, LLC.
@@ -19,8 +19,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
@@ -46,16 +46,16 @@ Boston, MA 02111-1307, USA. */
#undef CC1_SPEC
#define CC1_SPEC \
-"%{t4: -mapcs-32 -mlittle-endian -march=armv4 ; \
- t4be: -mapcs-32 -mbig-endian -march=armv4 ; \
+"%{t4: -mlittle-endian -march=armv4 ; \
+ t4be: -mbig-endian -march=armv4 ; \
t4t: -mthumb -mthumb-interwork -mlittle-endian -march=armv4t ; \
t4tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv4t ; \
- t5: -mapcs-32 -mlittle-endian -march=armv5 ; \
- t5be: -mapcs-32 -mbig-endian -march=armv5 ; \
+ t5: -mlittle-endian -march=armv5 ; \
+ t5be: -mbig-endian -march=armv5 ; \
t5t: -mthumb -mthumb-interwork -mlittle-endian -march=armv5 ; \
t5tbe: -mthumb -mthumb-interwork -mbig-endian -march=armv5 ; \
- txscale: -mapcs-32 -mlittle-endian -mcpu=xscale ; \
- txscalebe: -mapcs-32 -mbig-endian -mcpu=xscale ; \
+ txscale: -mlittle-endian -mcpu=xscale ; \
+ txscalebe: -mbig-endian -mcpu=xscale ; \
: -march=armv4}"
/* The -Q options from svr4.h aren't understood and must be removed. */
diff --git a/contrib/gcc/config/arm/wince-pe.h b/contrib/gcc/config/arm/wince-pe.h
index fb47485..530340f 100644
--- a/contrib/gcc/config/arm/wince-pe.h
+++ b/contrib/gcc/config/arm/wince-pe.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for ARM with WINCE-PE obj format.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Nick Clifton <nickc@redhat.com>
This file is part of GCC.
@@ -16,14 +16,12 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
-
-/* Override arm/pe.h's default apcs26 support. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (ARM_FLAG_APCS_32 | ARM_FLAG_SOFT_FLOAT | TARGET_FLAG_NOP_FUN | ARM_FLAG_MMU_TRAPS)
+#define TARGET_DEFAULT (MASK_NOP_FUN_DLLIMPORT)
#undef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
- { "marm", "mlittle-endian", "msoft-float", "mapcs-32", "mno-thumb-interwork" }
+ { "marm", "mlittle-endian", "msoft-float", "mno-thumb-interwork" }
diff --git a/contrib/gcc/config/arm/xscale-coff.h b/contrib/gcc/config/arm/xscale-coff.h
index d8fee7d..e275943 100644
--- a/contrib/gcc/config/arm/xscale-coff.h
+++ b/contrib/gcc/config/arm/xscale-coff.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Run-time Target Specification. */
#undef SUBTARGET_CPU_DEFAULT
diff --git a/contrib/gcc/config/arm/xscale-elf.h b/contrib/gcc/config/arm/xscale-elf.h
index aea8360..be7be08 100644
--- a/contrib/gcc/config/arm/xscale-elf.h
+++ b/contrib/gcc/config/arm/xscale-elf.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Run-time Target Specification. */
#ifndef TARGET_VERSION
diff --git a/contrib/gcc/config/darwin-64.c b/contrib/gcc/config/darwin-64.c
new file mode 100644
index 0000000..33094e3
--- /dev/null
+++ b/contrib/gcc/config/darwin-64.c
@@ -0,0 +1,77 @@
+/* Functions shipped in the ppc64 and x86_64 version of libgcc_s.1.dylib
+ in older Mac OS X versions, preserved for backwards compatibility.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#if defined (__ppc64__) || defined (__x86_64__)
+/* Many of these functions have probably never been used by anyone
+ anywhere on these targets, but it's hard to prove this, so they're defined
+ here. None are actually necessary, as demonstrated below by defining
+ each function using the operation it implements. */
+
+typedef long DI;
+typedef unsigned long uDI;
+typedef int SI;
+typedef unsigned int uSI;
+typedef int word_type __attribute__ ((mode (__word__)));
+
+DI __ashldi3 (DI x, word_type c);
+DI __ashrdi3 (DI x, word_type c);
+int __clzsi2 (uSI x);
+word_type __cmpdi2 (DI x, DI y);
+int __ctzsi2 (uSI x);
+DI __divdi3 (DI x, DI y);
+uDI __lshrdi3 (uDI x, word_type c);
+DI __moddi3 (DI x, DI y);
+DI __muldi3 (DI x, DI y);
+DI __negdi2 (DI x);
+int __paritysi2 (uSI x);
+int __popcountsi2 (uSI x);
+word_type __ucmpdi2 (uDI x, uDI y);
+uDI __udivdi3 (uDI x, uDI y);
+uDI __udivmoddi4 (uDI x, uDI y, uDI *r);
+uDI __umoddi3 (uDI x, uDI y);
+
+DI __ashldi3 (DI x, word_type c) { return x << c; }
+DI __ashrdi3 (DI x, word_type c) { return x >> c; }
+int __clzsi2 (uSI x) { return __builtin_clz (x); }
+word_type __cmpdi2 (DI x, DI y) { return x < y ? 0 : x == y ? 1 : 2; }
+int __ctzsi2 (uSI x) { return __builtin_ctz (x); }
+DI __divdi3 (DI x, DI y) { return x / y; }
+uDI __lshrdi3 (uDI x, word_type c) { return x >> c; }
+DI __moddi3 (DI x, DI y) { return x % y; }
+DI __muldi3 (DI x, DI y) { return x * y; }
+DI __negdi2 (DI x) { return -x; }
+int __paritysi2 (uSI x) { return __builtin_parity (x); }
+int __popcountsi2 (uSI x) { return __builtin_popcount (x); }
+word_type __ucmpdi2 (uDI x, uDI y) { return x < y ? 0 : x == y ? 1 : 2; }
+uDI __udivdi3 (uDI x, uDI y) { return x / y; }
+uDI __udivmoddi4 (uDI x, uDI y, uDI *r) { *r = x % y; return x / y; }
+uDI __umoddi3 (uDI x, uDI y) { return x % y; }
+
+#endif /* __ppc64__ || __x86_64__ */
diff --git a/contrib/gcc/config/darwin-c.c b/contrib/gcc/config/darwin-c.c
index fb51455..88ce9ef 100644
--- a/contrib/gcc/config/darwin-c.c
+++ b/contrib/gcc/config/darwin-c.c
@@ -1,5 +1,5 @@
/* Darwin support needed only by C/C++ frontends.
- Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -27,18 +27,30 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "c-pragma.h"
#include "c-tree.h"
+#include "c-incpath.h"
+#include "c-common.h"
#include "toplev.h"
+#include "flags.h"
#include "tm_p.h"
+#include "cppdefault.h"
+#include "prefix.h"
/* Pragmas. */
-#define BAD(msgid) do { warning (msgid); return; } while (0)
+#define BAD(gmsgid) do { warning (OPT_Wpragmas, gmsgid); return; } while (0)
+#define BAD2(msgid, arg) do { warning (OPT_Wpragmas, msgid, arg); return; } while (0)
+
+static bool using_frameworks = false;
/* Maintain a small stack of alignments. This is similar to pragma
pack's stack, but simpler. */
static void push_field_alignment (int);
static void pop_field_alignment (void);
+static const char *find_subframework_file (const char *, const char *);
+static void add_system_framework_path (char *);
+static const char *find_subframework_header (cpp_reader *pfile, const char *header,
+ cpp_dir **dirp);
typedef struct align_stack
{
@@ -51,7 +63,7 @@ static struct align_stack * field_align_stack = NULL;
static void
push_field_alignment (int bit_alignment)
{
- align_stack *entry = (align_stack *) xmalloc (sizeof (align_stack));
+ align_stack *entry = XNEW (align_stack);
entry->alignment = maximum_field_alignment;
entry->prev = field_align_stack;
@@ -91,18 +103,18 @@ darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED)
const char *arg;
tree t, x;
- if (c_lex (&t) != CPP_NAME)
+ if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
arg = IDENTIFIER_POINTER (t);
if (strcmp (arg, "align"))
BAD ("malformed '#pragma options', ignoring");
- if (c_lex (&t) != CPP_EQ)
+ if (pragma_lex (&t) != CPP_EQ)
BAD ("malformed '#pragma options', ignoring");
- if (c_lex (&t) != CPP_NAME)
+ if (pragma_lex (&t) != CPP_NAME)
BAD ("malformed '#pragma options', ignoring");
- if (c_lex (&x) != CPP_EOF)
- warning ("junk at end of '#pragma options'");
+ if (pragma_lex (&x) != CPP_EOF)
+ warning (OPT_Wpragmas, "junk at end of '#pragma options'");
arg = IDENTIFIER_POINTER (t);
if (!strcmp (arg, "mac68k"))
@@ -112,7 +124,7 @@ darwin_pragma_options (cpp_reader *pfile ATTRIBUTE_UNUSED)
else if (!strcmp (arg, "reset"))
pop_field_alignment ();
else
- warning ("malformed '#pragma options align={mac68k|power|reset}', ignoring");
+ BAD ("malformed '#pragma options align={mac68k|power|reset}', ignoring");
}
/* #pragma unused ([var {, var}*]) */
@@ -123,19 +135,19 @@ darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED)
tree decl, x;
int tok;
- if (c_lex (&x) != CPP_OPEN_PAREN)
+ if (pragma_lex (&x) != CPP_OPEN_PAREN)
BAD ("missing '(' after '#pragma unused', ignoring");
while (1)
{
- tok = c_lex (&decl);
+ tok = pragma_lex (&decl);
if (tok == CPP_NAME && decl)
{
tree local = lookup_name (decl);
if (local && (TREE_CODE (local) == PARM_DECL
|| TREE_CODE (local) == VAR_DECL))
TREE_USED (local) = 1;
- tok = c_lex (&x);
+ tok = pragma_lex (&x);
if (tok != CPP_COMMA)
break;
}
@@ -144,6 +156,467 @@ darwin_pragma_unused (cpp_reader *pfile ATTRIBUTE_UNUSED)
if (tok != CPP_CLOSE_PAREN)
BAD ("missing ')' after '#pragma unused', ignoring");
- if (c_lex (&x) != CPP_EOF)
- warning ("junk at end of '#pragma unused'");
+ if (pragma_lex (&x) != CPP_EOF)
+ BAD ("junk at end of '#pragma unused'");
+}
+
+/* Parse the ms_struct pragma. */
+void
+darwin_pragma_ms_struct (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ const char *arg;
+ tree t;
+
+ if (pragma_lex (&t) != CPP_NAME)
+ BAD ("malformed '#pragma ms_struct', ignoring");
+ arg = IDENTIFIER_POINTER (t);
+
+ if (!strcmp (arg, "on"))
+ darwin_ms_struct = true;
+ else if (!strcmp (arg, "off") || !strcmp (arg, "reset"))
+ darwin_ms_struct = false;
+ else
+ BAD ("malformed '#pragma ms_struct {on|off|reset}', ignoring");
+
+ if (pragma_lex (&t) != CPP_EOF)
+ BAD ("junk at end of '#pragma ms_struct'");
+}
+
+static struct {
+ size_t len;
+ const char *name;
+ cpp_dir* dir;
+} *frameworks_in_use;
+static int num_frameworks = 0;
+static int max_frameworks = 0;
+
+
+/* Remember which frameworks have been seen, so that we can ensure
+ that all uses of that framework come from the same framework. DIR
+ is the place where the named framework NAME, which is of length
+ LEN, was found. We copy the directory name from NAME, as it will be
+ freed by others. */
+
+static void
+add_framework (const char *name, size_t len, cpp_dir *dir)
+{
+ char *dir_name;
+ int i;
+ for (i = 0; i < num_frameworks; ++i)
+ {
+ if (len == frameworks_in_use[i].len
+ && strncmp (name, frameworks_in_use[i].name, len) == 0)
+ {
+ return;
+ }
+ }
+ if (i >= max_frameworks)
+ {
+ max_frameworks = i*2;
+ max_frameworks += i == 0;
+ frameworks_in_use = xrealloc (frameworks_in_use,
+ max_frameworks*sizeof(*frameworks_in_use));
+ }
+ dir_name = XNEWVEC (char, len + 1);
+ memcpy (dir_name, name, len);
+ dir_name[len] = '\0';
+ frameworks_in_use[num_frameworks].name = dir_name;
+ frameworks_in_use[num_frameworks].len = len;
+ frameworks_in_use[num_frameworks].dir = dir;
+ ++num_frameworks;
+}
+
+/* Recall if we have seen the named framework NAME, before, and where
+ we saw it. NAME is LEN bytes long. The return value is the place
+ where it was seen before. */
+
+static struct cpp_dir*
+find_framework (const char *name, size_t len)
+{
+ int i;
+ for (i = 0; i < num_frameworks; ++i)
+ {
+ if (len == frameworks_in_use[i].len
+ && strncmp (name, frameworks_in_use[i].name, len) == 0)
+ {
+ return frameworks_in_use[i].dir;
+ }
+ }
+ return 0;
+}
+
+/* There are two directories in a framework that contain header files,
+ Headers and PrivateHeaders. We search Headers first as it is more
+ common to upgrade a header from PrivateHeaders to Headers and when
+ that is done, the old one might hang around and be out of data,
+ causing grief. */
+
+struct framework_header {const char * dirName; int dirNameLen; };
+static struct framework_header framework_header_dirs[] = {
+ { "Headers", 7 },
+ { "PrivateHeaders", 14 },
+ { NULL, 0 }
+};
+
+/* Returns a pointer to a malloced string that contains the real pathname
+ to the file, given the base name and the name. */
+
+static char *
+framework_construct_pathname (const char *fname, cpp_dir *dir)
+{
+ char *buf;
+ size_t fname_len, frname_len;
+ cpp_dir *fast_dir;
+ char *frname;
+ struct stat st;
+ int i;
+
+ /* Framework names must have a / in them. */
+ buf = strchr (fname, '/');
+ if (buf)
+ fname_len = buf - fname;
+ else
+ return 0;
+
+ fast_dir = find_framework (fname, fname_len);
+
+ /* Framework includes must all come from one framework. */
+ if (fast_dir && dir != fast_dir)
+ return 0;
+
+ frname = XNEWVEC (char, strlen (fname) + dir->len + 2
+ + strlen(".framework/") + strlen("PrivateHeaders"));
+ strncpy (&frname[0], dir->name, dir->len);
+ frname_len = dir->len;
+ if (frname_len && frname[frname_len-1] != '/')
+ frname[frname_len++] = '/';
+ strncpy (&frname[frname_len], fname, fname_len);
+ frname_len += fname_len;
+ strncpy (&frname[frname_len], ".framework/", strlen (".framework/"));
+ frname_len += strlen (".framework/");
+
+ if (fast_dir == 0)
+ {
+ frname[frname_len-1] = 0;
+ if (stat (frname, &st) == 0)
+ {
+ /* As soon as we find the first instance of the framework,
+ we stop and never use any later instance of that
+ framework. */
+ add_framework (fname, fname_len, dir);
+ }
+ else
+ {
+ /* If we can't find the parent directory, no point looking
+ further. */
+ free (frname);
+ return 0;
+ }
+ frname[frname_len-1] = '/';
+ }
+
+ /* Append framework_header_dirs and header file name */
+ for (i = 0; framework_header_dirs[i].dirName; i++)
+ {
+ strncpy (&frname[frname_len],
+ framework_header_dirs[i].dirName,
+ framework_header_dirs[i].dirNameLen);
+ strcpy (&frname[frname_len + framework_header_dirs[i].dirNameLen],
+ &fname[fname_len]);
+
+ if (stat (frname, &st) == 0)
+ return frname;
+ }
+
+ free (frname);
+ return 0;
+}
+
+/* Search for FNAME in sub-frameworks. pname is the context that we
+ wish to search in. Return the path the file was found at,
+ otherwise return 0. */
+
+static const char*
+find_subframework_file (const char *fname, const char *pname)
+{
+ char *sfrname;
+ const char *dot_framework = ".framework/";
+ char *bufptr;
+ int sfrname_len, i, fname_len;
+ struct cpp_dir *fast_dir;
+ static struct cpp_dir subframe_dir;
+ struct stat st;
+
+ bufptr = strchr (fname, '/');
+
+ /* Subframework files must have / in the name. */
+ if (bufptr == 0)
+ return 0;
+
+ fname_len = bufptr - fname;
+ fast_dir = find_framework (fname, fname_len);
+
+ /* Sub framework header filename includes parent framework name and
+ header name in the "CarbonCore/OSUtils.h" form. If it does not
+ include slash it is not a sub framework include. */
+ bufptr = strstr (pname, dot_framework);
+
+ /* If the parent header is not of any framework, then this header
+ cannot be part of any subframework. */
+ if (!bufptr)
+ return 0;
+
+ /* Now translate. For example, +- bufptr
+ fname = CarbonCore/OSUtils.h |
+ pname = /System/Library/Frameworks/Foundation.framework/Headers/Foundation.h
+ into
+ sfrname = /System/Library/Frameworks/Foundation.framework/Frameworks/CarbonCore.framework/Headers/OSUtils.h */
+
+ sfrname = XNEWVEC (char, strlen (pname) + strlen (fname) + 2 +
+ strlen ("Frameworks/") + strlen (".framework/")
+ + strlen ("PrivateHeaders"));
+
+ bufptr += strlen (dot_framework);
+
+ sfrname_len = bufptr - pname;
+
+ strncpy (&sfrname[0], pname, sfrname_len);
+
+ strncpy (&sfrname[sfrname_len], "Frameworks/", strlen ("Frameworks/"));
+ sfrname_len += strlen("Frameworks/");
+
+ strncpy (&sfrname[sfrname_len], fname, fname_len);
+ sfrname_len += fname_len;
+
+ strncpy (&sfrname[sfrname_len], ".framework/", strlen (".framework/"));
+ sfrname_len += strlen (".framework/");
+
+ /* Append framework_header_dirs and header file name */
+ for (i = 0; framework_header_dirs[i].dirName; i++)
+ {
+ strncpy (&sfrname[sfrname_len],
+ framework_header_dirs[i].dirName,
+ framework_header_dirs[i].dirNameLen);
+ strcpy (&sfrname[sfrname_len + framework_header_dirs[i].dirNameLen],
+ &fname[fname_len]);
+
+ if (stat (sfrname, &st) == 0)
+ {
+ if (fast_dir != &subframe_dir)
+ {
+ if (fast_dir)
+ warning (0, "subframework include %s conflicts with framework include",
+ fname);
+ else
+ add_framework (fname, fname_len, &subframe_dir);
+ }
+
+ return sfrname;
+ }
+ }
+ free (sfrname);
+
+ return 0;
+}
+
+/* Add PATH to the system includes. PATH must be malloc-ed and
+ NUL-terminated. System framework paths are C++ aware. */
+
+static void
+add_system_framework_path (char *path)
+{
+ int cxx_aware = 1;
+ cpp_dir *p;
+
+ p = XNEW (cpp_dir);
+ p->next = NULL;
+ p->name = path;
+ p->sysp = 1 + !cxx_aware;
+ p->construct = framework_construct_pathname;
+ using_frameworks = 1;
+
+ add_cpp_dir_path (p, SYSTEM);
+}
+
+/* Add PATH to the bracket includes. PATH must be malloc-ed and
+ NUL-terminated. */
+
+void
+add_framework_path (char *path)
+{
+ cpp_dir *p;
+
+ p = XNEW (cpp_dir);
+ p->next = NULL;
+ p->name = path;
+ p->sysp = 0;
+ p->construct = framework_construct_pathname;
+ using_frameworks = 1;
+
+ add_cpp_dir_path (p, BRACKET);
+}
+
+static const char *framework_defaults [] =
+ {
+ "/System/Library/Frameworks",
+ "/Library/Frameworks",
+ };
+
+/* Register the GNU objective-C runtime include path if STDINC. */
+
+void
+darwin_register_objc_includes (const char *sysroot, const char *iprefix,
+ int stdinc)
+{
+ const char *fname;
+ size_t len;
+ /* We do not do anything if we do not want the standard includes. */
+ if (!stdinc)
+ return;
+
+ fname = GCC_INCLUDE_DIR "-gnu-runtime";
+
+ /* Register the GNU OBJC runtime include path if we are compiling OBJC
+ with GNU-runtime. */
+
+ if (c_dialect_objc () && !flag_next_runtime)
+ {
+ char *str;
+ /* See if our directory starts with the standard prefix.
+ "Translate" them, i.e. replace /usr/local/lib/gcc... with
+ IPREFIX and search them first. */
+ if (iprefix && (len = cpp_GCC_INCLUDE_DIR_len) != 0 && !sysroot
+ && !strncmp (fname, cpp_GCC_INCLUDE_DIR, len))
+ {
+ str = concat (iprefix, fname + len, NULL);
+ /* FIXME: wrap the headers for C++awareness. */
+ add_path (str, SYSTEM, /*c++aware=*/false, false);
+ }
+
+ /* Should this directory start with the sysroot? */
+ if (sysroot)
+ str = concat (sysroot, fname, NULL);
+ else
+ str = update_path (fname, "");
+
+ add_path (str, SYSTEM, /*c++aware=*/false, false);
+ }
+}
+
+
+/* Register all the system framework paths if STDINC is true and setup
+ the missing_header callback for subframework searching if any
+ frameworks had been registered. */
+
+void
+darwin_register_frameworks (const char *sysroot,
+ const char *iprefix ATTRIBUTE_UNUSED, int stdinc)
+{
+ if (stdinc)
+ {
+ size_t i;
+
+ /* Setup default search path for frameworks. */
+ for (i=0; i<sizeof (framework_defaults)/sizeof(const char *); ++i)
+ {
+ char *str;
+ if (sysroot)
+ str = concat (sysroot, xstrdup (framework_defaults [i]), NULL);
+ else
+ str = xstrdup (framework_defaults[i]);
+ /* System Framework headers are cxx aware. */
+ add_system_framework_path (str);
+ }
+ }
+
+ if (using_frameworks)
+ cpp_get_callbacks (parse_in)->missing_header = find_subframework_header;
+}
+
+/* Search for HEADER in context dependent way. The return value is
+ the malloced name of a header to try and open, if any, or NULL
+ otherwise. This is called after normal header lookup processing
+ fails to find a header. We search each file in the include stack,
+ using FUNC, starting from the most deeply nested include and
+ finishing with the main input file. We stop searching when FUNC
+ returns nonzero. */
+
+static const char*
+find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp)
+{
+ const char *fname = header;
+ struct cpp_buffer *b;
+ const char *n;
+
+ for (b = cpp_get_buffer (pfile);
+ b && cpp_get_file (b) && cpp_get_path (cpp_get_file (b));
+ b = cpp_get_prev (b))
+ {
+ n = find_subframework_file (fname, cpp_get_path (cpp_get_file (b)));
+ if (n)
+ {
+ /* Logically, the place where we found the subframework is
+ the place where we found the Framework that contains the
+ subframework. This is useful for tracking wether or not
+ we are in a system header. */
+ *dirp = cpp_get_dir (cpp_get_file (b));
+ return n;
+ }
+ }
+
+ return 0;
+}
+
+/* Return the value of darwin_macosx_version_min suitable for the
+ __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro,
+ so '10.4.2' becomes 1042.
+ Print a warning if the version number is not known. */
+static const char *
+version_as_macro (void)
+{
+ static char result[] = "1000";
+
+ if (strncmp (darwin_macosx_version_min, "10.", 3) != 0)
+ goto fail;
+ if (! ISDIGIT (darwin_macosx_version_min[3]))
+ goto fail;
+ result[2] = darwin_macosx_version_min[3];
+ if (darwin_macosx_version_min[4] != '\0')
+ {
+ if (darwin_macosx_version_min[4] != '.')
+ goto fail;
+ if (! ISDIGIT (darwin_macosx_version_min[5]))
+ goto fail;
+ if (darwin_macosx_version_min[6] != '\0')
+ goto fail;
+ result[3] = darwin_macosx_version_min[5];
+ }
+ else
+ result[3] = '0';
+
+ return result;
+
+ fail:
+ error ("Unknown value %qs of -mmacosx-version-min",
+ darwin_macosx_version_min);
+ return "1000";
+}
+
+/* Define additional CPP flags for Darwin. */
+
+#define builtin_define(TXT) cpp_define (pfile, TXT)
+
+void
+darwin_cpp_builtins (cpp_reader *pfile)
+{
+ builtin_define ("__MACH__");
+ builtin_define ("__APPLE__");
+
+ /* __APPLE_CC__ is defined as some old Apple include files expect it
+ to be defined and won't work if it isn't. */
+ builtin_define_with_value ("__APPLE_CC__", "1", false);
+
+ if (darwin_macosx_version_min)
+ builtin_define_with_value ("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__",
+ version_as_macro(), false);
}
diff --git a/contrib/gcc/config/darwin-crt2.c b/contrib/gcc/config/darwin-crt2.c
index 1ea2413..69408d3 100644
--- a/contrib/gcc/config/darwin-crt2.c
+++ b/contrib/gcc/config/darwin-crt2.c
@@ -1,5 +1,5 @@
/* KeyMgr backwards-compatibility support for Darwin.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -24,8 +24,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* It is incorrect to include config.h here, because this file is being
compiled for the target, and hence definitions concerning only the host
@@ -34,6 +34,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "tconfig.h"
#include "tsystem.h"
+/* This file doesn't do anything useful on non-powerpc targets, since they
+ don't have backwards compatibility anyway. */
+
+#ifdef __ppc__
+
/* Homemade decls substituting for getsect.h and dyld.h, so cross
compilation works. */
struct mach_header;
@@ -149,3 +154,5 @@ __darwin_gcc3_preregister_frame_info (void)
_dyld_register_func_for_add_image (darwin_unwind_dyld_add_image_hook);
_dyld_register_func_for_remove_image (darwin_unwind_dyld_remove_image_hook);
}
+
+#endif /* __ppc__ */
diff --git a/contrib/gcc/config/darwin-crt3.c b/contrib/gcc/config/darwin-crt3.c
new file mode 100644
index 0000000..ac5e039
--- /dev/null
+++ b/contrib/gcc/config/darwin-crt3.c
@@ -0,0 +1,537 @@
+/* __cxa_atexit backwards-compatibility support for Darwin.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* Don't do anything if we are compiling for a kext multilib. */
+#ifdef __PIC__
+
+/* 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"
+#include "tsystem.h"
+
+#include <dlfcn.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* This file works around two different problems.
+
+ The first problem is that there is no __cxa_atexit on Mac OS versions
+ before 10.4. It fixes this by providing a complete atexit and
+ __cxa_atexit emulation called from the regular atexit.
+
+ The second problem is that on all shipping versions of Mac OS,
+ __cxa_finalize and exit() don't work right: they don't run routines
+ that were registered while other atexit routines are running. This
+ is worked around by wrapping each atexit/__cxa_atexit routine with
+ our own routine which ensures that any __cxa_atexit calls while it
+ is running are honoured.
+
+ There are still problems which this does not solve. Before 10.4,
+ shared objects linked with previous compilers won't have their
+ atexit calls properly interleaved with code compiled with newer
+ compilers. Also, atexit routines registered from shared objects
+ linked with previous compilers won't get the bug fix. */
+
+typedef int (*cxa_atexit_p)(void (*func) (void*), void* arg, const void* dso);
+typedef void (*cxa_finalize_p)(const void *dso);
+typedef int (*atexit_p)(void (*func)(void));
+
+/* These are from "keymgr.h". */
+extern void *_keymgr_get_and_lock_processwide_ptr (unsigned key);
+extern int _keymgr_get_and_lock_processwide_ptr_2 (unsigned, void **);
+extern int _keymgr_set_and_unlock_processwide_ptr (unsigned key, void *ptr);
+
+extern void *__keymgr_global[];
+typedef struct _Sinfo_Node {
+ unsigned int size ; /*size of this node*/
+ unsigned short major_version ; /*API major version.*/
+ unsigned short minor_version ; /*API minor version.*/
+ } _Tinfo_Node ;
+
+#ifdef __ppc__
+#define CHECK_KEYMGR_ERROR(e) \
+ (((_Tinfo_Node *)__keymgr_global[2])->major_version >= 4 ? (e) : 0)
+#else
+#define CHECK_KEYMGR_ERROR(e) (e)
+#endif
+
+/* Our globals are stored under this keymgr index. */
+#define KEYMGR_ATEXIT_LIST 14
+
+/* The different kinds of callback routines. */
+typedef void (*atexit_callback)(void);
+typedef void (*cxa_atexit_callback)(void *);
+
+/* This structure holds a routine to call. There may be extra fields
+ at the end of the structure that this code doesn't know about. */
+struct one_atexit_routine
+{
+ union {
+ atexit_callback ac;
+ cxa_atexit_callback cac;
+ } callback;
+ /* has_arg is 0/2/4 if 'ac' is live, 1/3/5 if 'cac' is live.
+ Higher numbers indicate a later version of the structure that this
+ code doesn't understand and will ignore. */
+ int has_arg;
+ void * arg;
+};
+
+struct atexit_routine_list
+{
+ struct atexit_routine_list * next;
+ struct one_atexit_routine r;
+};
+
+/* The various possibilities for status of atexit(). */
+enum atexit_status {
+ atexit_status_unknown = 0,
+ atexit_status_missing = 1,
+ atexit_status_broken = 2,
+ atexit_status_working = 16
+};
+
+struct keymgr_atexit_list
+{
+ /* Version of this list. This code knows only about version 0.
+ If the version is higher than 0, this code may add new atexit routines
+ but should not attempt to run the list. */
+ short version;
+ /* 1 if an atexit routine is currently being run by this code, 0
+ otherwise. */
+ char running_routines;
+ /* Holds a value from 'enum atexit_status'. */
+ unsigned char atexit_status;
+ /* The list of atexit and cxa_atexit routines registered. If
+ atexit_status_missing it contains all routines registered while
+ linked with this code. If atexit_status_broken it contains all
+ routines registered during cxa_finalize while linked with this
+ code. */
+ struct atexit_routine_list *l;
+ /* &__cxa_atexit; set if atexit_status >= atexit_status_broken. */
+ cxa_atexit_p cxa_atexit_f;
+ /* &__cxa_finalize; set if atexit_status >= atexit_status_broken. */
+ cxa_finalize_p cxa_finalize_f;
+ /* &atexit; set if atexit_status >= atexit_status_working
+ or atexit_status == atexit_status_missing. */
+ atexit_p atexit_f;
+};
+
+/* Return 0 if __cxa_atexit has the bug it has in Mac OS 10.4: it
+ fails to call routines registered while an atexit routine is
+ running. Return 1 if it works properly, and -1 if an error occurred. */
+
+struct atexit_data
+{
+ int result;
+ cxa_atexit_p cxa_atexit;
+};
+
+static void cxa_atexit_check_2 (void *arg)
+{
+ ((struct atexit_data *)arg)->result = 1;
+}
+
+static void cxa_atexit_check_1 (void *arg)
+{
+ struct atexit_data * aed = arg;
+ if (aed->cxa_atexit (cxa_atexit_check_2, arg, arg) != 0)
+ aed->result = -1;
+}
+
+static int
+check_cxa_atexit (cxa_atexit_p cxa_atexit, cxa_finalize_p cxa_finalize)
+{
+ struct atexit_data aed = { 0, cxa_atexit };
+
+ /* We re-use &aed as the 'dso' parameter, since it's a unique address. */
+ if (cxa_atexit (cxa_atexit_check_1, &aed, &aed) != 0)
+ return -1;
+ cxa_finalize (&aed);
+ if (aed.result == 0)
+ {
+ /* Call __cxa_finalize again to make sure that cxa_atexit_check_2
+ is removed from the list before AED goes out of scope. */
+ cxa_finalize (&aed);
+ aed.result = 0;
+ }
+ return aed.result;
+}
+
+#ifdef __ppc__
+/* This comes from Csu. It works only before 10.4. The prototype has
+ been altered a bit to avoid casting. */
+extern int _dyld_func_lookup(const char *dyld_func_name,
+ void *address) __attribute__((visibility("hidden")));
+
+static void our_atexit (void);
+
+/* We're running on 10.3.9. Find the address of the system atexit()
+ function. So easy to say, so hard to do. */
+static atexit_p
+find_atexit_10_3 (void)
+{
+ unsigned int (*dyld_image_count_fn)(void);
+ const char *(*dyld_get_image_name_fn)(unsigned int image_index);
+ const void *(*dyld_get_image_header_fn)(unsigned int image_index);
+ const void *(*NSLookupSymbolInImage_fn)(const void *image,
+ const char *symbolName,
+ unsigned int options);
+ void *(*NSAddressOfSymbol_fn)(const void *symbol);
+ unsigned i, count;
+
+ /* Find some dyld functions. */
+ _dyld_func_lookup("__dyld_image_count", &dyld_image_count_fn);
+ _dyld_func_lookup("__dyld_get_image_name", &dyld_get_image_name_fn);
+ _dyld_func_lookup("__dyld_get_image_header", &dyld_get_image_header_fn);
+ _dyld_func_lookup("__dyld_NSLookupSymbolInImage", &NSLookupSymbolInImage_fn);
+ _dyld_func_lookup("__dyld_NSAddressOfSymbol", &NSAddressOfSymbol_fn);
+
+ /* If any of these don't exist, that's an error. */
+ if (! dyld_image_count_fn || ! dyld_get_image_name_fn
+ || ! dyld_get_image_header_fn || ! NSLookupSymbolInImage_fn
+ || ! NSAddressOfSymbol_fn)
+ return NULL;
+
+ count = dyld_image_count_fn ();
+ for (i = 0; i < count; i++)
+ {
+ const char * path = dyld_get_image_name_fn (i);
+ const void * image;
+ const void * symbol;
+
+ if (strcmp (path, "/usr/lib/libSystem.B.dylib") != 0)
+ continue;
+ image = dyld_get_image_header_fn (i);
+ if (! image)
+ return NULL;
+ /* '4' is NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR. */
+ symbol = NSLookupSymbolInImage_fn (image, "_atexit", 4);
+ if (! symbol)
+ return NULL;
+ return NSAddressOfSymbol_fn (symbol);
+ }
+ return NULL;
+}
+#endif
+
+/* Create (if necessary), find, lock, fill in, and return our globals.
+ Return NULL on error, in which case the globals will not be locked.
+ The caller should call keymgr_set_and_unlock. */
+static struct keymgr_atexit_list *
+get_globals (void)
+{
+ struct keymgr_atexit_list * r;
+
+#ifdef __ppc__
+ /* 10.3.9 doesn't have _keymgr_get_and_lock_processwide_ptr_2 so the
+ PPC side can't use it. On 10.4 this just means the error gets
+ reported a little later when
+ _keymgr_set_and_unlock_processwide_ptr finds that the key was
+ never locked. */
+ r = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
+#else
+ void * rr;
+ if (_keymgr_get_and_lock_processwide_ptr_2 (KEYMGR_ATEXIT_LIST, &rr))
+ return NULL;
+ r = rr;
+#endif
+
+ if (r == NULL)
+ {
+ r = calloc (sizeof (struct keymgr_atexit_list), 1);
+ if (! r)
+ return NULL;
+ }
+
+ if (r->atexit_status == atexit_status_unknown)
+ {
+ void *handle;
+
+ handle = dlopen ("/usr/lib/libSystem.B.dylib", RTLD_NOLOAD);
+ if (!handle)
+ {
+#ifdef __ppc__
+ r->atexit_status = atexit_status_missing;
+ r->atexit_f = find_atexit_10_3 ();
+ if (! r->atexit_f)
+ goto error;
+ if (r->atexit_f (our_atexit))
+ goto error;
+#else
+ goto error;
+#endif
+ }
+ else
+ {
+ int chk_result;
+
+ r->cxa_atexit_f = (cxa_atexit_p)dlsym (handle, "__cxa_atexit");
+ r->cxa_finalize_f = (cxa_finalize_p)dlsym (handle, "__cxa_finalize");
+ if (! r->cxa_atexit_f || ! r->cxa_finalize_f)
+ goto error;
+
+ chk_result = check_cxa_atexit (r->cxa_atexit_f, r->cxa_finalize_f);
+ if (chk_result == -1)
+ goto error;
+ else if (chk_result == 0)
+ r->atexit_status = atexit_status_broken;
+ else
+ {
+ r->atexit_f = (atexit_p)dlsym (handle, "atexit");
+ if (! r->atexit_f)
+ goto error;
+ r->atexit_status = atexit_status_working;
+ }
+ }
+ }
+
+ return r;
+
+ error:
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, r);
+ return NULL;
+}
+
+/* Add TO_ADD to ATEXIT_LIST. ATEXIT_LIST may be NULL but is
+ always the result of calling _keymgr_get_and_lock_processwide_ptr and
+ so KEYMGR_ATEXIT_LIST is known to be locked; this routine is responsible
+ for unlocking it. */
+
+static int
+add_routine (struct keymgr_atexit_list * g,
+ const struct one_atexit_routine * to_add)
+{
+ struct atexit_routine_list * s
+ = malloc (sizeof (struct atexit_routine_list));
+ int result;
+
+ if (!s)
+ {
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+ return -1;
+ }
+ s->r = *to_add;
+ s->next = g->l;
+ g->l = s;
+ result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+ return CHECK_KEYMGR_ERROR (result) == 0 ? 0 : -1;
+}
+
+/* This runs the routines in G->L up to STOP. */
+static struct keymgr_atexit_list *
+run_routines (struct keymgr_atexit_list *g,
+ struct atexit_routine_list *stop)
+{
+ for (;;)
+ {
+ struct atexit_routine_list * cur = g->l;
+ if (! cur || cur == stop)
+ break;
+ g->l = cur->next;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+
+ switch (cur->r.has_arg) {
+ case 0: case 2: case 4:
+ cur->r.callback.ac ();
+ break;
+ case 1: case 3: case 5:
+ cur->r.callback.cac (cur->r.arg);
+ break;
+ default:
+ /* Don't understand, so don't call it. */
+ break;
+ }
+ free (cur);
+
+ g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
+ if (! g)
+ break;
+ }
+ return g;
+}
+
+/* Call the routine described by ROUTINE_PARAM and then call any
+ routines added to KEYMGR_ATEXIT_LIST while that routine was
+ running, all with in_cxa_finalize set. */
+
+static void
+cxa_atexit_wrapper (void* routine_param)
+{
+ struct one_atexit_routine * routine = routine_param;
+ struct keymgr_atexit_list *g;
+ struct atexit_routine_list * base = NULL;
+ char prev_running = 0;
+
+ g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
+ if (g)
+ {
+ prev_running = g->running_routines;
+ g->running_routines = 1;
+ base = g->l;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+ }
+
+ if (routine->has_arg)
+ routine->callback.cac (routine->arg);
+ else
+ routine->callback.ac ();
+
+ if (g)
+ g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
+ if (g)
+ g = run_routines (g, base);
+ if (g)
+ {
+ g->running_routines = prev_running;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+ }
+}
+
+#ifdef __ppc__
+/* This code is used while running on 10.3.9, when __cxa_atexit doesn't
+ exist in the system library. 10.3.9 only supported regular PowerPC,
+ so this code isn't necessary on x86 or ppc64. */
+
+/* This routine is called from the system atexit(); it runs everything
+ registered on the KEYMGR_ATEXIT_LIST. */
+
+static void
+our_atexit (void)
+{
+ struct keymgr_atexit_list *g;
+ char prev_running;
+
+ g = _keymgr_get_and_lock_processwide_ptr (KEYMGR_ATEXIT_LIST);
+ if (! g || g->version != 0 || g->atexit_status != atexit_status_missing)
+ return;
+
+ prev_running = g->running_routines;
+ g->running_routines = 1;
+ g = run_routines (g, NULL);
+ if (! g)
+ return;
+ g->running_routines = prev_running;
+ _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+}
+#endif
+
+/* This is our wrapper around atexit and __cxa_atexit. It will return
+ nonzero if an error occurs, and otherwise:
+ - if in_cxa_finalize is set, or running on 10.3.9, add R to
+ KEYMGR_ATEXIT_LIST; or
+ - call the system __cxa_atexit to add cxa_atexit_wrapper with an argument
+ that indicates how cxa_atexit_wrapper should call R. */
+
+static int
+atexit_common (const struct one_atexit_routine *r, const void *dso)
+{
+ struct keymgr_atexit_list *g = get_globals ();
+
+ if (! g)
+ return -1;
+
+ if (g->running_routines || g->atexit_status == atexit_status_missing)
+ return add_routine (g, r);
+
+ if (g->atexit_status >= atexit_status_working)
+ {
+ int result;
+ if (r->has_arg)
+ {
+ cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
+ result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
+ g);
+ if (CHECK_KEYMGR_ERROR (result))
+ return -1;
+ return cxa_atexit (r->callback.cac, r->arg, dso);
+ }
+ else
+ {
+ atexit_p atexit_f = g->atexit_f;
+ result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST,
+ g);
+ if (CHECK_KEYMGR_ERROR (result))
+ return -1;
+ return atexit_f (r->callback.ac);
+ }
+ }
+ else
+ {
+ cxa_atexit_p cxa_atexit = g->cxa_atexit_f;
+ struct one_atexit_routine *alloced;
+ int result;
+
+ result = _keymgr_set_and_unlock_processwide_ptr (KEYMGR_ATEXIT_LIST, g);
+ if (CHECK_KEYMGR_ERROR (result))
+ return -1;
+
+ alloced = malloc (sizeof (struct one_atexit_routine));
+ if (! alloced)
+ return -1;
+ *alloced = *r;
+ return cxa_atexit (cxa_atexit_wrapper, alloced, dso);
+ }
+}
+
+/* These are the actual replacement routines; they just funnel into
+ atexit_common. */
+
+int __cxa_atexit (cxa_atexit_callback func, void* arg,
+ const void* dso) __attribute__((visibility("hidden")));
+
+int
+__cxa_atexit (cxa_atexit_callback func, void* arg, const void* dso)
+{
+ struct one_atexit_routine r;
+ r.callback.cac = func;
+ r.has_arg = 1;
+ r.arg = arg;
+ return atexit_common (&r, dso);
+}
+
+int atexit (atexit_callback func) __attribute__((visibility("hidden")));
+
+/* Use __dso_handle to allow even bundles that call atexit() to be unloaded
+ on 10.4. */
+extern void __dso_handle;
+
+int
+atexit (atexit_callback func)
+{
+ struct one_atexit_routine r;
+ r.callback.ac = func;
+ r.has_arg = 0;
+ return atexit_common (&r, &__dso_handle);
+}
+
+#endif /* __PIC__ */
diff --git a/contrib/gcc/config/darwin-protos.h b/contrib/gcc/config/darwin-protos.h
index 3305112..8981ede 100644
--- a/contrib/gcc/config/darwin-protos.h
+++ b/contrib/gcc/config/darwin-protos.h
@@ -1,5 +1,5 @@
/* Prototypes.
- Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,33 +15,24 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+extern void darwin_init_sections (void);
extern int name_needs_quotes (const char *);
-extern void machopic_validate_stub_or_non_lazy_ptr (const char *, int);
+extern void machopic_validate_stub_or_non_lazy_ptr (const char *);
extern const char *machopic_function_base_name (void);
extern void machopic_output_function_base_name (FILE *);
-extern const char *machopic_stub_name (const char*);
-
-extern void machopic_picsymbol_stub_section (void);
-extern void machopic_picsymbol_stub1_section (void);
-extern void machopic_symbol_stub_section (void);
-extern void machopic_symbol_stub1_section (void);
-extern void machopic_lazy_symbol_ptr_section (void);
-extern void machopic_nl_symbol_ptr_section (void);
-
-extern void constructor_section (void);
-extern void destructor_section (void);
-extern void mod_init_section (void);
-extern void mod_term_section (void);
+extern const char *machopic_indirection_name (rtx, bool);
+extern const char *machopic_mcount_stub_name (void);
#ifdef RTX_CODE
+extern rtx machopic_function_base_sym (void);
extern int machopic_operand_p (rtx);
-extern enum machopic_addr_class machopic_classify_name (const char*);
+extern enum machopic_addr_class machopic_classify_symbol (rtx);
extern rtx machopic_indirect_data_reference (rtx, rtx);
extern rtx machopic_indirect_call_target (rtx);
@@ -53,69 +44,49 @@ extern void machopic_asm_out_destructor (rtx, int);
#ifdef TREE_CODE
-extern enum machopic_addr_class machopic_classify_ident (tree);
-extern void machopic_define_ident (tree);
-extern void machopic_define_name (const char*);
-extern int machopic_name_defined_p (const char*);
-extern int machopic_ident_defined_p (tree);
+extern void machopic_define_symbol (rtx);
extern void darwin_encode_section_info (tree, rtx, int);
-extern const char *darwin_strip_name_encoding (const char *);
+extern void darwin_set_default_type_attributes (tree);
#endif /* TREE_CODE */
extern void machopic_finish (FILE *);
-extern void darwin_exception_section (void);
-extern void darwin_eh_frame_section (void);
-extern void machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
-extern void machopic_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
+extern int machopic_reloc_rw_mask (void);
+extern section *machopic_select_section (tree, int, unsigned HOST_WIDE_INT);
+extern section *machopic_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+
+extern void darwin_unique_section (tree decl, int reloc);
+extern void darwin_asm_named_section (const char *, unsigned int, tree);
+extern void darwin_non_lazy_pcrel (FILE *, rtx);
+
+extern void darwin_emit_unwind_label (FILE *, tree, int, int);
+extern void darwin_emit_except_table_label (FILE *);
extern void darwin_pragma_ignore (struct cpp_reader *);
extern void darwin_pragma_options (struct cpp_reader *);
extern void darwin_pragma_unused (struct cpp_reader *);
+extern void darwin_pragma_ms_struct (struct cpp_reader *);
+extern void darwin_file_start (void);
extern void darwin_file_end (void);
-/* Expanded by EXTRA_SECTION_FUNCTIONS into varasm.o. */
-extern void const_section (void);
-extern void const_data_section (void);
-extern void cstring_section (void);
-extern void literal4_section (void);
-extern void literal8_section (void);
-extern void constructor_section (void);
-extern void mod_init_section (void);
-extern void mod_term_section (void);
-extern void destructor_section (void);
-extern void objc_class_section (void);
-extern void objc_meta_class_section (void);
-extern void objc_category_section (void);
-extern void objc_class_vars_section (void);
-extern void objc_instance_vars_section (void);
-extern void objc_cls_meth_section (void);
-extern void objc_inst_meth_section (void);
-extern void objc_cat_cls_meth_section (void);
-extern void objc_cat_inst_meth_section (void);
-extern void objc_selector_refs_section (void);
-extern void objc_selector_fixup_section (void);
-extern void objc_symbols_section (void);
-extern void objc_module_info_section (void);
-extern void objc_image_info_section (void);
-extern void objc_protocol_section (void);
-extern void objc_string_object_section (void);
-extern void objc_constant_string_object_section (void);
-extern void objc_class_names_section (void);
-extern void objc_meth_var_names_section (void);
-extern void objc_meth_var_types_section (void);
-extern void objc_cls_refs_section (void);
-extern void machopic_lazy_symbol_ptr_section (void);
-extern void machopic_nl_symbol_ptr_section (void);
-extern void machopic_symbol_stub_section (void);
-extern void machopic_picsymbol_stub_section (void);
+extern void darwin_mark_decl_preserved (const char *);
+
+extern tree darwin_handle_kext_attribute (tree *, tree, tree, int, bool *);
+extern tree darwin_handle_weak_import_attribute (tree *node, tree name,
+ tree args, int flags,
+ bool * no_add_attrs);
extern void machopic_output_stub (FILE *, const char *, const char *);
-extern void darwin_exception_section (void);
-extern void darwin_eh_frame_section (void);
extern void darwin_globalize_label (FILE *, const char *);
extern void darwin_assemble_visibility (tree, int);
extern void darwin_asm_output_dwarf_delta (FILE *, int, const char *,
const char *);
+extern void darwin_asm_output_dwarf_offset (FILE *, int, const char *,
+ section *);
+extern bool darwin_binds_local_p (tree);
+extern void darwin_cpp_builtins (struct cpp_reader *);
+extern void darwin_asm_output_anchor (rtx symbol);
+extern bool darwin_kextabi_p (void);
+extern void darwin_override_options (void);
diff --git a/contrib/gcc/config/darwin-sections.def b/contrib/gcc/config/darwin-sections.def
new file mode 100644
index 0000000..148b775
--- /dev/null
+++ b/contrib/gcc/config/darwin-sections.def
@@ -0,0 +1,63 @@
+DEF_SECTION (text_coal_section, SECTION_CODE,
+ ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", 0)
+DEF_SECTION (text_unlikely_coal_section, SECTION_CODE,
+ ".section __TEXT,__text_unlikely_coal,"
+ "coalesced,pure_instructions", 0)
+DEF_SECTION (const_section, 0, ".const", 0)
+DEF_SECTION (const_coal_section, 0,
+ ".section __TEXT,__const_coal,coalesced", 0)
+DEF_SECTION (const_data_section, 0, ".const_data", 0)
+DEF_SECTION (const_data_coal_section, 0,
+ ".section __DATA,__const_coal,coalesced", 0)
+DEF_SECTION (data_coal_section, SECTION_WRITE,
+ ".section __DATA,__datacoal_nt,coalesced", 0)
+DEF_SECTION (cstring_section, SECTION_MERGE, ".cstring", 0)
+DEF_SECTION (literal4_section, SECTION_MERGE, ".literal4", 0)
+DEF_SECTION (literal8_section, SECTION_MERGE, ".literal8", 0)
+DEF_SECTION (literal16_section, SECTION_MERGE, ".literal16", 0)
+DEF_SECTION (constructor_section, 0, ".constructor", 0)
+DEF_SECTION (mod_init_section, 0, ".mod_init_func", 0)
+DEF_SECTION (mod_term_section, 0, ".mod_term_func", 0)
+DEF_SECTION (destructor_section, 0, ".destructor", 0)
+DEF_SECTION (objc_class_section, 0, ".objc_class", 1)
+DEF_SECTION (objc_meta_class_section, 0, ".objc_meta_class", 1)
+DEF_SECTION (objc_category_section, 0, ".objc_category", 1)
+DEF_SECTION (objc_class_vars_section, 0, ".objc_class_vars", 1)
+DEF_SECTION (objc_instance_vars_section, 0, ".objc_instance_vars", 1)
+DEF_SECTION (objc_cls_meth_section, 0, ".objc_cls_meth", 1)
+DEF_SECTION (objc_inst_meth_section, 0, ".objc_inst_meth", 1)
+DEF_SECTION (objc_cat_cls_meth_section, 0, ".objc_cat_cls_meth", 1)
+DEF_SECTION (objc_cat_inst_meth_section, 0, ".objc_cat_inst_meth", 1)
+DEF_SECTION (objc_selector_refs_section, SECTION_MERGE, ".objc_message_refs", 1)
+DEF_SECTION (objc_selector_fixup_section, 0,
+ ".section __OBJC, __sel_fixup, regular, no_dead_strip", 1)
+DEF_SECTION (objc_symbols_section, 0, ".objc_symbols", 1)
+DEF_SECTION (objc_module_info_section, 0, ".objc_module_info", 1)
+DEF_SECTION (objc_protocol_section, 0, ".objc_protocol", 1)
+DEF_SECTION (objc_string_object_section, 0, ".objc_string_object", 1)
+DEF_SECTION (objc_constant_string_object_section, 0,
+ ".section __OBJC, __cstring_object, regular, no_dead_strip", 1)
+
+/* Fix-and-Continue image marker. */
+DEF_SECTION (objc_image_info_section, 0,
+ ".section __OBJC, __image_info, regular, no_dead_strip", 1)
+DEF_SECTION (objc_class_names_section, 0, ".objc_class_names", 1)
+DEF_SECTION (objc_meth_var_names_section, 0, ".objc_meth_var_names", 1)
+DEF_SECTION (objc_meth_var_types_section, 0, ".objc_meth_var_types", 1)
+DEF_SECTION (objc_cls_refs_section, SECTION_MERGE, ".objc_cls_refs", 1)
+
+DEF_SECTION (machopic_lazy_symbol_ptr_section, 0, ".lazy_symbol_pointer", 0)
+DEF_SECTION (machopic_nl_symbol_ptr_section, 0, ".non_lazy_symbol_pointer", 0)
+DEF_SECTION (machopic_symbol_stub_section, 0, ".symbol_stub", 0)
+DEF_SECTION (machopic_symbol_stub1_section, 0,
+ ".section __TEXT,__symbol_stub1,symbol_stubs,"
+ "pure_instructions,16", 0)
+DEF_SECTION (machopic_picsymbol_stub_section, 0, ".picsymbol_stub", 0)
+DEF_SECTION (machopic_picsymbol_stub1_section, 0,
+ ".section __TEXT,__picsymbolstub1,symbol_stubs,"
+ "pure_instructions,32", 0)
+DEF_SECTION (darwin_exception_section, 0,
+ ".section __DATA,__gcc_except_tab", 0)
+DEF_SECTION (darwin_eh_frame_section, 0,
+ ".section " EH_FRAME_SECTION_NAME ",__eh_frame"
+ EH_FRAME_SECTION_ATTR, 0)
diff --git a/contrib/gcc/config/darwin.c b/contrib/gcc/config/darwin.c
index c946e59..addef12 100644
--- a/contrib/gcc/config/darwin.c
+++ b/contrib/gcc/config/darwin.c
@@ -1,5 +1,6 @@
/* Functions for generic Darwin as target machine for GNU C compiler.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
+ 2005
Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -40,13 +41,109 @@ Boston, MA 02111-1307, USA. */
#include "function.h"
#include "ggc.h"
#include "langhooks.h"
+#include "target.h"
#include "tm_p.h"
-#include "errors.h"
+#include "toplev.h"
+#include "hashtab.h"
+
+/* Darwin supports a feature called fix-and-continue, which is used
+ for rapid turn around debugging. When code is compiled with the
+ -mfix-and-continue flag, two changes are made to the generated code
+ that allow the system to do things that it would normally not be
+ able to do easily. These changes allow gdb to load in
+ recompilation of a translation unit that has been changed into a
+ running program and replace existing functions and methods of that
+ translation unit with versions of those functions and methods
+ from the newly compiled translation unit. The new functions access
+ the existing static symbols from the old translation unit, if the
+ symbol existed in the unit to be replaced, and from the new
+ translation unit, otherwise.
+
+ The changes are to insert 5 nops at the beginning of all functions
+ and to use indirection to get at static symbols. The 5 nops
+ are required by consumers of the generated code. Currently, gdb
+ uses this to patch in a jump to the overriding function, this
+ allows all uses of the old name to forward to the replacement,
+ including existing function pointers and virtual methods. See
+ rs6000_emit_prologue for the code that handles the nop insertions.
+
+ The added indirection allows gdb to redirect accesses to static
+ symbols from the newly loaded translation unit to the existing
+ symbol, if any. @code{static} symbols are special and are handled by
+ setting the second word in the .non_lazy_symbol_pointer data
+ structure to symbol. See indirect_data for the code that handles
+ the extra indirection, and machopic_output_indirection and its use
+ of MACHO_SYMBOL_STATIC for the code that handles @code{static}
+ symbol indirection. */
+
+/* Section names. */
+section * darwin_sections[NUM_DARWIN_SECTIONS];
+
+/* True if we're setting __attribute__ ((ms_struct)). */
+int darwin_ms_struct = false;
+
+/* A get_unnamed_section callback used to switch to an ObjC section.
+ DIRECTIVE is as for output_section_asm_op. */
-static int machopic_data_defined_p (const char *);
-static void update_non_lazy_ptrs (const char *);
-static void update_stubs (const char *);
-static const char *machopic_non_lazy_ptr_name (const char*);
+static void
+output_objc_section_asm_op (const void *directive)
+{
+ static bool been_here = false;
+
+ if (! been_here)
+ {
+ static const enum darwin_section_enum tomark[] =
+ {
+ /* written, cold -> hot */
+ objc_cat_cls_meth_section,
+ objc_cat_inst_meth_section,
+ objc_string_object_section,
+ objc_constant_string_object_section,
+ objc_selector_refs_section,
+ objc_selector_fixup_section,
+ objc_cls_refs_section,
+ objc_class_section,
+ objc_meta_class_section,
+ /* shared, hot -> cold */
+ objc_cls_meth_section,
+ objc_inst_meth_section,
+ objc_protocol_section,
+ objc_class_names_section,
+ objc_meth_var_types_section,
+ objc_meth_var_names_section,
+ objc_category_section,
+ objc_class_vars_section,
+ objc_instance_vars_section,
+ objc_module_info_section,
+ objc_symbols_section
+ };
+ size_t i;
+
+ been_here = true;
+ for (i = 0; i < ARRAY_SIZE (tomark); i++)
+ switch_to_section (darwin_sections[tomark[i]]);
+ }
+ output_section_asm_op (directive);
+}
+
+/* Implement TARGET_ASM_INIT_SECTIONS. */
+
+void
+darwin_init_sections (void)
+{
+#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC) \
+ darwin_sections[NAME] = \
+ get_unnamed_section (FLAGS, (OBJC \
+ ? output_objc_section_asm_op \
+ : output_section_asm_op), \
+ "\t" DIRECTIVE);
+#include "config/darwin-sections.def"
+#undef DEF_SECTION
+
+ readonly_data_section = darwin_sections[const_section];
+ exception_section = darwin_sections[darwin_exception_section];
+ eh_frame_section = darwin_sections[darwin_eh_frame_section];
+}
int
name_needs_quotes (const char *name)
@@ -58,162 +155,114 @@ name_needs_quotes (const char *name)
return 0;
}
-/*
- * flag_pic = 1 ... generate only indirections
- * flag_pic = 2 ... generate indirections and pure code
- */
+/* Return true if SYM_REF can be used without an indirection. */
+static int
+machopic_symbol_defined_p (rtx sym_ref)
+{
+ if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_DEFINED)
+ return true;
+
+ /* If a symbol references local and is not an extern to this
+ file, then the symbol might be able to declared as defined. */
+ if (SYMBOL_REF_LOCAL_P (sym_ref) && ! SYMBOL_REF_EXTERNAL_P (sym_ref))
+ {
+ /* If the symbol references a variable and the variable is a
+ common symbol, then this symbol is not defined. */
+ if (SYMBOL_REF_FLAGS (sym_ref) & MACHO_SYMBOL_FLAG_VARIABLE)
+ {
+ tree decl = SYMBOL_REF_DECL (sym_ref);
+ if (!decl)
+ return true;
+ if (DECL_COMMON (decl))
+ return false;
+ }
+ return true;
+ }
+ return false;
+}
/* This module assumes that (const (symbol_ref "foo")) is a legal pic
reference, which will not be changed. */
-static GTY(()) tree machopic_defined_list;
-
enum machopic_addr_class
-machopic_classify_ident (tree ident)
+machopic_classify_symbol (rtx sym_ref)
{
- const char *name = IDENTIFIER_POINTER (ident);
- int lprefix = (((name[0] == '*' || name[0] == '&')
- && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
- || ( name[0] == '_'
- && name[1] == 'O'
- && name[2] == 'B'
- && name[3] == 'J'
- && name[4] == 'C'
- && name[5] == '_'));
- tree temp;
-
- /* The PIC base symbol is always defined. */
- if (! strcmp (name, "<pic base>"))
- return MACHOPIC_DEFINED_DATA;
-
- if (name[0] != '!')
- {
- /* Here if no special encoding to be found. */
- if (lprefix)
- {
- const char *name = IDENTIFIER_POINTER (ident);
- int len = strlen (name);
-
- if ((len > 5 && !strcmp (name + len - 5, "$stub"))
- || (len > 6 && !strcmp (name + len - 6, "$stub\"")))
- return MACHOPIC_DEFINED_FUNCTION;
- return MACHOPIC_DEFINED_DATA;
- }
+ int flags;
+ bool function_p;
+
+ flags = SYMBOL_REF_FLAGS (sym_ref);
+ function_p = SYMBOL_REF_FUNCTION_P (sym_ref);
+ if (machopic_symbol_defined_p (sym_ref))
+ return (function_p
+ ? MACHOPIC_DEFINED_FUNCTION : MACHOPIC_DEFINED_DATA);
+ else
+ return (function_p
+ ? MACHOPIC_UNDEFINED_FUNCTION : MACHOPIC_UNDEFINED_DATA);
+}
- for (temp = machopic_defined_list;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
- {
- if (ident == TREE_VALUE (temp))
- return MACHOPIC_DEFINED_DATA;
- }
+#ifndef TARGET_FIX_AND_CONTINUE
+#define TARGET_FIX_AND_CONTINUE 0
+#endif
- if (TREE_ASM_WRITTEN (ident))
- return MACHOPIC_DEFINED_DATA;
+/* Indicate when fix-and-continue style code generation is being used
+ and when a reference to data should be indirected so that it can be
+ rebound in a new translation unit to reference the original instance
+ of that data. Symbol names that are for code generation local to
+ the translation unit are bound to the new translation unit;
+ currently this means symbols that begin with L or _OBJC_;
+ otherwise, we indicate that an indirect reference should be made to
+ permit the runtime to rebind new instances of the translation unit
+ to the original instance of the data. */
- return MACHOPIC_UNDEFINED;
- }
+static int
+indirect_data (rtx sym_ref)
+{
+ int lprefix;
+ const char *name;
- else if (name[1] == 'D')
- return MACHOPIC_DEFINED_DATA;
+ /* If we aren't generating fix-and-continue code, don't do anything special. */
+ if (TARGET_FIX_AND_CONTINUE == 0)
+ return 0;
- else if (name[1] == 'T')
- return MACHOPIC_DEFINED_FUNCTION;
+ /* Otherwise, all symbol except symbols that begin with L or _OBJC_
+ are indirected. Symbols that begin with L and _OBJC_ are always
+ bound to the current translation unit as they are used for
+ generated local data of the translation unit. */
- /* It is possible that someone is holding a "stale" name, which has
- since been defined. See if there is a "defined" name (i.e,
- different from NAME only in having a '!D_' or a '!T_' instead of
- a '!d_' or '!t_' prefix) in the identifier hash tables. If so, say
- that this identifier is defined. */
- else if (name[1] == 'd' || name[1] == 't')
- {
- char *new_name;
- new_name = (char *)alloca (strlen (name) + 1);
- strcpy (new_name, name);
- new_name[1] = (name[1] == 'd') ? 'D' : 'T';
- if (maybe_get_identifier (new_name) != NULL)
- return (name[1] == 'd') ? MACHOPIC_DEFINED_DATA
- : MACHOPIC_DEFINED_FUNCTION;
- }
+ name = XSTR (sym_ref, 0);
- for (temp = machopic_defined_list; temp != NULL_TREE; temp = TREE_CHAIN (temp))
- {
- if (ident == TREE_VALUE (temp))
- {
- if (name[1] == 'T')
- return MACHOPIC_DEFINED_FUNCTION;
- else
- return MACHOPIC_DEFINED_DATA;
- }
- }
+ lprefix = (((name[0] == '*' || name[0] == '&')
+ && (name[1] == 'L' || (name[1] == '"' && name[2] == 'L')))
+ || (strncmp (name, "_OBJC_", 6) == 0));
- if (name[1] == 't' || name[1] == 'T')
- {
- if (lprefix)
- return MACHOPIC_DEFINED_FUNCTION;
- else
- return MACHOPIC_UNDEFINED_FUNCTION;
- }
- else
- {
- if (lprefix)
- return MACHOPIC_DEFINED_DATA;
- else
- return MACHOPIC_UNDEFINED_DATA;
- }
-}
-
-
-enum machopic_addr_class
-machopic_classify_name (const char *name)
-{
- return machopic_classify_ident (get_identifier (name));
+ return ! lprefix;
}
-int
-machopic_ident_defined_p (tree ident)
-{
- switch (machopic_classify_ident (ident))
- {
- case MACHOPIC_UNDEFINED:
- case MACHOPIC_UNDEFINED_DATA:
- case MACHOPIC_UNDEFINED_FUNCTION:
- return 0;
- default:
- return 1;
- }
-}
static int
-machopic_data_defined_p (const char *name)
+machopic_data_defined_p (rtx sym_ref)
{
- switch (machopic_classify_ident (get_identifier (name)))
+ if (indirect_data (sym_ref))
+ return 0;
+
+ switch (machopic_classify_symbol (sym_ref))
{
case MACHOPIC_DEFINED_DATA:
+ case MACHOPIC_DEFINED_FUNCTION:
return 1;
default:
return 0;
}
}
-int
-machopic_name_defined_p (const char *name)
-{
- return machopic_ident_defined_p (get_identifier (name));
-}
-
void
-machopic_define_ident (tree ident)
+machopic_define_symbol (rtx mem)
{
- if (!machopic_ident_defined_p (ident))
- machopic_defined_list =
- tree_cons (NULL_TREE, ident, machopic_defined_list);
-}
+ rtx sym_ref;
-void
-machopic_define_name (const char *name)
-{
- machopic_define_ident (get_identifier (name));
+ gcc_assert (GET_CODE (mem) == MEM);
+ sym_ref = XEXP (mem, 0);
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
}
static GTY(()) char * function_base;
@@ -221,12 +270,8 @@ static GTY(()) char * function_base;
const char *
machopic_function_base_name (void)
{
- const char *current_name;
/* if dynamic-no-pic is on, we should not get here */
- if (MACHO_DYNAMIC_NO_PIC_P)
- abort ();
- current_name =
- IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
+ gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
if (function_base == NULL)
function_base =
@@ -237,6 +282,30 @@ machopic_function_base_name (void)
return function_base;
}
+/* Return a SYMBOL_REF for the PIC function base. */
+
+rtx
+machopic_function_base_sym (void)
+{
+ rtx sym_ref;
+
+ sym_ref = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
+ SYMBOL_REF_FLAGS (sym_ref)
+ |= (MACHO_SYMBOL_FLAG_VARIABLE | MACHO_SYMBOL_FLAG_DEFINED);
+ return sym_ref;
+}
+
+/* Return either ORIG or (const:P (minus:P ORIG PIC_BASE)), depending
+ on whether pic_base is NULL or not. */
+static inline rtx
+gen_pic_offset (rtx orig, rtx pic_base)
+{
+ if (!pic_base)
+ return orig;
+ else
+ return gen_rtx_CONST (Pmode, gen_rtx_MINUS (Pmode, orig, pic_base));
+}
+
static GTY(()) const char * function_base_func_name;
static GTY(()) int current_pic_label_num;
@@ -245,9 +314,8 @@ machopic_output_function_base_name (FILE *file)
{
const char *current_name;
- /* If dynamic-no-pic is on, we should not get here. */
- if (MACHO_DYNAMIC_NO_PIC_P)
- abort ();
+ /* If dynamic-no-pic is on, we should not get here. */
+ gcc_assert (!MACHO_DYNAMIC_NO_PIC_P);
current_name =
IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
if (function_base_func_name != current_name)
@@ -258,180 +326,173 @@ machopic_output_function_base_name (FILE *file)
fprintf (file, "\"L%011d$pb\"", current_pic_label_num);
}
-static GTY(()) tree machopic_non_lazy_pointers;
+/* The suffix attached to non-lazy pointer symbols. */
+#define NON_LAZY_POINTER_SUFFIX "$non_lazy_ptr"
+/* The suffix attached to stub symbols. */
+#define STUB_SUFFIX "$stub"
-/* Return a non-lazy pointer name corresponding to the given name,
- either by finding it in our list of pointer names, or by generating
- a new one. */
+typedef struct machopic_indirection GTY (())
+{
+ /* The SYMBOL_REF for the entity referenced. */
+ rtx symbol;
+ /* The name of the stub or non-lazy pointer. */
+ const char * ptr_name;
+ /* True iff this entry is for a stub (as opposed to a non-lazy
+ pointer). */
+ bool stub_p;
+ /* True iff this stub or pointer pointer has been referenced. */
+ bool used;
+} machopic_indirection;
+
+/* A table mapping stub names and non-lazy pointer names to
+ SYMBOL_REFs for the stubbed-to and pointed-to entities. */
+
+static GTY ((param_is (struct machopic_indirection))) htab_t
+ machopic_indirections;
+
+/* Return a hash value for a SLOT in the indirections hash table. */
+
+static hashval_t
+machopic_indirection_hash (const void *slot)
+{
+ const machopic_indirection *p = (const machopic_indirection *) slot;
+ return htab_hash_string (p->ptr_name);
+}
-static const char *
-machopic_non_lazy_ptr_name (const char *name)
+/* Returns true if the KEY is the same as that associated with
+ SLOT. */
+
+static int
+machopic_indirection_eq (const void *slot, const void *key)
{
- const char *temp_name;
- tree temp, ident = get_identifier (name);
+ return strcmp (((const machopic_indirection *) slot)->ptr_name, key) == 0;
+}
- for (temp = machopic_non_lazy_pointers;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
+/* Return the name of the non-lazy pointer (if STUB_P is false) or
+ stub (if STUB_B is true) corresponding to the given name. */
+
+const char *
+machopic_indirection_name (rtx sym_ref, bool stub_p)
+{
+ char *buffer;
+ const char *name = XSTR (sym_ref, 0);
+ size_t namelen = strlen (name);
+ machopic_indirection *p;
+ void ** slot;
+ bool saw_star = false;
+ bool needs_quotes;
+ const char *suffix;
+ const char *prefix = user_label_prefix;
+ const char *quote = "";
+ tree id;
+
+ id = maybe_get_identifier (name);
+ if (id)
{
- if (ident == TREE_VALUE (temp))
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ tree id_orig = id;
+
+ while (IDENTIFIER_TRANSPARENT_ALIAS (id))
+ id = TREE_CHAIN (id);
+ if (id != id_orig)
+ {
+ name = IDENTIFIER_POINTER (id);
+ namelen = strlen (name);
+ }
}
- name = darwin_strip_name_encoding (name);
+ if (name[0] == '*')
+ {
+ saw_star = true;
+ prefix = "";
+ ++name;
+ --namelen;
+ }
- /* Try again, but comparing names this time. */
- for (temp = machopic_non_lazy_pointers;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
+ needs_quotes = name_needs_quotes (name);
+ if (needs_quotes)
{
- if (TREE_VALUE (temp))
- {
- temp_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- temp_name = darwin_strip_name_encoding (temp_name);
- if (strcmp (name, temp_name) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
- }
+ quote = "\"";
}
- {
- char *buffer;
- int namelen = strlen (name);
- int bufferlen = 0;
- tree ptr_name;
-
- buffer = alloca (namelen + strlen("$non_lazy_ptr") + 5);
-
- strcpy (buffer, "&L");
- bufferlen = 2;
- if (name[0] == '*')
- {
- memcpy (buffer + bufferlen, name+1, namelen-1+1);
- bufferlen += namelen-1;
- }
- else
- {
- buffer[bufferlen] = '_';
- memcpy (buffer + bufferlen +1, name, namelen+1);
- bufferlen += namelen +1;
- }
-
- memcpy (buffer + bufferlen, "$non_lazy_ptr", strlen("$non_lazy_ptr")+1);
- bufferlen += strlen("$non_lazy_ptr");
- ptr_name = get_identifier (buffer);
-
- machopic_non_lazy_pointers
- = tree_cons (ptr_name, ident, machopic_non_lazy_pointers);
-
- TREE_USED (machopic_non_lazy_pointers) = 0;
-
- return IDENTIFIER_POINTER (ptr_name);
- }
+ if (stub_p)
+ suffix = STUB_SUFFIX;
+ else
+ suffix = NON_LAZY_POINTER_SUFFIX;
+
+ buffer = alloca (strlen ("&L")
+ + strlen (prefix)
+ + namelen
+ + strlen (suffix)
+ + 2 * strlen (quote)
+ + 1 /* '\0' */);
+
+ /* Construct the name of the non-lazy pointer or stub. */
+ sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote);
+
+ if (!machopic_indirections)
+ machopic_indirections = htab_create_ggc (37,
+ machopic_indirection_hash,
+ machopic_indirection_eq,
+ /*htab_del=*/NULL);
+
+ slot = htab_find_slot_with_hash (machopic_indirections, buffer,
+ htab_hash_string (buffer), INSERT);
+ if (*slot)
+ {
+ p = (machopic_indirection *) *slot;
+ }
+ else
+ {
+ p = (machopic_indirection *) ggc_alloc (sizeof (machopic_indirection));
+ p->symbol = sym_ref;
+ p->ptr_name = xstrdup (buffer);
+ p->stub_p = stub_p;
+ p->used = false;
+ *slot = p;
+ }
+
+ return p->ptr_name;
}
-static GTY(()) tree machopic_stubs;
+/* Return the name of the stub for the mcount function. */
-/* Return the name of the stub corresponding to the given name,
- generating a new stub name if necessary. */
+const char*
+machopic_mcount_stub_name (void)
+{
+ rtx symbol = gen_rtx_SYMBOL_REF (Pmode, "*mcount");
+ return machopic_indirection_name (symbol, /*stub_p=*/true);
+}
-const char *
-machopic_stub_name (const char *name)
+/* If NAME is the name of a stub or a non-lazy pointer , mark the stub
+ or non-lazy pointer as used -- and mark the object to which the
+ pointer/stub refers as used as well, since the pointer/stub will
+ emit a reference to it. */
+
+void
+machopic_validate_stub_or_non_lazy_ptr (const char *name)
{
- tree temp, ident = get_identifier (name);
- const char *tname;
+ machopic_indirection *p;
- for (temp = machopic_stubs;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
+ p = ((machopic_indirection *)
+ (htab_find_with_hash (machopic_indirections, name,
+ htab_hash_string (name))));
+ if (p && ! p->used)
{
- if (ident == TREE_VALUE (temp))
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
- tname = IDENTIFIER_POINTER (TREE_VALUE (temp));
- if (strcmp (name, tname) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
- /* A library call name might not be section-encoded yet, so try
- it against a stripped name. */
- if (name[0] != '!'
- && tname[0] == '!'
- && strcmp (name, tname + 4) == 0)
- return IDENTIFIER_POINTER (TREE_PURPOSE (temp));
- }
+ const char *real_name;
+ tree id;
- name = darwin_strip_name_encoding (name);
-
- {
- char *buffer;
- int bufferlen = 0;
- int namelen = strlen (name);
- tree ptr_name;
- int needs_quotes = name_needs_quotes (name);
-
- buffer = alloca (namelen + 20);
-
- if (needs_quotes)
- {
- strcpy (buffer, "&\"L");
- bufferlen = strlen("&\"L");
- }
- else
- {
- strcpy (buffer, "&L");
- bufferlen = strlen("&L");
- }
-
- if (name[0] == '*')
- {
- memcpy (buffer + bufferlen, name+1, namelen - 1 +1);
- bufferlen += namelen - 1;
- }
- else
- {
- buffer[bufferlen] = '_';
- memcpy (buffer + bufferlen +1, name, namelen+1);
- bufferlen += namelen +1;
- }
-
- if (needs_quotes)
- {
- memcpy (buffer + bufferlen, "$stub\"", strlen("$stub\"")+1);
- bufferlen += strlen("$stub\"");
- }
- else
- {
- memcpy (buffer + bufferlen, "$stub", strlen("$stub")+1);
- bufferlen += strlen("$stub");
- }
- ptr_name = get_identifier (buffer);
-
- machopic_stubs = tree_cons (ptr_name, ident, machopic_stubs);
- TREE_USED (machopic_stubs) = 0;
-
- return IDENTIFIER_POINTER (ptr_name);
- }
-}
+ p->used = true;
-void
-machopic_validate_stub_or_non_lazy_ptr (const char *name, int validate_stub)
-{
- const char *real_name;
- tree temp, ident = get_identifier (name), id2;
+ /* Do what output_addr_const will do when we actually call it. */
+ if (SYMBOL_REF_DECL (p->symbol))
+ mark_decl_referenced (SYMBOL_REF_DECL (p->symbol));
- for (temp = (validate_stub ? machopic_stubs : machopic_non_lazy_pointers);
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
- if (ident == TREE_PURPOSE (temp))
- {
- /* Mark both the stub or non-lazy pointer as well as the
- original symbol as being referenced. */
- TREE_USED (temp) = 1;
- if (TREE_CODE (TREE_VALUE (temp)) == IDENTIFIER_NODE)
- mark_referenced (TREE_VALUE (temp));
- real_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- real_name = darwin_strip_name_encoding (real_name);
- id2 = maybe_get_identifier (real_name);
- if (id2)
- mark_referenced (id2);
- }
+ real_name = targetm.strip_name_encoding (XSTR (p->symbol, 0));
+
+ id = maybe_get_identifier (real_name);
+ if (id)
+ mark_referenced (id);
+ }
}
/* Transform ORIG, which may be any data source, to the corresponding
@@ -447,34 +508,32 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
if (GET_CODE (orig) == SYMBOL_REF)
{
- const char *name = XSTR (orig, 0);
- int defined = machopic_data_defined_p (name);
+ int defined = machopic_data_defined_p (orig);
if (defined && MACHO_DYNAMIC_NO_PIC_P)
{
#if defined (TARGET_TOC)
- emit_insn (gen_macho_high (reg, orig));
- emit_insn (gen_macho_low (reg, reg, orig));
+ /* Create a new register for CSE opportunities. */
+ rtx hi_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
+ emit_insn (gen_macho_high (hi_reg, orig));
+ emit_insn (gen_macho_low (reg, hi_reg, orig));
#else
/* some other cpu -- writeme! */
- abort ();
+ gcc_unreachable ();
#endif
return reg;
}
else if (defined)
{
#if defined (TARGET_TOC) || defined (HAVE_lo_sum)
- rtx pic_base = gen_rtx_SYMBOL_REF (Pmode,
- machopic_function_base_name ());
- rtx offset = gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode, orig, pic_base));
+ rtx pic_base = machopic_function_base_sym ();
+ rtx offset = gen_pic_offset (orig, pic_base);
#endif
#if defined (TARGET_TOC) /* i.e., PowerPC */
rtx hi_sum_reg = (no_new_pseudos ? reg : gen_reg_rtx (Pmode));
- if (reg == NULL)
- abort ();
+ gcc_assert (reg);
emit_insn (gen_rtx_SET (Pmode, hi_sum_reg,
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
@@ -485,7 +544,7 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
orig = reg;
#else
#if defined (HAVE_lo_sum)
- if (reg == 0) abort ();
+ gcc_assert (reg);
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_HIGH (Pmode, offset)));
@@ -499,11 +558,14 @@ machopic_indirect_data_reference (rtx orig, rtx reg)
return orig;
}
- ptr_ref = gen_rtx_SYMBOL_REF (Pmode,
- machopic_non_lazy_ptr_name (name));
+ ptr_ref = (gen_rtx_SYMBOL_REF
+ (Pmode,
+ machopic_indirection_name (orig, /*stub_p=*/false)));
- ptr_ref = gen_rtx_MEM (Pmode, ptr_ref);
- RTX_UNCHANGING_P (ptr_ref) = 1;
+ SYMBOL_REF_DATA (ptr_ref) = SYMBOL_REF_DATA (orig);
+
+ ptr_ref = gen_const_mem (Pmode, ptr_ref);
+ machopic_define_symbol (ptr_ref);
return ptr_ref;
}
@@ -574,22 +636,20 @@ machopic_indirect_call_target (rtx target)
if (GET_CODE (target) != MEM)
return target;
- if (MACHOPIC_INDIRECT && GET_CODE (XEXP (target, 0)) == SYMBOL_REF)
+ if (MACHOPIC_INDIRECT
+ && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
+ && !(SYMBOL_REF_FLAGS (XEXP (target, 0))
+ & MACHO_SYMBOL_FLAG_DEFINED))
{
- enum machine_mode mode = GET_MODE (XEXP (target, 0));
- const char *name = XSTR (XEXP (target, 0), 0);
-
- /* If the name is already defined, we need do nothing. */
- if (name[0] == '!' && name[1] == 'T')
- return target;
-
- if (!machopic_name_defined_p (name))
- {
- const char *stub_name = machopic_stub_name (name);
-
- XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
- RTX_UNCHANGING_P (target) = 1;
- }
+ rtx sym_ref = XEXP (target, 0);
+ const char *stub_name = machopic_indirection_name (sym_ref,
+ /*stub_p=*/true);
+ enum machine_mode mode = GET_MODE (sym_ref);
+
+ XEXP (target, 0) = gen_rtx_SYMBOL_REF (mode, stub_name);
+ SYMBOL_REF_DATA (XEXP (target, 0)) = SYMBOL_REF_DATA (sym_ref);
+ MEM_READONLY_P (target) = 1;
+ MEM_NOTRAP_P (target) = 1;
}
return target;
@@ -623,20 +683,18 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
return reg;
}
- /* if dynamic-no-pic then use 0 as the pic base */
+ /* if dynamic-no-pic we don't have a pic base */
if (MACHO_DYNAMIC_NO_PIC_P)
- pic_base = CONST0_RTX (Pmode);
+ pic_base = NULL;
else
- pic_base = gen_rtx_SYMBOL_REF (Pmode, machopic_function_base_name ());
+ pic_base = machopic_function_base_sym ();
if (GET_CODE (orig) == MEM)
{
if (reg == 0)
{
- if (reload_in_progress)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (!reload_in_progress);
+ reg = gen_reg_rtx (Pmode);
}
#ifdef HAVE_lo_sum
@@ -650,13 +708,12 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
rtx mem;
emit_insn (gen_macho_high (temp_reg, asym));
- mem = gen_rtx_MEM (GET_MODE (orig),
- gen_rtx_LO_SUM (Pmode, temp_reg, asym));
- RTX_UNCHANGING_P (mem) = 1;
+ mem = gen_const_mem (GET_MODE (orig),
+ gen_rtx_LO_SUM (Pmode, temp_reg, asym));
emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
#else
/* Some other CPU -- WriteMe! but right now there are no other platform that can use dynamic-no-pic */
- abort ();
+ gcc_unreachable ();
#endif
pic_ref = reg;
}
@@ -664,41 +721,37 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
if (GET_CODE (XEXP (orig, 0)) == SYMBOL_REF
|| GET_CODE (XEXP (orig, 0)) == LABEL_REF)
{
- rtx offset = gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode,
- XEXP (orig, 0),
- pic_base));
+ rtx offset = gen_pic_offset (XEXP (orig, 0), pic_base);
#if defined (TARGET_TOC) /* i.e., PowerPC */
/* Generating a new reg may expose opportunities for
common subexpression elimination. */
- rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (SImode);
+ rtx hi_sum_reg = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
rtx mem;
rtx insn;
rtx sum;
-
+
sum = gen_rtx_HIGH (Pmode, offset);
if (! MACHO_DYNAMIC_NO_PIC_P)
sum = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, sum);
emit_insn (gen_rtx_SET (Pmode, hi_sum_reg, sum));
- mem = gen_rtx_MEM (GET_MODE (orig),
- gen_rtx_LO_SUM (Pmode,
- hi_sum_reg, offset));
- RTX_UNCHANGING_P (mem) = 1;
+ mem = gen_const_mem (GET_MODE (orig),
+ gen_rtx_LO_SUM (Pmode,
+ hi_sum_reg, offset));
insn = emit_insn (gen_rtx_SET (VOIDmode, reg, mem));
- REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, pic_ref,
REG_NOTES (insn));
pic_ref = reg;
#else
emit_insn (gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode,
+ gen_rtx_REG (Pmode,
PIC_OFFSET_TABLE_REGNUM)));
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_HIGH (Pmode,
- gen_rtx_CONST (Pmode,
+ gen_rtx_CONST (Pmode,
offset))));
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_LO_SUM (Pmode, reg,
@@ -718,23 +771,21 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
}
#if 0
emit_insn (gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode,
+ gen_rtx_REG (Pmode,
PIC_OFFSET_TABLE_REGNUM)));
#endif
- pic_ref = gen_rtx_PLUS (Pmode,
- pic,
- gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode,
- XEXP (orig, 0),
- pic_base)));
+ if (reload_in_progress)
+ regs_ever_live[REGNO (pic)] = 1;
+ pic_ref = gen_rtx_PLUS (Pmode, pic,
+ gen_pic_offset (XEXP (orig, 0),
+ pic_base));
}
#if !defined (TARGET_TOC)
emit_move_insn (reg, pic_ref);
- pic_ref = gen_rtx_MEM (GET_MODE (orig), reg);
+ pic_ref = gen_const_mem (GET_MODE (orig), reg);
#endif
- RTX_UNCHANGING_P (pic_ref) = 1;
}
else
{
@@ -743,18 +794,14 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
if (GET_CODE (orig) == SYMBOL_REF
|| GET_CODE (orig) == LABEL_REF)
{
- rtx offset = gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode,
- orig, pic_base));
+ rtx offset = gen_pic_offset (orig, pic_base);
#if defined (TARGET_TOC) /* i.e., PowerPC */
rtx hi_sum_reg;
if (reg == 0)
{
- if (reload_in_progress)
- abort ();
- else
- reg = gen_reg_rtx (SImode);
+ gcc_assert (!reload_in_progress);
+ reg = gen_reg_rtx (Pmode);
}
hi_sum_reg = reg;
@@ -764,13 +811,12 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
? gen_rtx_HIGH (Pmode, offset)
: gen_rtx_PLUS (Pmode,
pic_offset_table_rtx,
- gen_rtx_HIGH (Pmode,
+ gen_rtx_HIGH (Pmode,
offset))));
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_LO_SUM (Pmode,
hi_sum_reg, offset)));
pic_ref = reg;
- RTX_UNCHANGING_P (pic_ref) = 1;
#else
emit_insn (gen_rtx_SET (VOIDmode, reg,
gen_rtx_HIGH (Pmode, offset)));
@@ -778,13 +824,13 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
gen_rtx_LO_SUM (Pmode, reg, offset)));
pic_ref = gen_rtx_PLUS (Pmode,
pic_offset_table_rtx, reg);
- RTX_UNCHANGING_P (pic_ref) = 1;
#endif
}
else
#endif /* HAVE_lo_sum */
{
- if (GET_CODE (orig) == REG)
+ if (REG_P (orig)
+ || GET_CODE (orig) == SUBREG)
{
return orig;
}
@@ -800,11 +846,11 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
emit_insn (gen_rtx_USE (VOIDmode,
pic_offset_table_rtx));
#endif
+ if (reload_in_progress)
+ regs_ever_live[REGNO (pic)] = 1;
pic_ref = gen_rtx_PLUS (Pmode,
pic,
- gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode,
- orig, pic_base)));
+ gen_pic_offset (orig, pic_base));
}
}
}
@@ -852,9 +898,6 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
else
pic_ref = gen_rtx_PLUS (Pmode, base, orig);
- if (RTX_UNCHANGING_P (base) && RTX_UNCHANGING_P (orig))
- RTX_UNCHANGING_P (pic_ref) = 1;
-
if (reg && is_complex)
{
emit_move_insn (reg, pic_ref);
@@ -872,9 +915,7 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
&& GET_CODE (XEXP (orig, 0)) == SYMBOL_REF)
{
rtx addr = machopic_legitimize_pic_address (XEXP (orig, 0), Pmode, reg);
-
- addr = gen_rtx_MEM (GET_MODE (orig), addr);
- RTX_UNCHANGING_P (addr) = RTX_UNCHANGING_P (orig);
+ addr = replace_equiv_address (orig, addr);
emit_move_insn (reg, addr);
pic_ref = reg;
}
@@ -882,25 +923,42 @@ machopic_legitimize_pic_address (rtx orig, enum machine_mode mode, rtx reg)
return pic_ref;
}
+/* Output the stub or non-lazy pointer in *SLOT, if it has been used.
+ DATA is the FILE* for assembly output. Called from
+ htab_traverse. */
-void
-machopic_finish (FILE *asm_out_file)
+static int
+machopic_output_indirection (void **slot, void *data)
{
- tree temp;
+ machopic_indirection *p = *((machopic_indirection **) slot);
+ FILE *asm_out_file = (FILE *) data;
+ rtx symbol;
+ const char *sym_name;
+ const char *ptr_name;
+
+ if (!p->used)
+ return 1;
+
+ symbol = p->symbol;
+ sym_name = XSTR (symbol, 0);
+ ptr_name = p->ptr_name;
- for (temp = machopic_stubs;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
+ if (p->stub_p)
{
- const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- const char *stub_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
char *sym;
char *stub;
+ tree id;
- if (! TREE_USED (temp))
- continue;
+ id = maybe_get_identifier (sym_name);
+ if (id)
+ {
+ tree id_orig = id;
- sym_name = darwin_strip_name_encoding (sym_name);
+ while (IDENTIFIER_TRANSPARENT_ALIAS (id))
+ id = TREE_CHAIN (id);
+ if (id != id_orig)
+ sym_name = IDENTIFIER_POINTER (id);
+ }
sym = alloca (strlen (sym_name) + 2);
if (sym_name[0] == '*' || sym_name[0] == '&')
@@ -908,50 +966,64 @@ machopic_finish (FILE *asm_out_file)
else if (sym_name[0] == '-' || sym_name[0] == '+')
strcpy (sym, sym_name);
else
- sym[0] = '_', strcpy (sym + 1, sym_name);
+ sprintf (sym, "%s%s", user_label_prefix, sym_name);
- stub = alloca (strlen (stub_name) + 2);
- if (stub_name[0] == '*' || stub_name[0] == '&')
- strcpy (stub, stub_name + 1);
+ stub = alloca (strlen (ptr_name) + 2);
+ if (ptr_name[0] == '*' || ptr_name[0] == '&')
+ strcpy (stub, ptr_name + 1);
else
- stub[0] = '_', strcpy (stub + 1, stub_name);
+ sprintf (stub, "%s%s", user_label_prefix, ptr_name);
machopic_output_stub (asm_out_file, sym, stub);
}
-
- for (temp = machopic_non_lazy_pointers;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
+ else if (! indirect_data (symbol)
+ && (machopic_symbol_defined_p (symbol)
+ || SYMBOL_REF_LOCAL_P (symbol)))
{
- const char *const sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
- const char *const lazy_name = IDENTIFIER_POINTER (TREE_PURPOSE (temp));
+ switch_to_section (data_section);
+ assemble_align (GET_MODE_ALIGNMENT (Pmode));
+ assemble_label (ptr_name);
+ assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
+ GET_MODE_SIZE (Pmode),
+ GET_MODE_ALIGNMENT (Pmode), 1);
+ }
+ else
+ {
+ rtx init = const0_rtx;
- if (! TREE_USED (temp))
- continue;
+ switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
+ assemble_name (asm_out_file, ptr_name);
+ fprintf (asm_out_file, ":\n");
- if (machopic_ident_defined_p (TREE_VALUE (temp)))
- {
- data_section ();
- assemble_align (GET_MODE_ALIGNMENT (Pmode));
- assemble_label (lazy_name);
- assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
- GET_MODE_SIZE (Pmode),
- GET_MODE_ALIGNMENT (Pmode), 1);
- }
- else
- {
- machopic_nl_symbol_ptr_section ();
- assemble_name (asm_out_file, lazy_name);
- fprintf (asm_out_file, ":\n");
+ fprintf (asm_out_file, "\t.indirect_symbol ");
+ assemble_name (asm_out_file, sym_name);
+ fprintf (asm_out_file, "\n");
- fprintf (asm_out_file, "\t.indirect_symbol ");
- assemble_name (asm_out_file, sym_name);
- fprintf (asm_out_file, "\n");
+ /* Variables that are marked with MACHO_SYMBOL_STATIC need to
+ have their symbol name instead of 0 in the second entry of
+ the non-lazy symbol pointer data structure when they are
+ defined. This allows the runtime to rebind newer instances
+ of the translation unit with the original instance of the
+ symbol. */
- assemble_integer (const0_rtx, GET_MODE_SIZE (Pmode),
- GET_MODE_ALIGNMENT (Pmode), 1);
- }
+ if ((SYMBOL_REF_FLAGS (symbol) & MACHO_SYMBOL_STATIC)
+ && machopic_symbol_defined_p (symbol))
+ init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
+
+ assemble_integer (init, GET_MODE_SIZE (Pmode),
+ GET_MODE_ALIGNMENT (Pmode), 1);
}
+
+ return 1;
+}
+
+void
+machopic_finish (FILE *asm_out_file)
+{
+ if (machopic_indirections)
+ htab_traverse_noresize (machopic_indirections,
+ machopic_output_indirection,
+ asm_out_file);
}
int
@@ -963,7 +1035,7 @@ machopic_operand_p (rtx op)
op = XEXP (op, 0);
if (GET_CODE (op) == SYMBOL_REF)
- return machopic_name_defined_p (XSTR (op, 0));
+ return machopic_symbol_defined_p (op);
else
return 0;
}
@@ -974,8 +1046,8 @@ machopic_operand_p (rtx op)
if (GET_CODE (op) == MINUS
&& GET_CODE (XEXP (op, 0)) == SYMBOL_REF
&& GET_CODE (XEXP (op, 1)) == SYMBOL_REF
- && machopic_name_defined_p (XSTR (XEXP (op, 0), 0))
- && machopic_name_defined_p (XSTR (XEXP (op, 1), 0)))
+ && machopic_symbol_defined_p (XEXP (op, 0))
+ && machopic_symbol_defined_p (XEXP (op, 1)))
return 1;
return 0;
@@ -988,174 +1060,95 @@ machopic_operand_p (rtx op)
void
darwin_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
{
- char code = '\0';
- int defined = 0;
rtx sym_ref;
- const char *orig_str;
- char *new_str;
- size_t len, new_len;
/* Do the standard encoding things first. */
default_encode_section_info (decl, rtl, first);
- /* With the introduction of symbol_ref flags, some of the following
- code has become redundant and should be removed at some point. */
-
- if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && !DECL_EXTERNAL (decl)
- && ((TREE_STATIC (decl)
- && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
- || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
- && DECL_INITIAL (decl) != error_mark_node)))
- defined = 1;
-
- if (TREE_CODE (decl) == FUNCTION_DECL)
- code = (defined ? 'T' : 't');
- else if (TREE_CODE (decl) == VAR_DECL)
- code = (defined ? 'D' : 'd');
-
- if (code == '\0')
+ if (TREE_CODE (decl) != FUNCTION_DECL && TREE_CODE (decl) != VAR_DECL)
return;
sym_ref = XEXP (rtl, 0);
- orig_str = XSTR (sym_ref, 0);
- len = strlen (orig_str) + 1;
-
- if (orig_str[0] == '!')
- {
- /* Already encoded; see if we need to change it. */
- if (code == orig_str[1])
- return;
- /* Yes, tweak a copy of the name and put it in a new string. */
- new_str = alloca (len);
- memcpy (new_str, orig_str, len);
- new_str[1] = code;
- XSTR (sym_ref, 0) = ggc_alloc_string (new_str, len);
- }
- else
- {
- /* Add the encoding. */
- new_len = len + 4;
- new_str = alloca (new_len);
- new_str[0] = '!';
- new_str[1] = code;
- new_str[2] = '_';
- new_str[3] = '_';
- memcpy (new_str + 4, orig_str, len);
- XSTR (sym_ref, 0) = ggc_alloc_string (new_str, new_len);
- }
- /* The non-lazy pointer list may have captured references to the
- old encoded name, change them. */
if (TREE_CODE (decl) == VAR_DECL)
- update_non_lazy_ptrs (XSTR (sym_ref, 0));
- else
- update_stubs (XSTR (sym_ref, 0));
-}
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_VARIABLE;
-/* Undo the effects of the above. */
+ if (!DECL_EXTERNAL (decl)
+ && (!TREE_PUBLIC (decl) || !DECL_WEAK (decl))
+ && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))
+ && ((TREE_STATIC (decl)
+ && (!DECL_COMMON (decl) || !TREE_PUBLIC (decl)))
+ || (!DECL_COMMON (decl) && DECL_INITIAL (decl)
+ && DECL_INITIAL (decl) != error_mark_node)))
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_FLAG_DEFINED;
-const char *
-darwin_strip_name_encoding (const char *str)
-{
- return str[0] == '!' ? str + 4 : str;
+ if (! TREE_PUBLIC (decl))
+ SYMBOL_REF_FLAGS (sym_ref) |= MACHO_SYMBOL_STATIC;
}
-/* Scan the list of non-lazy pointers and update any recorded names whose
- stripped name matches the argument. */
-
-static void
-update_non_lazy_ptrs (const char *name)
+void
+darwin_mark_decl_preserved (const char *name)
{
- const char *name1, *name2;
- tree temp;
-
- name1 = darwin_strip_name_encoding (name);
-
- for (temp = machopic_non_lazy_pointers;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
- {
- const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
-
- if (*sym_name == '!')
- {
- name2 = darwin_strip_name_encoding (sym_name);
- if (strcmp (name1, name2) == 0)
- {
- /* FIXME: This breaks the identifier hash table. */
- IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
- = (unsigned char *) name;
- break;
- }
- }
- }
+ fprintf (asm_out_file, ".no_dead_strip ");
+ assemble_name (asm_out_file, name);
+ fputc ('\n', asm_out_file);
}
-/* Scan the list of stubs and update any recorded names whose
- stripped name matches the argument. */
-
-static void
-update_stubs (const char *name)
+int
+machopic_reloc_rw_mask (void)
{
- const char *name1, *name2;
- tree temp;
-
- name1 = darwin_strip_name_encoding (name);
-
- for (temp = machopic_stubs;
- temp != NULL_TREE;
- temp = TREE_CHAIN (temp))
- {
- const char *sym_name = IDENTIFIER_POINTER (TREE_VALUE (temp));
-
- if (*sym_name == '!')
- {
- name2 = darwin_strip_name_encoding (sym_name);
- if (strcmp (name1, name2) == 0)
- {
- /* FIXME: This breaks the identifier hash table. */
- IDENTIFIER_NODE_CHECK (TREE_VALUE (temp))->identifier.id.str
- = (unsigned char *) name;
- break;
- }
- }
- }
+ return MACHOPIC_INDIRECT ? 3 : 0;
}
-void
+section *
machopic_select_section (tree exp, int reloc,
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
- void (*base_function)(void);
+ section *base_section;
+ bool weak_p = (DECL_P (exp) && DECL_WEAK (exp)
+ && (lookup_attribute ("weak", DECL_ATTRIBUTES (exp))
+ || ! lookup_attribute ("weak_import",
+ DECL_ATTRIBUTES (exp))));
- if (decl_readonly_section_1 (exp, reloc, MACHOPIC_INDIRECT))
- base_function = readonly_data_section;
+ if (TREE_CODE (exp) == FUNCTION_DECL)
+ {
+ if (reloc == 1)
+ base_section = (weak_p
+ ? darwin_sections[text_unlikely_coal_section]
+ : unlikely_text_section ());
+ else
+ base_section = weak_p ? darwin_sections[text_coal_section] : text_section;
+ }
+ else if (decl_readonly_section (exp, reloc))
+ base_section = weak_p ? darwin_sections[const_coal_section] : darwin_sections[const_section];
else if (TREE_READONLY (exp) || TREE_CONSTANT (exp))
- base_function = const_data_section;
+ base_section = weak_p ? darwin_sections[const_data_coal_section] : darwin_sections[const_data_section];
else
- base_function = data_section;
+ base_section = weak_p ? darwin_sections[data_coal_section] : data_section;
if (TREE_CODE (exp) == STRING_CST
&& ((size_t) TREE_STRING_LENGTH (exp)
- == strlen (TREE_STRING_POINTER (exp)) + 1)
- && ! flag_writable_strings)
- cstring_section ();
+ == strlen (TREE_STRING_POINTER (exp)) + 1))
+ return darwin_sections[cstring_section];
else if ((TREE_CODE (exp) == INTEGER_CST || TREE_CODE (exp) == REAL_CST)
&& flag_merge_constants)
{
- tree size = TYPE_SIZE (TREE_TYPE (exp));
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (exp));
if (TREE_CODE (size) == INTEGER_CST &&
TREE_INT_CST_LOW (size) == 4 &&
TREE_INT_CST_HIGH (size) == 0)
- literal4_section ();
+ return darwin_sections[literal4_section];
else if (TREE_CODE (size) == INTEGER_CST &&
TREE_INT_CST_LOW (size) == 8 &&
TREE_INT_CST_HIGH (size) == 0)
- literal8_section ();
+ return darwin_sections[literal8_section];
+ else if (TARGET_64BIT
+ && TREE_CODE (size) == INTEGER_CST
+ && TREE_INT_CST_LOW (size) == 16
+ && TREE_INT_CST_HIGH (size) == 0)
+ return darwin_sections[literal16_section];
else
- base_function ();
+ return base_section;
}
else if (TREE_CODE (exp) == CONSTRUCTOR
&& TREE_TYPE (exp)
@@ -1165,12 +1158,16 @@ machopic_select_section (tree exp, int reloc,
tree name = TYPE_NAME (TREE_TYPE (exp));
if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
- if (!strcmp (IDENTIFIER_POINTER (name), "NSConstantString"))
- objc_constant_string_object_section ();
- else if (!strcmp (IDENTIFIER_POINTER (name), "NXConstantString"))
- objc_string_object_section ();
+
+ if (!strcmp (IDENTIFIER_POINTER (name), "__builtin_ObjCString"))
+ {
+ if (flag_next_runtime)
+ return darwin_sections[objc_constant_string_object_section];
+ else
+ return darwin_sections[objc_string_object_section];
+ }
else
- base_function ();
+ return base_section;
}
else if (TREE_CODE (exp) == VAR_DECL &&
DECL_NAME (exp) &&
@@ -1181,87 +1178,95 @@ machopic_select_section (tree exp, int reloc,
const char *name = IDENTIFIER_POINTER (DECL_NAME (exp));
if (!strncmp (name, "_OBJC_CLASS_METHODS_", 20))
- objc_cls_meth_section ();
+ return darwin_sections[objc_cls_meth_section];
else if (!strncmp (name, "_OBJC_INSTANCE_METHODS_", 23))
- objc_inst_meth_section ();
+ return darwin_sections[objc_inst_meth_section];
else if (!strncmp (name, "_OBJC_CATEGORY_CLASS_METHODS_", 20))
- objc_cat_cls_meth_section ();
+ return darwin_sections[objc_cat_cls_meth_section];
else if (!strncmp (name, "_OBJC_CATEGORY_INSTANCE_METHODS_", 23))
- objc_cat_inst_meth_section ();
+ return darwin_sections[objc_cat_inst_meth_section];
else if (!strncmp (name, "_OBJC_CLASS_VARIABLES_", 22))
- objc_class_vars_section ();
+ return darwin_sections[objc_class_vars_section];
else if (!strncmp (name, "_OBJC_INSTANCE_VARIABLES_", 25))
- objc_instance_vars_section ();
+ return darwin_sections[objc_instance_vars_section];
else if (!strncmp (name, "_OBJC_CLASS_PROTOCOLS_", 22))
- objc_cat_cls_meth_section ();
+ return darwin_sections[objc_cat_cls_meth_section];
else if (!strncmp (name, "_OBJC_CLASS_NAME_", 17))
- objc_class_names_section ();
+ return darwin_sections[objc_class_names_section];
else if (!strncmp (name, "_OBJC_METH_VAR_NAME_", 20))
- objc_meth_var_names_section ();
+ return darwin_sections[objc_meth_var_names_section];
else if (!strncmp (name, "_OBJC_METH_VAR_TYPE_", 20))
- objc_meth_var_types_section ();
+ return darwin_sections[objc_meth_var_types_section];
else if (!strncmp (name, "_OBJC_CLASS_REFERENCES", 22))
- objc_cls_refs_section ();
+ return darwin_sections[objc_cls_refs_section];
else if (!strncmp (name, "_OBJC_CLASS_", 12))
- objc_class_section ();
+ return darwin_sections[objc_class_section];
else if (!strncmp (name, "_OBJC_METACLASS_", 16))
- objc_meta_class_section ();
+ return darwin_sections[objc_meta_class_section];
else if (!strncmp (name, "_OBJC_CATEGORY_", 15))
- objc_category_section ();
+ return darwin_sections[objc_category_section];
else if (!strncmp (name, "_OBJC_SELECTOR_REFERENCES", 25))
- objc_selector_refs_section ();
+ return darwin_sections[objc_selector_refs_section];
else if (!strncmp (name, "_OBJC_SELECTOR_FIXUP", 20))
- objc_selector_fixup_section ();
+ return darwin_sections[objc_selector_fixup_section];
else if (!strncmp (name, "_OBJC_SYMBOLS", 13))
- objc_symbols_section ();
+ return darwin_sections[objc_symbols_section];
else if (!strncmp (name, "_OBJC_MODULES", 13))
- objc_module_info_section ();
+ return darwin_sections[objc_module_info_section];
else if (!strncmp (name, "_OBJC_IMAGE_INFO", 16))
- objc_image_info_section ();
+ return darwin_sections[objc_image_info_section];
else if (!strncmp (name, "_OBJC_PROTOCOL_INSTANCE_METHODS_", 32))
- objc_cat_inst_meth_section ();
+ return darwin_sections[objc_cat_inst_meth_section];
else if (!strncmp (name, "_OBJC_PROTOCOL_CLASS_METHODS_", 29))
- objc_cat_cls_meth_section ();
+ return darwin_sections[objc_cat_cls_meth_section];
else if (!strncmp (name, "_OBJC_PROTOCOL_REFS_", 20))
- objc_cat_cls_meth_section ();
+ return darwin_sections[objc_cat_cls_meth_section];
else if (!strncmp (name, "_OBJC_PROTOCOL_", 15))
- objc_protocol_section ();
+ return darwin_sections[objc_protocol_section];
else
- base_function ();
+ return base_section;
}
else
- base_function ();
+ return base_section;
}
/* This can be called with address expressions as "rtx".
They must go in "const". */
-void
+section *
machopic_select_rtx_section (enum machine_mode mode, rtx x,
unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
- if (GET_MODE_SIZE (mode) == 8)
- literal8_section ();
+ if (GET_MODE_SIZE (mode) == 8
+ && (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE))
+ return darwin_sections[literal8_section];
else if (GET_MODE_SIZE (mode) == 4
&& (GET_CODE (x) == CONST_INT
|| GET_CODE (x) == CONST_DOUBLE))
- literal4_section ();
+ return darwin_sections[literal4_section];
+ else if (TARGET_64BIT
+ && GET_MODE_SIZE (mode) == 16
+ && (GET_CODE (x) == CONST_INT
+ || GET_CODE (x) == CONST_DOUBLE
+ || GET_CODE (x) == CONST_VECTOR))
+ return darwin_sections[literal16_section];
else if (MACHOPIC_INDIRECT
&& (GET_CODE (x) == SYMBOL_REF
|| GET_CODE (x) == CONST
|| GET_CODE (x) == LABEL_REF))
- const_data_section ();
+ return darwin_sections[const_data_section];
else
- const_section ();
+ return darwin_sections[const_section];
}
void
machopic_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
{
if (MACHOPIC_INDIRECT)
- mod_init_section ();
+ switch_to_section (darwin_sections[mod_init_section]);
else
- constructor_section ();
+ switch_to_section (darwin_sections[constructor_section]);
assemble_align (POINTER_SIZE);
assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
@@ -1273,9 +1278,9 @@ void
machopic_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
{
if (MACHOPIC_INDIRECT)
- mod_term_section ();
+ switch_to_section (darwin_sections[mod_term_section]);
else
- destructor_section ();
+ switch_to_section (darwin_sections[destructor_section]);
assemble_align (POINTER_SIZE);
assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
@@ -1290,13 +1295,168 @@ darwin_globalize_label (FILE *stream, const char *name)
default_globalize_label (stream, name);
}
+void
+darwin_asm_named_section (const char *name,
+ unsigned int flags ATTRIBUTE_UNUSED,
+ tree decl ATTRIBUTE_UNUSED)
+{
+ fprintf (asm_out_file, "\t.section %s\n", name);
+}
+
+void
+darwin_unique_section (tree decl ATTRIBUTE_UNUSED, int reloc ATTRIBUTE_UNUSED)
+{
+ /* Darwin does not use unique sections. */
+}
+
+/* Handle __attribute__ ((apple_kext_compatibility)).
+ This only applies to darwin kexts for 2.95 compatibility -- it shrinks the
+ vtable for classes with this attribute (and their descendants) by not
+ outputting the new 3.0 nondeleting destructor. This means that such
+ objects CANNOT be allocated on the stack or as globals UNLESS they have
+ a completely empty `operator delete'.
+ Luckily, this fits in with the Darwin kext model.
+
+ This attribute also disables gcc3's potential overlaying of derived
+ class data members on the padding at the end of the base class. */
+
+tree
+darwin_handle_kext_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
+{
+ /* APPLE KEXT stuff -- only applies with pure static C++ code. */
+ if (! TARGET_KEXTABI)
+ {
+ warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
+ "only when compiling a kext", IDENTIFIER_POINTER (name));
+
+ *no_add_attrs = true;
+ }
+ else if (TREE_CODE (*node) != RECORD_TYPE)
+ {
+ warning (0, "%<%s%> 2.95 vtable-compatability attribute applies "
+ "only to C++ classes", IDENTIFIER_POINTER (name));
+
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "weak_import" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+tree
+darwin_handle_weak_import_attribute (tree *node, tree name,
+ tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags),
+ bool * no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
+ {
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+ else
+ declare_weak (*node);
+
+ return NULL_TREE;
+}
+
+static void
+no_dead_strip (FILE *file, const char *lab)
+{
+ fprintf (file, ".no_dead_strip %s\n", lab);
+}
+
+/* Emit a label for an FDE, making it global and/or weak if appropriate.
+ The third parameter is nonzero if this is for exception handling.
+ The fourth parameter is nonzero if this is just a placeholder for an
+ FDE that we are omitting. */
+
+void
+darwin_emit_unwind_label (FILE *file, tree decl, int for_eh, int empty)
+{
+ const char *base;
+ char *lab;
+ bool need_quotes;
+
+ if (DECL_ASSEMBLER_NAME_SET_P (decl))
+ base = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ else
+ base = IDENTIFIER_POINTER (DECL_NAME (decl));
+
+ base = targetm.strip_name_encoding (base);
+ need_quotes = name_needs_quotes (base);
+
+ if (! for_eh)
+ return;
+
+ lab = concat (need_quotes ? "\"" : "", user_label_prefix, base, ".eh",
+ need_quotes ? "\"" : "", NULL);
+
+ if (TREE_PUBLIC (decl))
+ fprintf (file, "\t%s %s\n",
+ (DECL_VISIBILITY (decl) != VISIBILITY_HIDDEN
+ ? ".globl"
+ : ".private_extern"),
+ lab);
+
+ if (DECL_WEAK (decl))
+ fprintf (file, "\t.weak_definition %s\n", lab);
+
+ if (empty)
+ {
+ fprintf (file, "%s = 0\n", lab);
+
+ /* Mark the absolute .eh and .eh1 style labels as needed to
+ ensure that we don't dead code strip them and keep such
+ labels from another instantiation point until we can fix this
+ properly with group comdat support. */
+ no_dead_strip (file, lab);
+ }
+ else
+ fprintf (file, "%s:\n", lab);
+
+ free (lab);
+}
+
+static GTY(()) unsigned long except_table_label_num;
+
+void
+darwin_emit_except_table_label (FILE *file)
+{
+ char section_start_label[30];
+
+ ASM_GENERATE_INTERNAL_LABEL (section_start_label, "GCC_except_table",
+ except_table_label_num++);
+ ASM_OUTPUT_LABEL (file, section_start_label);
+}
+/* Generate a PC-relative reference to a Mach-O non-lazy-symbol. */
+
+void
+darwin_non_lazy_pcrel (FILE *file, rtx addr)
+{
+ const char *nlp_name;
+
+ gcc_assert (GET_CODE (addr) == SYMBOL_REF);
+
+ nlp_name = machopic_indirection_name (addr, /*stub_p=*/false);
+ fputs ("\t.long\t", file);
+ ASM_OUTPUT_LABELREF (file, nlp_name);
+ fputs ("-.", file);
+}
+
/* Emit an assembler directive to set visibility for a symbol. The
only supported visibilities are VISIBILITY_DEFAULT and
VISIBILITY_HIDDEN; the latter corresponds to Darwin's "private
extern". There is no MACH-O equivalent of ELF's
VISIBILITY_INTERNAL or VISIBILITY_PROTECTED. */
-void
+void
darwin_assemble_visibility (tree decl, int vis)
{
if (vis == VISIBILITY_DEFAULT)
@@ -1309,8 +1469,8 @@ darwin_assemble_visibility (tree decl, int vis)
fputs ("\n", asm_out_file);
}
else
- warning ("internal and protected visibility attributes not supported"
- "in this configuration; ignored");
+ warning (OPT_Wattributes, "internal and protected visibility attributes "
+ "not supported in this configuration; ignored");
}
/* Output a difference of two labels that will be an assembly time
@@ -1323,21 +1483,79 @@ darwin_assemble_visibility (tree decl, int vis)
static int darwin_dwarf_label_counter;
void
-darwin_asm_output_dwarf_delta (FILE *file, int size ATTRIBUTE_UNUSED,
+darwin_asm_output_dwarf_delta (FILE *file, int size,
const char *lab1, const char *lab2)
{
- const char *p = lab1 + (lab1[0] == '*');
- int islocaldiff = (p[0] == 'L');
+ int islocaldiff = (lab1[0] == '*' && lab1[1] == 'L'
+ && lab2[0] == '*' && lab2[1] == 'L');
+ const char *directive = (size == 8 ? ".quad" : ".long");
if (islocaldiff)
fprintf (file, "\t.set L$set$%d,", darwin_dwarf_label_counter);
else
- fprintf (file, "\t%s\t", ".long");
- assemble_name (file, lab1);
+ fprintf (file, "\t%s\t", directive);
+ assemble_name_raw (file, lab1);
fprintf (file, "-");
- assemble_name (file, lab2);
+ assemble_name_raw (file, lab2);
if (islocaldiff)
- fprintf (file, "\n\t.long L$set$%d", darwin_dwarf_label_counter++);
+ fprintf (file, "\n\t%s L$set$%d", directive, darwin_dwarf_label_counter++);
+}
+
+/* Output labels for the start of the DWARF sections if necessary. */
+void
+darwin_file_start (void)
+{
+ if (write_symbols == DWARF2_DEBUG)
+ {
+ static const char * const debugnames[] =
+ {
+ DEBUG_FRAME_SECTION,
+ DEBUG_INFO_SECTION,
+ DEBUG_ABBREV_SECTION,
+ DEBUG_ARANGES_SECTION,
+ DEBUG_MACINFO_SECTION,
+ DEBUG_LINE_SECTION,
+ DEBUG_LOC_SECTION,
+ DEBUG_PUBNAMES_SECTION,
+ DEBUG_STR_SECTION,
+ DEBUG_RANGES_SECTION
+ };
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (debugnames); i++)
+ {
+ int namelen;
+
+ switch_to_section (get_section (debugnames[i], SECTION_DEBUG, NULL));
+
+ gcc_assert (strncmp (debugnames[i], "__DWARF,", 8) == 0);
+ gcc_assert (strchr (debugnames[i] + 8, ','));
+
+ namelen = strchr (debugnames[i] + 8, ',') - (debugnames[i] + 8);
+ fprintf (asm_out_file, "Lsection%.*s:\n", namelen, debugnames[i] + 8);
+ }
+ }
+}
+
+/* Output an offset in a DWARF section on Darwin. On Darwin, DWARF section
+ offsets are not represented using relocs in .o files; either the
+ section never leaves the .o file, or the linker or other tool is
+ responsible for parsing the DWARF and updating the offsets. */
+
+void
+darwin_asm_output_dwarf_offset (FILE *file, int size, const char * lab,
+ section *base)
+{
+ char sname[64];
+ int namelen;
+
+ gcc_assert (base->common.flags & SECTION_NAMED);
+ gcc_assert (strncmp (base->named.name, "__DWARF,", 8) == 0);
+ gcc_assert (strchr (base->named.name + 8, ','));
+
+ namelen = strchr (base->named.name + 8, ',') - (base->named.name + 8);
+ sprintf (sname, "*Lsection%.*s", namelen, base->named.name + 8);
+ darwin_asm_output_dwarf_delta (file, size, lab, sname);
}
void
@@ -1346,10 +1564,81 @@ darwin_file_end (void)
machopic_finish (asm_out_file);
if (strcmp (lang_hooks.name, "GNU C++") == 0)
{
- constructor_section ();
- destructor_section ();
+ switch_to_section (darwin_sections[constructor_section]);
+ switch_to_section (darwin_sections[destructor_section]);
ASM_OUTPUT_ALIGN (asm_out_file, 1);
}
+ fprintf (asm_out_file, "\t.subsections_via_symbols\n");
+}
+
+/* TODO: Add a language hook for identifying if a decl is a vtable. */
+#define DARWIN_VTABLE_P(DECL) 0
+
+/* Cross-module name binding. Darwin does not support overriding
+ functions at dynamic-link time, except for vtables in kexts. */
+
+bool
+darwin_binds_local_p (tree decl)
+{
+ return default_binds_local_p_1 (decl,
+ TARGET_KEXTABI && DARWIN_VTABLE_P (decl));
+}
+
+#if 0
+/* See TARGET_ASM_OUTPUT_ANCHOR for why we can't do this yet. */
+/* The Darwin's implementation of TARGET_ASM_OUTPUT_ANCHOR. Define the
+ anchor relative to ".", the current section position. We cannot use
+ the default one because ASM_OUTPUT_DEF is wrong for Darwin. */
+
+void
+darwin_asm_output_anchor (rtx symbol)
+{
+ fprintf (asm_out_file, "\t.set\t");
+ assemble_name (asm_out_file, XSTR (symbol, 0));
+ fprintf (asm_out_file, ", . + " HOST_WIDE_INT_PRINT_DEC "\n",
+ SYMBOL_REF_BLOCK_OFFSET (symbol));
+}
+#endif
+
+/* Set the darwin specific attributes on TYPE. */
+void
+darwin_set_default_type_attributes (tree type)
+{
+ if (darwin_ms_struct
+ && TREE_CODE (type) == RECORD_TYPE)
+ TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("ms_struct"),
+ NULL_TREE,
+ TYPE_ATTRIBUTES (type));
+}
+
+/* True, iff we're generating code for loadable kernel extentions. */
+
+bool
+darwin_kextabi_p (void) {
+ return flag_apple_kext;
+}
+
+void
+darwin_override_options (void)
+{
+ if (flag_apple_kext && strcmp (lang_hooks.name, "GNU C++") != 0)
+ {
+ warning (0, "command line option %<-fapple-kext%> is only valid for C++");
+ flag_apple_kext = 0;
+ }
+ if (flag_mkernel || flag_apple_kext)
+ {
+ /* -mkernel implies -fapple-kext for C++ */
+ if (strcmp (lang_hooks.name, "GNU C++") == 0)
+ flag_apple_kext = 1;
+
+ flag_no_common = 1;
+
+ /* No EH in kexts. */
+ flag_exceptions = 0;
+ /* No -fnon-call-exceptions data in kexts. */
+ flag_non_call_exceptions = 0;
+ }
}
#include "gt-darwin.h"
diff --git a/contrib/gcc/config/darwin.h b/contrib/gcc/config/darwin.h
index c6ff93f..9467bad 100644
--- a/contrib/gcc/config/darwin.h
+++ b/contrib/gcc/config/darwin.h
@@ -1,5 +1,6 @@
/* Target definitions for Darwin (Mac OS X) systems.
- Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 2000, 2001, 2002, 2003, 2004,
+ 2005
Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
@@ -17,8 +18,11 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef CONFIG_DARWIN_H
+#define CONFIG_DARWIN_H
/* The definitions in this file are common to all processor types
running Darwin, which is the kernel for Mac OS X. Darwin is
@@ -30,21 +34,13 @@ Boston, MA 02111-1307, USA. */
/* Although NeXT ran on many different architectures, as of Jan 2001
the only supported Darwin targets are PowerPC and x86. */
-/* Technically, STANDARD_EXEC_PREFIX should be /usr/libexec/, but in
- practice this makes it hard to install new compilers elsewhere, so
- leave it undefined and expect system builders to set configure args
- correctly. */
-
/* One of Darwin's NeXT legacies is the Mach-O format, which is partly
like a.out and partly like COFF, with additional features like
multi-architecture binary support. */
#define OBJECT_FORMAT_MACHO
-/* Suppress g++ attempt to link in the math library automatically.
- (Some Darwin versions have a libm, but they seem to cause problems
- for C++ executables.) */
-
+/* Suppress g++ attempt to link in the math library automatically. */
#define MATH_LIBRARY ""
/* We have atexit. */
@@ -84,6 +80,9 @@ Boston, MA 02111-1307, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 0
+/* True if pragma ms_struct is in effect. */
+extern GTY(()) int darwin_ms_struct;
+
/* This table intercepts weirdo options whose names would interfere
with normal driver conventions, and either translates them into
standardly-named options, or adds a 'Z' so that they can get to
@@ -114,27 +113,45 @@ Boston, MA 02111-1307, USA. */
{ "-bundle", "-Zbundle" }, \
{ "-bundle_loader", "-Zbundle_loader" }, \
{ "-weak_reference_mismatches", "-Zweak_reference_mismatches" }, \
+ { "-dead_strip", "-Zdead_strip" }, \
+ { "-no_dead_strip_inits_and_terms", "-Zno_dead_strip_inits_and_terms" }, \
{ "-dependency-file", "-MF" }, \
{ "-dylib_file", "-Zdylib_file" }, \
{ "-dynamic", "-Zdynamic" }, \
{ "-dynamiclib", "-Zdynamiclib" }, \
{ "-exported_symbols_list", "-Zexported_symbols_list" }, \
- { "-seg_addr_table_filename", "-Zseg_addr_table_filename" }, \
+ { "-gfull", "-g -fno-eliminate-unused-debug-symbols" }, \
+ { "-gused", "-g -feliminate-unused-debug-symbols" }, \
+ { "-segaddr", "-Zsegaddr" }, \
+ { "-segs_read_only_addr", "-Zsegs_read_only_addr" }, \
+ { "-segs_read_write_addr", "-Zsegs_read_write_addr" }, \
+ { "-seg_addr_table", "-Zseg_addr_table" }, \
+ { "-seg_addr_table_filename", "-Zfn_seg_addr_table_filename" }, \
+ { "-fapple-kext", "-fapple-kext -static -Wa,-static" }, \
{ "-filelist", "-Xlinker -filelist -Xlinker" }, \
+ { "-findirect-virtual-calls", "-fapple-kext" }, \
{ "-flat_namespace", "-Zflat_namespace" }, \
{ "-force_cpusubtype_ALL", "-Zforce_cpusubtype_ALL" }, \
{ "-force_flat_namespace", "-Zforce_flat_namespace" }, \
+ { "-framework", "-Xlinker -framework -Xlinker" }, \
+ { "-fterminated-vtables", "-fapple-kext" }, \
{ "-image_base", "-Zimage_base" }, \
{ "-init", "-Zinit" }, \
{ "-install_name", "-Zinstall_name" }, \
+ { "-mkernel", "-mkernel -static -Wa,-static" }, \
{ "-multiply_defined_unused", "-Zmultiplydefinedunused" }, \
{ "-multiply_defined", "-Zmultiply_defined" }, \
{ "-multi_module", "-Zmulti_module" }, \
{ "-static", "-static -Wa,-static" }, \
{ "-single_module", "-Zsingle_module" }, \
- { "-unexported_symbols_list", "-Zunexported_symbols_list" }, \
+ { "-unexported_symbols_list", "-Zunexported_symbols_list" }, \
SUBTARGET_OPTION_TRANSLATE_TABLE
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ darwin_override_options (); \
+ } while (0)
+
/* These compiler options take n arguments. */
#undef WORD_SWITCH_TAKES_ARG
@@ -158,10 +175,13 @@ Boston, MA 02111-1307, USA. */
!strcmp (STR, "read_only_relocs") ? 1 : \
!strcmp (STR, "sectcreate") ? 3 : \
!strcmp (STR, "sectorder") ? 3 : \
- !strcmp (STR, "Zseg_addr_table_filename") ?1 :\
+ !strcmp (STR, "Zsegaddr") ? 2 : \
+ !strcmp (STR, "Zsegs_read_only_addr") ? 1 : \
+ !strcmp (STR, "Zsegs_read_write_addr") ? 1 : \
+ !strcmp (STR, "Zseg_addr_table") ? 1 : \
+ !strcmp (STR, "Zfn_seg_addr_table_filename") ? 1 :\
!strcmp (STR, "seg1addr") ? 1 : \
!strcmp (STR, "segprot") ? 3 : \
- !strcmp (STR, "seg_addr_table") ? 1 : \
!strcmp (STR, "sub_library") ? 1 : \
!strcmp (STR, "sub_umbrella") ? 1 : \
!strcmp (STR, "umbrella") ? 1 : \
@@ -177,10 +197,25 @@ Boston, MA 02111-1307, USA. */
!strcmp (STR, "dylinker_install_name") ? 1 : \
0)
-/* Machine dependent cpp options. */
+#define SUBTARGET_C_COMMON_OVERRIDE_OPTIONS do { \
+ if (flag_mkernel || flag_apple_kext) \
+ { \
+ if (flag_use_cxa_atexit == 2) \
+ flag_use_cxa_atexit = 0; \
+ /* kexts should always be built without the coalesced sections \
+ because the kernel loader doesn't grok such sections. */ \
+ flag_weak = 0; \
+ /* No RTTI in kexts. */ \
+ flag_rtti = 0; \
+ } \
+ } while (0)
+
+/* Machine dependent cpp options. Don't add more options here, add
+ them to darwin_cpp_builtins in darwin-c.c. */
#undef CPP_SPEC
-#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}"
+#define CPP_SPEC "%{static:%{!dynamic:-D__STATIC__}}%{!static:-D__DYNAMIC__}" \
+ " %{pthread:-D_REENTRANT}"
/* This is mostly a clone of the standard LINK_COMMAND_SPEC, plus
precomp, libtool, and fat build additions. Also we
@@ -193,16 +228,21 @@ Boston, MA 02111-1307, USA. */
#define LINK_COMMAND_SPEC "\
%{!fdump=*:%{!fsyntax-only:%{!precomp:%{!c:%{!M:%{!MM:%{!E:%{!S:\
%{!Zdynamiclib:%(linker)}%{Zdynamiclib:/usr/bin/libtool} \
- %{!Zdynamiclib:-arch %(darwin_arch)} \
- %{Zdynamiclib:-arch_only %(darwin_arch)} \
%l %X %{d} %{s} %{t} %{Z} \
%{!Zdynamiclib:%{A} %{e*} %{m} %{N} %{n} %{r} %{u*} %{x} %{z}} \
%{@:-o %f%u.out}%{!@:%{o*}%{!o:-o a.out}} \
- %{!Zdynamiclib:%{!A:%{!nostdlib:%{!nostartfiles:%S}}}} \
- %{L*} %(link_libgcc) %o %{fprofile-arcs|fprofile-generate:-lgcov} \
- %{!nostdlib:%{!nodefaultlibs:%G %L}} \
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} \
- %{!--help:%{!no-c++filt|c++filt:| c++filt }} }}}}}}}}"
+ %{!A:%{!nostdlib:%{!nostartfiles:%S}}} \
+ %{L*} %{fopenmp:%:include(libgomp.spec)%(link_gomp)} \
+ %(link_libgcc) %o %{fprofile-arcs|fprofile-generate|coverage:-lgcov} \
+ %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %G %L}} \
+ %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} }}}}}}}}"
+
+#ifdef TARGET_SYSTEM_ROOT
+#define LINK_SYSROOT_SPEC \
+ "%{isysroot*:-syslibroot %*;:-syslibroot " TARGET_SYSTEM_ROOT "}"
+#else
+#define LINK_SYSROOT_SPEC "%{isysroot*:-syslibroot %*}"
+#endif
/* Please keep the random linker options in alphabetical order (modulo
'Z' and 'no' prefixes). Options that can only go to one of libtool
@@ -213,14 +253,16 @@ Boston, MA 02111-1307, USA. */
their names so all of them get passed. */
#define LINK_SPEC \
"%{static}%{!static:-dynamic} \
+ %{fgnu-runtime:%:replace-outfile(-lobjc -lobjc-gnu)}\
%{!Zdynamiclib: \
+ %{Zforce_cpusubtype_ALL:-arch %(darwin_arch) -force_cpusubtype_ALL} \
+ %{!Zforce_cpusubtype_ALL:-arch %(darwin_subarch)} \
%{Zbundle:-bundle} \
%{Zbundle_loader*:-bundle_loader %*} \
%{client_name*} \
%{compatibility_version*:%e-compatibility_version only allowed with -dynamiclib\
} \
%{current_version*:%e-current_version only allowed with -dynamiclib} \
- %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
%{Zforce_flat_namespace:-force_flat_namespace} \
%{Zinstall_name*:%e-install_name only allowed with -dynamiclib} \
%{keep_private_externs} \
@@ -232,7 +274,8 @@ Boston, MA 02111-1307, USA. */
%{client_name*:%e-client_name not allowed with -dynamiclib} \
%{compatibility_version*} \
%{current_version*} \
- %{Zforce_cpusubtype_ALL:%e-force_cpusubtype_ALL not allowed with -dynamiclib} \
+ %{Zforce_cpusubtype_ALL:-arch_only %(darwin_arch)} \
+ %{!Zforce_cpusubtype_ALL: -arch_only %(darwin_subarch)} \
%{Zforce_flat_namespace:%e-force_flat_namespace not allowed with -dynamiclib} \
%{Zinstall_name*:-install_name %*} \
%{keep_private_externs:%e-keep_private_externs not allowed with -dynamiclib} \
@@ -242,6 +285,8 @@ Boston, MA 02111-1307, USA. */
%{Zallowable_client*:-allowable_client %*} \
%{Zbind_at_load:-bind_at_load} \
%{Zarch_errors_fatal:-arch_errors_fatal} \
+ %{Zdead_strip:-dead_strip} \
+ %{Zno_dead_strip_inits_and_terms:-no_dead_strip_inits_and_terms} \
%{Zdylib_file*:-dylib_file %*} \
%{Zdynamic:-dynamic}\
%{Zexported_symbols_list*:-exported_symbols_list %*} \
@@ -249,20 +294,31 @@ Boston, MA 02111-1307, USA. */
%{headerpad_max_install_names*} \
%{Zimage_base*:-image_base %*} \
%{Zinit*:-init %*} \
+ %{mmacosx-version-min=*:-macosx_version_min %*} \
+ %{!mmacosx-version-min=*:%{shared-libgcc:-macosx_version_min 10.3}} \
%{nomultidefs} \
%{Zmulti_module:-multi_module} %{Zsingle_module:-single_module} \
%{Zmultiply_defined*:-multiply_defined %*} \
+ %{!Zmultiply_defined*:%{shared-libgcc: \
+ %:version-compare(< 10.5 mmacosx-version-min= -multiply_defined) \
+ %:version-compare(< 10.5 mmacosx-version-min= suppress)}} \
%{Zmultiplydefinedunused*:-multiply_defined_unused %*} \
%{prebind} %{noprebind} %{nofixprebinding} %{prebind_all_twolevel_modules} \
%{read_only_relocs} \
- %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} %{seg_addr_table*} \
- %{Zseg_addr_table_filename*:-seg_addr_table_filename %*} \
+ %{sectcreate*} %{sectorder*} %{seg1addr*} %{segprot*} \
+ %{Zsegaddr*:-segaddr %*} \
+ %{Zsegs_read_only_addr*:-segs_read_only_addr %*} \
+ %{Zsegs_read_write_addr*:-segs_read_write_addr %*} \
+ %{Zseg_addr_table*: -seg_addr_table %*} \
+ %{Zfn_seg_addr_table_filename*:-seg_addr_table_filename %*} \
%{sub_library*} %{sub_umbrella*} \
+ " LINK_SYSROOT_SPEC " \
%{twolevel_namespace} %{twolevel_namespace_hints} \
%{umbrella*} \
%{undefined*} \
%{Zunexported_symbols_list*:-unexported_symbols_list %*} \
%{Zweak_reference_mismatches*:-weak_reference_mismatches %*} \
+ %{!Zweak_reference_mismatches*:-weak_reference_mismatches non-weak} \
%{X} \
%{y*} \
%{w} \
@@ -274,32 +330,80 @@ Boston, MA 02111-1307, USA. */
/* Machine dependent libraries. */
-#undef LIB_SPEC
#define LIB_SPEC "%{!static:-lSystem}"
-/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
+/* Support -mmacosx-version-min by supplying different (stub) libgcc_s.dylib
+ libraries to link against, and by not linking against libgcc_s on
+ earlier-than-10.3.9.
+
+ Note that by default, -lgcc_eh is not linked against! This is
+ because in a future version of Darwin the EH frame information may
+ be in a new format, or the fallback routine might be changed; if
+ you want to explicitly link against the static version of those
+ routines, because you know you don't need to unwind through system
+ libraries, you need to explicitly say -static-libgcc.
+
+ If it is linked against, it has to be before -lgcc, because it may
+ need symbols from -lgcc. */
+#undef REAL_LIBGCC_SPEC
+#define REAL_LIBGCC_SPEC \
+ "%{static-libgcc|static: -lgcc_eh -lgcc; \
+ shared-libgcc|fexceptions|fgnu-runtime: \
+ %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_s.10.5) \
+ -lgcc; \
+ :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_s.10.5) \
+ -lgcc}"
+
+/* We specify crt0.o as -lcrt0.o so that ld will search the library path.
+
+ crt3.o provides __cxa_atexit on systems that don't have it. Since
+ it's only used with C++, which requires passing -shared-libgcc, key
+ off that to avoid unnecessarily adding a destructor to every
+ powerpc program built. */
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC \
- "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
- %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
- %{!static:%{object:-lgcrt0.o} \
- %{!object:%{preload:-lgcrt0.o} \
- %{!preload:-lgcrt1.o -lcrt2.o}}}} \
- %{!pg:%{static:-lcrt0.o} \
- %{!static:%{object:-lcrt0.o} \
- %{!object:%{preload:-lcrt0.o} \
- %{!preload:-lcrt1.o -lcrt2.o}}}}}}"
+#define STARTFILE_SPEC \
+ "%{!Zdynamiclib:%{Zbundle:%{!static:-lbundle1.o}} \
+ %{!Zbundle:%{pg:%{static:-lgcrt0.o} \
+ %{!static:%{object:-lgcrt0.o} \
+ %{!object:%{preload:-lgcrt0.o} \
+ %{!preload:-lgcrt1.o %(darwin_crt2)}}}} \
+ %{!pg:%{static:-lcrt0.o} \
+ %{!static:%{object:-lcrt0.o} \
+ %{!object:%{preload:-lcrt0.o} \
+ %{!preload:-lcrt1.o %(darwin_crt2)}}}}}} \
+ %{shared-libgcc:%:version-compare(< 10.5 mmacosx-version-min= crt3.o%s)}"
/* The native Darwin linker doesn't necessarily place files in the order
that they're specified on the link line. Thus, it is pointless
to put anything in ENDFILE_SPEC. */
/* #define ENDFILE_SPEC "" */
+/* Default Darwin ASM_SPEC, very simple. */
+#define ASM_SPEC "-arch %(darwin_arch) \
+ %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL}"
+
/* We use Dbx symbol format. */
#define DBX_DEBUGGING_INFO 1
+/* Also enable Dwarf 2 as an option. */
+#define DWARF2_DEBUGGING_INFO
+#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+
+#define DEBUG_FRAME_SECTION "__DWARF,__debug_frame,regular,debug"
+#define DEBUG_INFO_SECTION "__DWARF,__debug_info,regular,debug"
+#define DEBUG_ABBREV_SECTION "__DWARF,__debug_abbrev,regular,debug"
+#define DEBUG_ARANGES_SECTION "__DWARF,__debug_aranges,regular,debug"
+#define DEBUG_MACINFO_SECTION "__DWARF,__debug_macinfo,regular,debug"
+#define DEBUG_LINE_SECTION "__DWARF,__debug_line,regular,debug"
+#define DEBUG_LOC_SECTION "__DWARF,__debug_loc,regular,debug"
+#define DEBUG_PUBNAMES_SECTION "__DWARF,__debug_pubnames,regular,debug"
+#define DEBUG_STR_SECTION "__DWARF,__debug_str,regular,debug"
+#define DEBUG_RANGES_SECTION "__DWARF,__debug_ranges,regular,debug"
+
/* When generating stabs debugging, use N_BINCL entries. */
#define DBX_USE_BINCL
@@ -310,12 +414,76 @@ Boston, MA 02111-1307, USA. */
/* gdb needs a null N_SO at the end of each file for scattered loading. */
-#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
-do { text_section (); \
- fprintf (FILE, \
- "\t.stabs \"%s\",%d,0,0,Letext\nLetext:\n", "" , N_SO); \
- } while (0)
+#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
+
+/* GCC's definition of 'one_only' is the same as its definition of 'weak'. */
+#define MAKE_DECL_ONE_ONLY(DECL) (DECL_WEAK (DECL) = 1)
+
+/* Mach-O supports 'weak imports', and 'weak definitions' in coalesced
+ sections. machopic_select_section ensures that weak variables go in
+ coalesced sections. Weak aliases (or any other kind of aliases) are
+ not supported. Weak symbols that aren't visible outside the .s file
+ are not supported. */
+#define ASM_WEAKEN_DECL(FILE, DECL, NAME, ALIAS) \
+ do { \
+ if (ALIAS) \
+ { \
+ warning (0, "alias definitions not supported in Mach-O; ignored"); \
+ break; \
+ } \
+ \
+ if (! DECL_EXTERNAL (DECL) && TREE_PUBLIC (DECL)) \
+ targetm.asm_out.globalize_label (FILE, NAME); \
+ if (DECL_EXTERNAL (DECL)) \
+ fputs ("\t.weak_reference ", FILE); \
+ else if (! lookup_attribute ("weak", DECL_ATTRIBUTES (DECL)) \
+ && lookup_attribute ("weak_import", DECL_ATTRIBUTES (DECL))) \
+ break; \
+ else if (TREE_PUBLIC (DECL)) \
+ fputs ("\t.weak_definition ", FILE); \
+ else \
+ break; \
+ assemble_name (FILE, NAME); \
+ fputc ('\n', FILE); \
+ } while (0)
+
+/* Darwin has the pthread routines in libSystem, which every program
+ links to, so there's no need for weak-ness for that. */
+#define GTHREAD_USE_WEAK 0
+
+/* The Darwin linker imposes two limitations on common symbols: they
+ can't have hidden visibility, and they can't appear in dylibs. As
+ a consequence, we should never use common symbols to represent
+ vague linkage. */
+#undef USE_COMMON_FOR_ONE_ONLY
+#define USE_COMMON_FOR_ONE_ONLY 0
+
+/* The Darwin linker doesn't want coalesced symbols to appear in
+ a static archive's table of contents. */
+#undef TARGET_WEAK_NOT_IN_ARCHIVE_TOC
+#define TARGET_WEAK_NOT_IN_ARCHIVE_TOC 1
+
+/* On Darwin, we don't (at the time of writing) have linkonce sections
+ with names, so it's safe to make the class data not comdat. */
+#define TARGET_CXX_CLASS_DATA_ALWAYS_COMDAT hook_bool_void_false
+
+/* We make exception information linkonce. */
+#undef TARGET_USES_WEAK_UNWIND_INFO
+#define TARGET_USES_WEAK_UNWIND_INFO 1
+
+/* We need to use a nonlocal label for the start of an EH frame: the
+ Darwin linker requires that a coalesced section start with a label.
+ Unfortunately, it also requires that 'debug' sections don't contain
+ labels. */
+#undef FRAME_BEGIN_LABEL
+#define FRAME_BEGIN_LABEL (for_eh ? "EH_frame" : "Lframe")
+
+/* Emit a label for the FDE corresponding to DECL. EMPTY means
+ emit a label for an empty FDE. */
+#define TARGET_ASM_EMIT_UNWIND_LABEL darwin_emit_unwind_label
+
+/* Emit a label to separate the exception table. */
+#define TARGET_ASM_EMIT_EXCEPT_TABLE_LABEL darwin_emit_except_table_label
/* Our profiling scheme doesn't LP labels and counter words. */
@@ -358,7 +526,7 @@ do { text_section (); \
/* The RTTI data (e.g., __ti4name) is common and public (and static),
but it does need to be referenced via indirect PIC data pointers.
- The machopic_define_name calls are telling the machopic subsystem
+ The machopic_define_symbol calls are telling the machopic subsystem
that the name *is* defined in this module, so it doesn't need to
make them indirect. */
@@ -368,35 +536,37 @@ do { text_section (); \
const char *xname = NAME; \
if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
- if ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL)) \
- machopic_define_name (xname); \
+ if (! DECL_WEAK (DECL) \
+ && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ machopic_define_symbol (DECL_RTL (DECL)); \
if ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL)) \
(* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
ASM_OUTPUT_LABEL (FILE, xname); \
- /* Darwin doesn't support zero-size objects, so give them a \
+ /* Darwin doesn't support zero-size objects, so give them a \
byte. */ \
if (tree_low_cst (DECL_SIZE_UNIT (DECL), 1) == 0) \
assemble_zeros (1); \
} while (0)
-#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
+#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
do { \
- const char *xname = NAME; \
- if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
- xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
- if ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL)) \
- machopic_define_name (xname); \
- if ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL)) \
+ const char *xname = NAME; \
+ if (GET_CODE (XEXP (DECL_RTL (DECL), 0)) != SYMBOL_REF) \
+ xname = IDENTIFIER_POINTER (DECL_NAME (DECL)); \
+ if (! DECL_WEAK (DECL) \
+ && ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL))) \
+ machopic_define_symbol (DECL_RTL (DECL)); \
+ if ((TREE_STATIC (DECL) \
+ && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
+ || DECL_INITIAL (DECL)) \
(* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
- ASM_OUTPUT_LABEL (FILE, xname); \
+ ASM_OUTPUT_LABEL (FILE, xname); \
} while (0)
#define ASM_DECLARE_CONSTANT_NAME(FILE, NAME, EXP, SIZE) \
@@ -414,19 +584,24 @@ do { text_section (); \
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF(FILE,NAME) \
do { \
- const char *xname = darwin_strip_name_encoding (NAME); \
+ const char *xname = (NAME); \
if (! strcmp (xname, "<pic base>")) \
machopic_output_function_base_name(FILE); \
else if (xname[0] == '&' || xname[0] == '*') \
{ \
int len = strlen (xname); \
if (len > 6 && !strcmp ("$stub", xname + len - 5)) \
- machopic_validate_stub_or_non_lazy_ptr (xname, 1); \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
else if (len > 7 && !strcmp ("$stub\"", xname + len - 6)) \
- machopic_validate_stub_or_non_lazy_ptr (xname, 1); \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
else if (len > 14 && !strcmp ("$non_lazy_ptr", xname + len - 13)) \
- machopic_validate_stub_or_non_lazy_ptr (xname, 0); \
- fputs (&xname[1], FILE); \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ else if (len > 15 && !strcmp ("$non_lazy_ptr\"", xname + len - 14)) \
+ machopic_validate_stub_or_non_lazy_ptr (xname); \
+ if (xname[1] != '"' && name_needs_quotes (&xname[1])) \
+ fprintf (FILE, "\"%s\"", &xname[1]); \
+ else \
+ fputs (&xname[1], FILE); \
} \
else if (xname[0] == '+' || xname[0] == '-') \
fprintf (FILE, "\"%s\"", xname); \
@@ -434,18 +609,20 @@ do { text_section (); \
fprintf (FILE, "L%s", xname); \
else if (!strncmp (xname, ".objc_class_name_", 17)) \
fprintf (FILE, "%s", xname); \
+ else if (xname[0] != '"' && name_needs_quotes (xname)) \
+ fprintf (FILE, "\"%s\"", xname); \
else \
- fprintf (FILE, "_%s", xname); \
+ asm_fprintf (FILE, "%U%s", xname); \
} while (0)
/* Output before executable code. */
#undef TEXT_SECTION_ASM_OP
-#define TEXT_SECTION_ASM_OP ".text"
+#define TEXT_SECTION_ASM_OP "\t.text"
/* Output before writable data. */
#undef DATA_SECTION_ASM_OP
-#define DATA_SECTION_ASM_OP ".data"
+#define DATA_SECTION_ASM_OP "\t.data"
#undef ALIGN_ASM_OP
#define ALIGN_ASM_OP ".align"
@@ -460,231 +637,51 @@ do { text_section (); \
#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
+ unsigned HOST_WIDE_INT _new_size = SIZE; \
fputs (".lcomm ", (FILE)); \
assemble_name ((FILE), (NAME)); \
- fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), \
+ if (_new_size == 0) _new_size = 1; \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", _new_size, \
floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
if ((DECL) && ((TREE_STATIC (DECL) \
&& (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
|| DECL_INITIAL (DECL))) \
- (* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
- if ((DECL) && ((TREE_STATIC (DECL) \
- && (!DECL_COMMON (DECL) || !TREE_PUBLIC (DECL))) \
- || DECL_INITIAL (DECL))) \
- machopic_define_name (NAME); \
+ { \
+ (* targetm.encode_section_info) (DECL, DECL_RTL (DECL), false); \
+ machopic_define_symbol (DECL_RTL (DECL)); \
+ } \
} while (0)
-/* The maximum alignment which the object file format can support.
- For Mach-O, this is 2^15. */
+/* The maximum alignment which the object file format can support in
+ bits. For Mach-O, this is 2^15 bytes. */
#undef MAX_OFILE_ALIGNMENT
-#define MAX_OFILE_ALIGNMENT 0x8000
-
-/* Create new Mach-O sections. */
-
-#undef SECTION_FUNCTION
-#define SECTION_FUNCTION(FUNCTION, SECTION, DIRECTIVE, OBJC) \
-extern void FUNCTION (void); \
-void \
-FUNCTION (void) \
-{ \
- if (in_section != SECTION) \
- { \
- if (OBJC) \
- objc_section_init (); \
- data_section (); \
- if (asm_out_file) \
- fprintf (asm_out_file, "%s\n", DIRECTIVE); \
- in_section = SECTION; \
- } \
-} \
-
-/* Darwin uses many types of special sections. */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS \
- in_const, in_const_data, in_cstring, in_literal4, in_literal8, \
- in_constructor, in_destructor, in_mod_init, in_mod_term, \
- in_objc_class, in_objc_meta_class, in_objc_category, \
- in_objc_class_vars, in_objc_instance_vars, \
- in_objc_cls_meth, in_objc_inst_meth, \
- in_objc_cat_cls_meth, in_objc_cat_inst_meth, \
- in_objc_selector_refs, \
- in_objc_selector_fixup, \
- in_objc_symbols, in_objc_module_info, \
- in_objc_protocol, in_objc_string_object, \
- in_objc_constant_string_object, \
- in_objc_image_info, \
- in_objc_class_names, in_objc_meth_var_names, \
- in_objc_meth_var_types, in_objc_cls_refs, \
- in_machopic_nl_symbol_ptr, \
- in_machopic_lazy_symbol_ptr, \
- in_machopic_symbol_stub, \
- in_machopic_symbol_stub1, \
- in_machopic_picsymbol_stub, \
- in_machopic_picsymbol_stub1, \
- in_darwin_exception, in_darwin_eh_frame, \
- num_sections
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
-static void objc_section_init (void); \
-SECTION_FUNCTION (const_section, \
- in_const, \
- ".const", 0) \
-SECTION_FUNCTION (const_data_section, \
- in_const_data, \
- ".const_data", 0) \
-SECTION_FUNCTION (cstring_section, \
- in_cstring, \
- ".cstring", 0) \
-SECTION_FUNCTION (literal4_section, \
- in_literal4, \
- ".literal4", 0) \
-SECTION_FUNCTION (literal8_section, \
- in_literal8, \
- ".literal8", 0) \
-SECTION_FUNCTION (constructor_section, \
- in_constructor, \
- ".constructor", 0) \
-SECTION_FUNCTION (mod_init_section, \
- in_mod_init, \
- ".mod_init_func", 0) \
-SECTION_FUNCTION (mod_term_section, \
- in_mod_term, \
- ".mod_term_func", 0) \
-SECTION_FUNCTION (destructor_section, \
- in_destructor, \
- ".destructor", 0) \
-SECTION_FUNCTION (objc_class_section, \
- in_objc_class, \
- ".objc_class", 1) \
-SECTION_FUNCTION (objc_meta_class_section, \
- in_objc_meta_class, \
- ".objc_meta_class", 1) \
-SECTION_FUNCTION (objc_category_section, \
- in_objc_category, \
- ".objc_category", 1) \
-SECTION_FUNCTION (objc_class_vars_section, \
- in_objc_class_vars, \
- ".objc_class_vars", 1) \
-SECTION_FUNCTION (objc_instance_vars_section, \
- in_objc_instance_vars, \
- ".objc_instance_vars", 1) \
-SECTION_FUNCTION (objc_cls_meth_section, \
- in_objc_cls_meth, \
- ".objc_cls_meth", 1) \
-SECTION_FUNCTION (objc_inst_meth_section, \
- in_objc_inst_meth, \
- ".objc_inst_meth", 1) \
-SECTION_FUNCTION (objc_cat_cls_meth_section, \
- in_objc_cat_cls_meth, \
- ".objc_cat_cls_meth", 1) \
-SECTION_FUNCTION (objc_cat_inst_meth_section, \
- in_objc_cat_inst_meth, \
- ".objc_cat_inst_meth", 1) \
-SECTION_FUNCTION (objc_selector_refs_section, \
- in_objc_selector_refs, \
- ".objc_message_refs", 1) \
-SECTION_FUNCTION (objc_selector_fixup_section, \
- in_objc_selector_fixup, \
- ".section __OBJC, __sel_fixup", 1) \
-SECTION_FUNCTION (objc_symbols_section, \
- in_objc_symbols, \
- ".objc_symbols", 1) \
-SECTION_FUNCTION (objc_module_info_section, \
- in_objc_module_info, \
- ".objc_module_info", 1) \
-SECTION_FUNCTION (objc_protocol_section, \
- in_objc_protocol, \
- ".objc_protocol", 1) \
-SECTION_FUNCTION (objc_string_object_section, \
- in_objc_string_object, \
- ".objc_string_object", 1) \
-SECTION_FUNCTION (objc_constant_string_object_section, \
- in_objc_constant_string_object, \
- ".section __OBJC, __cstring_object", 1) \
-/* Fix-and-Continue image marker. */ \
-SECTION_FUNCTION (objc_image_info_section, \
- in_objc_image_info, \
- ".section __OBJC, __image_info", 1) \
-SECTION_FUNCTION (objc_class_names_section, \
- in_objc_class_names, \
- ".objc_class_names", 1) \
-SECTION_FUNCTION (objc_meth_var_names_section, \
- in_objc_meth_var_names, \
- ".objc_meth_var_names", 1) \
-SECTION_FUNCTION (objc_meth_var_types_section, \
- in_objc_meth_var_types, \
- ".objc_meth_var_types", 1) \
-SECTION_FUNCTION (objc_cls_refs_section, \
- in_objc_cls_refs, \
- ".objc_cls_refs", 1) \
- \
-SECTION_FUNCTION (machopic_lazy_symbol_ptr_section, \
- in_machopic_lazy_symbol_ptr, \
- ".lazy_symbol_pointer", 0) \
-SECTION_FUNCTION (machopic_nl_symbol_ptr_section, \
- in_machopic_nl_symbol_ptr, \
- ".non_lazy_symbol_pointer", 0) \
-SECTION_FUNCTION (machopic_symbol_stub_section, \
- in_machopic_symbol_stub, \
- ".symbol_stub", 0) \
-SECTION_FUNCTION (machopic_symbol_stub1_section, \
- in_machopic_symbol_stub1, \
- ".section __TEXT,__symbol_stub1,symbol_stubs,pure_instructions,16", 0)\
-SECTION_FUNCTION (machopic_picsymbol_stub_section, \
- in_machopic_picsymbol_stub, \
- ".picsymbol_stub", 0) \
-SECTION_FUNCTION (machopic_picsymbol_stub1_section, \
- in_machopic_picsymbol_stub1, \
- ".section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32", 0)\
-SECTION_FUNCTION (darwin_exception_section, \
- in_darwin_exception, \
- ".section __DATA,__gcc_except_tab", 0) \
-SECTION_FUNCTION (darwin_eh_frame_section, \
- in_darwin_eh_frame, \
- ".section __TEXT,__eh_frame", 0) \
- \
-static void \
-objc_section_init (void) \
-{ \
- static int been_here = 0; \
- \
- if (been_here == 0) \
- { \
- been_here = 1; \
- /* written, cold -> hot */ \
- objc_cat_cls_meth_section (); \
- objc_cat_inst_meth_section (); \
- objc_string_object_section (); \
- objc_constant_string_object_section (); \
- objc_selector_refs_section (); \
- objc_selector_fixup_section (); \
- objc_cls_refs_section (); \
- objc_class_section (); \
- objc_meta_class_section (); \
- /* shared, hot -> cold */ \
- objc_cls_meth_section (); \
- objc_inst_meth_section (); \
- objc_protocol_section (); \
- objc_class_names_section (); \
- objc_meth_var_types_section (); \
- objc_meth_var_names_section (); \
- objc_category_section (); \
- objc_class_vars_section (); \
- objc_instance_vars_section (); \
- objc_module_info_section (); \
- objc_symbols_section (); \
- } \
-}
-
-#define READONLY_DATA_SECTION const_section
+#define MAX_OFILE_ALIGNMENT (0x8000 * 8)
+
+/* Declare the section variables. */
+#ifndef USED_FOR_TARGET
+enum darwin_section_enum {
+#define DEF_SECTION(NAME, FLAGS, DIRECTIVE, OBJC) NAME,
+#include "darwin-sections.def"
+#undef DEF_SECTION
+ NUM_DARWIN_SECTIONS
+};
+extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS];
+#endif
#undef TARGET_ASM_SELECT_SECTION
#define TARGET_ASM_SELECT_SECTION machopic_select_section
+#define USE_SELECT_SECTION_FOR_FUNCTIONS
+
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION machopic_select_rtx_section
+#undef TARGET_ASM_UNIQUE_SECTION
+#define TARGET_ASM_UNIQUE_SECTION darwin_unique_section
+#undef TARGET_ASM_FUNCTION_RODATA_SECTION
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK machopic_reloc_rw_mask
+
#define ASM_DECLARE_UNRESOLVED_REFERENCE(FILE,NAME) \
do { \
@@ -714,21 +711,40 @@ objc_section_init (void) \
/* Emit an assembler directive to set visibility for a symbol. Used
to support visibility attribute and Darwin's private extern
- feature. */
+ feature. */
#undef TARGET_ASM_ASSEMBLE_VISIBILITY
#define TARGET_ASM_ASSEMBLE_VISIBILITY darwin_assemble_visibility
+/* Extra attributes for Darwin. */
+#define SUBTARGET_ATTRIBUTE_TABLE \
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \
+ { "apple_kext_compatibility", 0, 0, false, true, false, \
+ darwin_handle_kext_attribute }, \
+ { "weak_import", 0, 0, true, false, false, \
+ darwin_handle_weak_import_attribute }
#undef ASM_GENERATE_INTERNAL_LABEL
#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM))
-/* Since we have a separate readonly data section, define this so that
- jump tables end up in text rather than data. */
+#undef TARGET_ASM_MARK_DECL_PRESERVED
+#define TARGET_ASM_MARK_DECL_PRESERVED darwin_mark_decl_preserved
-#ifndef JUMP_TABLES_IN_TEXT_SECTION
-#define JUMP_TABLES_IN_TEXT_SECTION 1
-#endif
+/* Set on a symbol with SYMBOL_FLAG_FUNCTION or
+ MACHO_SYMBOL_FLAG_VARIABLE to indicate that the function or
+ variable has been defined in this translation unit.
+ When porting Mach-O to new architectures you need to make
+ sure these aren't clobbered by the backend. */
+
+#define MACHO_SYMBOL_FLAG_VARIABLE (SYMBOL_FLAG_MACH_DEP)
+#define MACHO_SYMBOL_FLAG_DEFINED ((SYMBOL_FLAG_MACH_DEP) << 1)
+
+/* Set on a symbol to indicate when fix-and-continue style code
+ generation is being used and the symbol refers to a static symbol
+ that should be rebound from new instances of a translation unit to
+ the original instance of the data. */
+
+#define MACHO_SYMBOL_STATIC ((SYMBOL_FLAG_MACH_DEP) << 2)
/* Symbolic names for various things we might know about a symbol. */
@@ -744,13 +760,13 @@ enum machopic_addr_class {
#define MACHO_DYNAMIC_NO_PIC_P (TARGET_DYNAMIC_NO_PIC)
#define MACHOPIC_INDIRECT (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
-#define MACHOPIC_JUST_INDIRECT (flag_pic == 1 || MACHO_DYNAMIC_NO_PIC_P)
-#define MACHOPIC_PURE (flag_pic == 2 && ! MACHO_DYNAMIC_NO_PIC_P)
+#define MACHOPIC_JUST_INDIRECT (MACHO_DYNAMIC_NO_PIC_P)
+#define MACHOPIC_PURE (flag_pic && ! MACHO_DYNAMIC_NO_PIC_P)
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO darwin_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING
-#define TARGET_STRIP_NAME_ENCODING darwin_strip_name_encoding
+#define TARGET_STRIP_NAME_ENCODING default_strip_name_encoding
#define GEN_BINDER_NAME_FOR_STUB(BUF,STUB,STUB_LENGTH) \
do { \
@@ -786,7 +802,7 @@ enum machopic_addr_class {
#define GEN_LAZY_PTR_NAME_FOR_SYMBOL(BUF,SYMBOL,SYMBOL_LENGTH) \
do { \
- const char *symbol_ = darwin_strip_name_encoding (SYMBOL); \
+ const char *symbol_ = (SYMBOL); \
char *buffer_ = (BUF); \
if (symbol_[0] == '"') \
{ \
@@ -808,30 +824,140 @@ enum machopic_addr_class {
} \
} while (0)
-#define TARGET_ASM_EXCEPTION_SECTION darwin_exception_section
+#define EH_FRAME_SECTION_NAME "__TEXT"
+#define EH_FRAME_SECTION_ATTR ",coalesced,no_toc+strip_static_syms+live_support"
-#define TARGET_ASM_EH_FRAME_SECTION darwin_eh_frame_section
+/* Java runtime class list. */
+#define JCR_SECTION_NAME "__DATA,jcr,regular,no_dead_strip"
#undef ASM_PREFERRED_EH_DATA_FORMAT
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE,GLOBAL) \
(((CODE) == 2 && (GLOBAL) == 1) \
- ? (DW_EH_PE_pcrel | DW_EH_PE_indirect) : \
+ ? (DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4) : \
((CODE) == 1 || (GLOBAL) == 0) ? DW_EH_PE_pcrel : DW_EH_PE_absptr)
#define ASM_OUTPUT_DWARF_DELTA(FILE,SIZE,LABEL1,LABEL2) \
darwin_asm_output_dwarf_delta (FILE, SIZE, LABEL1, LABEL2)
+#define ASM_OUTPUT_DWARF_OFFSET(FILE,SIZE,LABEL,BASE) \
+ darwin_asm_output_dwarf_offset (FILE, SIZE, LABEL, BASE)
+
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(ASM_OUT_FILE, ENCODING, SIZE, ADDR, DONE) \
+ if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) { \
+ darwin_non_lazy_pcrel (ASM_OUT_FILE, ADDR); \
+ goto DONE; \
+ }
+
+/* Experimentally, putting jump tables in text is faster on SPEC.
+ Also this is needed for correctness for coalesced functions. */
+
+#ifndef JUMP_TABLES_IN_TEXT_SECTION
+#define JUMP_TABLES_IN_TEXT_SECTION 1
+#endif
+
#define TARGET_TERMINATE_DW2_EH_FRAME_INFO false
+#define TARGET_ASM_INIT_SECTIONS darwin_init_sections
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION darwin_asm_named_section
+
+/* Handle pragma weak and pragma pack. */
+#define HANDLE_SYSV_PRAGMA 1
+
+#define HANDLE_PRAGMA_PACK_PUSH_POP 1
+
#define DARWIN_REGISTER_TARGET_PRAGMAS() \
do { \
c_register_pragma (0, "mark", darwin_pragma_ignore); \
c_register_pragma (0, "options", darwin_pragma_options); \
c_register_pragma (0, "segment", darwin_pragma_ignore); \
c_register_pragma (0, "unused", darwin_pragma_unused); \
+ c_register_pragma (0, "ms_struct", darwin_pragma_ms_struct); \
} while (0)
#undef ASM_APP_ON
#define ASM_APP_ON ""
#undef ASM_APP_OFF
#define ASM_APP_OFF ""
+
+void darwin_register_frameworks (const char *, const char *, int);
+void darwin_register_objc_includes (const char *, const char *, int);
+#define TARGET_EXTRA_PRE_INCLUDES darwin_register_objc_includes
+#define TARGET_EXTRA_INCLUDES darwin_register_frameworks
+
+void add_framework_path (char *);
+#define TARGET_OPTF add_framework_path
+
+#define TARGET_POSIX_IO
+
+/* All new versions of Darwin have C99 functions. */
+
+#define TARGET_C99_FUNCTIONS 1
+
+#define WINT_TYPE "int"
+
+/* Every program on darwin links against libSystem which contains the pthread
+ routines, so there's no need to explicitly call out when doing threaded
+ work. */
+
+#undef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS ""
+
+/* Darwin can't support anchors until we can cope with the adjustments
+ to size that ASM_DECLARE_OBJECT_NAME and ASM_DECLARE_CONSTANT_NAME
+ when outputting members of an anchor block and the linker can be
+ taught to keep them together or we find some other suitable
+ code-gen technique. */
+
+#if 0
+#define TARGET_ASM_OUTPUT_ANCHOR darwin_asm_output_anchor
+#else
+#define TARGET_ASM_OUTPUT_ANCHOR NULL
+#endif
+
+/* Attempt to turn on execute permission for the stack. This may be
+ used by INITIALIZE_TRAMPOLINE of the target needs it (that is,
+ if the target machine can change execute permissions on a page).
+
+ There is no way to query the execute permission of the stack, so
+ we always issue the mprotect() call.
+
+ Unfortunately it is not possible to make this namespace-clean.
+
+ Also note that no errors should be emitted by this code; it is
+ considered dangerous for library calls to send messages to
+ stdout/stderr. */
+
+#define ENABLE_EXECUTE_STACK \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (void *addr) \
+{ \
+ extern int mprotect (void *, size_t, int); \
+ extern int getpagesize (void); \
+ static int size; \
+ static long mask; \
+ \
+ char *page, *end; \
+ \
+ if (size == 0) \
+ { \
+ size = getpagesize(); \
+ mask = ~((long) size - 1); \
+ } \
+ \
+ page = (char *) (((long) addr) & mask); \
+ end = (char *) ((((long) (addr + (TARGET_64BIT ? 48 : 40))) & mask) + size); \
+ \
+ /* 7 == PROT_READ | PROT_WRITE | PROT_EXEC */ \
+ (void) mprotect (page, end - page, 7); \
+}
+
+/* For Apple KEXTs, we make the constructors return this to match gcc
+ 2.95. */
+#define TARGET_CXX_CDTOR_RETURNS_THIS (darwin_kextabi_p)
+extern int flag_mkernel;
+extern int flag_apple_kext;
+#define TARGET_KEXTABI flag_apple_kext
+
+#endif /* CONFIG_DARWIN_H */
diff --git a/contrib/gcc/config/darwin.opt b/contrib/gcc/config/darwin.opt
new file mode 100644
index 0000000..9fee719
--- /dev/null
+++ b/contrib/gcc/config/darwin.opt
@@ -0,0 +1,40 @@
+; Processor-independent options for Darwin.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mfix-and-continue
+Target Report Var(darwin_fix_and_continue)
+Generate code suitable for fast turn around debugging
+
+mmacosx-version-min=
+Target Joined Report Var(darwin_macosx_version_min)
+The earliest MacOS X version on which this program will run
+
+mone-byte-bool
+Target RejectNegative Report Var(darwin_one_byte_bool)
+Set sizeof(bool) to 1
+
+fapple-kext
+Target Report Var(flag_apple_kext)
+Generate code for darwin loadable kernel extentions
+
+mkernel
+Target Report Var(flag_mkernel)
+Generate code for the kernel or loadable kernel extentions
diff --git a/contrib/gcc/config/darwin9.h b/contrib/gcc/config/darwin9.h
new file mode 100644
index 0000000..2965f19
--- /dev/null
+++ b/contrib/gcc/config/darwin9.h
@@ -0,0 +1,13 @@
+/* The linker can generate branch islands. */
+#define DARWIN_LINKER_GENERATES_ISLANDS 1
+
+#undef ASM_OUTPUT_ALIGNED_COMMON
+#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
+ do { \
+ unsigned HOST_WIDE_INT _new_size = (SIZE); \
+ fprintf ((FILE), ".comm "); \
+ assemble_name ((FILE), (NAME)); \
+ if (_new_size == 0) _new_size = 1; \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", \
+ _new_size, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
+ } while (0)
diff --git a/contrib/gcc/config/dbx.h b/contrib/gcc/config/dbx.h
index eb20452..3c81534 100644
--- a/contrib/gcc/config/dbx.h
+++ b/contrib/gcc/config/dbx.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file causes gcc to prefer using DBX (stabs) debugging
information. The configure script will add a #include of this file
diff --git a/contrib/gcc/config/dbxcoff.h b/contrib/gcc/config/dbxcoff.h
index 76a910f..b6eaec9 100644
--- a/contrib/gcc/config/dbxcoff.h
+++ b/contrib/gcc/config/dbxcoff.h
@@ -1,5 +1,5 @@
/* Definitions needed when using stabs embedded in COFF sections.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file may be included by any COFF target which wishes to
support -gstabs generating stabs in sections, as produced by gas
@@ -34,43 +34,22 @@ Boston, MA 02111-1307, USA. */
/* Be function-relative for block and source line stab directives. */
-#undef DBX_BLOCKS_FUNCTION_RELATIVE
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
/* but, to make this work, functions must appear prior to line info. */
-#undef DBX_FUNCTION_FIRST
#define DBX_FUNCTION_FIRST
/* Generate a blank trailing N_SO to mark the end of the .o file, since
we can't depend upon the linker to mark .o file boundaries with
embedded stabs. */
-#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
- asm_fprintf (FILE, \
- "\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
+#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
/* Like block addresses, stabs line numbers are relative to the
current function. */
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE, COUNTER) \
-{ if (write_symbols == SDB_DEBUG) { \
- fprintf ((FILE), "\t.ln\t%d\n", \
- ((sdb_begin_function_line > -1) \
- ? (LINE) - sdb_begin_function_line : 1)); \
- } else if (write_symbols == DBX_DEBUG) { \
- char buffer[256]; \
- ASM_GENERATE_INTERNAL_LABEL (buffer, "LM", COUNTER); \
- fprintf (FILE, ".stabn 68,0,%d,", LINE); \
- assemble_name (FILE, buffer); \
- putc ('-', FILE); \
- assemble_name (FILE, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
- putc ('\n', FILE); \
- (*targetm.asm_out.internal_label) (FILE, "LM", COUNTER); \
- } }
+#define DBX_LINES_FUNCTION_RELATIVE 1
/* When generating stabs debugging, use N_BINCL entries. */
diff --git a/contrib/gcc/config/dbxelf.h b/contrib/gcc/config/dbxelf.h
index e636dad..a317686 100644
--- a/contrib/gcc/config/dbxelf.h
+++ b/contrib/gcc/config/dbxelf.h
@@ -1,5 +1,5 @@
/* Definitions needed when using stabs embedded in ELF sections.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file may be included by any ELF target which wishes to
support -gstabs generating stabs in sections, as produced by gas
@@ -34,17 +34,14 @@ Boston, MA 02111-1307, USA. */
way, gdb expects it, and it reduces the number of relocation
entries... */
-#undef DBX_BLOCKS_FUNCTION_RELATIVE
#define DBX_BLOCKS_FUNCTION_RELATIVE 1
/* ... but, to make this work, functions must appear prior to line info. */
-#undef DBX_FUNCTION_FIRST
#define DBX_FUNCTION_FIRST
/* When generating stabs debugging, use N_BINCL entries. */
-#undef DBX_USE_BINCL
#define DBX_USE_BINCL
/* There is no limit to the length of stabs strings. */
@@ -56,29 +53,12 @@ Boston, MA 02111-1307, USA. */
/* Like block addresses, stabs line numbers are relative to the
current function. */
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE, COUNTER) \
-do \
- { \
- char temp[256]; \
- ASM_GENERATE_INTERNAL_LABEL (temp, "LM", COUNTER); \
- fprintf (FILE, "\t.stabn 68,0,%d,", LINE); \
- assemble_name (FILE, temp); \
- putc ('-', FILE); \
- assemble_name (FILE, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
- putc ('\n', FILE); \
- (*targetm.asm_out.internal_label) (FILE, "LM", COUNTER); \
- } \
-while (0)
+#define DBX_LINES_FUNCTION_RELATIVE 1
/* Generate a blank trailing N_SO to mark the end of the .o file, since
we can't depend upon the linker to mark .o file boundaries with
embedded stabs. */
-#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
- asm_fprintf (FILE, \
- "\t.text\n\t.stabs \"\",%d,0,0,%LLetext\n%LLetext:\n", N_SO)
+#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
#endif /* ! GCC_DBX_ELF_H */
diff --git a/contrib/gcc/config/dfp-bit.c b/contrib/gcc/config/dfp-bit.c
new file mode 100644
index 0000000..c9374c5
--- /dev/null
+++ b/contrib/gcc/config/dfp-bit.c
@@ -0,0 +1,541 @@
+/* This is a software decimal floating point library.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* This implements IEEE 754R decimal floating point arithmetic, but
+ does not provide a mechanism for setting the rounding mode, or for
+ generating or handling exceptions. Conversions between decimal
+ floating point types and other types depend on C library functions.
+
+ Contributed by Ben Elliston <bje@au.ibm.com>. */
+
+/* The intended way to use this file is to make two copies, add `#define '
+ to one copy, then compile both copies and add them to libgcc.a. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "config/dfp-bit.h"
+
+/* Forward declarations. */
+#if WIDTH == 32 || WIDTH_TO == 32
+void __host_to_ieee_32 (_Decimal32 in, decimal32 *out);
+void __ieee_to_host_32 (decimal32 in, _Decimal32 *out);
+#endif
+#if WIDTH == 64 || WIDTH_TO == 64
+void __host_to_ieee_64 (_Decimal64 in, decimal64 *out);
+void __ieee_to_host_64 (decimal64 in, _Decimal64 *out);
+#endif
+#if WIDTH == 128 || WIDTH_TO == 128
+void __host_to_ieee_128 (_Decimal128 in, decimal128 *out);
+void __ieee_to_host_128 (decimal128 in, _Decimal128 *out);
+#endif
+
+/* A pointer to a unary decNumber operation. */
+typedef decNumber* (*dfp_unary_func)
+ (decNumber *, decNumber *, decContext *);
+
+/* A pointer to a binary decNumber operation. */
+typedef decNumber* (*dfp_binary_func)
+ (decNumber *, decNumber *, decNumber *, decContext *);
+
+extern unsigned long __dec_byte_swap (unsigned long);
+
+/* Unary operations. */
+
+static inline DFP_C_TYPE
+dfp_unary_op (dfp_unary_func op, DFP_C_TYPE arg)
+{
+ DFP_C_TYPE result;
+ decContext context;
+ decNumber arg1, res;
+ IEEE_TYPE a, encoded_result;
+
+ HOST_TO_IEEE (arg, &a);
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ TO_INTERNAL (&a, &arg1);
+
+ /* Perform the operation. */
+ op (&res, &arg1, &context);
+
+ if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+ DFP_RAISE (0);
+
+ TO_ENCODED (&encoded_result, &res, &context);
+ IEEE_TO_HOST (encoded_result, &result);
+ return result;
+}
+
+/* Binary operations. */
+
+static inline DFP_C_TYPE
+dfp_binary_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ DFP_C_TYPE result;
+ decContext context;
+ decNumber arg1, arg2, res;
+ IEEE_TYPE a, b, encoded_result;
+
+ HOST_TO_IEEE (arg_a, &a);
+ HOST_TO_IEEE (arg_b, &b);
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ TO_INTERNAL (&a, &arg1);
+ TO_INTERNAL (&b, &arg2);
+
+ /* Perform the operation. */
+ op (&res, &arg1, &arg2, &context);
+
+ if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+ DFP_RAISE (0);
+
+ TO_ENCODED (&encoded_result, &res, &context);
+ IEEE_TO_HOST (encoded_result, &result);
+ return result;
+}
+
+/* Comparison operations. */
+
+static inline int
+dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ IEEE_TYPE a, b;
+ decContext context;
+ decNumber arg1, arg2, res;
+ int result;
+
+ HOST_TO_IEEE (arg_a, &a);
+ HOST_TO_IEEE (arg_b, &b);
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ TO_INTERNAL (&a, &arg1);
+ TO_INTERNAL (&b, &arg2);
+
+ /* Perform the comparison. */
+ op (&res, &arg1, &arg2, &context);
+
+ if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
+ DFP_RAISE (0);
+
+ if (decNumberIsNegative (&res))
+ result = -1;
+ else if (decNumberIsZero (&res))
+ result = 0;
+ else
+ result = 1;
+
+ return result;
+}
+
+
+#if defined(L_conv_sd)
+void
+__host_to_ieee_32 (_Decimal32 in, decimal32 *out)
+{
+ uint32_t t;
+
+ if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+ {
+ memcpy (&t, &in, 4);
+ t = __dec_byte_swap (t);
+ memcpy (out, &t, 4);
+ }
+ else
+ memcpy (out, &in, 4);
+}
+
+void
+__ieee_to_host_32 (decimal32 in, _Decimal32 *out)
+{
+ uint32_t t;
+
+ if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+ {
+ memcpy (&t, &in, 4);
+ t = __dec_byte_swap (t);
+ memcpy (out, &t, 4);
+ }
+ else
+ memcpy (out, &in, 4);
+}
+#endif /* L_conv_sd */
+
+#if defined(L_conv_dd)
+static void
+__swap64 (char *src, char *dst)
+{
+ uint32_t t1, t2;
+
+ if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+ {
+ memcpy (&t1, src, 4);
+ memcpy (&t2, src + 4, 4);
+ t1 = __dec_byte_swap (t1);
+ t2 = __dec_byte_swap (t2);
+ memcpy (dst, &t2, 4);
+ memcpy (dst + 4, &t1, 4);
+ }
+ else
+ memcpy (dst, src, 8);
+}
+
+void
+__host_to_ieee_64 (_Decimal64 in, decimal64 *out)
+{
+ __swap64 ((char *) &in, (char *) out);
+}
+
+void
+__ieee_to_host_64 (decimal64 in, _Decimal64 *out)
+{
+ __swap64 ((char *) &in, (char *) out);
+}
+#endif /* L_conv_dd */
+
+#if defined(L_conv_td)
+static void
+__swap128 (char *src, char *dst)
+{
+ uint32_t t1, t2, t3, t4;
+
+ if (!LIBGCC2_FLOAT_WORDS_BIG_ENDIAN)
+ {
+ memcpy (&t1, src, 4);
+ memcpy (&t2, src + 4, 4);
+ memcpy (&t3, src + 8, 4);
+ memcpy (&t4, src + 12, 4);
+ t1 = __dec_byte_swap (t1);
+ t2 = __dec_byte_swap (t2);
+ t3 = __dec_byte_swap (t3);
+ t4 = __dec_byte_swap (t4);
+ memcpy (dst, &t4, 4);
+ memcpy (dst + 4, &t3, 4);
+ memcpy (dst + 8, &t2, 4);
+ memcpy (dst + 12, &t1, 4);
+ }
+ else
+ memcpy (dst, src, 16);
+}
+
+void
+__host_to_ieee_128 (_Decimal128 in, decimal128 *out)
+{
+ __swap128 ((char *) &in, (char *) out);
+}
+
+void
+__ieee_to_host_128 (decimal128 in, _Decimal128 *out)
+{
+ __swap128 ((char *) &in, (char *) out);
+}
+#endif /* L_conv_td */
+
+#if defined(L_addsub_sd) || defined(L_addsub_dd) || defined(L_addsub_td)
+DFP_C_TYPE
+DFP_ADD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ return dfp_binary_op (decNumberAdd, arg_a, arg_b);
+}
+
+DFP_C_TYPE
+DFP_SUB (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ return dfp_binary_op (decNumberSubtract, arg_a, arg_b);
+}
+#endif /* L_addsub */
+
+#if defined(L_mul_sd) || defined(L_mul_dd) || defined(L_mul_td)
+DFP_C_TYPE
+DFP_MULTIPLY (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ return dfp_binary_op (decNumberMultiply, arg_a, arg_b);
+}
+#endif /* L_mul */
+
+#if defined(L_div_sd) || defined(L_div_dd) || defined(L_div_td)
+DFP_C_TYPE
+DFP_DIVIDE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ return dfp_binary_op (decNumberDivide, arg_a, arg_b);
+}
+#endif /* L_div */
+
+#if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
+CMPtype
+DFP_EQ (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For EQ return zero for true, nonzero for false. */
+ return stat != 0;
+}
+#endif /* L_eq */
+
+#if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
+CMPtype
+DFP_NE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For NE return nonzero for true, zero for false. */
+ return stat != 0;
+}
+#endif /* L_ne */
+
+#if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
+CMPtype
+DFP_LT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For LT return -1 (<0) for true, 1 for false. */
+ return (stat == -1) ? -1 : 1;
+}
+#endif /* L_lt */
+
+#if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
+CMPtype
+DFP_GT (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For GT return 1 (>0) for true, -1 for false. */
+ return (stat == 1) ? 1 : -1;
+}
+#endif
+
+#if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
+CMPtype
+DFP_LE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For LE return 0 (<= 0) for true, 1 for false. */
+ return stat == 1;
+}
+#endif /* L_le */
+
+#if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
+CMPtype
+DFP_GE (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ int stat;
+ stat = dfp_compare_op (decNumberCompare, arg_a, arg_b);
+ /* For GE return 1 (>=0) for true, -1 for false. */
+ return (stat != -1) ? 1 : -1;
+}
+#endif /* L_ge */
+
+#define BUFMAX 128
+
+#if defined (L_sd_to_dd) || defined (L_sd_to_td) || defined (L_dd_to_sd) \
+ || defined (L_dd_to_td) || defined (L_td_to_sd) || defined (L_td_to_dd)
+DFP_C_TYPE_TO
+DFP_TO_DFP (DFP_C_TYPE f_from)
+{
+ DFP_C_TYPE_TO f_to;
+ IEEE_TYPE s_from;
+ IEEE_TYPE_TO s_to;
+ decNumber d;
+ decContext context;
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ HOST_TO_IEEE (f_from, &s_from);
+ TO_INTERNAL (&s_from, &d);
+ TO_ENCODED_TO (&s_to, &d, &context);
+ if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+ DFP_RAISE (DEC_Inexact);
+
+ IEEE_TO_HOST_TO (s_to, &f_to);
+ return f_to;
+}
+#endif
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si) \
+ || defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+ || defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+ || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+INT_TYPE
+DFP_TO_INT (DFP_C_TYPE x)
+{
+ /* decNumber's decimal* types have the same format as C's _Decimal*
+ types, but they have different calling conventions. */
+
+ IEEE_TYPE s;
+ char buf[BUFMAX];
+ char *pos;
+ decNumber qval, n1, n2;
+ decContext context;
+
+ decContextDefault (&context, CONTEXT_INIT);
+ /* Need non-default rounding mode here. */
+ context.round = DEC_ROUND_DOWN;
+
+ HOST_TO_IEEE (x, &s);
+ TO_INTERNAL (&s, &n1);
+ /* Rescale if the exponent is less than zero. */
+ decNumberToIntegralValue (&n2, &n1, &context);
+ /* Get a value to use for the quantize call. */
+ decNumberFromString (&qval, (char *) "1.0", &context);
+ /* Force the exponent to zero. */
+ decNumberQuantize (&n1, &n2, &qval, &context);
+ /* This is based on text in N1107 section 5.1; it might turn out to be
+ undefined behavior instead. */
+ if (context.status & DEC_Invalid_operation)
+ {
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si)
+ if (decNumberIsNegative(&n2))
+ return INT_MIN;
+ else
+ return INT_MAX;
+#elif defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di)
+ if (decNumberIsNegative(&n2))
+ /* Find a defined constant that will work here. */
+ return (-9223372036854775807LL - 1LL);
+ else
+ /* Find a defined constant that will work here. */
+ return 9223372036854775807LL;
+#elif defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi)
+ return UINT_MAX;
+#elif defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+ /* Find a defined constant that will work here. */
+ return 18446744073709551615ULL;
+#endif
+ }
+ /* Get a string, which at this point will not include an exponent. */
+ decNumberToString (&n1, buf);
+ /* Ignore the fractional part. */
+ pos = strchr (buf, '.');
+ if (pos)
+ *pos = 0;
+ /* Use a C library function to convert to the integral type. */
+ return STR_TO_INT (buf, NULL, 10);
+}
+#endif
+
+#if defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td) \
+ || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
+ || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td) \
+ || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+DFP_C_TYPE
+INT_TO_DFP (INT_TYPE i)
+{
+ DFP_C_TYPE f;
+ IEEE_TYPE s;
+ char buf[BUFMAX];
+ decContext context;
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ /* Use a C library function to get a floating point string. */
+ sprintf (buf, INT_FMT ".0", CAST_FOR_FMT(i));
+ /* Convert from the floating point string to a decimal* type. */
+ FROM_STRING (&s, buf, &context);
+ IEEE_TO_HOST (s, &f);
+ if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+ DFP_RAISE (DEC_Inexact);
+ return f;
+}
+#endif
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
+ || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
+ && LIBGCC2_HAS_XF_MODE)
+BFP_TYPE
+DFP_TO_BFP (DFP_C_TYPE f)
+{
+ IEEE_TYPE s;
+ char buf[BUFMAX];
+
+ HOST_TO_IEEE (f, &s);
+ /* Write the value to a string. */
+ TO_STRING (&s, buf);
+ /* Read it as the binary floating point type and return that. */
+ return STR_TO_BFP (buf, NULL);
+}
+#endif
+
+#if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
+ || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
+ || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
+ && LIBGCC2_HAS_XF_MODE)
+DFP_C_TYPE
+BFP_TO_DFP (BFP_TYPE x)
+{
+ DFP_C_TYPE f;
+ IEEE_TYPE s;
+ char buf[BUFMAX];
+ decContext context;
+
+ decContextDefault (&context, CONTEXT_INIT);
+ context.round = CONTEXT_ROUND;
+
+ /* Use a C library function to write the floating point value to a string. */
+#ifdef BFP_VIA_TYPE
+ /* FIXME: Is there a better way to output an XFmode variable in C? */
+ sprintf (buf, BFP_FMT, (BFP_VIA_TYPE) x);
+#else
+ sprintf (buf, BFP_FMT, x);
+#endif
+
+ /* Convert from the floating point string to a decimal* type. */
+ FROM_STRING (&s, buf, &context);
+ IEEE_TO_HOST (s, &f);
+ if (CONTEXT_TRAPS && (context.status & DEC_Inexact) != 0)
+ DFP_RAISE (DEC_Inexact);
+ return f;
+}
+#endif
+
+#if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
+CMPtype
+DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
+{
+ decNumber arg1, arg2;
+ IEEE_TYPE a, b;
+
+ HOST_TO_IEEE (arg_a, &a);
+ HOST_TO_IEEE (arg_b, &b);
+ TO_INTERNAL (&a, &arg1);
+ TO_INTERNAL (&b, &arg2);
+ return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
+}
+#endif /* L_unord_sd || L_unord_dd || L_unord_td */
diff --git a/contrib/gcc/config/dfp-bit.h b/contrib/gcc/config/dfp-bit.h
new file mode 100644
index 0000000..a6c7798
--- /dev/null
+++ b/contrib/gcc/config/dfp-bit.h
@@ -0,0 +1,513 @@
+/* Header file for dfp-bit.c.
+ Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#ifndef _DFPBIT_H
+#define _DFPBIT_H
+
+#include "tconfig.h"
+#include "coretypes.h"
+#include "tm.h"
+
+#ifndef LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
+#endif
+
+#ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#endif
+
+#ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
+#endif
+
+#ifndef LIBGCC2_HAS_XF_MODE
+#define LIBGCC2_HAS_XF_MODE \
+ (BITS_PER_UNIT == 8 && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80)
+#endif
+
+/* Depending on WIDTH, define a number of macros:
+
+ DFP_C_TYPE: type of the arguments to the libgcc functions;
+ (eg _Decimal32)
+
+ IEEE_TYPE: the corresponding (encoded) IEEE754R type;
+ (eg decimal32)
+
+ TO_INTERNAL: the name of the decNumber function to convert an
+ encoded value into the decNumber internal representation;
+
+ TO_ENCODED: the name of the decNumber function to convert an
+ internally represented decNumber into the encoded
+ representation.
+
+ FROM_STRING: the name of the decNumber function to read an
+ encoded value from a string.
+
+ TO_STRING: the name of the decNumber function to write an
+ encoded value to a string. */
+
+#if WIDTH == 32
+#define DFP_C_TYPE _Decimal32
+#define IEEE_TYPE decimal32
+#define HOST_TO_IEEE __host_to_ieee_32
+#define IEEE_TO_HOST __ieee_to_host_32
+#define TO_INTERNAL __decimal32ToNumber
+#define TO_ENCODED __decimal32FromNumber
+#define FROM_STRING __decimal32FromString
+#define TO_STRING __decimal32ToString
+#elif WIDTH == 64
+#define DFP_C_TYPE _Decimal64
+#define IEEE_TYPE decimal64
+#define HOST_TO_IEEE __host_to_ieee_64
+#define IEEE_TO_HOST __ieee_to_host_64
+#define TO_INTERNAL __decimal64ToNumber
+#define TO_ENCODED __decimal64FromNumber
+#define FROM_STRING __decimal64FromString
+#define TO_STRING __decimal64ToString
+#elif WIDTH == 128
+#define DFP_C_TYPE _Decimal128
+#define IEEE_TYPE decimal128
+#define HOST_TO_IEEE __host_to_ieee_128
+#define IEEE_TO_HOST __ieee_to_host_128
+#define TO_INTERNAL __decimal128ToNumber
+#define TO_ENCODED __decimal128FromNumber
+#define FROM_STRING __decimal128FromString
+#define TO_STRING __decimal128ToString
+#else
+#error invalid decimal float word width
+#endif
+
+/* We define __DEC_EVAL_METHOD__ to 2, saying that we evaluate all
+ operations and constants to the range and precision of the _Decimal128
+ type. Make it so. */
+#if WIDTH == 32
+#define CONTEXT_INIT DEC_INIT_DECIMAL32
+#elif WIDTH == 64
+#define CONTEXT_INIT DEC_INIT_DECIMAL64
+#elif WIDTH == 128
+#define CONTEXT_INIT DEC_INIT_DECIMAL128
+#endif
+
+/* Define CONTEXT_ROUND to obtain the current decNumber rounding mode. */
+extern enum rounding __decGetRound (void);
+#define CONTEXT_ROUND __decGetRound ()
+
+extern int __dfp_traps;
+#define CONTEXT_TRAPS __dfp_traps
+#define CONTEXT_ERRORS(context) context.status & DEC_Errors
+extern void __dfp_raise (int);
+#define DFP_RAISE(A) __dfp_raise(A)
+
+/* Conversions between different decimal float types use WIDTH_TO to
+ determine additional macros to define. */
+
+#if defined (L_dd_to_sd) || defined (L_td_to_sd)
+#define WIDTH_TO 32
+#elif defined (L_sd_to_dd) || defined (L_td_to_dd)
+#define WIDTH_TO 64
+#elif defined (L_sd_to_td) || defined (L_dd_to_td)
+#define WIDTH_TO 128
+#endif
+
+/* If WIDTH_TO is defined, define additional macros:
+
+ DFP_C_TYPE_TO: type of the result of dfp to dfp conversion.
+
+ IEEE_TYPE_TO: the corresponding (encoded) IEEE754R type.
+
+ TO_ENCODED_TO: the name of the decNumber function to convert an
+ internally represented decNumber into the encoded representation
+ for the destination. */
+
+#if WIDTH_TO == 32
+#define DFP_C_TYPE_TO _Decimal32
+#define IEEE_TYPE_TO decimal32
+#define TO_ENCODED_TO __decimal32FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_32
+#elif WIDTH_TO == 64
+#define DFP_C_TYPE_TO _Decimal64
+#define IEEE_TYPE_TO decimal64
+#define TO_ENCODED_TO __decimal64FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_64
+#elif WIDTH_TO == 128
+#define DFP_C_TYPE_TO _Decimal128
+#define IEEE_TYPE_TO decimal128
+#define TO_ENCODED_TO __decimal128FromNumber
+#define IEEE_TO_HOST_TO __ieee_to_host_128
+#endif
+
+/* Conversions between decimal float types and integral types use INT_KIND
+ to determine the data type and C functions to use. */
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si) \
+ || defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td)
+#define INT_KIND 1
+#elif defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+ || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td)
+#define INT_KIND 2
+#elif defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+ || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td)
+#define INT_KIND 3
+#elif defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi) \
+ || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+#define INT_KIND 4
+#endif
+
+/* If INT_KIND is defined, define additional macros:
+
+ INT_TYPE: The integer data type.
+
+ INT_FMT: The format string for writing the integer to a string.
+
+ CAST_FOR_FMT: Cast variable of INT_KIND to C type for sprintf.
+ This works for ILP32 and LP64, won't for other type size systems.
+
+ STR_TO_INT: The function to read the integer from a string. */
+
+#if INT_KIND == 1
+#define INT_TYPE SItype
+#define INT_FMT "%d"
+#define CAST_FOR_FMT(A) (int)A
+#define STR_TO_INT strtol
+#elif INT_KIND == 2
+#define INT_TYPE DItype
+#define INT_FMT "%lld"
+#define CAST_FOR_FMT(A) (long long)A
+#define STR_TO_INT strtoll
+#elif INT_KIND == 3
+#define INT_TYPE USItype
+#define INT_FMT "%u"
+#define CAST_FOR_FMT(A) (unsigned int)A
+#define STR_TO_INT strtoul
+#elif INT_KIND == 4
+#define INT_TYPE UDItype
+#define INT_FMT "%llu"
+#define CAST_FOR_FMT(A) (unsigned long long)A
+#define STR_TO_INT strtoull
+#endif
+
+/* Conversions between decimal float types and binary float types use
+ BFP_KIND to determine the data type and C functions to use. */
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td)
+#define BFP_KIND 1
+#elif defined (L_sd_to_df) || defined (L_dd_to_df ) || defined (L_td_to_df) \
+ || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td)
+#define BFP_KIND 2
+#elif defined (L_sd_to_xf) || defined (L_dd_to_xf ) || defined (L_td_to_xf) \
+ || defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)
+#define BFP_KIND 3
+#endif
+
+/* If BFP_KIND is defined, define additional macros:
+
+ BFP_TYPE: The binary floating point data type.
+
+ BFP_FMT: The format string for writing the value to a string.
+
+ STR_TO_BFP: The function to read the value from a string. */
+
+#if BFP_KIND == 1
+/* strtof is declared in <stdlib.h> only for C99. */
+extern float strtof (const char *, char **);
+#define BFP_TYPE SFtype
+#define BFP_FMT "%e"
+#define STR_TO_BFP strtof
+
+#elif BFP_KIND == 2
+#define BFP_TYPE DFtype
+#define BFP_FMT "%e"
+#define STR_TO_BFP strtod
+
+#elif BFP_KIND == 3
+#if LIBGCC2_HAS_XF_MODE
+/* These aren't used if XF mode is not supported. */
+#define BFP_TYPE XFtype
+#define BFP_FMT "%e"
+#define BFP_VIA_TYPE double
+#define STR_TO_BFP strtod
+#endif
+
+#endif /* BFP_KIND */
+
+#if WIDTH == 128 || WIDTH_TO == 128
+#include "decimal128.h"
+#endif
+#if WIDTH == 64 || WIDTH_TO == 64
+#include "decimal64.h"
+#endif
+#if WIDTH == 32 || WIDTH_TO == 32
+#include "decimal32.h"
+#endif
+#include "decNumber.h"
+
+/* Names of arithmetic functions. */
+
+#if WIDTH == 32
+#define DFP_ADD __addsd3
+#define DFP_SUB __subsd3
+#define DFP_MULTIPLY __mulsd3
+#define DFP_DIVIDE __divsd3
+#define DFP_EQ __eqsd2
+#define DFP_NE __nesd2
+#define DFP_LT __ltsd2
+#define DFP_GT __gtsd2
+#define DFP_LE __lesd2
+#define DFP_GE __gesd2
+#define DFP_UNORD __unordsd2
+#elif WIDTH == 64
+#define DFP_ADD __adddd3
+#define DFP_SUB __subdd3
+#define DFP_MULTIPLY __muldd3
+#define DFP_DIVIDE __divdd3
+#define DFP_EQ __eqdd2
+#define DFP_NE __nedd2
+#define DFP_LT __ltdd2
+#define DFP_GT __gtdd2
+#define DFP_LE __ledd2
+#define DFP_GE __gedd2
+#define DFP_UNORD __unorddd2
+#elif WIDTH == 128
+#define DFP_ADD __addtd3
+#define DFP_SUB __subtd3
+#define DFP_MULTIPLY __multd3
+#define DFP_DIVIDE __divtd3
+#define DFP_EQ __eqtd2
+#define DFP_NE __netd2
+#define DFP_LT __lttd2
+#define DFP_GT __gttd2
+#define DFP_LE __letd2
+#define DFP_GE __getd2
+#define DFP_UNORD __unordtd2
+#endif
+
+/* Names of functions to convert between different decimal float types. */
+
+#if WIDTH == 32
+#if WIDTH_TO == 64
+#define DFP_TO_DFP __extendsddd2
+#elif WIDTH_TO == 128
+#define DFP_TO_DFP __extendsdtd2
+#endif
+#elif WIDTH == 64
+#if WIDTH_TO == 32
+#define DFP_TO_DFP __truncddsd2
+#elif WIDTH_TO == 128
+#define DFP_TO_DFP __extendddtd2
+#endif
+#elif WIDTH == 128
+#if WIDTH_TO == 32
+#define DFP_TO_DFP __trunctdsd2
+#elif WIDTH_TO == 64
+#define DFP_TO_DFP __trunctddd2
+#endif
+#endif
+
+/* Names of functions to convert between decimal float and integers. */
+
+#if WIDTH == 32
+#if INT_KIND == 1
+#define INT_TO_DFP __floatsisd
+#define DFP_TO_INT __fixsdsi
+#elif INT_KIND == 2
+#define INT_TO_DFP __floatdisd
+#define DFP_TO_INT __fixsddi
+#elif INT_KIND == 3
+#define INT_TO_DFP __floatunssisd
+#define DFP_TO_INT __fixunssdsi
+#elif INT_KIND == 4
+#define INT_TO_DFP __floatunsdisd
+#define DFP_TO_INT __fixunssddi
+#endif
+#elif WIDTH == 64
+#if INT_KIND == 1
+#define INT_TO_DFP __floatsidd
+#define DFP_TO_INT __fixddsi
+#elif INT_KIND == 2
+#define INT_TO_DFP __floatdidd
+#define DFP_TO_INT __fixdddi
+#elif INT_KIND == 3
+#define INT_TO_DFP __floatunssidd
+#define DFP_TO_INT __fixunsddsi
+#elif INT_KIND == 4
+#define INT_TO_DFP __floatunsdidd
+#define DFP_TO_INT __fixunsdddi
+#endif
+#elif WIDTH == 128
+#if INT_KIND == 1
+#define INT_TO_DFP __floatsitd
+#define DFP_TO_INT __fixtdsi
+#elif INT_KIND == 2
+#define INT_TO_DFP __floatditd
+#define DFP_TO_INT __fixtddi
+#elif INT_KIND == 3
+#define INT_TO_DFP __floatunssitd
+#define DFP_TO_INT __fixunstdsi
+#elif INT_KIND == 4
+#define INT_TO_DFP __floatunsditd
+#define DFP_TO_INT __fixunstddi
+#endif
+#endif
+
+/* Names of functions to convert between decimal float and binary float. */
+
+#if WIDTH == 32
+#if BFP_KIND == 1
+#define BFP_TO_DFP __extendsfsd
+#define DFP_TO_BFP __truncsdsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP __truncdfsd
+#define DFP_TO_BFP __extendsddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP __truncxfsd
+#define DFP_TO_BFP __extendsdxf
+#endif /* BFP_KIND */
+
+#elif WIDTH == 64
+#if BFP_KIND == 1
+#define BFP_TO_DFP __extendsfdd
+#define DFP_TO_BFP __truncddsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP __extenddfdd
+#define DFP_TO_BFP __truncdddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP __truncxfdd
+#define DFP_TO_BFP __extendddxf
+#endif /* BFP_KIND */
+
+#elif WIDTH == 128
+#if BFP_KIND == 1
+#define BFP_TO_DFP __extendsftd
+#define DFP_TO_BFP __trunctdsf
+#elif BFP_KIND == 2
+#define BFP_TO_DFP __extenddftd
+#define DFP_TO_BFP __trunctddf
+#elif BFP_KIND == 3
+#define BFP_TO_DFP __extendxftd
+#define DFP_TO_BFP __trunctdxf
+#endif /* BFP_KIND */
+
+#endif /* WIDTH */
+
+/* Some handy typedefs. */
+
+typedef float SFtype __attribute__ ((mode (SF)));
+typedef float DFtype __attribute__ ((mode (DF)));
+#if LIBGCC2_HAS_XF_MODE
+typedef float XFtype __attribute__ ((mode (XF)));
+#endif /* LIBGCC2_HAS_XF_MODE */
+
+typedef int SItype __attribute__ ((mode (SI)));
+typedef int DItype __attribute__ ((mode (DI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef unsigned int UDItype __attribute__ ((mode (DI)));
+
+/* The type of the result of a decimal float comparison. This must
+ match `word_mode' in GCC for the target. */
+
+typedef int CMPtype __attribute__ ((mode (word)));
+
+/* Prototypes. */
+
+#if defined (L_mul_sd) || defined (L_mul_dd) || defined (L_mul_td)
+extern DFP_C_TYPE DFP_MULTIPLY (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_div_sd) || defined (L_div_dd) || defined (L_div_td)
+extern DFP_C_TYPE DFP_DIVIDE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_addsub_sd) || defined (L_addsub_dd) || defined (L_addsub_td)
+extern DFP_C_TYPE DFP_ADD (DFP_C_TYPE, DFP_C_TYPE);
+extern DFP_C_TYPE DFP_SUB (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_eq_sd) || defined (L_eq_dd) || defined (L_eq_td)
+extern CMPtype DFP_EQ (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_ne_sd) || defined (L_ne_dd) || defined (L_ne_td)
+extern CMPtype DFP_NE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_lt_sd) || defined (L_lt_dd) || defined (L_lt_td)
+extern CMPtype DFP_LT (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_gt_sd) || defined (L_gt_dd) || defined (L_gt_td)
+extern CMPtype DFP_GT (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_le_sd) || defined (L_le_dd) || defined (L_le_td)
+extern CMPtype DFP_LE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_ge_sd) || defined (L_ge_dd) || defined (L_ge_td)
+extern CMPtype DFP_GE (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_unord_sd) || defined (L_unord_dd) || defined (L_unord_td)
+extern CMPtype DFP_UNORD (DFP_C_TYPE, DFP_C_TYPE);
+#endif
+
+#if defined (L_sd_to_dd) || defined (L_sd_to_td) || defined (L_dd_to_sd) \
+ || defined (L_dd_to_td) || defined (L_td_to_sd) || defined (L_td_to_dd)
+extern DFP_C_TYPE_TO DFP_TO_DFP (DFP_C_TYPE);
+#endif
+
+#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si) \
+ || defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di) \
+ || defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi) \
+ || defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
+extern INT_TYPE DFP_TO_INT (DFP_C_TYPE);
+#endif
+
+#if defined (L_si_to_sd) || defined (L_si_to_dd) || defined (L_si_to_td) \
+ || defined (L_di_to_sd) || defined (L_di_to_dd) || defined (L_di_to_td) \
+ || defined (L_usi_to_sd) || defined (L_usi_to_dd) || defined (L_usi_to_td) \
+ || defined (L_udi_to_sd) || defined (L_udi_to_dd) || defined (L_udi_to_td)
+extern DFP_C_TYPE INT_TO_DFP (INT_TYPE);
+#endif
+
+#if defined (L_sd_to_sf) || defined (L_dd_to_sf) || defined (L_td_to_sf) \
+ || defined (L_sd_to_df) || defined (L_dd_to_df) || defined (L_td_to_df) \
+ || ((defined (L_sd_to_xf) || defined (L_dd_to_xf) || defined (L_td_to_xf)) \
+ && LIBGCC2_HAS_XF_MODE)
+extern BFP_TYPE DFP_TO_BFP (DFP_C_TYPE);
+#endif
+
+#if defined (L_sf_to_sd) || defined (L_sf_to_dd) || defined (L_sf_to_td) \
+ || defined (L_df_to_sd) || defined (L_df_to_dd) || defined (L_df_to_td) \
+ || ((defined (L_xf_to_sd) || defined (L_xf_to_dd) || defined (L_xf_to_td)) \
+ && LIBGCC2_HAS_XF_MODE)
+extern DFP_C_TYPE BFP_TO_DFP (BFP_TYPE);
+#endif
+
+#endif /* _DFPBIT_H */
diff --git a/contrib/gcc/config/elfos.h b/contrib/gcc/config/elfos.h
index 6a138f9..a2bd49f 100644
--- a/contrib/gcc/config/elfos.h
+++ b/contrib/gcc/config/elfos.h
@@ -1,6 +1,6 @@
/* elfos.h -- operating system specific defines to be used when
targeting GCC for some generic ELF system
- Copyright (C) 1991, 1994, 1995, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1991, 1994, 1995, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
Based on svr4.h contributed by Ron Guilmette (rfg@netcom.com).
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OBJFMT_CPP_BUILTINS() \
do \
@@ -58,10 +58,6 @@ Boston, MA 02111-1307, USA. */
#define PCC_BITFIELD_TYPE_MATTERS 1
#endif
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-
-#define TARGET_MEM_FUNCTIONS
-
/* Handle #pragma weak and #pragma pack. */
#define HANDLE_SYSV_PRAGMA 1
@@ -225,6 +221,8 @@ Boston, MA 02111-1307, USA. */
#define TARGET_ASM_SELECT_RTX_SECTION default_elf_select_rtx_section
#undef TARGET_ASM_SELECT_SECTION
#define TARGET_ASM_SELECT_SECTION default_elf_select_section
+#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS
+#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS true
/* Define the strings used for the special svr4 .type and .size directives.
These strings generally do not vary from one system running svr4 to
@@ -431,14 +429,15 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_ASCII(FILE, STR, LENGTH) \
do \
{ \
- register const unsigned char *_ascii_bytes = \
+ const unsigned char *_ascii_bytes = \
(const unsigned char *) (STR); \
- register const unsigned char *limit = _ascii_bytes + (LENGTH); \
- register unsigned bytes_in_chunk = 0; \
+ const unsigned char *limit = _ascii_bytes + (LENGTH); \
+ const unsigned char *last_null = NULL; \
+ unsigned bytes_in_chunk = 0; \
\
for (; _ascii_bytes < limit; _ascii_bytes++) \
{ \
- register const unsigned char *p; \
+ const unsigned char *p; \
\
if (bytes_in_chunk >= 60) \
{ \
@@ -446,8 +445,14 @@ Boston, MA 02111-1307, USA. */
bytes_in_chunk = 0; \
} \
\
- for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
- continue; \
+ if (_ascii_bytes > last_null) \
+ { \
+ for (p = _ascii_bytes; p < limit && *p != '\0'; p++) \
+ continue; \
+ last_null = p; \
+ } \
+ else \
+ p = last_null; \
\
if (p < limit && (p - _ascii_bytes) <= (long)STRING_LIMIT) \
{ \
diff --git a/contrib/gcc/config/floatunsidf.c b/contrib/gcc/config/floatunsidf.c
new file mode 100644
index 0000000..ff28112
--- /dev/null
+++ b/contrib/gcc/config/floatunsidf.c
@@ -0,0 +1,15 @@
+/* Public domain. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float DFtype __attribute__ ((mode (DF)));
+
+DFtype
+__floatunsidf (USItype u)
+{
+ SItype s = (SItype) u;
+ DFtype r = (DFtype) s;
+ if (s < 0)
+ r += (DFtype)2.0 * (DFtype) ((USItype) 1
+ << (sizeof (USItype) * __CHAR_BIT__ - 1));
+ return r;
+}
diff --git a/contrib/gcc/config/floatunsisf.c b/contrib/gcc/config/floatunsisf.c
new file mode 100644
index 0000000..11d4aa7
--- /dev/null
+++ b/contrib/gcc/config/floatunsisf.c
@@ -0,0 +1,18 @@
+/* Public domain. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float SFtype __attribute__ ((mode (SF)));
+
+SFtype
+__floatunsisf (USItype u)
+{
+ SItype s = (SItype) u;
+ if (s < 0)
+ {
+ /* As in expand_float, compute (u & 1) | (u >> 1) to ensure
+ correct rounding if a nonzero bit is shifted out. */
+ return (SFtype) 2.0 * (SFtype) (SItype) ((u & 1) | (u >> 1));
+ }
+ else
+ return (SFtype) s;
+}
diff --git a/contrib/gcc/config/floatunsitf.c b/contrib/gcc/config/floatunsitf.c
new file mode 100644
index 0000000..955d676
--- /dev/null
+++ b/contrib/gcc/config/floatunsitf.c
@@ -0,0 +1,15 @@
+/* Public domain. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float TFtype __attribute__ ((mode (TF)));
+
+TFtype
+__floatunsitf (USItype u)
+{
+ SItype s = (SItype) u;
+ TFtype r = (TFtype) s;
+ if (s < 0)
+ r += (TFtype)2.0 * (TFtype) ((USItype) 1
+ << (sizeof (USItype) * __CHAR_BIT__ - 1));
+ return r;
+}
diff --git a/contrib/gcc/config/floatunsixf.c b/contrib/gcc/config/floatunsixf.c
new file mode 100644
index 0000000..5251168
--- /dev/null
+++ b/contrib/gcc/config/floatunsixf.c
@@ -0,0 +1,15 @@
+/* Public domain. */
+typedef int SItype __attribute__ ((mode (SI)));
+typedef unsigned int USItype __attribute__ ((mode (SI)));
+typedef float XFtype __attribute__ ((mode (XF)));
+
+XFtype
+__floatunsixf (USItype u)
+{
+ SItype s = (SItype) u;
+ XFtype r = (XFtype) s;
+ if (s < 0)
+ r += (XFtype)2.0 * (XFtype) ((USItype) 1
+ << (sizeof (USItype) * __CHAR_BIT__ - 1));
+ return r;
+}
diff --git a/contrib/gcc/config/fp-bit.c b/contrib/gcc/config/fp-bit.c
index e7556c4..bdf04ff 100644
--- a/contrib/gcc/config/fp-bit.c
+++ b/contrib/gcc/config/fp-bit.c
@@ -1,37 +1,33 @@
/* This is a software floating point library which can be used
for targets without hardware floating point.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003,
+ 2004, 2005 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.
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
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 with other programs, and to distribute
-those programs 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 another program.)
-
-This file is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with this program; 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. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* This implements IEEE 754 format arithmetic, but does not provide a
mechanism for setting the rounding mode, or for generating or handling
@@ -160,14 +156,15 @@ INLINE
static int
isnan ( fp_number_type * x)
{
- return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
+ return __builtin_expect (x->class == CLASS_SNAN || x->class == CLASS_QNAN,
+ 0);
}
INLINE
static int
isinf ( fp_number_type * x)
{
- return x->class == CLASS_INFINITY;
+ return __builtin_expect (x->class == CLASS_INFINITY, 0);
}
#endif /* NO_NANS */
@@ -186,6 +183,22 @@ flip_sign ( fp_number_type * x)
x->sign = !x->sign;
}
+/* Count leading zeroes in N. */
+INLINE
+static int
+clzusi (USItype n)
+{
+ extern int __clzsi2 (USItype);
+ if (sizeof (USItype) == sizeof (unsigned int))
+ return __builtin_clz (n);
+ else if (sizeof (USItype) == sizeof (unsigned long))
+ return __builtin_clzl (n);
+ else if (sizeof (USItype) == sizeof (unsigned long long))
+ return __builtin_clzll (n);
+ else
+ return __clzsi2 (n);
+}
+
extern FLO_type pack_d ( fp_number_type * );
#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
@@ -233,7 +246,7 @@ pack_d ( fp_number_type * src)
}
else
{
- if (src->normal_exp < NORMAL_EXPMIN)
+ if (__builtin_expect (src->normal_exp < NORMAL_EXPMIN, 0))
{
#ifdef NO_DENORMALS
/* Go straight to a zero representation if denormals are not
@@ -280,7 +293,7 @@ pack_d ( fp_number_type * src)
#endif /* NO_DENORMALS */
}
else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
- && src->normal_exp > EXPBIAS)
+ && __builtin_expect (src->normal_exp > EXPBIAS, 0))
{
exp = EXPMAX;
fraction = 0;
@@ -544,7 +557,8 @@ unpack_d (FLO_union_type * src, fp_number_type * dst)
dst->fraction.ll = fraction;
}
}
- else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
+ else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
+ && __builtin_expect (exp == EXPMAX, 0))
{
/* Huge exponent*/
if (fraction == 0)
@@ -633,6 +647,7 @@ _fpadd_parts (fp_number_type * a,
they're the same */
{
int diff;
+ int sdiff;
a_normal_exp = a->normal_exp;
b_normal_exp = b->normal_exp;
@@ -640,21 +655,21 @@ _fpadd_parts (fp_number_type * a,
b_fraction = b->fraction.ll;
diff = a_normal_exp - b_normal_exp;
+ sdiff = diff;
if (diff < 0)
diff = -diff;
if (diff < FRAC_NBITS)
{
- /* ??? This does shifts one bit at a time. Optimize. */
- while (a_normal_exp > b_normal_exp)
+ if (sdiff > 0)
{
- b_normal_exp++;
- LSHIFT (b_fraction);
+ b_normal_exp += diff;
+ LSHIFT (b_fraction, diff);
}
- while (b_normal_exp > a_normal_exp)
+ else if (sdiff < 0)
{
- a_normal_exp++;
- LSHIFT (a_fraction);
+ a_normal_exp += diff;
+ LSHIFT (a_fraction, diff);
}
}
else
@@ -715,7 +730,7 @@ _fpadd_parts (fp_number_type * a,
if (tmp->fraction.ll >= IMPLICIT_2)
{
- LSHIFT (tmp->fraction.ll);
+ LSHIFT (tmp->fraction.ll, 1);
tmp->normal_exp++;
}
return tmp;
@@ -899,32 +914,28 @@ _fpmul_parts ( fp_number_type * a,
high |= 1;
low <<= 1;
}
- /* rounding is tricky. if we only round if it won't make us round later. */
-#if 0
- if (low & FRACHIGH2)
- {
- if (((high & GARDMASK) != GARDMSB)
- && (((high + 1) & GARDMASK) == GARDMSB))
- {
- /* don't round, it gets done again later. */
- }
- else
- {
- high++;
- }
- }
-#endif
+
if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
{
if (high & (1 << NGARDS))
{
- /* half way, so round to even */
- high += GARDROUND + 1;
+ /* Because we're half way, we would round to even by adding
+ GARDROUND + 1, except that's also done in the packing
+ function, and rounding twice will lose precision and cause
+ the result to be too far off. Example: 32-bit floats with
+ bit patterns 0xfff * 0x3f800400 ~= 0xfff (less than 0.5ulp
+ off), not 0x1000 (more than 0.5ulp off). */
}
else if (low)
{
- /* but we really weren't half way */
+ /* We're a further than half way by a small amount corresponding
+ to the bits set in "low". Knowing that, we round here and
+ not in pack_d, because there we don't have "low" available
+ anymore. */
high += GARDROUND + 1;
+
+ /* Avoid further rounding in pack_d. */
+ high &= ~(fractype) GARDMASK;
}
}
tmp->fraction.ll = high;
@@ -951,7 +962,7 @@ multiply (FLO_type arg_a, FLO_type arg_b)
return pack_d (res);
}
-#endif /* L_mul_sf || L_mul_df */
+#endif /* L_mul_sf || L_mul_df || L_mul_tf */
#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
static inline __attribute__ ((__always_inline__)) fp_number_type *
@@ -1028,13 +1039,21 @@ _fpdiv_parts (fp_number_type * a,
{
if (quotient & (1 << NGARDS))
{
- /* half way, so round to even */
- quotient += GARDROUND + 1;
+ /* Because we're half way, we would round to even by adding
+ GARDROUND + 1, except that's also done in the packing
+ function, and rounding twice will lose precision and cause
+ the result to be too far off. */
}
else if (numerator)
{
- /* but we really weren't half way, more bits exist */
+ /* We're a further than half way by the small amount
+ corresponding to the bits set in "numerator". Knowing
+ that, we round here and not in pack_d, because there we
+ don't have "numerator" available anymore. */
quotient += GARDROUND + 1;
+
+ /* Avoid further rounding in pack_d. */
+ quotient &= ~(fractype) GARDMASK;
}
}
@@ -1330,6 +1349,8 @@ si_to_float (SItype arg_a)
}
else
{
+ USItype uarg;
+ int shift;
in.normal_exp = FRACBITS + NGARDS;
if (in.sign)
{
@@ -1339,15 +1360,17 @@ si_to_float (SItype arg_a)
{
return (FLO_type)(- MAX_SI_INT - 1);
}
- in.fraction.ll = (-arg_a);
+ uarg = (-arg_a);
}
else
- in.fraction.ll = arg_a;
+ uarg = arg_a;
- while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+ in.fraction.ll = uarg;
+ shift = clzusi (uarg) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
+ if (shift > 0)
{
- in.fraction.ll <<= 1;
- in.normal_exp -= 1;
+ in.fraction.ll <<= shift;
+ in.normal_exp -= shift;
}
}
return pack_d (&in);
@@ -1367,19 +1390,23 @@ usi_to_float (USItype arg_a)
}
else
{
+ int shift;
in.class = CLASS_NUMBER;
in.normal_exp = FRACBITS + NGARDS;
in.fraction.ll = arg_a;
- while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
- {
- in.fraction.ll >>= 1;
- in.normal_exp += 1;
- }
- while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
+ shift = clzusi (arg_a) - (BITS_PER_SI - 1 - FRACBITS - NGARDS);
+ if (shift < 0)
+ {
+ fractype guard = in.fraction.ll & (((fractype)1 << -shift) - 1);
+ in.fraction.ll >>= -shift;
+ in.fraction.ll |= (guard != 0);
+ in.normal_exp -= shift;
+ }
+ else if (shift > 0)
{
- in.fraction.ll <<= 1;
- in.normal_exp -= 1;
+ in.fraction.ll <<= shift;
+ in.normal_exp -= shift;
}
}
return pack_d (&in);
diff --git a/contrib/gcc/config/fp-bit.h b/contrib/gcc/config/fp-bit.h
index 6221c9e..0f03f87 100644
--- a/contrib/gcc/config/fp-bit.h
+++ b/contrib/gcc/config/fp-bit.h
@@ -1,30 +1,31 @@
/* Header file for fp-bit.c. */
-/* Copyright (C) 2000, 2002, 2003
- Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2002, 2003, 2006 Free Software Foundation, Inc.
This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
-
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* 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. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef GCC_FP_BIT_H
#define GCC_FP_BIT_H
@@ -88,7 +89,9 @@ Boston, MA 02111-1307, USA. */
#endif /* ! FINE_GRAINED_LIBRARIES */
#if __LDBL_MANT_DIG__ == 113 || __LDBL_MANT_DIG__ == 106
-# define TMODES
+# if defined(TFLOAT) || defined(L_sf_to_tf) || defined(L_df_to_tf)
+# define TMODES
+# endif
#endif
typedef float SFtype __attribute__ ((mode (SF)));
@@ -104,9 +107,10 @@ typedef int DItype __attribute__ ((mode (DI)));
typedef int TItype __attribute__ ((mode (TI)));
#endif
-/* The type of the result of a fp compare */
+/* The type of the result of a floating point comparison. This must
+ match `word_mode' in GCC for the target. */
#ifndef CMPtype
-#define CMPtype SItype
+typedef int CMPtype __attribute__ ((mode (word)));
#endif
typedef unsigned int UHItype __attribute__ ((mode (HI)));
@@ -319,7 +323,7 @@ typedef unsigned int UTItype __attribute__ ((mode (TI)));
#endif
/* Preserve the sticky-bit when shifting fractions to the right. */
-#define LSHIFT(a) { a = (a & 1) | (a >> 1); }
+#define LSHIFT(a, s) { a = (a >> s) | !!(a & (((fractype) 1 << s) - 1)); }
/* numeric parameters */
/* F_D_BITOFF is the number of bits offset between the MSB of the mantissa
diff --git a/contrib/gcc/config/freebsd-nthr.h b/contrib/gcc/config/freebsd-nthr.h
index 65add9b..711ce0e 100644
--- a/contrib/gcc/config/freebsd-nthr.h
+++ b/contrib/gcc/config/freebsd-nthr.h
@@ -16,7 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define FBSD_NO_THREADS
diff --git a/contrib/gcc/config/gnu.h b/contrib/gcc/config/gnu.h
index 23a8a73..79c64c7 100644
--- a/contrib/gcc/config/gnu.h
+++ b/contrib/gcc/config/gnu.h
@@ -12,10 +12,6 @@
#undef STANDARD_INCLUDE_DIR
#define STANDARD_INCLUDE_DIR "/include"
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-#undef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-
/* The system headers under GNU are C++-aware. */
#define NO_IMPLICIT_EXTERN_C
diff --git a/contrib/gcc/config/gofast.h b/contrib/gcc/config/gofast.h
index 81dd9f6..67b5c48 100644
--- a/contrib/gcc/config/gofast.h
+++ b/contrib/gcc/config/gofast.h
@@ -1,5 +1,6 @@
/* US Software GOFAST floating point library support.
- Copyright (C) 1994, 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1998, 1999, 2002, 2003, 2004
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* The US Software GOFAST library requires special optabs support.
This file is intended to be included by config/ARCH/ARCH.c. It
diff --git a/contrib/gcc/config/host-darwin.c b/contrib/gcc/config/host-darwin.c
new file mode 100644
index 0000000..d881951
--- /dev/null
+++ b/contrib/gcc/config/host-darwin.c
@@ -0,0 +1,79 @@
+/* Darwin host-specific hook definitions.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include <sys/mman.h>
+#include "toplev.h"
+#include "config/host-darwin.h"
+
+/* Yes, this is really supposed to work. */
+static char pch_address_space[1024*1024*1024] __attribute__((aligned (4096)));
+
+/* Return the address of the PCH address space, if the PCH will fit in it. */
+
+void *
+darwin_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED)
+{
+ if (sz <= sizeof (pch_address_space))
+ return pch_address_space;
+ else
+ return NULL;
+}
+
+/* Check ADDR and SZ for validity, and deallocate (using munmap) that part of
+ pch_address_space beyond SZ. */
+
+int
+darwin_gt_pch_use_address (void *addr, size_t sz, int fd, size_t off)
+{
+ const size_t pagesize = getpagesize();
+ void *mmap_result;
+ int ret;
+
+ gcc_assert ((size_t)pch_address_space % pagesize == 0
+ && sizeof (pch_address_space) % pagesize == 0);
+
+ ret = (addr == pch_address_space && sz <= sizeof (pch_address_space));
+ if (! ret)
+ sz = 0;
+
+ /* Round the size to a whole page size. Normally this is a no-op. */
+ sz = (sz + pagesize - 1) / pagesize * pagesize;
+
+ if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0)
+ fatal_error ("couldn't unmap pch_address_space: %m");
+
+ if (ret)
+ {
+ mmap_result = mmap (addr, sz,
+ PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
+ fd, off);
+
+ /* The file might not be mmap-able. */
+ ret = mmap_result != (void *) MAP_FAILED;
+
+ /* Sanity check for broken MAP_FIXED. */
+ gcc_assert (!ret || mmap_result == addr);
+ }
+
+ return ret;
+}
diff --git a/contrib/gcc/config/host-darwin.h b/contrib/gcc/config/host-darwin.h
new file mode 100644
index 0000000..98b2a3f
--- /dev/null
+++ b/contrib/gcc/config/host-darwin.h
@@ -0,0 +1,28 @@
+/* Darwin host-specific hook definitions.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+extern void * darwin_gt_pch_get_address (size_t sz, int fd);
+extern int darwin_gt_pch_use_address (void *addr, size_t sz, int fd,
+ size_t off);
+
+#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
+#define HOST_HOOKS_GT_PCH_GET_ADDRESS darwin_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
+#define HOST_HOOKS_GT_PCH_USE_ADDRESS darwin_gt_pch_use_address
diff --git a/contrib/gcc/config/host-hpux.c b/contrib/gcc/config/host-hpux.c
new file mode 100644
index 0000000..2ca5ba9
--- /dev/null
+++ b/contrib/gcc/config/host-hpux.c
@@ -0,0 +1,136 @@
+/* HP-UX host-specific hook definitions.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include <sys/mman.h>
+#include <unistd.h>
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+
+#ifndef MAP_FAILED
+#define MAP_FAILED (void *)-1L
+#endif
+
+static void *hpux_gt_pch_get_address (size_t, int);
+static int hpux_gt_pch_use_address (void *, size_t, int, size_t);
+
+#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
+#define HOST_HOOKS_GT_PCH_GET_ADDRESS hpux_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
+#define HOST_HOOKS_GT_PCH_USE_ADDRESS hpux_gt_pch_use_address
+
+/* For various ports, try to guess a fixed spot in the vm space
+ that's probably free. */
+#if (defined(__hppa__) || defined(__ia64__)) && defined(__LP64__)
+# define TRY_EMPTY_VM_SPACE 0x8000000000000000
+#elif defined(__hppa__) || defined(__ia64__)
+# define TRY_EMPTY_VM_SPACE 0x60000000
+#else
+# define TRY_EMPTY_VM_SPACE 0
+#endif
+
+/* Determine a location where we might be able to reliably allocate
+ SIZE bytes. FD is the PCH file, though we should return with the
+ file unmapped. */
+
+static void *
+hpux_gt_pch_get_address (size_t size, int fd)
+{
+ void *addr;
+
+ addr = mmap ((void *)TRY_EMPTY_VM_SPACE, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+
+ /* If we failed the map, that means there's *no* free space. */
+ if (addr == (void *) MAP_FAILED)
+ return NULL;
+ /* Unmap the area before returning. */
+ munmap (addr, size);
+
+ return addr;
+}
+
+/* Map SIZE bytes of FD+OFFSET at BASE. Return 1 if we succeeded at
+ mapping the data at BASE, -1 if we couldn't.
+
+ It's not possibly to reliably mmap a file using MAP_PRIVATE to
+ a specific START address on either hpux or linux. First we see
+ if mmap with MAP_PRIVATE works. If it does, we are off to the
+ races. If it doesn't, we try an anonymous private mmap since the
+ kernel is more likely to honor the BASE address in anonymous maps.
+ We then copy the data to the anonymous private map. This assumes
+ of course that we don't need to change the data in the PCH file
+ after it is created.
+
+ This approach obviously causes a performance penalty but there is
+ little else we can do given the current PCH implementation. */
+
+static int
+hpux_gt_pch_use_address (void *base, size_t size, int fd, size_t offset)
+{
+ void *addr;
+
+ /* We're called with size == 0 if we're not planning to load a PCH
+ file at all. This allows the hook to free any static space that
+ we might have allocated at link time. */
+ if (size == 0)
+ return -1;
+
+ /* Try to map the file with MAP_PRIVATE. */
+ addr = mmap (base, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, offset);
+
+ if (addr == base)
+ return 1;
+
+ if (addr != (void *) MAP_FAILED)
+ munmap (addr, size);
+
+ /* Try to make an anonymous private mmap at the desired location. */
+ addr = mmap (base, size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ if (addr != base)
+ {
+ if (addr != (void *) MAP_FAILED)
+ munmap (addr, size);
+ return -1;
+ }
+
+ if (lseek (fd, offset, SEEK_SET) == (off_t)-1)
+ return -1;
+
+ while (size)
+ {
+ ssize_t nbytes;
+
+ nbytes = read (fd, base, MIN (size, SSIZE_MAX));
+ if (nbytes <= 0)
+ return -1;
+ base = (char *) base + nbytes;
+ size -= nbytes;
+ }
+
+ return 1;
+}
+
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/host-linux.c b/contrib/gcc/config/host-linux.c
index d5fea9d..795bb55 100644
--- a/contrib/gcc/config/host-linux.c
+++ b/contrib/gcc/config/host-linux.c
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
diff --git a/contrib/gcc/config/host-solaris.c b/contrib/gcc/config/host-solaris.c
index 4fa7a5b..df5f473 100644
--- a/contrib/gcc/config/host-solaris.c
+++ b/contrib/gcc/config/host-solaris.c
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
diff --git a/contrib/gcc/config/i386/athlon.md b/contrib/gcc/config/i386/athlon.md
index 4ce9a38..6d92b94 100644
--- a/contrib/gcc/config/i386/athlon.md
+++ b/contrib/gcc/config/i386/athlon.md
@@ -123,7 +123,7 @@
(define_cpu_unit "athlon-fmul" "athlon_fp")
(define_cpu_unit "athlon-fstore" "athlon_fp")
(define_reservation "athlon-fany" "(athlon-fstore | athlon-fmul | athlon-fadd)")
-(define_reservation "athlon-faddmul" "(athlon-fmul | athlon-fadd)")
+(define_reservation "athlon-faddmul" "(athlon-fadd | athlon-fmul)")
;; Vector operations usually consume many of pipes.
(define_reservation "athlon-fvector" "(athlon-fadd + athlon-fmul + athlon-fstore)")
@@ -131,26 +131,26 @@
;; Jump instructions are executed in the branch unit completely transparent to us
(define_insn_reservation "athlon_branch" 0
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "ibr"))
"athlon-direct,athlon-ieu")
(define_insn_reservation "athlon_call" 0
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "call,callv"))
"athlon-vector,athlon-ieu")
;; Latency of push operation is 3 cycles, but ESP value is available
;; earlier
(define_insn_reservation "athlon_push" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "push"))
"athlon-direct,athlon-agu,athlon-store")
(define_insn_reservation "athlon_pop" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "pop"))
"athlon-vector,athlon-load,athlon-ieu")
(define_insn_reservation "athlon_pop_k8" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "pop"))
"athlon-double,(athlon-ieu+athlon-load)")
(define_insn_reservation "athlon_leave" 3
@@ -158,13 +158,13 @@
(eq_attr "type" "leave"))
"athlon-vector,(athlon-ieu+athlon-load)")
(define_insn_reservation "athlon_leave_k8" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "leave"))
"athlon-double,(athlon-ieu+athlon-load)")
;; Lea executes in AGU unit with 2 cycles latency.
(define_insn_reservation "athlon_lea" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "lea"))
"athlon-direct,athlon-agu,nothing")
@@ -176,13 +176,13 @@
"athlon-vector,athlon-ieu0,athlon-mult,nothing,nothing,athlon-ieu0")
;; ??? Widening multiply is vector or double.
(define_insn_reservation "athlon_imul_k8_DI" 4
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "imul")
(and (eq_attr "mode" "DI")
(eq_attr "memory" "none,unknown"))))
"athlon-direct0,athlon-ieu0,athlon-mult,nothing,athlon-ieu0")
(define_insn_reservation "athlon_imul_k8" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "imul")
(eq_attr "memory" "none,unknown")))
"athlon-direct0,athlon-ieu0,athlon-mult,athlon-ieu0")
@@ -192,18 +192,18 @@
(eq_attr "memory" "load,both")))
"athlon-vector,athlon-load,athlon-ieu,athlon-mult,nothing,nothing,athlon-ieu")
(define_insn_reservation "athlon_imul_mem_k8_DI" 7
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "imul")
(and (eq_attr "mode" "DI")
(eq_attr "memory" "load,both"))))
"athlon-vector,athlon-load,athlon-ieu,athlon-mult,nothing,athlon-ieu")
(define_insn_reservation "athlon_imul_mem_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "imul")
(eq_attr "memory" "load,both")))
"athlon-vector,athlon-load,athlon-ieu,athlon-mult,athlon-ieu")
-;; Idiv can not execute in parallel with other instructions. Dealing with it
+;; Idiv cannot execute in parallel with other instructions. Dealing with it
;; as with short latency vector instruction is good approximation avoiding
;; scheduler from trying too hard to can hide it's latency by overlap with
;; other instructions.
@@ -211,59 +211,59 @@
;; of the other code
(define_insn_reservation "athlon_idiv" 6
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "idiv")
(eq_attr "memory" "none,unknown")))
"athlon-vector,(athlon-ieu0*6+(athlon-fpsched,athlon-fvector))")
(define_insn_reservation "athlon_idiv_mem" 9
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "idiv")
(eq_attr "memory" "load,both")))
"athlon-vector,((athlon-load,athlon-ieu0*6)+(athlon-fpsched,athlon-fvector))")
;; The parallelism of string instructions is not documented. Model it same way
;; as idiv to create smaller automata. This probably does not matter much.
(define_insn_reservation "athlon_str" 6
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "str")
(eq_attr "memory" "load,both,store")))
"athlon-vector,athlon-load,athlon-ieu0*6")
(define_insn_reservation "athlon_idirect" 1
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "direct")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "none,unknown"))))
"athlon-direct,athlon-ieu")
(define_insn_reservation "athlon_ivector" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "none,unknown"))))
"athlon-vector,athlon-ieu,athlon-ieu")
(define_insn_reservation "athlon_idirect_loadmov" 3
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "imov")
(eq_attr "memory" "load")))
"athlon-direct,athlon-load")
(define_insn_reservation "athlon_idirect_load" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "direct")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "load"))))
"athlon-direct,athlon-load,athlon-ieu")
(define_insn_reservation "athlon_ivector_load" 6
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "load"))))
"athlon-vector,athlon-load,athlon-ieu,athlon-ieu")
(define_insn_reservation "athlon_idirect_movstore" 1
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "imov")
(eq_attr "memory" "store")))
"athlon-direct,athlon-agu,athlon-store")
(define_insn_reservation "athlon_idirect_both" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "direct")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "both"))))
@@ -271,7 +271,7 @@
athlon-ieu,athlon-store,
athlon-store")
(define_insn_reservation "athlon_ivector_both" 6
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "both"))))
@@ -280,14 +280,14 @@
athlon-ieu,
athlon-store")
(define_insn_reservation "athlon_idirect_store" 1
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "direct")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "store"))))
"athlon-direct,(athlon-ieu+athlon-agu),
athlon-store")
(define_insn_reservation "athlon_ivector_store" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "unit" "integer,unknown")
(eq_attr "memory" "store"))))
@@ -302,7 +302,7 @@
(eq_attr "mode" "XF"))))
"athlon-vector,athlon-fpload2,athlon-fvector*9")
(define_insn_reservation "athlon_fldxf_k8" 13
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fmov")
(and (eq_attr "memory" "load")
(eq_attr "mode" "XF"))))
@@ -314,7 +314,7 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fany")
(define_insn_reservation "athlon_fld_k8" 2
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fstore")
@@ -326,7 +326,7 @@
(eq_attr "mode" "XF"))))
"athlon-vector,(athlon-fpsched+athlon-agu),(athlon-store2+(athlon-fvector*7))")
(define_insn_reservation "athlon_fstxf_k8" 8
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fmov")
(and (eq_attr "memory" "store,both")
(eq_attr "mode" "XF"))))
@@ -337,16 +337,16 @@
(eq_attr "memory" "store,both")))
"athlon-direct,(athlon-fpsched+athlon-agu),(athlon-fstore+athlon-store)")
(define_insn_reservation "athlon_fst_k8" 2
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fmov")
(eq_attr "memory" "store,both")))
"athlon-direct,(athlon-fpsched+athlon-agu),(athlon-fstore+athlon-store)")
(define_insn_reservation "athlon_fist" 4
- (and (eq_attr "cpu" "athlon,k8")
- (eq_attr "type" "fistp"))
+ (and (eq_attr "cpu" "athlon,k8,generic64")
+ (eq_attr "type" "fistp,fisttp"))
"athlon-direct,(athlon-fpsched+athlon-agu),(athlon-fstore+athlon-store)")
(define_insn_reservation "athlon_fmov" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fmov"))
"athlon-direct,athlon-fpsched,athlon-faddmul")
(define_insn_reservation "athlon_fadd_load" 4
@@ -355,12 +355,12 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_fadd_load_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fop")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_fadd" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fop"))
"athlon-direct,athlon-fpsched,athlon-fadd")
(define_insn_reservation "athlon_fmul_load" 4
@@ -369,16 +369,16 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fmul")
(define_insn_reservation "athlon_fmul_load_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fmul")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fmul")
(define_insn_reservation "athlon_fmul" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fmul"))
"athlon-direct,athlon-fpsched,athlon-fmul")
(define_insn_reservation "athlon_fsgn" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fsgn"))
"athlon-direct,athlon-fpsched,athlon-fmul")
(define_insn_reservation "athlon_fdiv_load" 24
@@ -387,7 +387,7 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fmul")
(define_insn_reservation "athlon_fdiv_load_k8" 13
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fdiv")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fmul")
@@ -396,16 +396,16 @@
(eq_attr "type" "fdiv"))
"athlon-direct,athlon-fpsched,athlon-fmul")
(define_insn_reservation "athlon_fdiv_k8" 11
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "fdiv"))
"athlon-direct,athlon-fpsched,athlon-fmul")
(define_insn_reservation "athlon_fpspc_load" 103
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "fpspc")
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload,athlon-fvector")
(define_insn_reservation "athlon_fpspc" 100
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fpspc"))
"athlon-vector,athlon-fpsched,athlon-fvector")
(define_insn_reservation "athlon_fcmov_load" 7
@@ -418,12 +418,12 @@
(eq_attr "type" "fcmov"))
"athlon-vector,athlon-fpsched,athlon-fvector")
(define_insn_reservation "athlon_fcmov_load_k8" 17
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fcmov")
(eq_attr "memory" "load")))
"athlon-vector,athlon-fploadk8,athlon-fvector")
(define_insn_reservation "athlon_fcmov_k8" 15
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "fcmov"))
"athlon-vector,athlon-fpsched,athlon-fvector")
;; fcomi is vector decoded by uses only one pipe.
@@ -434,13 +434,13 @@
(eq_attr "memory" "load"))))
"athlon-vector,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_fcomi_load_k8" 5
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fcmp")
(and (eq_attr "athlon_decode" "vector")
(eq_attr "memory" "load"))))
"athlon-vector,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_fcomi" 3
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "athlon_decode" "vector")
(eq_attr "type" "fcmp")))
"athlon-vector,athlon-fpsched,athlon-fadd")
@@ -450,18 +450,18 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_fcom_load_k8" 4
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "fcmp")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_fcom" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "fcmp"))
"athlon-direct,athlon-fpsched,athlon-fadd")
;; Never seen by the scheduler because we still don't do post reg-stack
;; scheduling.
;(define_insn_reservation "athlon_fxch" 2
-; (and (eq_attr "cpu" "athlon,k8")
+; (and (eq_attr "cpu" "athlon,k8,generic64")
; (eq_attr "type" "fxch"))
; "athlon-direct,athlon-fpsched,athlon-fany")
@@ -477,8 +477,13 @@
(and (eq_attr "type" "ssemov")
(match_operand:DF 1 "memory_operand" "")))
"athlon-direct,athlon-fploadk8,athlon-fstore")
+(define_insn_reservation "athlon_movsd_load_generic64" 2
+ (and (eq_attr "cpu" "generic64")
+ (and (eq_attr "type" "ssemov")
+ (match_operand:DF 1 "memory_operand" "")))
+ "athlon-double,athlon-fploadk8,(athlon-fstore+athlon-fmul)")
(define_insn_reservation "athlon_movaps_load_k8" 2
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssemov")
(and (eq_attr "mode" "V4SF,V2DF,TI")
(eq_attr "memory" "load"))))
@@ -496,7 +501,7 @@
(eq_attr "memory" "load"))))
"athlon-vector,athlon-fpload,(athlon-fany*2)")
(define_insn_reservation "athlon_movss_load_k8" 1
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssemov")
(and (eq_attr "mode" "SF,DI")
(eq_attr "memory" "load"))))
@@ -507,57 +512,57 @@
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fany")
(define_insn_reservation "athlon_mmxsseld_k8" 2
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "mmxmov,ssemov")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fploadk8,athlon-fstore")
(define_insn_reservation "athlon_mmxssest" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "mmxmov,ssemov")
(and (eq_attr "mode" "V4SF,V2DF,TI")
(eq_attr "memory" "store,both"))))
"athlon-vector,(athlon-fpsched+athlon-agu),((athlon-fstore+athlon-store2)*2)")
(define_insn_reservation "athlon_mmxssest_k8" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "mmxmov,ssemov")
(and (eq_attr "mode" "V4SF,V2DF,TI")
(eq_attr "memory" "store,both"))))
"athlon-double,(athlon-fpsched+athlon-agu),((athlon-fstore+athlon-store2)*2)")
(define_insn_reservation "athlon_mmxssest_short" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "mmxmov,ssemov")
(eq_attr "memory" "store,both")))
"athlon-direct,(athlon-fpsched+athlon-agu),(athlon-fstore+athlon-store)")
-(define_insn_reservation "athlon_movaps" 2
- (and (eq_attr "cpu" "k8")
+(define_insn_reservation "athlon_movaps_k8" 2
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssemov")
(eq_attr "mode" "V4SF,V2DF,TI")))
- "athlon-double,athlon-fpsched,(athlon-faddmul+athlon-faddmul)")
-(define_insn_reservation "athlon_movaps_k8" 2
+ "athlon-double,athlon-fpsched,((athlon-faddmul+athlon-faddmul) | (athlon-faddmul, athlon-faddmul))")
+(define_insn_reservation "athlon_movaps" 2
(and (eq_attr "cpu" "athlon")
(and (eq_attr "type" "ssemov")
(eq_attr "mode" "V4SF,V2DF,TI")))
"athlon-vector,athlon-fpsched,(athlon-faddmul+athlon-faddmul)")
(define_insn_reservation "athlon_mmxssemov" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "mmxmov,ssemov"))
"athlon-direct,athlon-fpsched,athlon-faddmul")
(define_insn_reservation "athlon_mmxmul_load" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "mmxmul")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-fmul")
(define_insn_reservation "athlon_mmxmul" 3
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "mmxmul"))
"athlon-direct,athlon-fpsched,athlon-fmul")
(define_insn_reservation "athlon_mmx_load" 3
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "unit" "mmx")
(eq_attr "memory" "load")))
"athlon-direct,athlon-fpload,athlon-faddmul")
(define_insn_reservation "athlon_mmx" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "unit" "mmx"))
"athlon-direct,athlon-fpsched,athlon-faddmul")
;; SSE operations are handled by the i387 unit as well. The latency
@@ -565,23 +570,23 @@
(define_insn_reservation "athlon_sselog_load" 3
(and (eq_attr "cpu" "athlon")
- (and (eq_attr "type" "sselog")
+ (and (eq_attr "type" "sselog,sselog1")
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload2,(athlon-fmul*2)")
(define_insn_reservation "athlon_sselog_load_k8" 5
- (and (eq_attr "cpu" "k8")
- (and (eq_attr "type" "sselog")
+ (and (eq_attr "cpu" "k8,generic64")
+ (and (eq_attr "type" "sselog,sselog1")
(eq_attr "memory" "load")))
"athlon-double,athlon-fpload2k8,(athlon-fmul*2)")
(define_insn_reservation "athlon_sselog" 3
(and (eq_attr "cpu" "athlon")
- (eq_attr "type" "sselog"))
+ (eq_attr "type" "sselog,sselog1"))
"athlon-vector,athlon-fpsched,athlon-fmul*2")
(define_insn_reservation "athlon_sselog_k8" 3
- (and (eq_attr "cpu" "k8")
- (eq_attr "type" "sselog"))
+ (and (eq_attr "cpu" "k8,generic64")
+ (eq_attr "type" "sselog,sselog1"))
"athlon-double,athlon-fpsched,athlon-fmul")
-;; ??? pcmp executes in addmul, probably not wortwhile to brother about that.
+;; ??? pcmp executes in addmul, probably not worthwhile to bother about that.
(define_insn_reservation "athlon_ssecmp_load" 2
(and (eq_attr "cpu" "athlon")
(and (eq_attr "type" "ssecmp")
@@ -589,13 +594,13 @@
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_ssecmp_load_k8" 4
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssecmp")
(and (eq_attr "mode" "SF,DF,DI,TI")
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_ssecmp" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssecmp")
(eq_attr "mode" "SF,DF,DI,TI")))
"athlon-direct,athlon-fpsched,athlon-fadd")
@@ -605,7 +610,7 @@
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload2,(athlon-fadd*2)")
(define_insn_reservation "athlon_ssecmpvector_load_k8" 5
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssecmp")
(eq_attr "memory" "load")))
"athlon-double,athlon-fpload2k8,(athlon-fadd*2)")
@@ -614,7 +619,7 @@
(eq_attr "type" "ssecmp"))
"athlon-vector,athlon-fpsched,(athlon-fadd*2)")
(define_insn_reservation "athlon_ssecmpvector_k8" 3
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "ssecmp"))
"athlon-double,athlon-fpsched,(athlon-fadd*2)")
(define_insn_reservation "athlon_ssecomi_load" 4
@@ -623,12 +628,12 @@
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_ssecomi_load_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssecomi")
(eq_attr "memory" "load")))
"athlon-vector,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_ssecomi" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(eq_attr "type" "ssecmp"))
"athlon-vector,athlon-fpsched,athlon-fadd")
(define_insn_reservation "athlon_sseadd_load" 4
@@ -638,13 +643,13 @@
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fpload,athlon-fadd")
(define_insn_reservation "athlon_sseadd_load_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "sseadd")
(and (eq_attr "mode" "SF,DF,DI")
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fploadk8,athlon-fadd")
(define_insn_reservation "athlon_sseadd" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "sseadd")
(eq_attr "mode" "SF,DF,DI")))
"athlon-direct,athlon-fpsched,athlon-fadd")
@@ -654,7 +659,7 @@
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload2,(athlon-fadd*2)")
(define_insn_reservation "athlon_sseaddvector_load_k8" 7
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "sseadd")
(eq_attr "memory" "load")))
"athlon-double,athlon-fpload2k8,(athlon-fadd*2)")
@@ -663,7 +668,7 @@
(eq_attr "type" "sseadd"))
"athlon-vector,athlon-fpsched,(athlon-fadd*2)")
(define_insn_reservation "athlon_sseaddvector_k8" 5
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "sseadd"))
"athlon-double,athlon-fpsched,(athlon-fadd*2)")
@@ -673,28 +678,28 @@
;; cvtss2sd
(define_insn_reservation "athlon_ssecvt_cvtss2sd_load_k8" 4
- (and (eq_attr "cpu" "k8,athlon")
+ (and (eq_attr "cpu" "k8,athlon,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "direct")
(and (eq_attr "mode" "DF")
(eq_attr "memory" "load")))))
"athlon-direct,athlon-fploadk8,athlon-fstore")
(define_insn_reservation "athlon_ssecvt_cvtss2sd" 2
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "direct")
(eq_attr "mode" "DF"))))
"athlon-direct,athlon-fpsched,athlon-fstore")
;; cvtps2pd. Model same way the other double decoded FP conversions.
(define_insn_reservation "athlon_ssecvt_cvtps2pd_load_k8" 5
- (and (eq_attr "cpu" "k8,athlon")
+ (and (eq_attr "cpu" "k8,athlon,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "double")
(and (eq_attr "mode" "V2DF,V4SF,TI")
(eq_attr "memory" "load")))))
"athlon-double,athlon-fpload2k8,(athlon-fstore*2)")
(define_insn_reservation "athlon_ssecvt_cvtps2pd_k8" 3
- (and (eq_attr "cpu" "k8,athlon")
+ (and (eq_attr "cpu" "k8,athlon,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "double")
(eq_attr "mode" "V2DF,V4SF,TI"))))
@@ -717,7 +722,7 @@
(eq_attr "memory" "load")))))
"athlon-vector,athlon-fpload,(athlon-fstore*2)")
(define_insn_reservation "athlon_sseicvt_cvtsi2ss_load_k8" 9
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "sseicvt")
(and (eq_attr "athlon_decode" "double")
(and (eq_attr "mode" "SF,DF")
@@ -725,7 +730,7 @@
"athlon-double,athlon-fploadk8,(athlon-fstore*2)")
;; cvtsi2sd reg,reg is double decoded (vector on Athlon)
(define_insn_reservation "athlon_sseicvt_cvtsi2sd_k8" 11
- (and (eq_attr "cpu" "k8,athlon")
+ (and (eq_attr "cpu" "k8,athlon,generic64")
(and (eq_attr "type" "sseicvt")
(and (eq_attr "athlon_decode" "double")
(and (eq_attr "mode" "SF,DF")
@@ -733,7 +738,7 @@
"athlon-double,athlon-fploadk8,athlon-fstore")
;; cvtsi2ss reg, reg is doublepath
(define_insn_reservation "athlon_sseicvt_cvtsi2ss" 14
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "sseicvt")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "mode" "SF,DF")
@@ -741,7 +746,7 @@
"athlon-vector,athlon-fploadk8,(athlon-fvector*2)")
;; cvtsd2ss mem,reg is doublepath, troughput unknown, latency 9
(define_insn_reservation "athlon_ssecvt_cvtsd2ss_load_k8" 9
- (and (eq_attr "cpu" "k8,athlon")
+ (and (eq_attr "cpu" "k8,athlon,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "double")
(and (eq_attr "mode" "SF")
@@ -749,14 +754,14 @@
"athlon-double,athlon-fploadk8,(athlon-fstore*3)")
;; cvtsd2ss reg,reg is vectorpath, troughput unknown, latency 12
(define_insn_reservation "athlon_ssecvt_cvtsd2ss" 12
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "mode" "SF")
(eq_attr "memory" "none")))))
"athlon-vector,athlon-fpsched,(athlon-fvector*3)")
(define_insn_reservation "athlon_ssecvt_cvtpd2ps_load_k8" 8
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "mode" "V4SF,V2DF,TI")
@@ -765,7 +770,7 @@
;; cvtpd2ps mem,reg is vectorpath, troughput unknown, latency 10
;; ??? Why it is fater than cvtsd2ss?
(define_insn_reservation "athlon_ssecvt_cvtpd2ps" 8
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssecvt")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "mode" "V4SF,V2DF,TI")
@@ -773,7 +778,7 @@
"athlon-vector,athlon-fpsched,athlon-fvector*2")
;; cvtsd2si mem,reg is doublepath, troughput 1, latency 9
(define_insn_reservation "athlon_secvt_cvtsX2si_load" 9
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "sseicvt")
(and (eq_attr "athlon_decode" "vector")
(and (eq_attr "mode" "SI,DI")
@@ -788,7 +793,7 @@
(eq_attr "memory" "none")))))
"athlon-vector,athlon-fpsched,athlon-fvector")
(define_insn_reservation "athlon_ssecvt_cvtsX2si_k8" 9
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "sseicvt")
(and (eq_attr "athlon_decode" "double")
(and (eq_attr "mode" "SI,DI")
@@ -803,13 +808,13 @@
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fpload,athlon-fmul")
(define_insn_reservation "athlon_ssemul_load_k8" 6
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssemul")
(and (eq_attr "mode" "SF,DF")
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fploadk8,athlon-fmul")
(define_insn_reservation "athlon_ssemul" 4
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssemul")
(eq_attr "mode" "SF,DF")))
"athlon-direct,athlon-fpsched,athlon-fmul")
@@ -819,7 +824,7 @@
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload2,(athlon-fmul*2)")
(define_insn_reservation "athlon_ssemulvector_load_k8" 7
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssemul")
(eq_attr "memory" "load")))
"athlon-double,athlon-fpload2k8,(athlon-fmul*2)")
@@ -828,7 +833,7 @@
(eq_attr "type" "ssemul"))
"athlon-vector,athlon-fpsched,(athlon-fmul*2)")
(define_insn_reservation "athlon_ssemulvector_k8" 5
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "ssemul"))
"athlon-double,athlon-fpsched,(athlon-fmul*2)")
;; divsd timings. divss is faster
@@ -839,13 +844,13 @@
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fpload,athlon-fmul*17")
(define_insn_reservation "athlon_ssediv_load_k8" 22
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssediv")
(and (eq_attr "mode" "SF,DF")
(eq_attr "memory" "load"))))
"athlon-direct,athlon-fploadk8,athlon-fmul*17")
(define_insn_reservation "athlon_ssediv" 20
- (and (eq_attr "cpu" "athlon,k8")
+ (and (eq_attr "cpu" "athlon,k8,generic64")
(and (eq_attr "type" "ssediv")
(eq_attr "mode" "SF,DF")))
"athlon-direct,athlon-fpsched,athlon-fmul*17")
@@ -855,7 +860,7 @@
(eq_attr "memory" "load")))
"athlon-vector,athlon-fpload2,athlon-fmul*34")
(define_insn_reservation "athlon_ssedivvector_load_k8" 35
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(and (eq_attr "type" "ssediv")
(eq_attr "memory" "load")))
"athlon-double,athlon-fpload2k8,athlon-fmul*34")
@@ -864,6 +869,6 @@
(eq_attr "type" "ssediv"))
"athlon-vector,athlon-fmul*34")
(define_insn_reservation "athlon_ssedivvector_k8" 39
- (and (eq_attr "cpu" "k8")
+ (and (eq_attr "cpu" "k8,generic64")
(eq_attr "type" "ssediv"))
"athlon-double,athlon-fmul*34")
diff --git a/contrib/gcc/config/i386/att.h b/contrib/gcc/config/i386/att.h
index 4ee85ae..28d0f6c 100644
--- a/contrib/gcc/config/i386/att.h
+++ b/contrib/gcc/config/i386/att.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Define the syntax of instructions and addresses. */
diff --git a/contrib/gcc/config/i386/beos-elf.h b/contrib/gcc/config/i386/beos-elf.h
index 50c3926..f1e2cf8 100644
--- a/contrib/gcc/config/i386/beos-elf.h
+++ b/contrib/gcc/config/i386/beos-elf.h
@@ -1,5 +1,6 @@
/* Definitions for Intel x86 running BeOS
- Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (i386 BeOS/ELF)");
@@ -55,6 +56,8 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 16
+#define TARGET_DECLSPEC 1
+
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
@@ -63,13 +66,7 @@ Boston, MA 02111-1307, USA. */
builtin_define ("_X86_"); \
builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
- builtin_define ("__declspec(x)=__attribute__((x))"); \
builtin_assert ("system=beos"); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
@@ -234,8 +231,5 @@ Boston, MA 02111-1307, USA. */
/* BeOS headers are C++-aware (and often use C++). */
#define NO_IMPLICIT_EXTERN_C
-/* Define this macro if in some cases global symbols from one translation
- unit may not be bound to undefined symbols in another translation unit
- without user intervention. For instance, under Microsoft Windows
- symbols must be explicitly imported from shared libraries (DLLs). */
-#define MULTIPLE_SYMBOL_SPACES
+/* BeOS uses explicit import from shared libraries. */
+#define MULTIPLE_SYMBOL_SPACES 1
diff --git a/contrib/gcc/config/i386/biarch64.h b/contrib/gcc/config/i386/biarch64.h
index 532cfe7..46a55b0 100644
--- a/contrib/gcc/config/i386/biarch64.h
+++ b/contrib/gcc/config/i386/biarch64.h
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_64BIT_DEFAULT MASK_64BIT
#define TARGET_BI_ARCH 1
diff --git a/contrib/gcc/config/i386/bsd.h b/contrib/gcc/config/i386/bsd.h
index 905b232e..4c32399 100644
--- a/contrib/gcc/config/i386/bsd.h
+++ b/contrib/gcc/config/i386/bsd.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Use the Sequent Symmetry assembler syntax. */
diff --git a/contrib/gcc/config/i386/constraints.md b/contrib/gcc/config/i386/constraints.md
new file mode 100644
index 0000000..0ab4995
--- /dev/null
+++ b/contrib/gcc/config/i386/constraints.md
@@ -0,0 +1,152 @@
+;; Constraint definitions for IA-32 and x86-64.
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Unused letters:
+;;; B H TU W
+;;; h jk vw z
+
+;; Integer register constraints.
+;; It is not necessary to define 'r' here.
+(define_register_constraint "R" "LEGACY_REGS"
+ "Legacy register---the eight integer registers available on all
+ i386 processors (@code{a}, @code{b}, @code{c}, @code{d},
+ @code{si}, @code{di}, @code{bp}, @code{sp}).")
+
+(define_register_constraint "q" "TARGET_64BIT ? GENERAL_REGS : Q_REGS"
+ "Any register accessible as @code{@var{r}l}. In 32-bit mode, @code{a},
+ @code{b}, @code{c}, and @code{d}; in 64-bit mode, any integer register.")
+
+(define_register_constraint "Q" "Q_REGS"
+ "Any register accessible as @code{@var{r}h}: @code{a}, @code{b},
+ @code{c}, and @code{d}.")
+
+(define_register_constraint "l" "INDEX_REGS"
+ "@internal Any register that can be used as the index in a base+index
+ memory access: that is, any general register except the stack pointer.")
+
+(define_register_constraint "a" "AREG"
+ "The @code{a} register.")
+
+(define_register_constraint "b" "BREG"
+ "The @code{b} register.")
+
+(define_register_constraint "c" "CREG"
+ "The @code{c} register.")
+
+(define_register_constraint "d" "DREG"
+ "The @code{d} register.")
+
+(define_register_constraint "S" "SIREG"
+ "The @code{si} register.")
+
+(define_register_constraint "D" "DIREG"
+ "The @code{di} register.")
+
+(define_register_constraint "A" "AD_REGS"
+ "The @code{a} and @code{d} registers, as a pair (for instructions
+ that return half the result in one and half in the other).")
+
+;; Floating-point register constraints.
+(define_register_constraint "f"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FLOAT_REGS : NO_REGS"
+ "Any 80387 floating-point (stack) register.")
+
+(define_register_constraint "t"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FP_TOP_REG : NO_REGS"
+ "Top of 80387 floating-point stack (@code{%st(0)}).")
+
+(define_register_constraint "u"
+ "TARGET_80387 || TARGET_FLOAT_RETURNS_IN_80387 ? FP_SECOND_REG : NO_REGS"
+ "Second from top of 80387 floating-point stack (@code{%st(1)}).")
+
+;; Vector registers (also used for plain floating point nowadays).
+(define_register_constraint "y" "TARGET_MMX ? MMX_REGS : NO_REGS"
+ "Any MMX register.")
+
+(define_register_constraint "x" "TARGET_SSE ? SSE_REGS : NO_REGS"
+ "Any SSE register.")
+
+(define_register_constraint "Y" "TARGET_SSE2? SSE_REGS : NO_REGS"
+ "@internal Any SSE2 register.")
+
+;; Integer constant constraints.
+(define_constraint "I"
+ "Integer constant in the range 0 @dots{} 31, for 32-bit shifts."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 31")))
+
+(define_constraint "J"
+ "Integer constant in the range 0 @dots{} 63, for 64-bit shifts."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 63")))
+
+(define_constraint "K"
+ "Signed 8-bit integer constant."
+ (and (match_code "const_int")
+ (match_test "ival >= -128 && ival <= 127")))
+
+(define_constraint "L"
+ "@code{0xFF} or @code{0xFFFF}, for andsi as a zero-extending move."
+ (and (match_code "const_int")
+ (match_test "ival == 0xFF || ival == 0xFFFF")))
+
+(define_constraint "M"
+ "0, 1, 2, or 3 (shifts for the @code{lea} instruction)."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 3")))
+
+(define_constraint "N"
+ "Unsigned 8-bit integer constant (for @code{in} and @code{out}
+ instructions)."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 255")))
+
+(define_constraint "O"
+ "@internal Integer constant in the range 0 @dots{} 127, for 128-bit shifts."
+ (and (match_code "const_int")
+ (match_test "ival >= 0 && ival <= 127")))
+
+;; Floating-point constant constraints.
+;; We allow constants even if TARGET_80387 isn't set, because the
+;; stack register converter may need to load 0.0 into the function
+;; value register (top of stack).
+(define_constraint "G"
+ "Standard 80387 floating point constant."
+ (and (match_code "const_double")
+ (match_test "standard_80387_constant_p (op)")))
+
+;; This can theoretically be any mode's CONST0_RTX.
+(define_constraint "C"
+ "Standard SSE floating point constant."
+ (match_test "standard_sse_constant_p (op)"))
+
+;; Constant-or-symbol-reference constraints.
+
+(define_constraint "e"
+ "32-bit signed integer constant, or a symbolic reference known
+ to fit that range (for immediate operands in sign-extending x86-64
+ instructions)."
+ (match_operand 0 "x86_64_immediate_operand"))
+
+(define_constraint "Z"
+ "32-bit unsigned integer constant, or a symbolic reference known
+ to fit that range (for immediate operands in zero-extending x86-64
+ instructions)."
+ (match_operand 0 "x86_64_zext_immediate_operand"))
diff --git a/contrib/gcc/config/i386/crtdll.h b/contrib/gcc/config/i386/crtdll.h
index afdae58..0ef8561 100644
--- a/contrib/gcc/config/i386/crtdll.h
+++ b/contrib/gcc/config/i386/crtdll.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef EXTRA_OS_CPP_BUILTINS
#define EXTRA_OS_CPP_BUILTINS() \
diff --git a/contrib/gcc/config/i386/crtfastmath.c b/contrib/gcc/config/i386/crtfastmath.c
new file mode 100644
index 0000000..5991442
--- /dev/null
+++ b/contrib/gcc/config/i386/crtfastmath.c
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2005 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 with other programs, and to distribute
+ * those programs 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 another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not 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.
+ */
+
+#define MXCSR_DAZ (1 << 6) /* Enable denormals are zero mode */
+#define MXCSR_FTZ (1 << 15) /* Enable flush to zero mode */
+
+#define FXSAVE (1 << 24)
+#define SSE (1 << 25)
+
+static void __attribute__((constructor))
+#ifndef __x86_64__
+/* The i386 ABI only requires 4-byte stack alignment, so this is necessary
+ to make sure the fxsave struct gets correct alignment.
+ See PR27537 and PR28621. */
+__attribute__ ((force_align_arg_pointer))
+#endif
+set_fast_math (void)
+{
+#ifndef __x86_64__
+ /* All 64-bit targets have SSE and DAZ; only check them explicitly
+ for 32-bit ones. */
+ unsigned int eax, ebx, ecx, edx;
+
+ /* See if we can use cpuid. */
+ asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+ "pushl %0; popfl; pushfl; popl %0; popfl"
+ : "=&r" (eax), "=&r" (ebx)
+ : "i" (0x00200000));
+
+ if (((eax ^ ebx) & 0x00200000) == 0)
+ return;
+
+ /* Check the highest input value for eax. */
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (0));
+
+ if (eax == 0)
+ return;
+
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1"
+ : "=a" (eax), "=r" (ebx), "=c" (ecx), "=d" (edx)
+ : "0" (1));
+
+ if (edx & SSE)
+ {
+ unsigned int mxcsr = __builtin_ia32_stmxcsr ();
+
+ mxcsr |= MXCSR_FTZ;
+
+ if (edx & FXSAVE)
+ {
+ /* Check if DAZ is available. */
+ struct
+ {
+ unsigned short int cwd;
+ unsigned short int swd;
+ unsigned short int twd;
+ unsigned short int fop;
+ long int fip;
+ long int fcs;
+ long int foo;
+ long int fos;
+ long int mxcsr;
+ long int mxcsr_mask;
+ long int st_space[32];
+ long int xmm_space[32];
+ long int padding[56];
+ } __attribute__ ((aligned (16))) fxsave;
+
+ __builtin_memset (&fxsave, 0, sizeof (fxsave));
+
+ asm volatile ("fxsave %0" : "=m" (fxsave) : "m" (fxsave));
+
+ if (fxsave.mxcsr_mask & MXCSR_DAZ)
+ mxcsr |= MXCSR_DAZ;
+ }
+
+ __builtin_ia32_ldmxcsr (mxcsr);
+ }
+#else
+ unsigned int mxcsr = __builtin_ia32_stmxcsr ();
+ mxcsr |= MXCSR_DAZ | MXCSR_FTZ;
+ __builtin_ia32_ldmxcsr (mxcsr);
+#endif
+}
diff --git a/contrib/gcc/config/i386/cygming.h b/contrib/gcc/config/i386/cygming.h
index f67e048..957c02e 100644
--- a/contrib/gcc/config/i386/cygming.h
+++ b/contrib/gcc/config/i386/cygming.h
@@ -1,6 +1,7 @@
/* Operating system specific defines to be used when targeting GCC for
hosting on Windows32, using a Unix style C library and tools.
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,50 +18,41 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define DBX_DEBUGGING_INFO 1
#define SDB_DEBUGGING_INFO 1
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-#define TARGET_EXECUTABLE_SUFFIX ".exe"
+#ifdef HAVE_GAS_PE_SECREL32_RELOC
+#define DWARF2_DEBUGGING_INFO 1
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) (write_symbols == DWARF2_DEBUG \
+ ? svr4_dbx_register_map[n] \
+ : dbx_register_map[n])
+
+/* Use section relative relocations for debugging offsets. Unlike
+ other targets that fake this by putting the section VMA at 0, PE
+ won't allow it. */
+#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL, SECTION) \
+ do { \
+ if (SIZE != 4) \
+ abort (); \
+ \
+ fputs ("\t.secrel32\t", FILE); \
+ assemble_name (FILE, LABEL); \
+ } while (0)
+#endif
-#define TARGET_IS_PE_COFF 1
+#define TARGET_EXECUTABLE_SUFFIX ".exe"
#include <stdio.h>
-/* Masks for subtarget switches used by other files. */
-#define MASK_NOP_FUN_DLLIMPORT 0x08000000 /* Ignore dllimport for functions */
-
-/* Used in winnt.c. */
-#define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
-
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{ "cygwin", 0, N_("Use the Cygwin interface") }, \
-{ "no-cygwin", 0, N_("Use the Mingw32 interface") }, \
-{ "windows", 0, N_("Create GUI application") }, \
-{ "no-win32", 0, N_("Don't set Windows defines") }, \
-{ "win32", 0, N_("Set Windows defines") }, \
-{ "console", 0, N_("Create console application") },\
-{ "dll", 0, N_("Generate code for a DLL") }, \
-{ "nop-fun-dllimport", MASK_NOP_FUN_DLLIMPORT, \
- N_("Ignore dllimport for functions") }, \
-{ "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" }, \
-{ "threads", 0, N_("Use Mingw-specific thread support") },
-
#define MAYBE_UWIN_CPP_BUILTINS() /* Nothing. */
-/* 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. */
-
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
@@ -69,13 +61,15 @@ Boston, MA 02111-1307, USA. */
builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
builtin_define ("__fastcall=__attribute__((__fastcall__))"); \
builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
- builtin_define ("__declspec(x)=__attribute__((x))"); \
if (!flag_iso) \
{ \
builtin_define ("_stdcall=__attribute__((__stdcall__))"); \
builtin_define ("_fastcall=__attribute__((__fastcall__))"); \
builtin_define ("_cdecl=__attribute__((__cdecl__))"); \
} \
+ /* Even though linkonce works with static libs, this is needed \
+ to compare typeinfo symbols across dll boundaries. */ \
+ builtin_define ("__GXX_MERGED_TYPEINFO_NAMES=0"); \
MAYBE_UWIN_CPP_BUILTINS (); \
EXTRA_OS_CPP_BUILTINS (); \
} \
@@ -83,7 +77,7 @@ Boston, MA 02111-1307, USA. */
/* Get tree.c to declare a target-specific specialization of
merge_decl_attributes. */
-#define TARGET_DLLIMPORT_DECL_ATTRIBUTES
+#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
/* This macro defines names of additional specifications to put in the specs
that can be used in various specifications like CC1_SPEC. Its definition
@@ -114,52 +108,14 @@ Boston, MA 02111-1307, USA. */
union tree_node;
#define TREE union tree_node *
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_drectve
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- DRECTVE_SECTION_FUNCTION \
- SWITCH_TO_SECTION_FUNCTION
-
-#define DRECTVE_SECTION_FUNCTION \
-void \
-drectve_section (void) \
-{ \
- if (in_section != in_drectve) \
- { \
- fprintf (asm_out_file, "%s\n", "\t.section .drectve\n"); \
- in_section = in_drectve; \
- } \
-}
-void drectve_section (void);
+#define drectve_section() \
+ (fprintf (asm_out_file, "\t.section .drectve\n"), \
+ in_section = NULL)
/* Older versions of gas don't handle 'r' as data.
Explicitly set data flag with 'd'. */
#define READONLY_DATA_SECTION_ASM_OP "\t.section .rdata,\"dr\""
-/* Switch to SECTION (an `enum in_section').
-
- ??? This facility should be provided by GCC proper.
- The problem is that we want to temporarily switch sections in
- ASM_DECLARE_OBJECT_NAME and then switch back to the original section
- afterwards. */
-#define SWITCH_TO_SECTION_FUNCTION \
-void switch_to_section (enum in_section, tree); \
-void \
-switch_to_section (enum in_section section, tree decl) \
-{ \
- switch (section) \
- { \
- case in_text: text_section (); break; \
- case in_data: data_section (); break; \
- case in_readonly_data: readonly_data_section (); break; \
- case in_named: named_section (decl, NULL, 0); break; \
- case in_drectve: drectve_section (); break; \
- default: abort (); break; \
- } \
-}
-
/* Don't allow flag_pic to propagate since gas may produce invalid code
otherwise. */
@@ -168,7 +124,7 @@ switch_to_section (enum in_section section, tree decl) \
do { \
if (flag_pic) \
{ \
- warning ("-f%s ignored for target (all code is position independent)",\
+ warning (0, "-f%s ignored for target (all code is position independent)",\
(flag_pic > 1) ? "PIC" : "pic"); \
flag_pic = 0; \
} \
@@ -191,8 +147,8 @@ do { \
section and we need to set DECL_SECTION_NAME so we do that here.
Note that we can be called twice on the same decl. */
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
+#undef SUBTARGET_ENCODE_SECTION_INFO
+#define SUBTARGET_ENCODE_SECTION_INFO i386_pe_encode_section_info
#undef TARGET_STRIP_NAME_ENCODING
#define TARGET_STRIP_NAME_ENCODING i386_pe_strip_name_encoding_full
@@ -200,6 +156,9 @@ do { \
#undef ASM_OUTPUT_LABELREF
#define ASM_OUTPUT_LABELREF i386_pe_output_labelref
+#undef COMMON_ASM_OP
+#define COMMON_ASM_OP "\t.comm\t"
+
/* Output a common block. */
#undef ASM_OUTPUT_COMMON
#define ASM_OUTPUT_COMMON(STREAM, NAME, SIZE, ROUNDED) \
@@ -247,14 +206,12 @@ do { \
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
-/* Define this macro if in some cases global symbols from one translation
- unit may not be bound to undefined symbols in another translation unit
- without user intervention. For instance, under Microsoft Windows
- symbols must be explicitly imported from shared libraries (DLLs). */
-#define MULTIPLE_SYMBOL_SPACES
+/* Windows uses explicit import from shared libraries. */
+#define MULTIPLE_SYMBOL_SPACES 1
extern void i386_pe_unique_section (TREE, int);
#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
#define SUPPORTS_ONE_ONLY 1
@@ -285,7 +242,7 @@ extern void i386_pe_unique_section (TREE, int);
do \
{ \
if (TREE_CODE (DECL) == FUNCTION_DECL) \
- i386_pe_record_external_function (NAME); \
+ i386_pe_record_external_function ((DECL), (NAME)); \
} \
while (0)
@@ -317,7 +274,7 @@ extern void i386_pe_unique_section (TREE, int);
#define PROFILE_HOOK(LABEL) \
if (MAIN_NAME_P (DECL_NAME (current_function_decl))) \
{ \
- emit_call_insn (gen_rtx (CALL, VOIDmode, \
+ emit_call_insn (gen_rtx_CALL (VOIDmode, \
gen_rtx_MEM (FUNCTION_MODE, \
gen_rtx_SYMBOL_REF (Pmode, "_monstartup")), \
const0_rtx)); \
@@ -333,7 +290,7 @@ extern void i386_pe_unique_section (TREE, int);
/* External function declarations. */
-extern void i386_pe_record_external_function (const char *);
+extern void i386_pe_record_external_function (tree, const char *);
extern void i386_pe_declare_function_type (FILE *, const char *, int);
extern void i386_pe_record_exported_symbol (const char *, int);
extern void i386_pe_file_end (void);
@@ -353,6 +310,16 @@ extern int i386_pe_dllimport_name_p (const char *);
#undef BIGGEST_ALIGNMENT
#define BIGGEST_ALIGNMENT 128
+/* Biggest alignment supported by the object file format of this
+ machine. Use this macro to limit the alignment which can be
+ specified using the `__attribute__ ((aligned (N)))' construct. If
+ not defined, the default value is `BIGGEST_ALIGNMENT'. */
+#undef MAX_OFILE_ALIGNMENT
+/* IMAGE_SCN_ALIGN_8192BYTES is the largest section alignment flag
+ specified in the PECOFF60 spec. Native MS compiler also limits
+ user-specified alignment to 8192 bytes. */
+#define MAX_OFILE_ALIGNMENT (8192 * 8)
+
/* Native complier aligns internal doubles in structures on dword boundaries. */
#undef BIGGEST_FIELD_ALIGNMENT
#define BIGGEST_FIELD_ALIGNMENT 64
@@ -384,6 +351,39 @@ extern int i386_pe_dllimport_name_p (const char *);
ASM_OUTPUT_DEF (STREAM, alias, IDENTIFIER_POINTER (TARGET)); \
} while (0)
+/* GNU as supports weak symbols on PECOFF. */
+#ifdef HAVE_GAS_WEAK
+#define ASM_WEAKEN_LABEL(FILE, NAME) \
+ do \
+ { \
+ fputs ("\t.weak\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputc ('\n', (FILE)); \
+ } \
+ while (0)
+#endif /* HAVE_GAS_WEAK */
+
+/* FIXME: SUPPORTS_WEAK && TARGET_HAVE_NAMED_SECTIONS is true,
+ but for .jcr section to work we also need crtbegin and crtend
+ objects. */
+#define TARGET_USE_JCR_SECTION 0
+
+/* Decide whether it is safe to use a local alias for a virtual function
+ when constructing thunks. */
+#undef TARGET_USE_LOCAL_THUNK_ALIAS_P
+#define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL))
+
+#define SUBTARGET_ATTRIBUTE_TABLE \
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \
+ { "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute }
+
+/* mcount() does not need a counter variable. */
+#undef NO_PROFILE_COUNTERS
+#define NO_PROFILE_COUNTERS 1
+
+#define TARGET_VALID_DLLIMPORT_ATTRIBUTE_P i386_pe_valid_dllimport_attribute_p
+#define TARGET_CXX_ADJUST_CLASS_AT_DEFINITION i386_pe_adjust_class_at_definition
+
#undef TREE
#ifndef BUFSIZ
diff --git a/contrib/gcc/config/i386/cygming.opt b/contrib/gcc/config/i386/cygming.opt
new file mode 100644
index 0000000..d430e08
--- /dev/null
+++ b/contrib/gcc/config/i386/cygming.opt
@@ -0,0 +1,48 @@
+; Cygwin- and MinGW-specific options.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mconsole
+Target RejectNegative
+Create console application
+
+mcygwin
+Target
+Use the Cygwin interface
+
+mdll
+Target RejectNegative
+Generate code for a DLL
+
+mnop-fun-dllimport
+Target Report Var(TARGET_NOP_FUN_DLLIMPORT)
+Ignore dllimport for functions
+
+mthreads
+Target RejectNegative
+Use Mingw-specific thread support
+
+mwin32
+Target
+Set Windows defines
+
+mwindows
+Target
+Create GUI application
diff --git a/contrib/gcc/config/i386/cygwin.asm b/contrib/gcc/config/i386/cygwin.asm
index c8378fa..5b65689 100644
--- a/contrib/gcc/config/i386/cygwin.asm
+++ b/contrib/gcc/config/i386/cygwin.asm
@@ -23,8 +23,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/i386/cygwin.h b/contrib/gcc/config/i386/cygwin.h
index def39f4..a7d5e47 100644
--- a/contrib/gcc/config/i386/cygwin.h
+++ b/contrib/gcc/config/i386/cygwin.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (x86 Cygwin)");
@@ -204,7 +204,7 @@ void mingw_scan (int, const char * const *, char **);
#define GCC_DRIVER_HOST_INITIALIZATION \
do \
{ \
- mingw_scan(argc, argv, (char **) &spec_machine); \
+ mingw_scan(argc, (const char * const *) argv, (char **) &spec_machine); \
} \
while (0)
#else
@@ -224,7 +224,17 @@ do \
add_prefix (&startfile_prefixes,\
concat (standard_startfile_prefix, "w32api", NULL),\
"GCC", PREFIX_PRIORITY_LAST, 0, NULL);\
- mingw_scan(argc, argv, &spec_machine); \
+ mingw_scan(argc, (const char * const *) argv, &spec_machine); \
} \
while (0)
#endif
+
+/* Binutils does not handle weak symbols from dlls correctly. For now,
+ do not use them unnecessarily in gthr-posix.h. */
+#define GTHREAD_USE_WEAK 0
+
+/* Every program on cygwin links against cygwin1.dll which contains
+ the pthread routines. There is no need to explicitly link them
+ and the -pthread flag is not recognized. */
+#undef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS ""
diff --git a/contrib/gcc/config/i386/cygwin1.c b/contrib/gcc/config/i386/cygwin1.c
index 88c44fc..68b38dc 100644
--- a/contrib/gcc/config/i386/cygwin1.c
+++ b/contrib/gcc/config/i386/cygwin1.c
@@ -1,6 +1,6 @@
/* Helper routines for cygwin-specific command-line parsing.
Contributed by Christopher Faylor (cgf@redhat.com)
- Copyright 2003 Free Software Foundation, Inc.
+ Copyright 2003, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
diff --git a/contrib/gcc/config/i386/cygwin2.c b/contrib/gcc/config/i386/cygwin2.c
index 2947f5a..90738a2 100644
--- a/contrib/gcc/config/i386/cygwin2.c
+++ b/contrib/gcc/config/i386/cygwin2.c
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
diff --git a/contrib/gcc/config/i386/darwin-libgcc.10.4.ver b/contrib/gcc/config/i386/darwin-libgcc.10.4.ver
new file mode 100644
index 0000000..aaeb934
--- /dev/null
+++ b/contrib/gcc/config/i386/darwin-libgcc.10.4.ver
@@ -0,0 +1,81 @@
+__Unwind_Backtrace
+__Unwind_DeleteException
+__Unwind_FindEnclosingFunction
+__Unwind_Find_FDE
+__Unwind_ForcedUnwind
+__Unwind_GetCFA
+__Unwind_GetDataRelBase
+__Unwind_GetGR
+__Unwind_GetIP
+__Unwind_GetLanguageSpecificData
+__Unwind_GetRegionStart
+__Unwind_GetTextRelBase
+__Unwind_RaiseException
+__Unwind_Resume
+__Unwind_Resume_or_Rethrow
+__Unwind_SetGR
+__Unwind_SetIP
+___absvdi2
+___absvsi2
+___addvdi3
+___addvsi3
+___ashldi3
+___ashrdi3
+___clear_cache
+___clzdi2
+___clzsi2
+___cmpdi2
+___ctzdi2
+___ctzsi2
+___deregister_frame
+___deregister_frame_info
+___deregister_frame_info_bases
+___divdc3
+___divdi3
+___divsc3
+___divxc3
+___enable_execute_stack
+___ffsdi2
+___fixdfdi
+___fixsfdi
+___fixunsdfdi
+___fixunsdfsi
+___fixunssfdi
+___fixunssfsi
+___fixunsxfdi
+___fixunsxfsi
+___fixxfdi
+___floatdidf
+___floatdisf
+___floatdixf
+___gcc_personality_v0
+___lshrdi3
+___moddi3
+___muldc3
+___muldi3
+___mulsc3
+___mulvdi3
+___mulvsi3
+___mulxc3
+___negdi2
+___negvdi2
+___negvsi2
+___paritydi2
+___paritysi2
+___popcountdi2
+___popcountsi2
+___powidf2
+___powisf2
+___powixf2
+___register_frame
+___register_frame_info
+___register_frame_info_bases
+___register_frame_info_table
+___register_frame_info_table_bases
+___register_frame_table
+___subvdi3
+___subvsi3
+___ucmpdi2
+___udivdi3
+___udivmoddi4
+___umoddi3
diff --git a/contrib/gcc/config/i386/darwin-libgcc.10.5.ver b/contrib/gcc/config/i386/darwin-libgcc.10.5.ver
new file mode 100644
index 0000000..02a0858
--- /dev/null
+++ b/contrib/gcc/config/i386/darwin-libgcc.10.5.ver
@@ -0,0 +1,85 @@
+__Unwind_Backtrace
+__Unwind_DeleteException
+__Unwind_FindEnclosingFunction
+__Unwind_Find_FDE
+__Unwind_ForcedUnwind
+__Unwind_GetCFA
+__Unwind_GetDataRelBase
+__Unwind_GetGR
+__Unwind_GetIP
+__Unwind_GetIPInfo
+__Unwind_GetLanguageSpecificData
+__Unwind_GetRegionStart
+__Unwind_GetTextRelBase
+__Unwind_RaiseException
+__Unwind_Resume
+__Unwind_Resume_or_Rethrow
+__Unwind_SetGR
+__Unwind_SetIP
+___absvdi2
+___absvsi2
+___addvdi3
+___addvsi3
+___ashldi3
+___ashrdi3
+___clear_cache
+___clzdi2
+___clzsi2
+___cmpdi2
+___ctzdi2
+___ctzsi2
+___deregister_frame
+___deregister_frame_info
+___deregister_frame_info_bases
+___divdc3
+___divdi3
+___divsc3
+___divxc3
+___enable_execute_stack
+___ffsdi2
+___fixdfdi
+___fixsfdi
+___fixunsdfdi
+___fixunsdfsi
+___fixunssfdi
+___fixunssfsi
+___fixunsxfdi
+___fixunsxfsi
+___fixxfdi
+___floatdidf
+___floatdisf
+___floatdixf
+___floatundidf
+___floatundisf
+___floatundixf
+___gcc_personality_v0
+___lshrdi3
+___moddi3
+___muldc3
+___muldi3
+___mulsc3
+___mulvdi3
+___mulvsi3
+___mulxc3
+___negdi2
+___negvdi2
+___negvsi2
+___paritydi2
+___paritysi2
+___popcountdi2
+___popcountsi2
+___powidf2
+___powisf2
+___powixf2
+___register_frame
+___register_frame_info
+___register_frame_info_bases
+___register_frame_info_table
+___register_frame_info_table_bases
+___register_frame_table
+___subvdi3
+___subvsi3
+___ucmpdi2
+___udivdi3
+___udivmoddi4
+___umoddi3
diff --git a/contrib/gcc/config/i386/darwin.h b/contrib/gcc/config/i386/darwin.h
index 8246b9e..55b55ab 100644
--- a/contrib/gcc/config/i386/darwin.h
+++ b/contrib/gcc/config/i386/darwin.h
@@ -1,5 +1,5 @@
/* Target definitions for x86 running Darwin.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004, 2005 Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
This file is part of GCC.
@@ -16,44 +16,79 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Enable Mach-O bits in generic x86 code. */
#undef TARGET_MACHO
#define TARGET_MACHO 1
-#define TARGET_VERSION fprintf (stderr, " (i386 Darwin)");
+#define TARGET_VERSION fprintf (stderr, " (i686 Darwin)");
+
+#undef TARGET_64BIT
+#define TARGET_64BIT (target_flags & MASK_64BIT)
+
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __x86_64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
+
+/* Size of the Obj-C jump buffer. */
+#define OBJC_JBLEN ((TARGET_64BIT) ? ((9 * 2) + 3 + 16) : (18))
+
+#undef TARGET_FPMATH_DEFAULT
+#define TARGET_FPMATH_DEFAULT (TARGET_SSE ? FPMATH_SSE : FPMATH_387)
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define ("__i386__"); \
builtin_define ("__LITTLE_ENDIAN__"); \
- builtin_define ("__MACH__"); \
- builtin_define ("__APPLE__"); \
+ darwin_cpp_builtins (pfile); \
} \
while (0)
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+#undef MAX_BITS_PER_WORD
+#define MAX_BITS_PER_WORD 64
+
+#undef FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN
+#define FORCE_PREFERRED_STACK_BOUNDARY_IN_MAIN (0)
+
/* We want -fPIC by default, unless we're using -static to compile for
the kernel or some such. */
#undef CC1_SPEC
-#define CC1_SPEC "%{!static:-fPIC}"
+#define CC1_SPEC "%{!mkernel:%{!static:%{!mdynamic-no-pic:-fPIC}}} \
+ %{g: %{!fno-eliminate-unused-debug-symbols: -feliminate-unused-debug-symbols }}"
-/* Use the following macro for any Darwin/x86-specific command-line option
- translation. */
-#define SUBTARGET_OPTION_TRANSLATE_TABLE
+#undef ASM_SPEC
+#define ASM_SPEC "-arch %(darwin_arch) -force_cpusubtype_ALL"
-#define ASM_SPEC "-arch i386 \
- %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
- %{!Zforce_cpusubtype_ALL:%{mmmx:-force_cpusubtype_ALL}\
- %{msse:-force_cpusubtype_ALL}\
- %{msse2:-force_cpusubtype_ALL}}"
+#define DARWIN_ARCH_SPEC "%{m64:x86_64;:i386}"
+#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC
#undef SUBTARGET_EXTRA_SPECS
-#define SUBTARGET_EXTRA_SPECS \
- { "darwin_arch", "i386" },
+#define SUBTARGET_EXTRA_SPECS \
+ { "darwin_arch", DARWIN_ARCH_SPEC }, \
+ { "darwin_crt2", "" }, \
+ { "darwin_subarch", DARWIN_SUBARCH_SPEC },
+
+/* Use the following macro for any Darwin/x86-specific command-line option
+ translation. */
+#define SUBTARGET_OPTION_TRANSLATE_TABLE \
+ { "", "" }
/* The Darwin assembler mostly follows AT&T syntax. */
#undef ASSEMBLER_DIALECT
@@ -66,6 +101,10 @@ Boston, MA 02111-1307, USA. */
#define SHIFT_DOUBLE_OMITS_COUNT 0
+extern void darwin_x86_file_end (void);
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END darwin_x86_file_end
+
/* Define the syntax of pseudo-ops, labels and comments. */
/* String containing the assembler's comment-starter. */
@@ -75,34 +114,39 @@ Boston, MA 02111-1307, USA. */
/* By default, target has a 80387, uses IEEE compatible arithmetic,
and returns float values in the 387. */
-#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
-
-/* TARGET_DEEP_BRANCH_PREDICTION is incompatible with Mach-O PIC. */
-
-#undef TARGET_DEEP_BRANCH_PREDICTION
-#define TARGET_DEEP_BRANCH_PREDICTION 0
+#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_128BIT_LONG_DOUBLE)
/* For now, disable dynamic-no-pic. We'll need to go through i386.c
with a fine-tooth comb looking for refs to flag_pic! */
#define MASK_MACHO_DYNAMIC_NO_PIC 0
#define TARGET_DYNAMIC_NO_PIC (target_flags & MASK_MACHO_DYNAMIC_NO_PIC)
+#undef GOT_SYMBOL_NAME
+#define GOT_SYMBOL_NAME (machopic_function_base_name ())
+
/* Define the syntax of pseudo-ops, labels and comments. */
#define LPREFIX "L"
+/* These are used by -fbranch-probabilities */
+#define HOT_TEXT_SECTION_NAME "__TEXT,__text,regular,pure_instructions"
+#define UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
+ "__TEXT,__unlikely,regular,pure_instructions"
+
/* Assembler pseudos to introduce constants of various size. */
#define ASM_BYTE_OP "\t.byte\t"
#define ASM_SHORT "\t.word\t"
#define ASM_LONG "\t.long\t"
-/* Darwin as doesn't do ".quad". */
+#define ASM_QUAD "\t.quad\t"
+
+#define SUBTARGET_ENCODE_SECTION_INFO darwin_encode_section_info
#undef ASM_OUTPUT_ALIGN
#define ASM_OUTPUT_ALIGN(FILE,LOG) \
do { if ((LOG) != 0) \
{ \
- if (in_text_section ()) \
+ if (in_section == text_section) \
fprintf (FILE, "\t%s %d,0x90\n", ALIGN_ASM_OP, (LOG)); \
else \
fprintf (FILE, "\t%s %d\n", ALIGN_ASM_OP, (LOG)); \
@@ -129,11 +173,73 @@ Boston, MA 02111-1307, USA. */
#undef FUNCTION_PROFILER
#define FUNCTION_PROFILER(FILE, LABELNO) \
do { \
- if (MACHOPIC_INDIRECT) \
+ if (MACHOPIC_INDIRECT && !TARGET_64BIT) \
{ \
- const char *name = machopic_stub_name ("*mcount"); \
+ const char *name = machopic_mcount_stub_name (); \
fprintf (FILE, "\tcall %s\n", name+1); /* skip '&' */ \
- machopic_validate_stub_or_non_lazy_ptr (name, /*stub:*/1); \
+ machopic_validate_stub_or_non_lazy_ptr (name); \
} \
else fprintf (FILE, "\tcall mcount\n"); \
} while (0)
+
+#define C_COMMON_OVERRIDE_OPTIONS \
+ do { \
+ SUBTARGET_C_COMMON_OVERRIDE_OPTIONS; \
+ } while (0)
+
+/* Darwin on x86_64 uses dwarf-2 by default. */
+#undef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE (TARGET_64BIT ? DWARF2_DEBUG : DBX_DEBUG)
+
+/* Darwin uses the standard DWARF register numbers but the default
+ register numbers for STABS. Fortunately for 64-bit code the
+ default and the standard are the same. */
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+ (TARGET_64BIT ? dbx64_register_map[n] \
+ : write_symbols == DWARF2_DEBUG ? svr4_dbx_register_map[n] \
+ : dbx_register_map[n])
+
+/* Unfortunately, the 32-bit EH information also doesn't use the standard
+ DWARF register numbers. */
+#define DWARF2_FRAME_REG_OUT(n, for_eh) \
+ (! (for_eh) || write_symbols != DWARF2_DEBUG || TARGET_64BIT ? (n) \
+ : (n) == 5 ? 4 \
+ : (n) == 4 ? 5 \
+ : (n) >= 11 && (n) <= 18 ? (n) + 1 \
+ : (n))
+
+#undef REGISTER_TARGET_PRAGMAS
+#define REGISTER_TARGET_PRAGMAS() DARWIN_REGISTER_TARGET_PRAGMAS()
+
+#undef TARGET_SET_DEFAULT_TYPE_ATTRIBUTES
+#define TARGET_SET_DEFAULT_TYPE_ATTRIBUTES darwin_set_default_type_attributes
+
+/* For 64-bit, we need to add 4 because @GOTPCREL is relative to the
+ end of the instruction, but without the 4 we'd only have the right
+ address for the start of the instruction. */
+#undef ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX
+#define ASM_MAYBE_OUTPUT_ENCODED_ADDR_RTX(FILE, ENCODING, SIZE, ADDR, DONE) \
+ if (TARGET_64BIT) \
+ { \
+ if ((SIZE) == 4 && ((ENCODING) & 0x70) == DW_EH_PE_pcrel) \
+ { \
+ fputs (ASM_LONG, FILE); \
+ assemble_name (FILE, XSTR (ADDR, 0)); \
+ fputs ("+4@GOTPCREL", FILE); \
+ goto DONE; \
+ } \
+ } \
+ else \
+ { \
+ if (ENCODING == ASM_PREFERRED_EH_DATA_FORMAT (2, 1)) \
+ { \
+ darwin_non_lazy_pcrel (FILE, ADDR); \
+ goto DONE; \
+ } \
+ }
+
+/* This needs to move since i386 uses the first flag and other flags are
+ used in Mach-O. */
+#undef MACHO_SYMBOL_FLAG_VARIABLE
+#define MACHO_SYMBOL_FLAG_VARIABLE ((SYMBOL_FLAG_MACH_DEP) << 3)
diff --git a/contrib/gcc/config/i386/darwin64.h b/contrib/gcc/config/i386/darwin64.h
new file mode 100644
index 0000000..01686fa
--- /dev/null
+++ b/contrib/gcc/config/i386/darwin64.h
@@ -0,0 +1,35 @@
+/* Target definitions for x86_64 running Darwin.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Contributed by Apple Computer Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (x86_64 Darwin)");
+
+#undef DARWIN_ARCH_SPEC
+#define DARWIN_ARCH_SPEC "%{m32:i386;:x86_64}"
+
+#undef DARWIN_SUBARCH_SPEC
+#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "darwin_arch", DARWIN_ARCH_SPEC }, \
+ { "darwin_crt2", "" }, \
+ { "darwin_subarch", DARWIN_SUBARCH_SPEC },
diff --git a/contrib/gcc/config/i386/djgpp.h b/contrib/gcc/config/i386/djgpp.h
index cee9480..4e9f471 100644
--- a/contrib/gcc/config/i386/djgpp.h
+++ b/contrib/gcc/config/i386/djgpp.h
@@ -1,5 +1,5 @@
/* Configuration for an i386 running MS-DOS with DJGPP.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Support generation of DWARF2 debugging info. */
#define DWARF2_DEBUGGING_INFO 1
@@ -169,26 +169,16 @@ Boston, MA 02111-1307, USA. */
/* Used to be defined in xm-djgpp.h, but moved here for cross-compilers. */
#define LIBSTDCXX "-lstdcxx"
-/* -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)
-
#define TARGET_VERSION fprintf (stderr, " (80386, MS-DOS DJGPP)");
-#undef SUBTARGET_SWITCHES
-#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) \
+ if (TARGET_BNU210) \
{ \
- warning ("-mbnu210 is ignored (option is obsolete)"); \
+ warning (0, "-mbnu210 is ignored (option is obsolete)"); \
} \
} \
while (0)
diff --git a/contrib/gcc/config/i386/djgpp.opt b/contrib/gcc/config/i386/djgpp.opt
new file mode 100644
index 0000000..3ef5da3
--- /dev/null
+++ b/contrib/gcc/config/i386/djgpp.opt
@@ -0,0 +1,26 @@
+; DJGPP-specific options.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+;; -mbnu210 is now ignored and obsolete. It was used to enable support for
+;; weak symbols, and .gnu.linkonce support.
+mbnu210
+Target Var(TARGET_BNU210)
+Ignored (obsolete)
diff --git a/contrib/gcc/config/i386/driver-i386.c b/contrib/gcc/config/i386/driver-i386.c
new file mode 100644
index 0000000..ffcee4e
--- /dev/null
+++ b/contrib/gcc/config/i386/driver-i386.c
@@ -0,0 +1,300 @@
+/* Subroutines for the gcc driver.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include <stdlib.h>
+
+const char *host_detect_local_cpu (int argc, const char **argv);
+
+#ifdef GCC_VERSION
+#define cpuid(num,a,b,c,d) \
+ asm volatile ("xchgl %%ebx, %1; cpuid; xchgl %%ebx, %1" \
+ : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \
+ : "0" (num))
+
+#define bit_CMPXCHG8B (1 << 8)
+#define bit_CMOV (1 << 15)
+#define bit_MMX (1 << 23)
+#define bit_SSE (1 << 25)
+#define bit_SSE2 (1 << 26)
+
+#define bit_SSE3 (1 << 0)
+#define bit_CMPXCHG16B (1 << 13)
+
+#define bit_3DNOW (1 << 31)
+#define bit_3DNOWP (1 << 30)
+#define bit_LM (1 << 29)
+
+/* This will be called by the spec parser in gcc.c when it sees
+ a %:local_cpu_detect(args) construct. Currently it will be called
+ with either "arch" or "tune" as argument depending on if -march=native
+ or -mtune=native is to be substituted.
+
+ It returns a string containing new command line parameters to be
+ put at the place of the above two options, depending on what CPU
+ this is executed. E.g. "-march=k8" on an AMD64 machine
+ for -march=native.
+
+ ARGC and ARGV are set depending on the actual arguments given
+ in the spec. */
+const char *host_detect_local_cpu (int argc, const char **argv)
+{
+ const char *cpu = NULL;
+ enum processor_type processor = PROCESSOR_I386;
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int max_level;
+ unsigned int vendor;
+ unsigned int ext_level;
+ unsigned char has_mmx = 0, has_3dnow = 0, has_3dnowp = 0, has_sse = 0;
+ unsigned char has_sse2 = 0, has_sse3 = 0, has_cmov = 0;
+ unsigned char has_longmode = 0, has_cmpxchg8b = 0;
+ unsigned char is_amd = 0;
+ unsigned int family = 0;
+ bool arch;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "arch") == 0;
+ if (!arch && strcmp (argv[0], "tune"))
+ return NULL;
+
+#ifndef __x86_64__
+ /* See if we can use cpuid. */
+ asm volatile ("pushfl; pushfl; popl %0; movl %0,%1; xorl %2,%0;"
+ "pushl %0; popfl; pushfl; popl %0; popfl"
+ : "=&r" (eax), "=&r" (ebx)
+ : "i" (0x00200000));
+
+ if (((eax ^ ebx) & 0x00200000) == 0)
+ goto done;
+#endif
+
+ processor = PROCESSOR_PENTIUM;
+
+ /* Check the highest input value for eax. */
+ cpuid (0, eax, ebx, ecx, edx);
+ max_level = eax;
+ /* We only look at the first four characters. */
+ vendor = ebx;
+ if (max_level == 0)
+ goto done;
+
+ cpuid (1, eax, ebx, ecx, edx);
+ has_cmpxchg8b = !!(edx & bit_CMPXCHG8B);
+ has_cmov = !!(edx & bit_CMOV);
+ has_mmx = !!(edx & bit_MMX);
+ has_sse = !!(edx & bit_SSE);
+ has_sse2 = !!(edx & bit_SSE2);
+ has_sse3 = !!(ecx & bit_SSE3);
+ /* We don't care for extended family. */
+ family = (eax >> 8) & ~(1 << 4);
+
+ cpuid (0x80000000, eax, ebx, ecx, edx);
+ ext_level = eax;
+ if (ext_level >= 0x80000000)
+ {
+ cpuid (0x80000001, eax, ebx, ecx, edx);
+ has_3dnow = !!(edx & bit_3DNOW);
+ has_3dnowp = !!(edx & bit_3DNOWP);
+ has_longmode = !!(edx & bit_LM);
+ }
+
+ is_amd = vendor == *(unsigned int*)"Auth";
+
+ if (is_amd)
+ {
+ if (has_mmx)
+ processor = PROCESSOR_K6;
+ if (has_3dnowp)
+ processor = PROCESSOR_ATHLON;
+ if (has_sse2 || has_longmode)
+ processor = PROCESSOR_K8;
+ }
+ else
+ {
+ switch (family)
+ {
+ case 5:
+ /* Default is PROCESSOR_PENTIUM. */
+ break;
+ case 6:
+ processor = PROCESSOR_PENTIUMPRO;
+ break;
+ case 15:
+ processor = PROCESSOR_PENTIUM4;
+ break;
+ default:
+ /* We have no idea. Use something reasonable. */
+ if (arch)
+ {
+ if (has_sse3)
+ {
+ if (has_longmode)
+ cpu = "nocona";
+ else
+ cpu = "prescott";
+ }
+ else if (has_sse2)
+ cpu = "pentium4";
+ else if (has_cmov)
+ cpu = "pentiumpro";
+ else if (has_mmx)
+ cpu = "pentium-mmx";
+ else if (has_cmpxchg8b)
+ cpu = "pentium";
+ else
+ cpu = "i386";
+ }
+ else
+ cpu = "generic";
+ goto done;
+ break;
+ }
+ }
+
+ switch (processor)
+ {
+ case PROCESSOR_I386:
+ cpu = "i386";
+ break;
+ case PROCESSOR_I486:
+ cpu = "i486";
+ break;
+ case PROCESSOR_PENTIUM:
+ if (has_mmx)
+ cpu = "pentium-mmx";
+ else
+ cpu = "pentium";
+ break;
+ case PROCESSOR_PENTIUMPRO:
+ if (arch)
+ {
+ if (has_sse3)
+ {
+ if (has_longmode)
+ {
+ /* It is Core 2 Duo. */
+ cpu = "nocona";
+ }
+ else
+ {
+ /* It is Core Duo. */
+ cpu = "prescott";
+ }
+ }
+ else if (has_sse2)
+ {
+ /* It is Pentium M. */
+ cpu = "pentium4";
+ }
+ else if (has_sse)
+ {
+ /* It is Pentium III. */
+ cpu = "pentium3";
+ }
+ else if (has_mmx)
+ {
+ /* It is Pentium II. */
+ cpu = "pentium2";
+ }
+ else
+ {
+ /* Default to Pentium Pro. */
+ cpu = "pentiumpro";
+ }
+ }
+ else
+ {
+ /* For -mtune, we default to -mtune=generic. */
+ cpu = "generic";
+ }
+ break;
+ case PROCESSOR_K6:
+ if (has_3dnow)
+ cpu = "k6-3";
+ else
+ cpu = "k6";
+ break;
+ case PROCESSOR_ATHLON:
+ if (has_sse)
+ cpu = "athlon-4";
+ else
+ cpu = "athlon";
+ break;
+ case PROCESSOR_PENTIUM4:
+ if (has_sse3)
+ {
+ if (has_longmode)
+ cpu = "nocona";
+ else
+ cpu = "prescott";
+ }
+ else
+ cpu = "pentium4";
+ break;
+ case PROCESSOR_K8:
+ cpu = "k8";
+ break;
+ case PROCESSOR_NOCONA:
+ cpu = "nocona";
+ break;
+ case PROCESSOR_GENERIC32:
+ case PROCESSOR_GENERIC64:
+ cpu = "generic";
+ break;
+ default:
+ abort ();
+ break;
+ }
+
+done:
+ return concat ("-m", argv[0], "=", cpu, NULL);
+}
+#else
+/* If we aren't compiling with GCC we just provide a minimal
+ default value. */
+const char *host_detect_local_cpu (int argc, const char **argv)
+{
+ const char *cpu;
+ bool arch;
+
+ if (argc < 1)
+ return NULL;
+
+ arch = strcmp (argv[0], "arch") == 0;
+ if (!arch && strcmp (argv[0], "tune"))
+ return NULL;
+
+ if (arch)
+ {
+ /* FIXME: i386 is wrong for 64bit compiler. How can we tell if
+ we are generating 64bit or 32bit code? */
+ cpu = "i386";
+ }
+ else
+ cpu = "generic";
+
+ return concat ("-m", argv[0], "=", cpu, NULL);
+}
+#endif /* GCC_VERSION */
diff --git a/contrib/gcc/config/i386/emmintrin.h b/contrib/gcc/config/i386/emmintrin.h
index 2869063..d30184b 100644
--- a/contrib/gcc/config/i386/emmintrin.h
+++ b/contrib/gcc/config/i386/emmintrin.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +14,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -25,7 +25,7 @@
Public License. */
/* Implemented from the specification included in the Intel C++ Compiler
- User Guide and Reference, version 8.0. */
+ User Guide and Reference, version 9.0. */
#ifndef _EMMINTRIN_H_INCLUDED
#define _EMMINTRIN_H_INCLUDED
@@ -34,358 +34,395 @@
#include <xmmintrin.h>
/* SSE2 */
-typedef double __v2df __attribute__ ((mode (V2DF)));
-typedef int __v2di __attribute__ ((mode (V2DI)));
-typedef int __v4si __attribute__ ((mode (V4SI)));
-typedef int __v8hi __attribute__ ((mode (V8HI)));
-typedef int __v16qi __attribute__ ((mode (V16QI)));
+typedef double __v2df __attribute__ ((__vector_size__ (16)));
+typedef long long __v2di __attribute__ ((__vector_size__ (16)));
+typedef int __v4si __attribute__ ((__vector_size__ (16)));
+typedef short __v8hi __attribute__ ((__vector_size__ (16)));
+typedef char __v16qi __attribute__ ((__vector_size__ (16)));
+
+/* The Intel API is flexible enough that we must allow aliasing with other
+ vector types, and their scalar components. */
+typedef long long __m128i __attribute__ ((__vector_size__ (16), __may_alias__));
+typedef double __m128d __attribute__ ((__vector_size__ (16), __may_alias__));
/* Create a selector for use with the SHUFPD instruction. */
#define _MM_SHUFFLE2(fp1,fp0) \
(((fp1) << 1) | (fp0))
-#define __m128i __v2di
-#define __m128d __v2df
+/* Create a vector with element 0 as F and the rest zero. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_set_sd (double __F)
+{
+ return __extension__ (__m128d){ __F, 0 };
+}
-/* Create a vector with element 0 as *P and the rest zero. */
-static __inline __m128d
-_mm_load_sd (double const *__P)
+/* Create a vector with both elements equal to F. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_set1_pd (double __F)
{
- return (__m128d) __builtin_ia32_loadsd (__P);
+ return __extension__ (__m128d){ __F, __F };
}
-/* Create a vector with all two elements equal to *P. */
-static __inline __m128d
-_mm_load1_pd (double const *__P)
+static __inline __m128d __attribute__((__always_inline__))
+_mm_set_pd1 (double __F)
{
- __v2df __tmp = __builtin_ia32_loadsd (__P);
- return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,0));
+ return _mm_set1_pd (__F);
}
-static __inline __m128d
-_mm_load_pd1 (double const *__P)
+/* Create a vector with the lower value X and upper value W. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_set_pd (double __W, double __X)
{
- return _mm_load1_pd (__P);
+ return __extension__ (__m128d){ __X, __W };
+}
+
+/* Create a vector with the lower value W and upper value X. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_setr_pd (double __W, double __X)
+{
+ return __extension__ (__m128d){ __W, __X };
+}
+
+/* Create a vector of zeros. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_setzero_pd (void)
+{
+ return __extension__ (__m128d){ 0.0, 0.0 };
+}
+
+/* Sets the low DPFP value of A from the low value of B. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_move_sd (__m128d __A, __m128d __B)
+{
+ return (__m128d) __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
}
/* Load two DPFP values from P. The address must be 16-byte aligned. */
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_load_pd (double const *__P)
{
- return (__m128d) __builtin_ia32_loadapd (__P);
+ return *(__m128d *)__P;
}
/* Load two DPFP values from P. The address need not be 16-byte aligned. */
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_loadu_pd (double const *__P)
{
- return (__m128d) __builtin_ia32_loadupd (__P);
+ return __builtin_ia32_loadupd (__P);
}
-/* Load two DPFP values in reverse order. The address must be aligned. */
-static __inline __m128d
-_mm_loadr_pd (double const *__P)
+/* Create a vector with all two elements equal to *P. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_load1_pd (double const *__P)
{
- __v2df __tmp = __builtin_ia32_loadapd (__P);
- return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,1));
+ return _mm_set1_pd (*__P);
}
-/* Create a vector with element 0 as F and the rest zero. */
-static __inline __m128d
-_mm_set_sd (double __F)
+/* Create a vector with element 0 as *P and the rest zero. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_load_sd (double const *__P)
{
- return (__m128d) __builtin_ia32_loadsd (&__F);
+ return _mm_set_sd (*__P);
}
-/* Create a vector with all two elements equal to F. */
-static __inline __m128d
-_mm_set1_pd (double __F)
+static __inline __m128d __attribute__((__always_inline__))
+_mm_load_pd1 (double const *__P)
{
- __v2df __tmp = __builtin_ia32_loadsd (&__F);
- return (__m128d) __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,0));
+ return _mm_load1_pd (__P);
}
-static __inline __m128d
-_mm_set_pd1 (double __F)
+/* Load two DPFP values in reverse order. The address must be aligned. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_loadr_pd (double const *__P)
{
- return _mm_set1_pd (__F);
+ __m128d __tmp = _mm_load_pd (__P);
+ return __builtin_ia32_shufpd (__tmp, __tmp, _MM_SHUFFLE2 (0,1));
}
-/* Create the vector [Z Y]. */
-static __inline __m128d
-_mm_set_pd (double __Z, double __Y)
+/* Store two DPFP values. The address must be 16-byte aligned. */
+static __inline void __attribute__((__always_inline__))
+_mm_store_pd (double *__P, __m128d __A)
{
- return (__v2df) {__Y, __Z};
+ *(__m128d *)__P = __A;
}
-/* Create the vector [Y Z]. */
-static __inline __m128d
-_mm_setr_pd (double __Z, double __Y)
+/* Store two DPFP values. The address need not be 16-byte aligned. */
+static __inline void __attribute__((__always_inline__))
+_mm_storeu_pd (double *__P, __m128d __A)
{
- return _mm_set_pd (__Y, __Z);
+ __builtin_ia32_storeupd (__P, __A);
}
-/* Create a vector of zeros. */
-static __inline __m128d
-_mm_setzero_pd (void)
+/* Stores the lower DPFP value. */
+static __inline void __attribute__((__always_inline__))
+_mm_store_sd (double *__P, __m128d __A)
{
- return (__m128d) __builtin_ia32_setzeropd ();
+ *__P = __builtin_ia32_vec_ext_v2df (__A, 0);
}
-/* Stores the lower DPFP value. */
-static __inline void
-_mm_store_sd (double *__P, __m128d __A)
+static __inline double __attribute__((__always_inline__))
+_mm_cvtsd_f64 (__m128d __A)
{
- __builtin_ia32_storesd (__P, (__v2df)__A);
+ return __builtin_ia32_vec_ext_v2df (__A, 0);
}
-/* Store the lower DPFP value across two words. */
-static __inline void
-_mm_store1_pd (double *__P, __m128d __A)
+static __inline void __attribute__((__always_inline__))
+_mm_storel_pd (double *__P, __m128d __A)
{
- __v2df __va = (__v2df)__A;
- __v2df __tmp = __builtin_ia32_shufpd (__va, __va, _MM_SHUFFLE2 (0,0));
- __builtin_ia32_storeapd (__P, __tmp);
+ _mm_store_sd (__P, __A);
}
-static __inline void
-_mm_store_pd1 (double *__P, __m128d __A)
+/* Stores the upper DPFP value. */
+static __inline void __attribute__((__always_inline__))
+_mm_storeh_pd (double *__P, __m128d __A)
{
- _mm_store1_pd (__P, __A);
+ *__P = __builtin_ia32_vec_ext_v2df (__A, 1);
}
-/* Store two DPFP values. The address must be 16-byte aligned. */
-static __inline void
-_mm_store_pd (double *__P, __m128d __A)
+/* Store the lower DPFP value across two words.
+ The address must be 16-byte aligned. */
+static __inline void __attribute__((__always_inline__))
+_mm_store1_pd (double *__P, __m128d __A)
{
- __builtin_ia32_storeapd (__P, (__v2df)__A);
+ _mm_store_pd (__P, __builtin_ia32_shufpd (__A, __A, _MM_SHUFFLE2 (0,0)));
}
-/* Store two DPFP values. The address need not be 16-byte aligned. */
-static __inline void
-_mm_storeu_pd (double *__P, __m128d __A)
+static __inline void __attribute__((__always_inline__))
+_mm_store_pd1 (double *__P, __m128d __A)
{
- __builtin_ia32_storeupd (__P, (__v2df)__A);
+ _mm_store1_pd (__P, __A);
}
/* Store two DPFP values in reverse order. The address must be aligned. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_storer_pd (double *__P, __m128d __A)
{
- __v2df __va = (__v2df)__A;
- __v2df __tmp = __builtin_ia32_shufpd (__va, __va, _MM_SHUFFLE2 (0,1));
- __builtin_ia32_storeapd (__P, __tmp);
+ _mm_store_pd (__P, __builtin_ia32_shufpd (__A, __A, _MM_SHUFFLE2 (0,1)));
}
-/* Sets the low DPFP value of A from the low value of B. */
-static __inline __m128d
-_mm_move_sd (__m128d __A, __m128d __B)
+static __inline int __attribute__((__always_inline__))
+_mm_cvtsi128_si32 (__m128i __A)
{
- return (__m128d) __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
+ return __builtin_ia32_vec_ext_v4si ((__v4si)__A, 0);
+}
+
+#ifdef __x86_64__
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvtsi128_si64 (__m128i __A)
+{
+ return __builtin_ia32_vec_ext_v2di ((__v2di)__A, 0);
}
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvtsi128_si64x (__m128i __A)
+{
+ return __builtin_ia32_vec_ext_v2di ((__v2di)__A, 0);
+}
+#endif
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_add_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_addpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_add_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_addsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_sub_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_subpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_sub_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_subsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_mul_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_mulpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_mul_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_mulsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_div_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_divpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_div_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_divsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_sqrt_pd (__m128d __A)
{
return (__m128d)__builtin_ia32_sqrtpd ((__v2df)__A);
}
/* Return pair {sqrt (A[0), B[1]}. */
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_sqrt_sd (__m128d __A, __m128d __B)
{
__v2df __tmp = __builtin_ia32_movsd ((__v2df)__A, (__v2df)__B);
return (__m128d)__builtin_ia32_sqrtsd ((__v2df)__tmp);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_min_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_minpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_min_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_minsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_max_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_maxpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_max_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_maxsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_and_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_andpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_andnot_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_andnpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_or_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_orpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_xor_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_xorpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpeq_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpeqpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmplt_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpltpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmple_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmplepd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpgt_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpgtpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpge_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpgepd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpneq_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpneqpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnlt_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpnltpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnle_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpnlepd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpngt_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpngtpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnge_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpngepd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpord_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpordpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpunord_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpunordpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpeq_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpeqsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmplt_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpltsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmple_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmplesd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpgt_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
@@ -395,7 +432,7 @@ _mm_cmpgt_sd (__m128d __A, __m128d __B)
__A));
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpge_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
@@ -405,25 +442,25 @@ _mm_cmpge_sd (__m128d __A, __m128d __B)
__A));
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpneq_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpneqsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnlt_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpnltsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnle_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpnlesd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpngt_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
@@ -433,7 +470,7 @@ _mm_cmpngt_sd (__m128d __A, __m128d __B)
__A));
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpnge_sd (__m128d __A, __m128d __B)
{
return (__m128d) __builtin_ia32_movsd ((__v2df) __A,
@@ -443,478 +480,397 @@ _mm_cmpnge_sd (__m128d __A, __m128d __B)
__A));
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpord_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpordsd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cmpunord_sd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_cmpunordsd ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comieq_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdeq ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comilt_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdlt ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comile_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdle ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comigt_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdgt ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comige_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdge ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comineq_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_comisdneq ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomieq_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdeq ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomilt_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdlt ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomile_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdle ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomigt_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdgt ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomige_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdge ((__v2df)__A, (__v2df)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomineq_sd (__m128d __A, __m128d __B)
{
return __builtin_ia32_ucomisdneq ((__v2df)__A, (__v2df)__B);
}
-/* Create a vector with element 0 as *P and the rest zero. */
+/* Create a vector of Qi, where i is the element number. */
-static __inline __m128i
-_mm_load_si128 (__m128i const *__P)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set_epi64x (long long __q1, long long __q0)
{
- return (__m128i) __builtin_ia32_loaddqa ((char const *)__P);
+ return __extension__ (__m128i)(__v2di){ __q0, __q1 };
}
-static __inline __m128i
-_mm_loadu_si128 (__m128i const *__P)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set_epi64 (__m64 __q1, __m64 __q0)
{
- return (__m128i) __builtin_ia32_loaddqu ((char const *)__P);
+ return _mm_set_epi64x ((long long)__q1, (long long)__q0);
}
-static __inline __m128i
-_mm_loadl_epi64 (__m128i const *__P)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set_epi32 (int __q3, int __q2, int __q1, int __q0)
{
- return (__m128i) __builtin_ia32_movq2dq (*(unsigned long long *)__P);
+ return __extension__ (__m128i)(__v4si){ __q0, __q1, __q2, __q3 };
}
-static __inline void
-_mm_store_si128 (__m128i *__P, __m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set_epi16 (short __q7, short __q6, short __q5, short __q4,
+ short __q3, short __q2, short __q1, short __q0)
{
- __builtin_ia32_storedqa ((char *)__P, (__v16qi)__B);
+ return __extension__ (__m128i)(__v8hi){
+ __q0, __q1, __q2, __q3, __q4, __q5, __q6, __q7 };
}
-static __inline void
-_mm_storeu_si128 (__m128i *__P, __m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set_epi8 (char __q15, char __q14, char __q13, char __q12,
+ char __q11, char __q10, char __q09, char __q08,
+ char __q07, char __q06, char __q05, char __q04,
+ char __q03, char __q02, char __q01, char __q00)
{
- __builtin_ia32_storedqu ((char *)__P, (__v16qi)__B);
+ return __extension__ (__m128i)(__v16qi){
+ __q00, __q01, __q02, __q03, __q04, __q05, __q06, __q07,
+ __q08, __q09, __q10, __q11, __q12, __q13, __q14, __q15
+ };
}
-static __inline void
-_mm_storel_epi64 (__m128i *__P, __m128i __B)
+/* Set all of the elements of the vector to A. */
+
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set1_epi64x (long long __A)
{
- *(long long *)__P = __builtin_ia32_movdq2q ((__v2di)__B);
+ return _mm_set_epi64x (__A, __A);
}
-static __inline __m64
-_mm_movepi64_pi64 (__m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set1_epi64 (__m64 __A)
{
- return (__m64) __builtin_ia32_movdq2q ((__v2di)__B);
+ return _mm_set_epi64 (__A, __A);
}
-static __inline __m128i
-_mm_move_epi64 (__m128i __A)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set1_epi32 (int __A)
{
- return (__m128i) __builtin_ia32_movq ((__v2di)__A);
+ return _mm_set_epi32 (__A, __A, __A, __A);
}
-/* Create a vector of zeros. */
-static __inline __m128i
-_mm_setzero_si128 (void)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set1_epi16 (short __A)
{
- return (__m128i) __builtin_ia32_setzero128 ();
+ return _mm_set_epi16 (__A, __A, __A, __A, __A, __A, __A, __A);
}
-static __inline __m128i
-_mm_set_epi64 (__m64 __A, __m64 __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_set1_epi8 (char __A)
{
- __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
- __v2di __tmp2 = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__B);
- return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp2, __tmp);
+ return _mm_set_epi8 (__A, __A, __A, __A, __A, __A, __A, __A,
+ __A, __A, __A, __A, __A, __A, __A, __A);
}
-/* Create the vector [Z Y X W]. */
-static __inline __m128i
-_mm_set_epi32 (int __Z, int __Y, int __X, int __W)
+/* Create a vector of Qi, where i is the element number.
+ The parameter order is reversed from the _mm_set_epi* functions. */
+
+static __inline __m128i __attribute__((__always_inline__))
+_mm_setr_epi64 (__m64 __q0, __m64 __q1)
{
- union {
- int __a[4];
- __m128i __v;
- } __u;
+ return _mm_set_epi64 (__q1, __q0);
+}
- __u.__a[0] = __W;
- __u.__a[1] = __X;
- __u.__a[2] = __Y;
- __u.__a[3] = __Z;
+static __inline __m128i __attribute__((__always_inline__))
+_mm_setr_epi32 (int __q0, int __q1, int __q2, int __q3)
+{
+ return _mm_set_epi32 (__q3, __q2, __q1, __q0);
+}
- return __u.__v;
+static __inline __m128i __attribute__((__always_inline__))
+_mm_setr_epi16 (short __q0, short __q1, short __q2, short __q3,
+ short __q4, short __q5, short __q6, short __q7)
+{
+ return _mm_set_epi16 (__q7, __q6, __q5, __q4, __q3, __q2, __q1, __q0);
}
-#ifdef __x86_64__
-/* Create the vector [Z Y]. */
-static __inline __m128i
-_mm_set_epi64x (long long __Z, long long __Y)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_setr_epi8 (char __q00, char __q01, char __q02, char __q03,
+ char __q04, char __q05, char __q06, char __q07,
+ char __q08, char __q09, char __q10, char __q11,
+ char __q12, char __q13, char __q14, char __q15)
{
- union {
- long __a[2];
- __m128i __v;
- } __u;
+ return _mm_set_epi8 (__q15, __q14, __q13, __q12, __q11, __q10, __q09, __q08,
+ __q07, __q06, __q05, __q04, __q03, __q02, __q01, __q00);
+}
- __u.__a[0] = __Y;
- __u.__a[1] = __Z;
+/* Create a vector with element 0 as *P and the rest zero. */
- return __u.__v;
+static __inline __m128i __attribute__((__always_inline__))
+_mm_load_si128 (__m128i const *__P)
+{
+ return *__P;
}
-#endif
-/* Create the vector [S T U V Z Y X W]. */
-static __inline __m128i
-_mm_set_epi16 (short __Z, short __Y, short __X, short __W,
- short __V, short __U, short __T, short __S)
-{
- union {
- short __a[8];
- __m128i __v;
- } __u;
-
- __u.__a[0] = __S;
- __u.__a[1] = __T;
- __u.__a[2] = __U;
- __u.__a[3] = __V;
- __u.__a[4] = __W;
- __u.__a[5] = __X;
- __u.__a[6] = __Y;
- __u.__a[7] = __Z;
-
- return __u.__v;
-}
-
-/* Create the vector [S T U V Z Y X W]. */
-static __inline __m128i
-_mm_set_epi8 (char __Z, char __Y, char __X, char __W,
- char __V, char __U, char __T, char __S,
- char __Z1, char __Y1, char __X1, char __W1,
- char __V1, char __U1, char __T1, char __S1)
-{
- union {
- char __a[16];
- __m128i __v;
- } __u;
-
- __u.__a[0] = __S1;
- __u.__a[1] = __T1;
- __u.__a[2] = __U1;
- __u.__a[3] = __V1;
- __u.__a[4] = __W1;
- __u.__a[5] = __X1;
- __u.__a[6] = __Y1;
- __u.__a[7] = __Z1;
- __u.__a[8] = __S;
- __u.__a[9] = __T;
- __u.__a[10] = __U;
- __u.__a[11] = __V;
- __u.__a[12] = __W;
- __u.__a[13] = __X;
- __u.__a[14] = __Y;
- __u.__a[15] = __Z;
-
- return __u.__v;
-}
-
-static __inline __m128i
-_mm_set1_epi64 (__m64 __A)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_loadu_si128 (__m128i const *__P)
{
- __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
- return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp, __tmp);
+ return (__m128i) __builtin_ia32_loaddqu ((char const *)__P);
}
-static __inline __m128i
-_mm_set1_epi32 (int __A)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_loadl_epi64 (__m128i const *__P)
{
- __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__A);
- return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
+ return _mm_set_epi64 ((__m64)0LL, *(__m64 *)__P);
}
-#ifdef __x86_64__
-static __inline __m128i
-_mm_set1_epi64x (long long __A)
+static __inline void __attribute__((__always_inline__))
+_mm_store_si128 (__m128i *__P, __m128i __B)
{
- __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
- return (__m128i) __builtin_ia32_shufpd ((__v2df)__tmp, (__v2df)__tmp, _MM_SHUFFLE2 (0,0));
+ *__P = __B;
}
-#endif
-static __inline __m128i
-_mm_set1_epi16 (short __A)
+static __inline void __attribute__((__always_inline__))
+_mm_storeu_si128 (__m128i *__P, __m128i __B)
{
- int __Acopy = (unsigned short)__A;
- __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__Acopy);
- __tmp = (__v4si)__builtin_ia32_punpcklwd128 ((__v8hi)__tmp, (__v8hi)__tmp);
- return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
+ __builtin_ia32_storedqu ((char *)__P, (__v16qi)__B);
}
-static __inline __m128i
-_mm_set1_epi8 (char __A)
+static __inline void __attribute__((__always_inline__))
+_mm_storel_epi64 (__m128i *__P, __m128i __B)
{
- int __Acopy = (unsigned char)__A;
- __v4si __tmp = (__v4si)__builtin_ia32_loadd (&__Acopy);
- __tmp = (__v4si)__builtin_ia32_punpcklbw128 ((__v16qi)__tmp, (__v16qi)__tmp);
- __tmp = (__v4si)__builtin_ia32_punpcklbw128 ((__v16qi)__tmp, (__v16qi)__tmp);
- return (__m128i) __builtin_ia32_pshufd ((__v4si)__tmp, _MM_SHUFFLE (0,0,0,0));
-}
-
-static __inline __m128i
-_mm_setr_epi64 (__m64 __A, __m64 __B)
-{
- __v2di __tmp = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__A);
- __v2di __tmp2 = (__v2di)__builtin_ia32_movq2dq ((unsigned long long)__B);
- return (__m128i)__builtin_ia32_punpcklqdq128 (__tmp, __tmp2);
-}
-
-/* Create the vector [Z Y X W]. */
-static __inline __m128i
-_mm_setr_epi32 (int __W, int __X, int __Y, int __Z)
-{
- union {
- int __a[4];
- __m128i __v;
- } __u;
-
- __u.__a[0] = __W;
- __u.__a[1] = __X;
- __u.__a[2] = __Y;
- __u.__a[3] = __Z;
-
- return __u.__v;
-}
-/* Create the vector [S T U V Z Y X W]. */
-static __inline __m128i
-_mm_setr_epi16 (short __S, short __T, short __U, short __V,
- short __W, short __X, short __Y, short __Z)
-{
- union {
- short __a[8];
- __m128i __v;
- } __u;
-
- __u.__a[0] = __S;
- __u.__a[1] = __T;
- __u.__a[2] = __U;
- __u.__a[3] = __V;
- __u.__a[4] = __W;
- __u.__a[5] = __X;
- __u.__a[6] = __Y;
- __u.__a[7] = __Z;
-
- return __u.__v;
-}
-
-/* Create the vector [S T U V Z Y X W]. */
-static __inline __m128i
-_mm_setr_epi8 (char __S1, char __T1, char __U1, char __V1,
- char __W1, char __X1, char __Y1, char __Z1,
- char __S, char __T, char __U, char __V,
- char __W, char __X, char __Y, char __Z)
-{
- union {
- char __a[16];
- __m128i __v;
- } __u;
-
- __u.__a[0] = __S1;
- __u.__a[1] = __T1;
- __u.__a[2] = __U1;
- __u.__a[3] = __V1;
- __u.__a[4] = __W1;
- __u.__a[5] = __X1;
- __u.__a[6] = __Y1;
- __u.__a[7] = __Z1;
- __u.__a[8] = __S;
- __u.__a[9] = __T;
- __u.__a[10] = __U;
- __u.__a[11] = __V;
- __u.__a[12] = __W;
- __u.__a[13] = __X;
- __u.__a[14] = __Y;
- __u.__a[15] = __Z;
-
- return __u.__v;
-}
-
-static __inline __m128d
+ *(long long *)__P = __builtin_ia32_vec_ext_v2di ((__v2di)__B, 0);
+}
+
+static __inline __m64 __attribute__((__always_inline__))
+_mm_movepi64_pi64 (__m128i __B)
+{
+ return (__m64) __builtin_ia32_vec_ext_v2di ((__v2di)__B, 0);
+}
+
+static __inline __m128i __attribute__((__always_inline__))
+_mm_movpi64_epi64 (__m64 __A)
+{
+ return _mm_set_epi64 ((__m64)0LL, __A);
+}
+
+static __inline __m128i __attribute__((__always_inline__))
+_mm_move_epi64 (__m128i __A)
+{
+ return _mm_set_epi64 ((__m64)0LL, _mm_movepi64_pi64 (__A));
+}
+
+/* Create a vector of zeros. */
+static __inline __m128i __attribute__((__always_inline__))
+_mm_setzero_si128 (void)
+{
+ return __extension__ (__m128i)(__v4si){ 0, 0, 0, 0 };
+}
+
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtepi32_pd (__m128i __A)
{
return (__m128d)__builtin_ia32_cvtdq2pd ((__v4si) __A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtepi32_ps (__m128i __A)
{
return (__m128)__builtin_ia32_cvtdq2ps ((__v4si) __A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvtpd_epi32 (__m128d __A)
{
return (__m128i)__builtin_ia32_cvtpd2dq ((__v2df) __A);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtpd_pi32 (__m128d __A)
{
return (__m64)__builtin_ia32_cvtpd2pi ((__v2df) __A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpd_ps (__m128d __A)
{
return (__m128)__builtin_ia32_cvtpd2ps ((__v2df) __A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvttpd_epi32 (__m128d __A)
{
return (__m128i)__builtin_ia32_cvttpd2dq ((__v2df) __A);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvttpd_pi32 (__m128d __A)
{
return (__m64)__builtin_ia32_cvttpd2pi ((__v2df) __A);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtpi32_pd (__m64 __A)
{
return (__m128d)__builtin_ia32_cvtpi2pd ((__v2si) __A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvtps_epi32 (__m128 __A)
{
return (__m128i)__builtin_ia32_cvtps2dq ((__v4sf) __A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvttps_epi32 (__m128 __A)
{
return (__m128i)__builtin_ia32_cvttps2dq ((__v4sf) __A);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtps_pd (__m128 __A)
{
return (__m128d)__builtin_ia32_cvtps2pd ((__v4sf) __A);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvtsd_si32 (__m128d __A)
{
return __builtin_ia32_cvtsd2si ((__v2df) __A);
}
#ifdef __x86_64__
-static __inline long long
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvtsd_si64 (__m128d __A)
+{
+ return __builtin_ia32_cvtsd2si64 ((__v2df) __A);
+}
+
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
_mm_cvtsd_si64x (__m128d __A)
{
return __builtin_ia32_cvtsd2si64 ((__v2df) __A);
}
#endif
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvttsd_si32 (__m128d __A)
{
return __builtin_ia32_cvttsd2si ((__v2df) __A);
}
#ifdef __x86_64__
-static __inline long long
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvttsd_si64 (__m128d __A)
+{
+ return __builtin_ia32_cvttsd2si64 ((__v2df) __A);
+}
+
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
_mm_cvttsd_si64x (__m128d __A)
{
return __builtin_ia32_cvttsd2si64 ((__v2df) __A);
}
#endif
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsd_ss (__m128 __A, __m128d __B)
{
return (__m128)__builtin_ia32_cvtsd2ss ((__v4sf) __A, (__v2df) __B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtsi32_sd (__m128d __A, int __B)
{
return (__m128d)__builtin_ia32_cvtsi2sd ((__v2df) __A, __B);
}
#ifdef __x86_64__
-static __inline __m128d
+/* Intel intrinsic. */
+static __inline __m128d __attribute__((__always_inline__))
+_mm_cvtsi64_sd (__m128d __A, long long __B)
+{
+ return (__m128d)__builtin_ia32_cvtsi642sd ((__v2df) __A, __B);
+}
+
+/* Microsoft intrinsic. */
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtsi64x_sd (__m128d __A, long long __B)
{
return (__m128d)__builtin_ia32_cvtsi642sd ((__v2df) __A, __B);
}
#endif
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_cvtss_sd (__m128d __A, __m128 __B)
{
return (__m128d)__builtin_ia32_cvtss2sd ((__v2df) __A, (__v4sf)__B);
@@ -922,465 +878,496 @@ _mm_cvtss_sd (__m128d __A, __m128 __B)
#define _mm_shuffle_pd(__A, __B, __C) ((__m128d)__builtin_ia32_shufpd ((__v2df)__A, (__v2df)__B, (__C)))
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_unpackhi_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_unpckhpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_unpacklo_pd (__m128d __A, __m128d __B)
{
return (__m128d)__builtin_ia32_unpcklpd ((__v2df)__A, (__v2df)__B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_loadh_pd (__m128d __A, double const *__B)
{
- return (__m128d)__builtin_ia32_loadhpd ((__v2df)__A, (__v2si *)__B);
-}
-
-static __inline void
-_mm_storeh_pd (double *__A, __m128d __B)
-{
- __builtin_ia32_storehpd ((__v2si *)__A, (__v2df)__B);
+ return (__m128d)__builtin_ia32_loadhpd ((__v2df)__A, __B);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_loadl_pd (__m128d __A, double const *__B)
{
- return (__m128d)__builtin_ia32_loadlpd ((__v2df)__A, (__v2si *)__B);
-}
-
-static __inline void
-_mm_storel_pd (double *__A, __m128d __B)
-{
- __builtin_ia32_storelpd ((__v2si *)__A, (__v2df)__B);
+ return (__m128d)__builtin_ia32_loadlpd ((__v2df)__A, __B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_movemask_pd (__m128d __A)
{
return __builtin_ia32_movmskpd ((__v2df)__A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_packs_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_packsswb128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_packs_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_packssdw128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_packus_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_packuswb128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpackhi_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpckhbw128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpackhi_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpckhwd128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpackhi_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpckhdq128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpackhi_epi64 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpckhqdq128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpacklo_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpcklbw128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpacklo_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpcklwd128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpacklo_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpckldq128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_unpacklo_epi64 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_punpcklqdq128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_add_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_add_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_add_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddd128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_add_epi64 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddq128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_adds_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddsb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_adds_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddsw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_adds_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddusb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_adds_epu16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_paddusw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_sub_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_sub_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_sub_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubd128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_sub_epi64 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubq128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_subs_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubsb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_subs_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubsw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_subs_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubusb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_subs_epu16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psubusw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_madd_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmaddwd128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_mulhi_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmulhw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_mullo_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmullw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_mul_su32 (__m64 __A, __m64 __B)
{
return (__m64)__builtin_ia32_pmuludq ((__v2si)__A, (__v2si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_mul_epu32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmuludq128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
-_mm_sll_epi16 (__m128i __A, __m128i __B)
+#if 0
+static __inline __m128i __attribute__((__always_inline__))
+_mm_slli_epi16 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psllw128 ((__v8hi)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_psllwi128 ((__v8hi)__A, __B);
}
-static __inline __m128i
-_mm_sll_epi32 (__m128i __A, __m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_slli_epi32 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_pslld128 ((__v4si)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B);
}
-static __inline __m128i
-_mm_sll_epi64 (__m128i __A, __m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_slli_epi64 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psllq128 ((__v2di)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_psllqi128 ((__v2di)__A, __B);
}
+#else
+#define _mm_slli_epi16(__A, __B) \
+ ((__m128i)__builtin_ia32_psllwi128 ((__v8hi)(__A), __B))
+#define _mm_slli_epi32(__A, __B) \
+ ((__m128i)__builtin_ia32_pslldi128 ((__v8hi)(__A), __B))
+#define _mm_slli_epi64(__A, __B) \
+ ((__m128i)__builtin_ia32_psllqi128 ((__v8hi)(__A), __B))
+#endif
-static __inline __m128i
-_mm_sra_epi16 (__m128i __A, __m128i __B)
+#if 0
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srai_epi16 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psraw128 ((__v8hi)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_psrawi128 ((__v8hi)__A, __B);
}
-static __inline __m128i
-_mm_sra_epi32 (__m128i __A, __m128i __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srai_epi32 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psrad128 ((__v4si)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_psradi128 ((__v4si)__A, __B);
}
+#else
+#define _mm_srai_epi16(__A, __B) \
+ ((__m128i)__builtin_ia32_psrawi128 ((__v8hi)(__A), __B))
+#define _mm_srai_epi32(__A, __B) \
+ ((__m128i)__builtin_ia32_psradi128 ((__v8hi)(__A), __B))
+#endif
-static __inline __m128i
-_mm_srl_epi16 (__m128i __A, __m128i __B)
+#if 0
+static __m128i __attribute__((__always_inline__))
+_mm_srli_si128 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psrlw128 ((__v8hi)__A, (__v2di)__B);
+ return ((__m128i)__builtin_ia32_psrldqi128 (__A, __B * 8));
}
-static __inline __m128i
-_mm_srl_epi32 (__m128i __A, __m128i __B)
+static __m128i __attribute__((__always_inline__))
+_mm_srli_si128 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psrld128 ((__v4si)__A, (__v2di)__B);
+ return ((__m128i)__builtin_ia32_pslldqi128 (__A, __B * 8));
}
+#else
+#define _mm_srli_si128(__A, __B) \
+ ((__m128i)__builtin_ia32_psrldqi128 (__A, (__B) * 8))
+#define _mm_slli_si128(__A, __B) \
+ ((__m128i)__builtin_ia32_pslldqi128 (__A, (__B) * 8))
+#endif
-static __inline __m128i
-_mm_srl_epi64 (__m128i __A, __m128i __B)
+#if 0
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srli_epi16 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psrlq128 ((__v2di)__A, (__v2di)__B);
+ return (__m128i)__builtin_ia32_psrlwi128 ((__v8hi)__A, __B);
}
-static __inline __m128i
-_mm_slli_epi16 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srli_epi32 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_psllwi128 ((__v8hi)__A, __B);
+ return (__m128i)__builtin_ia32_psrldi128 ((__v4si)__A, __B);
}
-static __inline __m128i
-_mm_slli_epi32 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srli_epi64 (__m128i __A, int __B)
{
- return (__m128i)__builtin_ia32_pslldi128 ((__v4si)__A, __B);
+ return (__m128i)__builtin_ia32_psrlqi128 ((__v2di)__A, __B);
}
+#else
+#define _mm_srli_epi16(__A, __B) \
+ ((__m128i)__builtin_ia32_psrlwi128 ((__v8hi)(__A), __B))
+#define _mm_srli_epi32(__A, __B) \
+ ((__m128i)__builtin_ia32_psrldi128 ((__v4si)(__A), __B))
+#define _mm_srli_epi64(__A, __B) \
+ ((__m128i)__builtin_ia32_psrlqi128 ((__v4si)(__A), __B))
+#endif
-static __inline __m128i
-_mm_slli_epi64 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_sll_epi16 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psllqi128 ((__v2di)__A, __B);
+ return (__m128i)__builtin_ia32_psllw128((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
-_mm_srai_epi16 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_sll_epi32 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psrawi128 ((__v8hi)__A, __B);
+ return (__m128i)__builtin_ia32_pslld128((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
-_mm_srai_epi32 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_sll_epi64 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psradi128 ((__v4si)__A, __B);
+ return (__m128i)__builtin_ia32_psllq128((__v2di)__A, (__v2di)__B);
}
-#if 0
-static __m128i __attribute__((__always_inline__))
-_mm_srli_si128 (__m128i __A, const int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_sra_epi16 (__m128i __A, __m128i __B)
{
- return ((__m128i)__builtin_ia32_psrldqi128 (__A, __B))
+ return (__m128i)__builtin_ia32_psraw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __m128i __attribute__((__always_inline__))
-_mm_srli_si128 (__m128i __A, const int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_sra_epi32 (__m128i __A, __m128i __B)
{
- return ((__m128i)__builtin_ia32_pslldqi128 (__A, __B))
+ return (__m128i)__builtin_ia32_psrad128 ((__v4si)__A, (__v4si)__B);
}
-#endif
-#define _mm_srli_si128(__A, __B) ((__m128i)__builtin_ia32_psrldqi128 (__A, __B))
-#define _mm_slli_si128(__A, __B) ((__m128i)__builtin_ia32_pslldqi128 (__A, __B))
-static __inline __m128i
-_mm_srli_epi16 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srl_epi16 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psrlwi128 ((__v8hi)__A, __B);
+ return (__m128i)__builtin_ia32_psrlw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
-_mm_srli_epi32 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srl_epi32 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psrldi128 ((__v4si)__A, __B);
+ return (__m128i)__builtin_ia32_psrld128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
-_mm_srli_epi64 (__m128i __A, int __B)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_srl_epi64 (__m128i __A, __m128i __B)
{
- return (__m128i)__builtin_ia32_psrlqi128 ((__v2di)__A, __B);
+ return (__m128i)__builtin_ia32_psrlq128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_and_si128 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pand128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_andnot_si128 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pandn128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_or_si128 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_por128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_xor_si128 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pxor128 ((__v2di)__A, (__v2di)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpeq_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpeqb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpeq_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpeqw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpeq_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpeqd128 ((__v4si)__A, (__v4si)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmplt_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtb128 ((__v16qi)__B, (__v16qi)__A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmplt_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtw128 ((__v8hi)__B, (__v8hi)__A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmplt_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtd128 ((__v4si)__B, (__v4si)__A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpgt_epi8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpgt_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cmpgt_epi32 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pcmpgtd128 ((__v4si)__A, (__v4si)__B);
}
-#define _mm_extract_epi16(__A, __B) __builtin_ia32_pextrw128 ((__v8hi)__A, __B)
+#if 0
+static __inline int __attribute__((__always_inline__))
+_mm_extract_epi16 (__m128i const __A, int const __N)
+{
+ return __builtin_ia32_vec_ext_v8hi ((__v8hi)__A, __N);
+}
-#define _mm_insert_epi16(__A, __B, __C) ((__m128i)__builtin_ia32_pinsrw128 ((__v8hi)__A, __B, __C))
+static __inline __m128i __attribute__((__always_inline__))
+_mm_insert_epi16 (__m128i const __A, int const __D, int const __N)
+{
+ return (__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)__A, __D, __N);
+}
+#else
+#define _mm_extract_epi16(A, N) \
+ ((int) __builtin_ia32_vec_ext_v8hi ((__v8hi)(A), (N)))
+#define _mm_insert_epi16(A, D, N) \
+ ((__m128i) __builtin_ia32_vec_set_v8hi ((__v8hi)(A), (D), (N)))
+#endif
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_max_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmaxsw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_max_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmaxub128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_min_epi16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pminsw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_min_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pminub128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_movemask_epi8 (__m128i __A)
{
return __builtin_ia32_pmovmskb128 ((__v16qi)__A);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_mulhi_epu16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pmulhuw128 ((__v8hi)__A, (__v8hi)__B);
@@ -1390,101 +1377,125 @@ _mm_mulhi_epu16 (__m128i __A, __m128i __B)
#define _mm_shufflelo_epi16(__A, __B) ((__m128i)__builtin_ia32_pshuflw ((__v8hi)__A, __B))
#define _mm_shuffle_epi32(__A, __B) ((__m128i)__builtin_ia32_pshufd ((__v4si)__A, __B))
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_maskmoveu_si128 (__m128i __A, __m128i __B, char *__C)
{
__builtin_ia32_maskmovdqu ((__v16qi)__A, (__v16qi)__B, __C);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_avg_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pavgb128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_avg_epu16 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_pavgw128 ((__v8hi)__A, (__v8hi)__B);
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_sad_epu8 (__m128i __A, __m128i __B)
{
return (__m128i)__builtin_ia32_psadbw128 ((__v16qi)__A, (__v16qi)__B);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_stream_si32 (int *__A, int __B)
{
__builtin_ia32_movnti (__A, __B);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_stream_si128 (__m128i *__A, __m128i __B)
{
__builtin_ia32_movntdq ((__v2di *)__A, (__v2di)__B);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_stream_pd (double *__A, __m128d __B)
{
__builtin_ia32_movntpd (__A, (__v2df)__B);
}
-static __inline __m128i
-_mm_movpi64_epi64 (__m64 __A)
-{
- return (__m128i)__builtin_ia32_movq2dq ((unsigned long long)__A);
-}
-
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_clflush (void const *__A)
{
- return __builtin_ia32_clflush (__A);
+ __builtin_ia32_clflush (__A);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_lfence (void)
{
__builtin_ia32_lfence ();
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_mfence (void)
{
__builtin_ia32_mfence ();
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvtsi32_si128 (int __A)
{
- return (__m128i) __builtin_ia32_loadd (&__A);
+ return _mm_set_epi32 (0, 0, 0, __A);
}
#ifdef __x86_64__
-static __inline __m128i
+/* Intel intrinsic. */
+static __inline __m128i __attribute__((__always_inline__))
+_mm_cvtsi64_si128 (long long __A)
+{
+ return _mm_set_epi64x (0, __A);
+}
+
+/* Microsoft intrinsic. */
+static __inline __m128i __attribute__((__always_inline__))
_mm_cvtsi64x_si128 (long long __A)
{
- return (__m128i) __builtin_ia32_movq2dq (__A);
+ return _mm_set_epi64x (0, __A);
}
#endif
-static __inline int
-_mm_cvtsi128_si32 (__m128i __A)
+/* Casts between various SP, DP, INT vector types. Note that these do no
+ conversion of values, they just change the type. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_castpd_ps(__m128d __A)
{
- int __tmp;
- __builtin_ia32_stored (&__tmp, (__v4si)__A);
- return __tmp;
+ return (__m128) __A;
}
-#ifdef __x86_64__
-static __inline long long
-_mm_cvtsi128_si64x (__m128i __A)
+static __inline __m128i __attribute__((__always_inline__))
+_mm_castpd_si128(__m128d __A)
{
- return __builtin_ia32_movdq2q ((__v2di)__A);
+ return (__m128i) __A;
+}
+
+static __inline __m128d __attribute__((__always_inline__))
+_mm_castps_pd(__m128 __A)
+{
+ return (__m128d) __A;
+}
+
+static __inline __m128i __attribute__((__always_inline__))
+_mm_castps_si128(__m128 __A)
+{
+ return (__m128i) __A;
+}
+
+static __inline __m128 __attribute__((__always_inline__))
+_mm_castsi128_ps(__m128i __A)
+{
+ return (__m128) __A;
+}
+
+static __inline __m128d __attribute__((__always_inline__))
+_mm_castsi128_pd(__m128i __A)
+{
+ return (__m128d) __A;
}
-#endif
#endif /* __SSE2__ */
diff --git a/contrib/gcc/config/i386/gas.h b/contrib/gcc/config/i386/gas.h
index 78195b9..8be55fb 100644
--- a/contrib/gcc/config/i386/gas.h
+++ b/contrib/gcc/config/i386/gas.h
@@ -1,5 +1,6 @@
/* Definitions for Intel 386 using GAS.
- Copyright (C) 1988, 1993, 1994, 1996, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1993, 1994, 1996, 2002, 2004
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Note that i386/seq-gas.h is a GAS configuration that does not use this
file. */
@@ -49,10 +50,6 @@ Boston, MA 02111-1307, USA. */
#define ASM_OUTPUT_IDENT(FILE, NAME) fprintf (FILE, "\t.ident \"%s\"\n", NAME);
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-
-#define TARGET_MEM_FUNCTIONS
-
/* In the past there was confusion as to what the argument to .align was
in GAS. For the last several years the rule has been this: for a.out
file formats that argument is LOG, and for all other file formats the
@@ -121,4 +118,8 @@ Boston, MA 02111-1307, USA. */
/* Print opcodes the way that GAS expects them. */
#define GAS_MNEMONICS 1
+/* The comment-starter string as GAS expects it. */
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START "#"
+
#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
diff --git a/contrib/gcc/config/i386/gmm_malloc.h b/contrib/gcc/config/i386/gmm_malloc.h
new file mode 100644
index 0000000..20d7f5e
--- /dev/null
+++ b/contrib/gcc/config/i386/gmm_malloc.h
@@ -0,0 +1,77 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file does not by itself cause
+ the resulting executable to be covered by the GNU General Public
+ License. This exception does not however invalidate any other
+ reasons why the executable file might be covered by the GNU General
+ Public License. */
+
+#ifndef _MM_MALLOC_H_INCLUDED
+#define _MM_MALLOC_H_INCLUDED
+
+#include <stdlib.h>
+#include <errno.h>
+
+static __inline__ void*
+_mm_malloc (size_t size, size_t align)
+{
+ void * malloc_ptr;
+ void * aligned_ptr;
+
+ /* Error if align is not a power of two. */
+ if (align & (align - 1))
+ {
+ errno = EINVAL;
+ return ((void*) 0);
+ }
+
+ if (size == 0)
+ return ((void *) 0);
+
+ /* Assume malloc'd pointer is aligned at least to sizeof (void*).
+ If necessary, add another sizeof (void*) to store the value
+ returned by malloc. Effectively this enforces a minimum alignment
+ of sizeof double. */
+ if (align < 2 * sizeof (void *))
+ align = 2 * sizeof (void *);
+
+ malloc_ptr = malloc (size + align);
+ if (!malloc_ptr)
+ return ((void *) 0);
+
+ /* Align We have at least sizeof (void *) space below malloc'd ptr. */
+ aligned_ptr = (void *) (((size_t) malloc_ptr + align)
+ & ~((size_t) (align) - 1));
+
+ /* Store the original pointer just before p. */
+ ((void **) aligned_ptr) [-1] = malloc_ptr;
+
+ return aligned_ptr;
+}
+
+static __inline__ void
+_mm_free (void * aligned_ptr)
+{
+ if (aligned_ptr)
+ free (((void **) aligned_ptr) [-1]);
+}
+
+#endif /* _MM_MALLOC_H_INCLUDED */
diff --git a/contrib/gcc/config/i386/gmon-sol2.c b/contrib/gcc/config/i386/gmon-sol2.c
index 8ea242b..fc5a2cf 100644
--- a/contrib/gcc/config/i386/gmon-sol2.c
+++ b/contrib/gcc/config/i386/gmon-sol2.c
@@ -53,22 +53,19 @@
* This code could easily be integrated with the original gmon.c and perhaps
* should be.
*/
+#include "tconfig.h"
+#include "tsystem.h"
+#include <fcntl.h> /* for creat() */
-#ifndef lint
-static char sccsid[] = "@(#)gmon.c 5.3 (Berkeley) 5/22/91";
-#endif /* not lint */
-
-#if 0
-#include <unistd.h>
-
-#endif
#ifdef DEBUG
#include <stdio.h>
#endif
-#if 0
-#include "i386/gmon.h"
-#else
+static void moncontrol (int);
+extern void monstartup (char *, char *);
+extern void _mcleanup (void);
+extern void internal_mcount (void);
+
struct phdr {
char *lpc;
@@ -90,6 +87,7 @@ struct tostruct {
long count;
unsigned short link;
};
+
struct rawarc {
unsigned long raw_frompc;
unsigned long raw_selfpc;
@@ -97,14 +95,9 @@ struct rawarc {
};
#define ROUNDDOWN(x,y) (((x)/(y))*(y))
#define ROUNDUP(x,y) ((((x)+(y)-1)/(y))*(y))
-#endif
/* char *minbrk; */
-#ifdef __alpha
-extern char *sbrk ();
-#endif
-
/*
* froms is actually a bunch of unsigned shorts indexing tos
*/
@@ -126,9 +119,8 @@ static int s_scale;
extern int errno;
-monstartup(lowpc, highpc)
- char *lowpc;
- char *highpc;
+void
+monstartup(char *lowpc, char *highpc)
{
int monsize;
char *buffer;
@@ -139,10 +131,10 @@ monstartup(lowpc, highpc)
* so the rest of the scaling (here and in gprof) stays in ints.
*/
lowpc = (char *)
- ROUNDDOWN((unsigned)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDDOWN((unsigned long)lowpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_lowpc = lowpc;
highpc = (char *)
- ROUNDUP((unsigned)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
+ ROUNDUP((unsigned long)highpc, HISTFRACTION*sizeof(HISTCOUNTER));
s_highpc = highpc;
s_textsize = highpc - lowpc;
monsize = (s_textsize / HISTFRACTION) + sizeof(struct phdr);
@@ -203,7 +195,8 @@ monstartup(lowpc, highpc)
moncontrol(1);
}
-_mcleanup()
+void
+_mcleanup (void)
{
int fd;
int fromindex;
@@ -220,7 +213,7 @@ _mcleanup()
}
# ifdef DEBUG
fprintf( stderr , "[mcleanup] sbuf 0x%x ssiz %d\n" , sbuf , ssiz );
-# endif DEBUG
+# endif /* DEBUG */
write( fd , sbuf , ssiz );
endfrom = s_textsize / (HASHFRACTION * sizeof(*froms));
@@ -234,7 +227,7 @@ _mcleanup()
fprintf( stderr ,
"[mcleanup] frompc 0x%x selfpc 0x%x count %d\n" ,
frompc , tos[toindex].selfpc , tos[toindex].count );
-# endif DEBUG
+# endif /* DEBUG */
rawarc.raw_frompc = (unsigned long) frompc;
rawarc.raw_selfpc = (unsigned long) tos[toindex].selfpc;
rawarc.raw_count = tos[toindex].count;
@@ -249,7 +242,8 @@ asm(".globl _mcount; _mcount: jmp internal_mcount");
/* This is for compatibility with old versions of gcc which used mcount. */
asm(".globl mcount; mcount: jmp internal_mcount");
-internal_mcount()
+void
+internal_mcount (void)
{
register char *selfpc;
register unsigned short *frompcindex;
@@ -271,10 +265,10 @@ internal_mcount()
frompcindex = (void *) __builtin_return_address (1);
if(!already_setup) {
- extern etext();
+ extern char etext[];
already_setup = 1;
/* monstartup(0, etext); */
- monstartup(0x08040000, etext);
+ monstartup((char*)0x08040000, etext);
#ifdef USE_ONEXIT
on_exit(_mcleanup, 0);
#else
@@ -387,15 +381,15 @@ overflow:
* profiling is what mcount checks to see if
* all the data structures are ready.
*/
-moncontrol(mode)
- int mode;
+static void
+moncontrol(int mode)
{
if (mode)
{
/* start */
profil((unsigned short *)(sbuf + sizeof(struct phdr)),
ssiz - sizeof(struct phdr),
- (int)s_lowpc, s_scale);
+ (long)s_lowpc, s_scale);
profiling = 0;
} else {
diff --git a/contrib/gcc/config/i386/gnu.h b/contrib/gcc/config/i386/gnu.h
index cc9994b..d40ff7d 100644
--- a/contrib/gcc/config/i386/gnu.h
+++ b/contrib/gcc/config/i386/gnu.h
@@ -8,11 +8,6 @@
do \
{ \
HURD_TARGET_OS_CPP_BUILTINS(); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
@@ -40,4 +35,4 @@
%{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
/* FIXME: Is a Hurd-specific fallback mechanism necessary? */
-#undef MD_FALLBACK_FRAME_STATE_FOR
+#undef MD_UNWIND_SUPPORT
diff --git a/contrib/gcc/config/i386/gthr-win32.c b/contrib/gcc/config/i386/gthr-win32.c
index c53369b..d13b539 100644
--- a/contrib/gcc/config/i386/gthr-win32.c
+++ b/contrib/gcc/config/i386/gthr-win32.c
@@ -20,8 +20,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
@@ -182,3 +182,73 @@ __gthr_win32_mutex_unlock (__gthread_mutex_t *mutex)
else
return 0;
}
+
+void
+__gthr_win32_recursive_mutex_init_function (__gthread_recursive_mutex_t *mutex)
+{
+ mutex->counter = -1;
+ mutex->depth = 0;
+ mutex->owner = 0;
+ mutex->sema = CreateSemaphore (NULL, 0, 65535, NULL);
+}
+
+int
+__gthr_win32_recursive_mutex_lock (__gthread_recursive_mutex_t *mutex)
+{
+ DWORD me = GetCurrentThreadId();
+ if (InterlockedIncrement (&mutex->counter) == 0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else if (mutex->owner == me)
+ {
+ InterlockedDecrement (&mutex->counter);
+ ++(mutex->depth);
+ }
+ else if (WaitForSingleObject (mutex->sema, INFINITE) == WAIT_OBJECT_0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else
+ {
+ /* WaitForSingleObject returns WAIT_FAILED, and we can only do
+ some best-effort cleanup here. */
+ InterlockedDecrement (&mutex->counter);
+ return 1;
+ }
+ return 0;
+}
+
+int
+__gthr_win32_recursive_mutex_trylock (__gthread_recursive_mutex_t *mutex)
+{
+ DWORD me = GetCurrentThreadId();
+ if (__GTHR_W32_InterlockedCompareExchange (&mutex->counter, 0, -1) < 0)
+ {
+ mutex->depth = 1;
+ mutex->owner = me;
+ }
+ else if (mutex->owner == me)
+ ++(mutex->depth);
+ else
+ return 1;
+
+ return 0;
+}
+
+int
+__gthr_win32_recursive_mutex_unlock (__gthread_recursive_mutex_t *mutex)
+{
+ --(mutex->depth);
+ if (mutex->depth == 0)
+ {
+ mutex->owner = 0;
+
+ if (InterlockedDecrement (&mutex->counter) >= 0)
+ return ReleaseSemaphore (mutex->sema, 1, NULL) ? 0 : 1;
+ }
+
+ return 0;
+}
diff --git a/contrib/gcc/config/i386/host-cygwin.c b/contrib/gcc/config/i386/host-cygwin.c
new file mode 100755
index 0000000..15bd273
--- /dev/null
+++ b/contrib/gcc/config/i386/host-cygwin.c
@@ -0,0 +1,81 @@
+/* Cygwin host-specific hook definitions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include <sys/mman.h>
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+#include "toplev.h"
+#include "diagnostic.h"
+
+static void * cygwin_gt_pch_get_address (size_t, int fd);
+static size_t cygwin_gt_pch_alloc_granularity (void);
+
+#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
+#define HOST_HOOKS_GT_PCH_GET_ADDRESS cygwin_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY
+#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY cygwin_gt_pch_alloc_granularity
+
+/* Granularity for reserving address space. */
+static const size_t va_granularity = 0x10000;
+
+/* Return the alignment required for allocating virtual memory. */
+static size_t
+cygwin_gt_pch_alloc_granularity (void)
+{
+ return va_granularity;
+}
+
+/* Identify an address that's likely to be free in a subsequent invocation
+ of the compiler. The area should be able to hold SIZE bytes. FD is an
+ open file descriptor if the host would like to probe with mmap. */
+static void *
+cygwin_gt_pch_get_address (size_t sz, int fd)
+{
+ void *base;
+ off_t p = lseek(fd, 0, SEEK_CUR);
+
+ if (p == (off_t) -1)
+ fatal_error ("can't get position in PCH file: %m");
+
+ /* Cygwin requires that the underlying file be at least
+ as large as the requested mapping. */
+ if ((size_t) p < sz)
+ {
+ if ( ftruncate (fd, sz) == -1 )
+ fatal_error ("can't extend PCH file: %m");
+ }
+
+ base = mmap (NULL, sz, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
+
+ if (base == MAP_FAILED)
+ base = NULL;
+ else
+ munmap (base, sz);
+
+ if (lseek (fd, p, SEEK_SET) == (off_t) -1 )
+ fatal_error ("can't set position in PCH file: %m");
+
+ return base;
+}
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/i386/host-i386-darwin.c b/contrib/gcc/config/i386/host-i386-darwin.c
new file mode 100644
index 0000000..3025bda
--- /dev/null
+++ b/contrib/gcc/config/i386/host-i386-darwin.c
@@ -0,0 +1,31 @@
+/* i386-darwin host-specific hook definitions.
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+#include "config/host-darwin.h"
+
+/* Darwin doesn't do anything special for x86 hosts; this file exists just
+ to include config/host-darwin.h. */
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/i386/host-mingw32.c b/contrib/gcc/config/i386/host-mingw32.c
new file mode 100644
index 0000000..a341e27
--- /dev/null
+++ b/contrib/gcc/config/i386/host-mingw32.c
@@ -0,0 +1,148 @@
+/* mingw32 host-specific hook definitions.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+#include "toplev.h"
+#include "diagnostic.h"
+
+
+#define WIN32_LEAN_AND_MEAN /* Not so important if we have windows.h.gch. */
+#include <windows.h>
+
+static void * mingw32_gt_pch_get_address (size_t, int);
+static int mingw32_gt_pch_use_address (void *, size_t, int, size_t);
+static size_t mingw32_gt_pch_alloc_granularity (void);
+
+#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
+#define HOST_HOOKS_GT_PCH_GET_ADDRESS mingw32_gt_pch_get_address
+#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
+#define HOST_HOOKS_GT_PCH_USE_ADDRESS mingw32_gt_pch_use_address
+#undef HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY
+#define HOST_HOOKS_GT_PCH_ALLOC_GRANULARITY mingw32_gt_pch_alloc_granularity
+
+static inline void w32_error(const char*, const char*, int, const char*);
+
+/* FIXME: Is this big enough? */
+static const size_t pch_VA_max_size = 128 * 1024 * 1024;
+
+/* Granularity for reserving address space. */
+static const size_t va_granularity = 0x10000;
+
+/* Print out the GetLastError() translation. */
+static inline void
+w32_error (const char* function, const char* file, int line,
+ const char* my_msg)
+{
+ LPSTR w32_msgbuf;
+ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER
+ | FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_IGNORE_INSERTS
+ | FORMAT_MESSAGE_MAX_WIDTH_MASK,
+ NULL, GetLastError(),
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPSTR) &w32_msgbuf, 0, NULL);
+ fprintf(stderr, "internal error in %s, at %s:%d: %s: %s\n",
+ function, trim_filename (file), line, my_msg, w32_msgbuf);
+ LocalFree ((HLOCAL)w32_msgbuf);
+}
+
+/* Granularity for reserving address space. */
+static size_t mingw32_gt_pch_alloc_granularity (void)
+{
+ return va_granularity;
+}
+
+/* Identify an address that's likely to be free in a subsequent invocation
+ of the compiler. The area should be able to hold SIZE bytes. FD is an
+ open file descriptor if the host would like to probe with mmap. */
+
+static void *
+mingw32_gt_pch_get_address (size_t size, int fd ATTRIBUTE_UNUSED)
+{
+ void* res;
+ size = (size + va_granularity - 1) & ~(va_granularity - 1);
+ if (size > pch_VA_max_size)
+ return NULL;
+
+ /* FIXME: We let system determine base by setting first arg to NULL.
+ Allocating at top of available address space avoids unnecessary
+ fragmentation of "ordinary" (malloc's) address space but may not be safe
+ with delayed load of system dll's. Preferred addresses for NT system
+ dlls is in 0x70000000 to 0x78000000 range.
+ If we allocate at bottom we need to reserve the address as early as possible
+ and at the same point in each invocation. */
+
+ res = VirtualAlloc (NULL, pch_VA_max_size,
+ MEM_RESERVE | MEM_TOP_DOWN,
+ PAGE_NOACCESS);
+ if (!res)
+ w32_error (__FUNCTION__, __FILE__, __LINE__, "VirtualAlloc");
+ else
+ /* We do not need the address space for now, so free it. */
+ VirtualFree (res, 0, MEM_RELEASE);
+
+ return res;
+}
+
+/* ADDR is an address returned by gt_pch_get_address. Attempt to allocate
+ SIZE bytes at the same address and load it with the data from FD at
+ OFFSET. Return -1 if we couldn't allocate memory at ADDR, return 0
+ if the memory is allocated but the data not loaded, return 1 if done. */
+
+static int
+mingw32_gt_pch_use_address (void *addr, size_t size, int fd,
+ size_t offset)
+{
+ void * mmap_addr;
+ static HANDLE mmap_handle;
+
+ if (size == 0)
+ return 0;
+
+ /* Offset must be also be a multiple of allocation granularity for
+ this to work. We can't change the offset. */
+ if ((offset & (va_granularity - 1)) != 0 || size > pch_VA_max_size)
+ return -1;
+
+ mmap_handle = CreateFileMapping ((HANDLE) _get_osfhandle (fd),
+ NULL, PAGE_WRITECOPY | SEC_COMMIT,
+ 0, 0, NULL);
+ if (mmap_handle == NULL)
+ {
+ w32_error (__FUNCTION__, __FILE__, __LINE__, "CreateFileMapping");
+ return -1;
+ }
+ mmap_addr = MapViewOfFileEx (mmap_handle, FILE_MAP_COPY, 0, offset,
+ size, addr);
+ if (mmap_addr != addr)
+ {
+ w32_error (__FUNCTION__, __FILE__, __LINE__, "MapViewOfFileEx");
+ CloseHandle(mmap_handle);
+ return -1;
+ }
+
+ return 1;
+}
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/i386/i386-aout.h b/contrib/gcc/config/i386/i386-aout.h
index 3b89788..9deb357 100644
--- a/contrib/gcc/config/i386/i386-aout.h
+++ b/contrib/gcc/config/i386/i386-aout.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (80386, BSD a.out syntax)");
diff --git a/contrib/gcc/config/i386/i386-coff.h b/contrib/gcc/config/i386/i386-coff.h
index 85a5193..bea8e19 100644
--- a/contrib/gcc/config/i386/i386-coff.h
+++ b/contrib/gcc/config/i386/i386-coff.h
@@ -1,7 +1,7 @@
/* Definitions for "naked" Intel 386 using coff object format files
and coff debugging info.
- Copyright (C) 1994, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1994, 2000, 2002, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (80386, COFF BSD syntax)");
@@ -60,4 +60,11 @@ Boston, MA 02111-1307, USA. */
#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+/* GNU as expects alignment to be the number of bytes instead of the log for
+ COFF targets. */
+
+#undef ASM_OUTPUT_ALIGN
+#define ASM_OUTPUT_ALIGN(FILE,LOG) \
+ if ((LOG)!=0) fprintf ((FILE), "\t.align %d\n", 1<<(LOG))
+
/* end of i386-coff.h */
diff --git a/contrib/gcc/config/i386/i386-interix.h b/contrib/gcc/config/i386/i386-interix.h
index 2a99ce5..5e9f7da 100644
--- a/contrib/gcc/config/i386/i386-interix.h
+++ b/contrib/gcc/config/i386/i386-interix.h
@@ -22,8 +22,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* The rest must follow. */
@@ -54,6 +54,8 @@ Boston, MA 02111-1307, USA. */
#define ASM_LOAD_ADDR(loc, reg) " leal " #loc "," #reg "\n"
+#define TARGET_DECLSPEC 1
+
/* cpp handles __STDC__ */
#define TARGET_OS_CPP_BUILTINS() \
do \
@@ -64,7 +66,6 @@ Boston, MA 02111-1307, USA. */
builtin_define ("_X86_=1"); \
builtin_define ("__stdcall=__attribute__((__stdcall__))"); \
builtin_define ("__cdecl=__attribute__((__cdecl__))"); \
- builtin_define ("__declspec(x)=__attribute__((x))"); \
builtin_assert ("system=unix"); \
builtin_assert ("system=interix"); \
if (preprocessing_asm_p ()) \
@@ -83,7 +84,7 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SPEC
/* Write out the correct language type definition for the header files.
Unless we have assembler language, write out the symbols for C.
- mieee is an Alpha specific variant. Cross polination a bad idea.
+ mieee is an Alpha specific variant. Cross pollination a bad idea.
*/
#define CPP_SPEC "-remap %{posix:-D_POSIX_SOURCE} \
-isystem %$INTERIX_ROOT/usr/include"
@@ -285,7 +286,6 @@ do \
} \
while (0)
-#define HOST_PTR_PRINTF "%p"
#define HOST_PTR_AS_INT unsigned long
#define PCC_BITFIELD_TYPE_MATTERS 1
@@ -336,14 +336,12 @@ while (0)
.data$ sections correctly. See corresponding note in i386/interix.c.
MK. */
-/* Define this macro if in some cases global symbols from one translation
- unit may not be bound to undefined symbols in another translation unit
- without user intervention. For instance, under Microsoft Windows
- symbols must be explicitly imported from shared libraries (DLLs). */
-#define MULTIPLE_SYMBOL_SPACES
+/* Interix uses explicit import from shared libraries. */
+#define MULTIPLE_SYMBOL_SPACES 1
extern void i386_pe_unique_section (tree, int);
#define TARGET_ASM_UNIQUE_SECTION i386_pe_unique_section
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
#define SUPPORTS_ONE_ONLY 1
#endif /* 0 */
diff --git a/contrib/gcc/config/i386/i386-interix3.h b/contrib/gcc/config/i386/i386-interix3.h
index 7ade70a..2c40461 100644
--- a/contrib/gcc/config/i386/i386-interix3.h
+++ b/contrib/gcc/config/i386/i386-interix3.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef CPP_SPEC
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
diff --git a/contrib/gcc/config/i386/i386-modes.def b/contrib/gcc/config/i386/i386-modes.def
index 36c6d42..40c12b1 100644
--- a/contrib/gcc/config/i386/i386-modes.def
+++ b/contrib/gcc/config/i386/i386-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine for GCC for IA-32.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,18 +15,18 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
-/* x86_64 ABI specifies both XF and TF modes.
+/* The x86_64 ABI specifies both XF and TF modes.
XFmode is __float80 is IEEE extended; TFmode is __float128
- is IEEE quad.
+ is IEEE quad. */
- IEEE extended is 128 bits wide, except in ILP32 mode, but we
- have to say it's 12 bytes so that the bitsize and wider_mode
- tables are correctly set up. We correct its size below. */
+FRACTIONAL_FLOAT_MODE (XF, 80, 12, ieee_extended_intel_96_format);
+FLOAT_MODE (TF, 16, ieee_quad_format);
-FLOAT_MODE (XF, 12, ieee_extended_intel_96_format);
+/* In ILP32 mode, XFmode has size 12 and alignment 4.
+ In LP64 mode, XFmode has size and alignment 16. */
ADJUST_FLOAT_FORMAT (XF, (TARGET_128BIT_LONG_DOUBLE
? &ieee_extended_intel_128_format
: TARGET_96_ROUND_53_LONG_DOUBLE
@@ -34,7 +34,6 @@ ADJUST_FLOAT_FORMAT (XF, (TARGET_128BIT_LONG_DOUBLE
: &ieee_extended_intel_96_format));
ADJUST_BYTESIZE (XF, TARGET_128BIT_LONG_DOUBLE ? 16 : 12);
ADJUST_ALIGNMENT (XF, TARGET_128BIT_LONG_DOUBLE ? 16 : 4);
-FLOAT_MODE (TF, 16, ieee_quad_format);
/* Add any extra modes needed to represent the condition code.
@@ -62,3 +61,19 @@ CC_MODE (CCNO);
CC_MODE (CCZ);
CC_MODE (CCFP);
CC_MODE (CCFPU);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
+VECTOR_MODE (INT, DI, 4); /* V4DI */
+VECTOR_MODE (INT, SI, 8); /* V8SI */
+VECTOR_MODE (INT, HI, 16); /* V16HI */
+VECTOR_MODE (INT, QI, 32); /* V32QI */
+VECTOR_MODE (FLOAT, DF, 4); /* V4DF */
+VECTOR_MODE (FLOAT, SF, 8); /* V8SF */
+
+/* The symbol Pmode stands for one of the above machine modes (usually SImode).
+ The tm.h file specifies which one. It is not a distinct mode. */
diff --git a/contrib/gcc/config/i386/i386-protos.h b/contrib/gcc/config/i386/i386-protos.h
index ea0e8f6..6b9ed89 100644
--- a/contrib/gcc/config/i386/i386-protos.h
+++ b/contrib/gcc/config/i386/i386-protos.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GCC for IA-32.
Copyright (C) 1988, 1992, 1994, 1995, 1996, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Functions in i386.c */
extern void override_options (void);
@@ -42,62 +43,15 @@ extern int standard_80387_constant_p (rtx);
extern const char *standard_80387_constant_opcode (rtx);
extern rtx standard_80387_constant_rtx (int);
extern int standard_sse_constant_p (rtx);
+extern const char *standard_sse_constant_opcode (rtx, rtx);
extern int symbolic_reference_mentioned_p (rtx);
extern bool extended_reg_mentioned_p (rtx);
extern bool x86_extended_QIreg_mentioned_p (rtx);
extern bool x86_extended_reg_mentioned_p (rtx);
-
-extern int any_fp_register_operand (rtx, enum machine_mode);
-extern int register_and_not_any_fp_reg_operand (rtx, enum machine_mode);
-
-extern int fp_register_operand (rtx, enum machine_mode);
-extern int register_and_not_fp_reg_operand (rtx, enum machine_mode);
-
-extern int x86_64_general_operand (rtx, enum machine_mode);
-extern int x86_64_szext_general_operand (rtx, enum machine_mode);
-extern int x86_64_nonmemory_operand (rtx, enum machine_mode);
-extern int x86_64_szext_nonmemory_operand (rtx, enum machine_mode);
-extern int x86_64_immediate_operand (rtx, enum machine_mode);
-extern int x86_64_zext_immediate_operand (rtx, enum machine_mode);
-extern int symbolic_operand (rtx, enum machine_mode);
-extern int tls_symbolic_operand (rtx, enum machine_mode);
-extern int global_dynamic_symbolic_operand (rtx, enum machine_mode);
-extern int local_dynamic_symbolic_operand (rtx, enum machine_mode);
-extern int initial_exec_symbolic_operand (rtx, enum machine_mode);
-extern int local_exec_symbolic_operand (rtx, enum machine_mode);
-extern int pic_symbolic_operand (rtx, enum machine_mode);
-extern int call_insn_operand (rtx, enum machine_mode);
-extern int sibcall_insn_operand (rtx, enum machine_mode);
-extern int constant_call_address_operand (rtx, enum machine_mode);
-extern int const0_operand (rtx, enum machine_mode);
-extern int const1_operand (rtx, enum machine_mode);
-extern int const248_operand (rtx, enum machine_mode);
-extern int incdec_operand (rtx, enum machine_mode);
-extern int reg_no_sp_operand (rtx, enum machine_mode);
-extern int mmx_reg_operand (rtx, enum machine_mode);
-extern int general_no_elim_operand (rtx, enum machine_mode);
-extern int nonmemory_no_elim_operand (rtx, enum machine_mode);
-extern int q_regs_operand (rtx, enum machine_mode);
-extern int non_q_regs_operand (rtx, enum machine_mode);
-extern int sse_comparison_operator (rtx, enum machine_mode);
-extern int fcmov_comparison_operator (rtx, enum machine_mode);
-extern int cmp_fp_expander_operand (rtx, enum machine_mode);
-extern int ix86_comparison_operator (rtx, enum machine_mode);
-extern int ext_register_operand (rtx, enum machine_mode);
-extern int binary_fp_operator (rtx, enum machine_mode);
-extern int mult_operator (rtx, enum machine_mode);
-extern int div_operator (rtx, enum machine_mode);
-extern int arith_or_logical_operator (rtx, enum machine_mode);
-extern int promotable_binary_operator (rtx, enum machine_mode);
-extern int memory_displacement_operand (rtx, enum machine_mode);
-extern int cmpsi_operand (rtx, enum machine_mode);
-extern int long_memory_operand (rtx, enum machine_mode);
-extern int aligned_operand (rtx, enum machine_mode);
-extern int compare_operator (rtx, enum machine_mode);
extern enum machine_mode ix86_cc_mode (enum rtx_code, rtx, rtx);
-extern int ix86_expand_movstr (rtx, rtx, rtx, rtx);
-extern int ix86_expand_clrstr (rtx, rtx, rtx);
+extern int ix86_expand_movmem (rtx, rtx, rtx, rtx);
+extern int ix86_expand_clrmem (rtx, rtx, rtx);
extern int ix86_expand_strlen (rtx, rtx, rtx, rtx);
extern bool legitimate_constant_p (rtx);
@@ -105,7 +59,6 @@ extern bool constant_address_p (rtx);
extern bool legitimate_pic_operand_p (rtx);
extern int legitimate_pic_address_disp_p (rtx);
extern int legitimate_address_p (enum machine_mode, rtx, int);
-extern rtx legitimize_pic_address (rtx, rtx);
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
extern void print_reg (rtx, int, FILE*);
@@ -116,22 +69,32 @@ extern bool output_addr_const_extra (FILE*, rtx);
extern void split_di (rtx[], int, rtx[], rtx[]);
extern void split_ti (rtx[], int, rtx[], rtx[]);
-extern const char *output_set_got (rtx);
+extern const char *output_set_got (rtx, rtx);
extern const char *output_387_binary_op (rtx, rtx*);
-extern const char *output_fix_trunc (rtx, rtx*);
+extern const char *output_387_reg_move (rtx, rtx*);
+extern const char *output_fix_trunc (rtx, rtx*, int);
extern const char *output_fp_compare (rtx, rtx*, int, int);
-extern void i386_dwarf_output_addr_const (FILE*, rtx);
-extern void i386_output_dwarf_dtprel (FILE*, int, rtx);
-
extern void ix86_expand_clear (rtx);
extern void ix86_expand_move (enum machine_mode, rtx[]);
extern void ix86_expand_vector_move (enum machine_mode, rtx[]);
+extern void ix86_expand_vector_move_misalign (enum machine_mode, rtx[]);
+extern void ix86_expand_push (enum machine_mode, rtx);
+extern rtx ix86_fixup_binary_operands (enum rtx_code,
+ enum machine_mode, rtx[]);
+extern void ix86_fixup_binary_operands_no_copy (enum rtx_code,
+ enum machine_mode, rtx[]);
extern void ix86_expand_binary_operator (enum rtx_code,
enum machine_mode, rtx[]);
extern int ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode,
rtx[]);
+extern rtx ix86_build_signbit_mask (enum machine_mode, bool, bool);
+extern void ix86_expand_fp_absneg_operator (enum rtx_code, enum machine_mode,
+ rtx[]);
+extern void ix86_expand_copysign (rtx []);
+extern void ix86_split_copysign_const (rtx []);
+extern void ix86_split_copysign_var (rtx []);
extern int ix86_unary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
extern int ix86_match_ccmode (rtx, enum machine_mode);
extern rtx ix86_expand_compare (enum rtx_code, rtx *, rtx *);
@@ -140,25 +103,25 @@ extern void ix86_expand_branch (enum rtx_code, rtx);
extern int ix86_expand_setcc (enum rtx_code, rtx);
extern int ix86_expand_int_movcc (rtx[]);
extern int ix86_expand_fp_movcc (rtx[]);
+extern bool ix86_expand_fp_vcond (rtx[]);
+extern bool ix86_expand_int_vcond (rtx[]);
extern int ix86_expand_int_addcc (rtx[]);
extern void ix86_expand_call (rtx, rtx, rtx, rtx, rtx, int);
extern void x86_initialize_trampoline (rtx, rtx, rtx);
extern rtx ix86_zero_extend_to_Pmode (rtx);
extern void ix86_split_long_move (rtx[]);
-extern void ix86_split_ashldi (rtx *, rtx);
-extern void ix86_split_ashrdi (rtx *, rtx);
-extern void ix86_split_lshrdi (rtx *, rtx);
+extern void ix86_split_ashl (rtx *, rtx, enum machine_mode);
+extern void ix86_split_ashr (rtx *, rtx, enum machine_mode);
+extern void ix86_split_lshr (rtx *, rtx, enum machine_mode);
extern rtx ix86_find_base_term (rtx);
extern int ix86_check_movabs (rtx, int);
-extern rtx assign_386_stack_local (enum machine_mode, int);
+extern rtx assign_386_stack_local (enum machine_mode, enum ix86_stack_slot);
extern int ix86_attr_length_immediate_default (rtx, int);
extern int ix86_attr_length_address_default (rtx);
extern enum machine_mode ix86_fp_compare_mode (enum rtx_code);
-extern int x86_64_sign_extended_value (rtx);
-extern int x86_64_zero_extended_value (rtx);
extern rtx ix86_libcall_value (enum machine_mode);
extern bool ix86_function_value_regno_p (int);
extern bool ix86_function_arg_regno_p (int);
@@ -166,36 +129,40 @@ extern int ix86_function_arg_boundary (enum machine_mode, tree);
extern int ix86_return_in_memory (tree);
extern void ix86_va_start (tree, rtx);
extern rtx ix86_va_arg (tree, tree);
-extern void ix86_setup_incoming_varargs (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int *, int);
extern rtx ix86_force_to_memory (enum machine_mode, rtx);
extern void ix86_free_from_memory (enum machine_mode);
-extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx, rtx, rtx, rtx);
-extern int ix86_hard_regno_mode_ok (int, enum machine_mode);
+extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
+ rtx, rtx, rtx, rtx);
+extern bool ix86_hard_regno_mode_ok (int, enum machine_mode);
+extern bool ix86_modes_tieable_p (enum machine_mode, enum machine_mode);
extern int ix86_register_move_cost (enum machine_mode, enum reg_class,
enum reg_class);
extern int ix86_secondary_memory_needed (enum reg_class, enum reg_class,
enum machine_mode, int);
+extern bool ix86_cannot_change_mode_class (enum machine_mode,
+ enum machine_mode, enum reg_class);
extern enum reg_class ix86_preferred_reload_class (rtx, enum reg_class);
+extern enum reg_class ix86_preferred_output_reload_class (rtx, enum reg_class);
extern int ix86_memory_move_cost (enum machine_mode, enum reg_class, int);
-extern void emit_i387_cw_initialization (rtx, rtx);
+extern int ix86_mode_needed (int, rtx);
+extern void emit_i387_cw_initialization (int);
extern bool ix86_fp_jump_nontrivial_p (enum rtx_code);
extern void x86_order_regs_for_local_alloc (void);
extern void x86_function_profiler (FILE *, int);
extern void x86_emit_floatuns (rtx [2]);
+extern void ix86_emit_fp_unordered_jump (rtx);
+
+extern void ix86_emit_i387_log1p (rtx, rtx);
+extern enum rtx_code ix86_reverse_condition (enum rtx_code, enum machine_mode);
#ifdef TREE_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
-extern int function_arg_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
tree, int);
-extern rtx ix86_function_value (tree);
-extern void ix86_init_builtins (void);
-extern rtx ix86_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+extern rtx ix86_function_value (tree, tree, bool);
#endif
#endif
@@ -206,27 +173,64 @@ extern int ix86_return_pops_args (tree, tree, int);
extern int ix86_data_alignment (tree, int);
extern int ix86_local_alignment (tree, int);
extern int ix86_constant_alignment (tree, int);
-extern tree ix86_handle_dll_attribute (tree *, tree, tree, int, bool *);
extern tree ix86_handle_shared_attribute (tree *, tree, tree, int, bool *);
+extern tree ix86_handle_selectany_attribute (tree *, tree, tree, int, bool *);
extern unsigned int i386_pe_section_type_flags (tree, const char *, int);
-extern void i386_pe_asm_named_section (const char *, unsigned int);
+extern void i386_pe_asm_named_section (const char *, unsigned int, tree);
extern int x86_field_alignment (tree, int);
#endif
extern rtx ix86_tls_get_addr (void);
-extern bool ix86_must_pass_in_stack (enum machine_mode mode, tree);
+extern rtx ix86_tls_module_base (void);
+
+extern void ix86_expand_vector_init (bool, rtx, rtx);
+extern void ix86_expand_vector_set (bool, rtx, rtx, int);
+extern void ix86_expand_vector_extract (bool, rtx, rtx, int);
+extern void ix86_expand_reduc_v4sf (rtx (*)(rtx, rtx, rtx), rtx, rtx);
-extern void ix86_expand_vector_init (rtx, rtx);
/* In winnt.c */
extern int i386_pe_dllexport_name_p (const char *);
extern int i386_pe_dllimport_name_p (const char *);
extern void i386_pe_unique_section (tree, int);
extern void i386_pe_declare_function_type (FILE *, const char *, int);
-extern void i386_pe_record_external_function (const char *);
+extern void i386_pe_record_external_function (tree, const char *);
extern void i386_pe_record_exported_symbol (const char *, int);
extern void i386_pe_asm_file_end (FILE *);
extern void i386_pe_encode_section_info (tree, rtx, int);
extern const char *i386_pe_strip_name_encoding (const char *);
extern const char *i386_pe_strip_name_encoding_full (const char *);
extern void i386_pe_output_labelref (FILE *, const char *);
+extern bool i386_pe_valid_dllimport_attribute_p (tree);
+
+/* In winnt-cxx.c and winnt-stubs.c */
+extern void i386_pe_adjust_class_at_definition (tree);
+extern bool i386_pe_type_dllimport_p (tree);
+extern bool i386_pe_type_dllexport_p (tree);
+
+extern rtx maybe_get_pool_constant (rtx);
+
+extern char internal_label_prefix[16];
+extern int internal_label_prefix_len;
+
+enum ix86_address_seg { SEG_DEFAULT, SEG_FS, SEG_GS };
+struct ix86_address
+{
+ rtx base, index, disp;
+ HOST_WIDE_INT scale;
+ enum ix86_address_seg seg;
+};
+
+extern int ix86_decompose_address (rtx, struct ix86_address *);
+extern int memory_address_length (rtx addr);
+extern void x86_output_aligned_bss (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, int);
+extern void x86_elf_aligned_common (FILE *, const char *,
+ unsigned HOST_WIDE_INT, int);
+
+#ifdef RTX_CODE
+extern void ix86_fp_comparison_codes (enum rtx_code code, enum rtx_code *,
+ enum rtx_code *, enum rtx_code *);
+extern enum rtx_code ix86_fp_compare_code_to_integer (enum rtx_code);
+#endif
+extern int asm_preferred_eh_data_format (int, int);
diff --git a/contrib/gcc/config/i386/i386.opt b/contrib/gcc/config/i386/i386.opt
new file mode 100644
index 0000000..2922f5d
--- /dev/null
+++ b/contrib/gcc/config/i386/i386.opt
@@ -0,0 +1,229 @@
+; Options for the IA-32 and AMD64 ports of the compiler.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+m128bit-long-double
+Target RejectNegative Report Mask(128BIT_LONG_DOUBLE)
+sizeof(long double) is 16
+
+m32
+Target RejectNegative Negative(m64) Report InverseMask(64BIT)
+Generate 32bit i386 code
+
+m386
+Target RejectNegative Undocumented
+;; Deprecated
+
+m3dnow
+Target Report Mask(3DNOW)
+Support 3DNow! built-in functions
+
+m486
+Target RejectNegative Undocumented
+;; Deprecated
+
+m64
+Target RejectNegative Negative(m32) Report Mask(64BIT)
+Generate 64bit x86-64 code
+
+m80387
+Target Report Mask(80387)
+Use hardware fp
+
+m96bit-long-double
+Target RejectNegative Report InverseMask(128BIT_LONG_DOUBLE)
+sizeof(long double) is 12
+
+maccumulate-outgoing-args
+Target Report Mask(ACCUMULATE_OUTGOING_ARGS)
+Reserve space for outgoing arguments in the function prologue
+
+malign-double
+Target Report Mask(ALIGN_DOUBLE)
+Align some doubles on dword boundary
+
+malign-functions=
+Target RejectNegative Joined Var(ix86_align_funcs_string)
+Function starts are aligned to this power of 2
+
+malign-jumps=
+Target RejectNegative Joined Var(ix86_align_jumps_string)
+Jump targets are aligned to this power of 2
+
+malign-loops=
+Target RejectNegative Joined Var(ix86_align_loops_string)
+Loop code aligned to this power of 2
+
+malign-stringops
+Target RejectNegative Report InverseMask(NO_ALIGN_STRINGOPS, ALIGN_STRINGOPS)
+Align destination of the string operations
+
+march=
+Target RejectNegative Joined Var(ix86_arch_string)
+Generate code for given CPU
+
+masm=
+Target RejectNegative Joined Var(ix86_asm_string)
+Use given assembler dialect
+
+mbranch-cost=
+Target RejectNegative Joined Var(ix86_branch_cost_string)
+Branches are this expensive (1-5, arbitrary units)
+
+mlarge-data-threshold=
+Target RejectNegative Joined Var(ix86_section_threshold_string)
+Data greater than given threshold will go into .ldata section in x86-64 medium model
+
+mcmodel=
+Target RejectNegative Joined Var(ix86_cmodel_string)
+Use given x86-64 code model
+
+mdebug-addr
+Target RejectNegative Var(TARGET_DEBUG_ADDR) Undocumented
+
+mdebug-arg
+Target RejectNegative Var(TARGET_DEBUG_ARG) Undocumented
+
+mfancy-math-387
+Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387)
+Generate sin, cos, sqrt for FPU
+
+mfp-ret-in-387
+Target Report Mask(FLOAT_RETURNS)
+Return values of functions in FPU registers
+
+mfpmath=
+Target RejectNegative Joined Var(ix86_fpmath_string)
+Generate floating point mathematics using given instruction set
+
+mhard-float
+Target RejectNegative Mask(80387) MaskExists
+Use hardware fp
+
+mieee-fp
+Target Report Mask(IEEE_FP)
+Use IEEE math for fp comparisons
+
+minline-all-stringops
+Target Report Mask(INLINE_ALL_STRINGOPS)
+Inline all known string operations
+
+mintel-syntax
+Target Undocumented
+;; Deprecated
+
+mmmx
+Target Report Mask(MMX)
+Support MMX built-in functions
+
+mms-bitfields
+Target Report Mask(MS_BITFIELD_LAYOUT)
+Use native (MS) bitfield layout
+
+mno-align-stringops
+Target RejectNegative Report Mask(NO_ALIGN_STRINGOPS) Undocumented
+
+mno-fancy-math-387
+Target RejectNegative Report Mask(NO_FANCY_MATH_387) Undocumented
+
+mno-push-args
+Target RejectNegative Report Mask(NO_PUSH_ARGS) Undocumented
+
+mno-red-zone
+Target RejectNegative Report Mask(NO_RED_ZONE) Undocumented
+
+momit-leaf-frame-pointer
+Target Report Mask(OMIT_LEAF_FRAME_POINTER)
+Omit the frame pointer in leaf functions
+
+mpentium
+Target RejectNegative Undocumented
+;; Deprecated
+
+mpentiumpro
+Target RejectNegative Undocumented
+;; Deprecated
+
+mpreferred-stack-boundary=
+Target RejectNegative Joined Var(ix86_preferred_stack_boundary_string)
+Attempt to keep stack aligned to this power of 2
+
+mpush-args
+Target Report InverseMask(NO_PUSH_ARGS, PUSH_ARGS)
+Use push instructions to save outgoing arguments
+
+mred-zone
+Target RejectNegative Report InverseMask(NO_RED_ZONE, RED_ZONE)
+Use red-zone in the x86-64 code
+
+mregparm=
+Target RejectNegative Joined Var(ix86_regparm_string)
+Number of registers used to pass integer arguments
+
+mrtd
+Target Report Mask(RTD)
+Alternate calling convention
+
+msoft-float
+Target InverseMask(80387)
+Do not use hardware fp
+
+msse
+Target Report Mask(SSE)
+Support MMX and SSE built-in functions and code generation
+
+msse2
+Target Report Mask(SSE2)
+Support MMX, SSE and SSE2 built-in functions and code generation
+
+msse3
+Target Report Mask(SSE3)
+Support MMX, SSE, SSE2 and SSE3 built-in functions and code generation
+
+msseregparm
+Target RejectNegative Mask(SSEREGPARM)
+Use SSE register passing conventions for SF and DF mode
+
+mstackrealign
+Target Report Var(ix86_force_align_arg_pointer)
+Realign stack in prologue
+
+msvr3-shlib
+Target Report Mask(SVR3_SHLIB)
+Uninitialized locals in .bss
+
+mstack-arg-probe
+Target Report Mask(STACK_PROBE)
+Enable stack probing
+
+mtls-dialect=
+Target RejectNegative Joined Var(ix86_tls_dialect_string)
+Use given thread-local storage dialect
+
+mtls-direct-seg-refs
+Target Report Mask(TLS_DIRECT_SEG_REFS)
+Use direct references against %gs when accessing tls data
+
+mtune=
+Target RejectNegative Joined Var(ix86_tune_string)
+Schedule code for given CPU
+
+;; Support Athlon 3Dnow builtins
+Mask(3DNOW_A)
diff --git a/contrib/gcc/config/i386/i386elf.h b/contrib/gcc/config/i386/i386elf.h
index ed6b41a..d99fe62 100644
--- a/contrib/gcc/config/i386/i386elf.h
+++ b/contrib/gcc/config/i386/i386elf.h
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Use stabs instead of DWARF debug format. */
#undef PREFERRED_DEBUGGING_TYPE
diff --git a/contrib/gcc/config/i386/k6.md b/contrib/gcc/config/i386/k6.md
index edd12f6..e0006ae 100644
--- a/contrib/gcc/config/i386/k6.md
+++ b/contrib/gcc/config/i386/k6.md
@@ -1,5 +1,6 @@
;; AMD K6/K6-2 Scheduling
-;; Copyright (C) 2002 ;; Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004
+;; Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,122 +16,253 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;
-;; The K6 has similar architecture to PPro. Important difference is, that
-;; there are only two decoders and they seems to be much slower than execution
-;; units. So we have to pay much more attention to proper decoding for
-;; schedulers. We share most of scheduler code for PPro in i386.c
+;; The K6 architecture is quite similar to PPro. Important difference is
+;; that there are only two decoders and they seems to be much slower than
+;; any of the execution units. So we have to pay much more attention to
+;; proper scheduling for the decoders.
+;; FIXME: We don't do that right now. A good start would be to sort the
+;; instructions based on length.
;;
-;; The fp unit is not pipelined and do one operation per two cycles including
-;; the FXCH.
+;; This description is based on data from the following documents:
;;
-;; alu describes both ALU units (ALU-X and ALU-Y).
-;; alux describes X alu unit
-;; fpu describes FPU unit
-;; load describes load unit.
-;; branch describes branch unit.
-;; store describes store unit. This unit is not modelled completely and only
-;; used to model lea operation. Otherwise it lie outside of the critical
-;; path.
+;; "AMD-K6 Processor Data Sheet (Preliminary information)"
+;; Advanced Micro Devices, Inc., 1998.
+;;
+;; "AMD-K6 Processor Code Optimization Application Note"
+;; Advanced Micro Devices, Inc., 2000.
+;;
+;; CPU execution units of the K6:
+;;
+;; store describes the Store unit. This unit is not modelled
+;; completely and it is only used to model lea operation.
+;; Otherwise it lies outside of any critical path.
+;; load describes the Load unit
+;; alux describes the Integer X unit
+;; mm describes the Multimedia unit, which shares a pipe
+;; with the Integer X unit. This unit is used for MMX,
+;; which is not implemented for K6.
+;; aluy describes the Integer Y unit
+;; fpu describes the FPU unit
+;; branch describes the Branch unit
+;;
+;; The fp unit is not pipelined, and it can only do one operation per two
+;; cycles, including fxcg.
+;;
+;; Generally this is a very poor description, but at least no worse than
+;; the old description, and a lot easier to extend to something more
+;; reasonable if anyone still cares enough about this architecture in 2004.
;;
;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
-;; The decoder specification is in the PPro section above!
-
-;; Shift instructions and certain arithmetic are issued only to X pipe.
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld"))
- 1 1)
-
-;; The QI mode arithmetic is issued to X pipe only.
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec")
- (eq_attr "mode" "QI")))
- 1 1)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,alu,icmp,test,imovx,incdec,setcc,lea"))
- 1 1)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "imov")
- (eq_attr "memory" "none")))
- 1 1)
-
-(define_function_unit "k6_branch" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "call,callv,ibr"))
- 1 1)
-
-;; Load unit have two cycle latency, but we take care for it in adjust_cost
-(define_function_unit "k6_load" 1 0
- (and (eq_attr "cpu" "k6")
- (ior (eq_attr "type" "pop,leave")
- (eq_attr "memory" "load,both")))
- 1 1)
-
-(define_function_unit "k6_load" 1 0
- (and (eq_attr "cpu" "k6")
- (and (eq_attr "type" "str")
- (eq_attr "memory" "load,both")))
- 10 10)
-
-;; Lea have two instructions, so latency is probably 2
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "lea"))
- 2 1)
-
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "str"))
- 10 10)
-
-(define_function_unit "k6_store" 1 0
- (and (eq_attr "cpu" "k6")
- (ior (eq_attr "type" "push")
- (eq_attr "memory" "store,both")))
- 1 1)
-
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fop,fmov,fcmp,fistp"))
- 2 2)
-
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fmul"))
- 2 2)
-
-;; ??? Guess
-(define_function_unit "k6_fpu" 1 1
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "fdiv,fpspc"))
- 56 56)
-
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "imul"))
- 2 2)
-
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "imul"))
- 2 2)
-
-;; ??? Guess
-(define_function_unit "k6_alu" 2 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "idiv"))
- 17 17)
-
-(define_function_unit "k6_alux" 1 0
- (and (eq_attr "cpu" "k6")
- (eq_attr "type" "idiv"))
- 17 17)
+(define_automaton "k6_decoder,k6_load_unit,k6_store_unit,k6_integer_units,k6_fpu_unit,k6_branch_unit")
+
+;; The K6 instruction decoding begins before the on-chip instruction cache is
+;; filled. Depending on the length of the instruction, two simple instructions
+;; can be decoded in two parallel short decoders, or one complex instruction can
+;; be decoded in either the long or the vector decoder. For all practical
+;; purposes, the long and vector decoder can be modelled as one decoder.
+(define_cpu_unit "k6_decode_short0" "k6_decoder")
+(define_cpu_unit "k6_decode_short1" "k6_decoder")
+(define_cpu_unit "k6_decode_long" "k6_decoder")
+(exclusion_set "k6_decode_long" "k6_decode_short0,k6_decode_short1")
+(define_reservation "k6_decode_short" "k6_decode_short0|k6_decode_short1")
+(define_reservation "k6_decode_vector" "k6_decode_long")
+
+(define_cpu_unit "k6_store" "k6_store_unit")
+(define_cpu_unit "k6_load" "k6_load_unit")
+(define_cpu_unit "k6_alux,k6_aluy" "k6_integer_units")
+(define_cpu_unit "k6_fpu" "k6_fpu_unit")
+(define_cpu_unit "k6_branch" "k6_branch_unit")
+
+;; Shift instructions and certain arithmetic are issued only on Integer X.
+(define_insn_reservation "k6_alux_only" 1
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld")
+ (eq_attr "memory" "none")))
+ "k6_decode_short,k6_alux")
+
+(define_insn_reservation "k6_alux_only_load" 3
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld")
+ (eq_attr "memory" "load")))
+ "k6_decode_short,k6_load,k6_alux")
+
+(define_insn_reservation "k6_alux_only_store" 3
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "ishift,ishift1,rotate,rotate1,alu1,negnot,cld")
+ (eq_attr "memory" "store,both,unknown")))
+ "k6_decode_long,k6_load,k6_alux,k6_store")
+
+;; Integer divide and multiply can only be issued on Integer X, too.
+(define_insn_reservation "k6_alu_imul" 2
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "imul"))
+ "k6_decode_vector,k6_alux*3")
+
+(define_insn_reservation "k6_alu_imul_load" 4
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imul")
+ (eq_attr "memory" "load")))
+ "k6_decode_vector,k6_load,k6_alux*3")
+
+(define_insn_reservation "k6_alu_imul_store" 4
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imul")
+ (eq_attr "memory" "store,both,unknown")))
+ "k6_decode_vector,k6_load,k6_alux*3,k6_store")
+
+;; ??? Guessed latencies based on the old pipeline description.
+(define_insn_reservation "k6_alu_idiv" 17
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "memory" "none")))
+ "k6_decode_vector,k6_alux*17")
+
+(define_insn_reservation "k6_alu_idiv_mem" 19
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "memory" "!none")))
+ "k6_decode_vector,k6_load,k6_alux*17")
+
+;; Basic word and doubleword ALU ops can be issued on both Integer units.
+(define_insn_reservation "k6_alu" 1
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec,setcc")
+ (eq_attr "memory" "none")))
+ "k6_decode_short,k6_alux|k6_aluy")
+
+(define_insn_reservation "k6_alu_load" 3
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec,setcc")
+ (eq_attr "memory" "load")))
+ "k6_decode_short,k6_load,k6_alux|k6_aluy")
+
+(define_insn_reservation "k6_alu_store" 3
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "alu,alu1,negnot,icmp,test,imovx,incdec,setcc")
+ (eq_attr "memory" "store,both,unknown")))
+ "k6_decode_long,k6_load,k6_alux|k6_aluy,k6_store")
+
+;; A "load immediate" operation does not require execution at all,
+;; it is available immediately after decoding. Special-case this.
+(define_insn_reservation "k6_alu_imov" 1
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (and (eq_attr "memory" "none")
+ (match_operand 1 "nonimmediate_operand"))))
+ "k6_decode_short,k6_alux|k6_aluy")
+
+(define_insn_reservation "k6_alu_imov_imm" 0
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (and (eq_attr "memory" "none")
+ (match_operand 1 "immediate_operand"))))
+ "k6_decode_short")
+
+(define_insn_reservation "k6_alu_imov_load" 2
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "load")))
+ "k6_decode_short,k6_load")
+
+(define_insn_reservation "k6_alu_imov_store" 1
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "store")))
+ "k6_decode_short,k6_store")
+
+(define_insn_reservation "k6_alu_imov_both" 2
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "imov")
+ (eq_attr "memory" "both,unknown")))
+ "k6_decode_long,k6_load,k6_alux|k6_aluy")
+
+;; The branch unit.
+(define_insn_reservation "k6_branch_call" 1
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "call,callv"))
+ "k6_decode_vector,k6_branch")
+
+(define_insn_reservation "k6_branch_branch" 1
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "ibr"))
+ "k6_decode_short,k6_branch")
+
+;; The load and units have two pipeline stages. The load latency is
+;; two cycles.
+(define_insn_reservation "k6_load_pop" 3
+ (and (eq_attr "cpu" "k6")
+ (ior (eq_attr "type" "pop")
+ (eq_attr "memory" "load,both")))
+ "k6_decode_short,k6_load")
+
+(define_insn_reservation "k6_load_leave" 5
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "leave"))
+ "k6_decode_long,k6_load,(k6_alux|k6_aluy)*2")
+
+;; ??? From the old pipeline description. Egad!
+;; ??? Apparently we take care of this reservation in adjust_cost.
+(define_insn_reservation "k6_load_str" 10
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "str")
+ (eq_attr "memory" "load,both")))
+ "k6_decode_vector,k6_load*10")
+
+;; The store unit handles lea and push. It is otherwise unmodelled.
+(define_insn_reservation "k6_store_lea" 2
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "lea"))
+ "k6_decode_short,k6_store,k6_alux|k6_aluy")
+
+(define_insn_reservation "k6_store_push" 2
+ (and (eq_attr "cpu" "k6")
+ (ior (eq_attr "type" "push")
+ (eq_attr "memory" "store,both")))
+ "k6_decode_short,k6_store")
+
+(define_insn_reservation "k6_store_str" 10
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "str"))
+ "k6_store*10")
+
+;; Most FPU instructions have latency 2 and throughput 2.
+(define_insn_reservation "k6_fpu" 2
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "fop,fmov,fcmp,fistp")
+ (eq_attr "memory" "none")))
+ "k6_decode_vector,k6_fpu*2")
+
+(define_insn_reservation "k6_fpu_load" 6
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "fop,fmov,fcmp,fistp")
+ (eq_attr "memory" "load,both")))
+ "k6_decode_short,k6_load,k6_fpu*2")
+
+(define_insn_reservation "k6_fpu_store" 6
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "fop,fmov,fcmp,fistp")
+ (eq_attr "memory" "store")))
+ "k6_decode_short,k6_store,k6_fpu*2")
+
+(define_insn_reservation "k6_fpu_fmul" 2
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "memory" "none")))
+ "k6_decode_short,k6_fpu*2")
+
+(define_insn_reservation "k6_fpu_fmul_load" 2
+ (and (eq_attr "cpu" "k6")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "memory" "load,both")))
+ "k6_decode_short,k6_load,k6_fpu*2")
+
+;; ??? Guessed latencies from the old pipeline description.
+(define_insn_reservation "k6_fpu_expensive" 56
+ (and (eq_attr "cpu" "k6")
+ (eq_attr "type" "fdiv,fpspc"))
+ "k6_decode_short,k6_fpu*56")
+
diff --git a/contrib/gcc/config/i386/kaos-i386.h b/contrib/gcc/config/i386/kaos-i386.h
index 3fdf883..fdf9ad2 100644
--- a/contrib/gcc/config/i386/kaos-i386.h
+++ b/contrib/gcc/config/i386/kaos-i386.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (i386/kaOS[ELF])", stderr);
diff --git a/contrib/gcc/config/i386/kfreebsd-gnu.h b/contrib/gcc/config/i386/kfreebsd-gnu.h
new file mode 100644
index 0000000..5e73815
--- /dev/null
+++ b/contrib/gcc/config/i386/kfreebsd-gnu.h
@@ -0,0 +1,26 @@
+/* Definitions for Intel 386 running kFreeBSD-based GNU systems with ELF format
+ Copyright (C) 2004
+ Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef LINK_EMULATION
+#define LINK_EMULATION "elf_i386_fbsd"
+#undef REG_NAME
+#define REG_NAME(reg) sc_ ## reg
diff --git a/contrib/gcc/config/i386/knetbsd-gnu.h b/contrib/gcc/config/i386/knetbsd-gnu.h
new file mode 100644
index 0000000..4892c3f
--- /dev/null
+++ b/contrib/gcc/config/i386/knetbsd-gnu.h
@@ -0,0 +1,24 @@
+/* Definitions for Intel 386 running kNetBSD-based GNU systems with ELF format
+ Copyright (C) 2004
+ Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef REG_NAME
+#define REG_NAME(reg) sc_ ## reg
diff --git a/contrib/gcc/config/i386/linux-unwind.h b/contrib/gcc/config/i386/linux-unwind.h
new file mode 100644
index 0000000..07979d3
--- /dev/null
+++ b/contrib/gcc/config/i386/linux-unwind.h
@@ -0,0 +1,181 @@
+/* DWARF2 EH unwinding support for AMD x86-64 and x86.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+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 with other programs, and to distribute
+those programs 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 another program.)
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs.
+ Don't use this at all if inhibit_libc is used. */
+
+#ifndef inhibit_libc
+
+#ifdef __x86_64__
+
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#define MD_FALLBACK_FRAME_STATE_FOR x86_64_fallback_frame_state
+
+static _Unwind_Reason_Code
+x86_64_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned char *pc = context->ra;
+ struct sigcontext *sc;
+ long new_cfa;
+
+ /* movq __NR_rt_sigreturn, %rax ; syscall */
+ if (*(unsigned char *)(pc+0) == 0x48
+ && *(unsigned long *)(pc+1) == 0x050f0000000fc0c7)
+ {
+ struct ucontext *uc_ = context->cfa;
+ /* The void * cast is necessary to avoid an aliasing warning.
+ The aliasing warning is correct, but should not be a problem
+ because it does not alias anything. */
+ sc = (struct sigcontext *) (void *) &uc_->uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->rsp;
+ fs->cfa_how = CFA_REG_OFFSET;
+ /* Register 7 is rsp */
+ fs->cfa_reg = 7;
+ 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->rax - new_cfa;
+ fs->regs.reg[1].how = REG_SAVED_OFFSET;
+ fs->regs.reg[1].loc.offset = (long)&sc->rdx - new_cfa;
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long)&sc->rcx - new_cfa;
+ fs->regs.reg[3].how = REG_SAVED_OFFSET;
+ fs->regs.reg[3].loc.offset = (long)&sc->rbx - new_cfa;
+ fs->regs.reg[4].how = REG_SAVED_OFFSET;
+ fs->regs.reg[4].loc.offset = (long)&sc->rsi - new_cfa;
+ fs->regs.reg[5].how = REG_SAVED_OFFSET;
+ fs->regs.reg[5].loc.offset = (long)&sc->rdi - new_cfa;
+ fs->regs.reg[6].how = REG_SAVED_OFFSET;
+ fs->regs.reg[6].loc.offset = (long)&sc->rbp - new_cfa;
+ fs->regs.reg[8].how = REG_SAVED_OFFSET;
+ fs->regs.reg[8].loc.offset = (long)&sc->r8 - new_cfa;
+ fs->regs.reg[9].how = REG_SAVED_OFFSET;
+ fs->regs.reg[9].loc.offset = (long)&sc->r9 - new_cfa;
+ fs->regs.reg[10].how = REG_SAVED_OFFSET;
+ fs->regs.reg[10].loc.offset = (long)&sc->r10 - new_cfa;
+ fs->regs.reg[11].how = REG_SAVED_OFFSET;
+ fs->regs.reg[11].loc.offset = (long)&sc->r11 - new_cfa;
+ fs->regs.reg[12].how = REG_SAVED_OFFSET;
+ fs->regs.reg[12].loc.offset = (long)&sc->r12 - new_cfa;
+ fs->regs.reg[13].how = REG_SAVED_OFFSET;
+ fs->regs.reg[13].loc.offset = (long)&sc->r13 - new_cfa;
+ fs->regs.reg[14].how = REG_SAVED_OFFSET;
+ fs->regs.reg[14].loc.offset = (long)&sc->r14 - new_cfa;
+ fs->regs.reg[15].how = REG_SAVED_OFFSET;
+ fs->regs.reg[15].loc.offset = (long)&sc->r15 - new_cfa;
+ fs->regs.reg[16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[16].loc.offset = (long)&sc->rip - new_cfa;
+ fs->retaddr_column = 16;
+ fs->signal_frame = 1;
+ return _URC_NO_REASON;
+}
+
+#else /* ifdef __x86_64__ */
+
+/* There's no sys/ucontext.h for glibc 2.0, so no
+ signal-turned-exceptions for them. There's also no configure-run for
+ the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the
+ target libc version macro should be enough. */
+#if !(__GLIBC__ == 2 && __GLIBC_MINOR__ == 0)
+
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#define MD_FALLBACK_FRAME_STATE_FOR x86_fallback_frame_state
+
+static _Unwind_Reason_Code
+x86_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ 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;
+ /* The void * cast is necessary to avoid an aliasing warning.
+ The aliasing warning is correct, but should not be a problem
+ because it does not alias anything. */
+ sc = (struct sigcontext *) (void *) &rt_->uc.uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = sc->REG_NAME(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->REG_NAME(eax) - new_cfa;
+ fs->regs.reg[3].how = REG_SAVED_OFFSET;
+ fs->regs.reg[3].loc.offset = (long)&sc->REG_NAME(ebx) - new_cfa;
+ fs->regs.reg[1].how = REG_SAVED_OFFSET;
+ fs->regs.reg[1].loc.offset = (long)&sc->REG_NAME(ecx) - new_cfa;
+ fs->regs.reg[2].how = REG_SAVED_OFFSET;
+ fs->regs.reg[2].loc.offset = (long)&sc->REG_NAME(edx) - new_cfa;
+ fs->regs.reg[6].how = REG_SAVED_OFFSET;
+ fs->regs.reg[6].loc.offset = (long)&sc->REG_NAME(esi) - new_cfa;
+ fs->regs.reg[7].how = REG_SAVED_OFFSET;
+ fs->regs.reg[7].loc.offset = (long)&sc->REG_NAME(edi) - new_cfa;
+ fs->regs.reg[5].how = REG_SAVED_OFFSET;
+ fs->regs.reg[5].loc.offset = (long)&sc->REG_NAME(ebp) - new_cfa;
+ fs->regs.reg[8].how = REG_SAVED_OFFSET;
+ fs->regs.reg[8].loc.offset = (long)&sc->REG_NAME(eip) - new_cfa;
+ fs->retaddr_column = 8;
+ fs->signal_frame = 1;
+ return _URC_NO_REASON;
+}
+#endif /* not glibc 2.0 */
+#endif /* ifdef __x86_64__ */
+#endif /* ifdef inhibit_libc */
diff --git a/contrib/gcc/config/i386/linux.h b/contrib/gcc/config/i386/linux.h
index e7d19ec..7eb2395 100644
--- a/contrib/gcc/config/i386/linux.h
+++ b/contrib/gcc/config/i386/linux.h
@@ -1,6 +1,6 @@
/* Definitions for Intel 386 running Linux-based GNU systems with ELF format.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002
- Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu.
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Output at beginning of assembler file. */
/* The .file command should always begin the output. */
@@ -74,20 +74,11 @@ Boston, MA 02111-1307, USA. */
do \
{ \
LINUX_TARGET_OS_CPP_BUILTINS(); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
#undef CPP_SPEC
-#ifdef USE_GNULIBC_1
-#define CPP_SPEC "%{posix:-D_POSIX_SOURCE}"
-#else
#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
-#endif
#undef CC1_SPEC
#define CC1_SPEC "%(cc1_cpu) %{profile:-p}"
@@ -108,24 +99,29 @@ Boston, MA 02111-1307, USA. */
/* If ELF is the default format, we should not use /lib/elf. */
+/* These macros may be overridden in k*bsd-gnu.h and i386/k*bsd-gnu.h. */
+#define LINK_EMULATION "elf_i386"
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "link_emulation", LINK_EMULATION },\
+ { "dynamic_linker", LINUX_DYNAMIC_LINKER }
+
#undef LINK_SPEC
-#ifdef USE_GNULIBC_1
-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
- %{!shared: \
- %{!ibcs: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
- %{static:-static}}}"
-#else
-#define LINK_SPEC "-m elf_i386 %{shared:-shared} \
+#define LINK_SPEC "-m %(link_emulation) %{shared:-shared} \
%{!shared: \
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{!dynamic-linker:-dynamic-linker %(dynamic_linker)}} \
%{static:-static}}}"
-#endif
+
+/* Similar to standard Linux, but adding -ffast-math support. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
/* A C statement (sans semicolon) to output to the stdio stream
FILE the assembler definition of uninitialized global DECL named
@@ -151,24 +147,6 @@ 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 do this by forcing the assembler to create undefined
- references to these symbols in the object file. */
-#undef CRT_CALL_STATIC_FUNCTION
-#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
- asm (SECTION_OP "\n\t" \
- "call " USER_LABEL_PREFIX #FUNC "\n" \
- TEXT_SECTION_ASM_OP "\n\t" \
- ".extern ___brk_addr\n\t" \
- ".type ___brk_addr,@object\n\t" \
- ".extern __environ\n\t" \
- ".type __environ,@object\n\t" \
- ".extern atexit\n\t" \
- ".type atexit,@function");
-#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) \
@@ -205,70 +183,12 @@ Boston, MA 02111-1307, USA. */
#undef NEED_INDICATE_EXEC_STACK
#define NEED_INDICATE_EXEC_STACK 1
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
+#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
-#ifdef IN_LIBGCC2
-/* There's no sys/ucontext.h for some (all?) libc1, so no
- signal-turned-exceptions for them. There's also no configure-run for
- the target, so we can't check on (e.g.) HAVE_SYS_UCONTEXT_H. Using the
- target libc1 macro should be enough. */
-#if !(defined (USE_GNULIBC_1) || (__GLIBC__ == 2 && __GLIBC_MINOR__ == 0))
-#include <signal.h>
-#include <sys/ucontext.h>
+/* This macro may be overridden in i386/k*bsd-gnu.h. */
+#define REG_NAME(reg) reg
-#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)
-#endif /* not USE_GNULIBC_1 */
-#endif /* IN_LIBGCC2 */
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* i386 glibc provides __stack_chk_guard in %gs:0x14. */
+#define TARGET_THREAD_SSP_OFFSET 0x14
+#endif
diff --git a/contrib/gcc/config/i386/linux64.h b/contrib/gcc/config/i386/linux64.h
index 98536c1..cc8ed16 100644
--- a/contrib/gcc/config/i386/linux64.h
+++ b/contrib/gcc/config/i386/linux64.h
@@ -1,5 +1,5 @@
/* Definitions for AMD x86-64 running Linux-based GNU systems with ELF format.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Jan Hubicka <jh@suse.cz>, based on linux.h.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (x86-64 Linux/ELF)");
@@ -25,11 +25,6 @@ Boston, MA 02111-1307, USA. */
do \
{ \
LINUX_TARGET_OS_CPP_BUILTINS(); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
@@ -54,143 +49,37 @@ Boston, MA 02111-1307, USA. */
When the -shared link option is used a final link is not being
done. */
+#define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
+#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2"
+
#undef LINK_SPEC
#define LINK_SPEC "%{!m32:-m elf_x86_64} %{m32:-m elf_i386} \
%{shared:-shared} \
%{!shared: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{m32:%{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
- %{!m32:%{!dynamic-linker:-dynamic-linker /lib64/ld-linux-x86-64.so.2}}} \
+ %{m32:%{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER32 "}} \
+ %{!m32:%{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}}} \
%{static:-static}}"
+/* Similar to standard Linux, but adding -ffast-math support. */
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ %{shared|pie:crtendS.o%s;:crtend.o%s} crtn.o%s"
+
#define MULTILIB_DEFAULTS { "m64" }
#undef NEED_INDICATE_EXEC_STACK
#define NEED_INDICATE_EXEC_STACK 1
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs.
- Don't use this at all if inhibit_libc is used. */
+#define MD_UNWIND_SUPPORT "config/i386/linux-unwind.h"
-#ifndef inhibit_libc
-#ifdef IN_LIBGCC2
-#include <signal.h>
-#include <sys/ucontext.h>
-#endif
+/* This macro may be overridden in i386/k*bsd-gnu.h. */
+#define REG_NAME(reg) reg
-#ifdef __x86_64__
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- struct sigcontext *sc_; \
- long new_cfa_; \
- \
- /* movq __NR_rt_sigreturn, %rax ; syscall */ \
- if (*(unsigned char *)(pc_+0) == 0x48 \
- && *(unsigned long *)(pc_+1) == 0x050f0000000fc0c7) \
- { \
- struct ucontext *uc_ = (CONTEXT)->cfa; \
- sc_ = (struct sigcontext *) &uc_->uc_mcontext; \
- } \
- else \
- break; \
- \
- new_cfa_ = sc_->rsp; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- /* Register 7 is rsp */ \
- (FS)->cfa_reg = 7; \
- (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_->rax - new_cfa_; \
- (FS)->regs.reg[1].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[1].loc.offset = (long)&sc_->rdx - new_cfa_; \
- (FS)->regs.reg[2].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[2].loc.offset = (long)&sc_->rcx - new_cfa_; \
- (FS)->regs.reg[3].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[3].loc.offset = (long)&sc_->rbx - new_cfa_; \
- (FS)->regs.reg[4].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[4].loc.offset = (long)&sc_->rsi - new_cfa_; \
- (FS)->regs.reg[5].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[5].loc.offset = (long)&sc_->rdi - new_cfa_; \
- (FS)->regs.reg[6].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[6].loc.offset = (long)&sc_->rbp - new_cfa_; \
- (FS)->regs.reg[8].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[8].loc.offset = (long)&sc_->r8 - new_cfa_; \
- (FS)->regs.reg[9].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[9].loc.offset = (long)&sc_->r9 - new_cfa_; \
- (FS)->regs.reg[10].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[10].loc.offset = (long)&sc_->r10 - new_cfa_; \
- (FS)->regs.reg[11].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[11].loc.offset = (long)&sc_->r11 - new_cfa_; \
- (FS)->regs.reg[12].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[12].loc.offset = (long)&sc_->r12 - new_cfa_; \
- (FS)->regs.reg[13].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[13].loc.offset = (long)&sc_->r13 - new_cfa_; \
- (FS)->regs.reg[14].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[14].loc.offset = (long)&sc_->r14 - new_cfa_; \
- (FS)->regs.reg[15].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[15].loc.offset = (long)&sc_->r15 - new_cfa_; \
- (FS)->regs.reg[16].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[16].loc.offset = (long)&sc_->rip - new_cfa_; \
- (FS)->retaddr_column = 16; \
- goto SUCCESS; \
- } while (0)
-#else /* ifdef __x86_64__ */
-#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)
-#endif /* ifdef __x86_64__ */
-#endif /* ifdef inhibit_libc */
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* i386 glibc provides __stack_chk_guard in %gs:0x14,
+ x86_64 glibc provides it in %fs:0x28. */
+#define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? 0x28 : 0x14)
+#endif
diff --git a/contrib/gcc/config/i386/lynx.h b/contrib/gcc/config/i386/lynx.h
index a926d14..799225a 100644
--- a/contrib/gcc/config/i386/lynx.h
+++ b/contrib/gcc/config/i386/lynx.h
@@ -1,5 +1,6 @@
-/* Definitions for Intel 386 running LynxOS.
- Copyright (C) 1993, 1995, 1996, 2002 Free Software Foundation, Inc.
+/* Definitions for LynxOS on i386.
+ Copyright (C) 1993, 1995, 1996, 2002, 2004, 2005
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,57 +16,76 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
-#define TARGET_VERSION fprintf (stderr, " (80386, LYNX BSD syntax)");
+#define TARGET_VERSION fputs (" (i386/LynxOS)", stderr);
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define_std ("I386"); \
- builtin_define_std ("Lynx"); \
- builtin_define_std ("IBITS32"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=lynx"); \
+ builtin_define ("__LITTLE_ENDIAN__"); \
+ builtin_define ("__x86__"); \
} \
while (0)
-/* The prefix to add to user-visible assembler symbols. */
+/* The svr4 ABI for the i386 says that records and unions are returned
+ in memory. */
-/* Override the svr3 convention of adding a leading underscore. */
+#define DEFAULT_PCC_STRUCT_RETURN 1
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
+/* BSS_SECTION_ASM_OP gets defined i386/unix.h. */
-/* Apparently LynxOS clobbers ebx when you call into the OS. */
+#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
+ asm_output_aligned_bss (FILE, DECL, NAME, SIZE, ALIGN)
-#undef CALL_USED_REGISTERS
-#define CALL_USED_REGISTERS \
-/*ax,dx,cx,bx,si,di,bp,sp,st,st1,st2,st3,st4,st5,st6,st7,arg*/ \
-{ 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }
+/* LynxOS's GDB counts the floating point registers from 16. */
-/* Prefix for internally generated assembler labels. If we aren't using
- underscores, we are using prefix `.'s to identify labels that should
- be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) \
+ (TARGET_64BIT ? dbx64_register_map[n] \
+ : (n) == 0 ? 0 \
+ : (n) == 1 ? 2 \
+ : (n) == 2 ? 1 \
+ : (n) == 3 ? 3 \
+ : (n) == 4 ? 6 \
+ : (n) == 5 ? 7 \
+ : (n) == 6 ? 5 \
+ : (n) == 7 ? 4 \
+ : ((n) >= FIRST_STACK_REG && (n) <= LAST_STACK_REG) ? (n) + 8 \
+ : (-1))
+
+/* A C statement to output to the stdio stream FILE an assembler
+ command to advance the location counter to a multiple of 1<<LOG
+ bytes if it is within MAX_SKIP bytes.
-#undef LPREFIX
-#define LPREFIX ".L"
+ This is used to align code labels according to Intel recommendations. */
-/* The prefix to add to user-visible assembler symbols. */
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ do { \
+ if ((LOG) != 0) { \
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ } \
+ } while (0)
+#endif
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
+/* Undefine SUBTARGET_EXTRA_SPECS it is empty anyway. We define it in
+ config/lynx.h. */
-/* If user-symbols don't have underscores,
- then it must take more than `L' to identify
- a label that should be ignored. */
+#undef SUBTARGET_EXTRA_SPECS
-/* This is how to store into the string BUF
- the symbol_ref name of an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class.
- This is suitable for output with `assemble_name'. */
+/* Undefine the definition from att.h to enable our default. */
-#undef ASM_GENERATE_INTERNAL_LABEL
-#define ASM_GENERATE_INTERNAL_LABEL(BUF,PREFIX,NUMBER) \
- sprintf ((BUF), ".%s%ld", (PREFIX), (long)(NUMBER))
+#undef ASM_OUTPUT_ALIGN
+
+/* Undefine the definition from elfos.h to enable our default. */
+
+#undef PREFERRED_DEBUGGING_TYPE
+
+/* The file i386.c defines TARGET_HAVE_TLS unconditionally if
+ HAVE_AS_TLS is defined. HAVE_AS_TLS is defined as gas support for
+ TLS is detected by configure. We undefine it here. */
+
+#undef HAVE_AS_TLS
diff --git a/contrib/gcc/config/i386/mingw32.h b/contrib/gcc/config/i386/mingw32.h
index 4bf0dda..6fd5d94 100644
--- a/contrib/gcc/config/i386/mingw32.h
+++ b/contrib/gcc/config/i386/mingw32.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
hosting on Windows32, using GNU tools and the Windows32 API Library.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (x86 MinGW)");
@@ -69,9 +69,13 @@ Boston, MA 02111-1307, USA. */
#define STARTFILE_SPEC "%{shared|mdll:dllcrt2%O%s} \
%{!shared:%{!mdll:crt2%O%s}} %{pg:gcrt2%O%s}"
-/* An additional prefix to try after the standard prefixes. */
-#undef MD_STARTFILE_PREFIX
-#define MD_STARTFILE_PREFIX "/mingw/lib/"
+/* Override startfile prefix defaults. */
+#ifndef STANDARD_STARTFILE_PREFIX_1
+#define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib/"
+#endif
+#ifndef STANDARD_STARTFILE_PREFIX_2
+#define STANDARD_STARTFILE_PREFIX_2 ""
+#endif
/* Output STRING, a string representing a filename, to FILE.
We canonicalize it to be in Unix format (backslashes are replaced
@@ -104,3 +108,7 @@ do { \
/* Define as short unsigned for compatibility with MS runtime. */
#undef WINT_TYPE
#define WINT_TYPE "short unsigned int"
+
+/* mingw32 uses the -mthreads option to enable thread support. */
+#undef GOMP_SELF_SPECS
+#define GOMP_SELF_SPECS "%{fopenmp: -mthreads}"
diff --git a/contrib/gcc/config/i386/mm3dnow.h b/contrib/gcc/config/i386/mm3dnow.h
new file mode 100644
index 0000000..7fdc6dc
--- /dev/null
+++ b/contrib/gcc/config/i386/mm3dnow.h
@@ -0,0 +1,220 @@
+/* Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file does not by itself cause
+ the resulting executable to be covered by the GNU General Public
+ License. This exception does not however invalidate any other
+ reasons why the executable file might be covered by the GNU General
+ Public License. */
+
+/* Implemented from the mm3dnow.h (of supposedly AMD origin) included with
+ MSVC 7.1. */
+
+#ifndef _MM3DNOW_H_INCLUDED
+#define _MM3DNOW_H_INCLUDED
+
+#ifdef __3dNOW__
+
+#include <mmintrin.h>
+
+/* Internal data types for implementing the intrinsics. */
+typedef float __v2sf __attribute__ ((__vector_size__ (8)));
+
+static __inline void
+_m_femms (void)
+{
+ __builtin_ia32_femms();
+}
+
+static __inline __m64
+_m_pavgusb (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pavgusb ((__v8qi)__A, (__v8qi)__B);
+}
+
+static __inline __m64
+_m_pf2id (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pf2id ((__v2sf)__A);
+}
+
+static __inline __m64
+_m_pfacc (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfacc ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfadd (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfadd ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfcmpeq (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfcmpeq ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfcmpge (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfcmpge ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfcmpgt (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfcmpgt ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfmax (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfmax ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfmin (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfmin ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfmul (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfmul ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfrcp (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pfrcp ((__v2sf)__A);
+}
+
+static __inline __m64
+_m_pfrcpit1 (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfrcpit1 ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfrcpit2 (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfrcpit2 ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfrsqrt (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pfrsqrt ((__v2sf)__A);
+}
+
+static __inline __m64
+_m_pfrsqit1 (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfrsqit1 ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfsub (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfsub ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfsubr (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfsubr ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pi2fd (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pi2fd ((__v2si)__A);
+}
+
+static __inline __m64
+_m_pmulhrw (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pmulhrw ((__v4hi)__A, (__v4hi)__B);
+}
+
+static __inline void
+_m_prefetch (void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+static __inline void
+_m_prefetchw (void *__P)
+{
+ __builtin_prefetch (__P, 1, 3 /* _MM_HINT_T0 */);
+}
+
+static __inline __m64
+_m_from_float (float __A)
+{
+ return (__m64)(__v2sf){ __A, 0 };
+}
+
+static __inline float
+_m_to_float (__m64 __A)
+{
+ union { __v2sf v; float a[2]; } __tmp = { (__v2sf)__A };
+ return __tmp.a[0];
+}
+
+#ifdef __3dNOW_A__
+
+static __inline __m64
+_m_pf2iw (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pf2iw ((__v2sf)__A);
+}
+
+static __inline __m64
+_m_pfnacc (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfnacc ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pfpnacc (__m64 __A, __m64 __B)
+{
+ return (__m64)__builtin_ia32_pfpnacc ((__v2sf)__A, (__v2sf)__B);
+}
+
+static __inline __m64
+_m_pi2fw (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pi2fw ((__v2si)__A);
+}
+
+static __inline __m64
+_m_pswapd (__m64 __A)
+{
+ return (__m64)__builtin_ia32_pswapdsf ((__v2sf)__A);
+}
+
+#endif /* __3dNOW_A__ */
+#endif /* __3dNOW__ */
+
+#endif /* _MM3DNOW_H_INCLUDED */
diff --git a/contrib/gcc/config/i386/mmintrin.h b/contrib/gcc/config/i386/mmintrin.h
index bd775e8..052198d 100644
--- a/contrib/gcc/config/i386/mmintrin.h
+++ b/contrib/gcc/config/i386/mmintrin.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -25,7 +26,7 @@
Public License. */
/* Implemented from the specification included in the Intel C++ Compiler
- User Guide and Reference, version 8.0. */
+ User Guide and Reference, version 9.0. */
#ifndef _MMINTRIN_H_INCLUDED
#define _MMINTRIN_H_INCLUDED
@@ -33,36 +34,36 @@
#ifndef __MMX__
# error "MMX instruction set not enabled"
#else
-/* The data type intended for user use. */
-typedef int __m64 __attribute__ ((__mode__ (__V2SI__)));
+/* The Intel API is flexible enough that we must allow aliasing with other
+ vector types, and their scalar components. */
+typedef int __m64 __attribute__ ((__vector_size__ (8), __may_alias__));
/* Internal data types for implementing the intrinsics. */
-typedef int __v2si __attribute__ ((__mode__ (__V2SI__)));
-typedef int __v4hi __attribute__ ((__mode__ (__V4HI__)));
-typedef int __v8qi __attribute__ ((__mode__ (__V8QI__)));
+typedef int __v2si __attribute__ ((__vector_size__ (8)));
+typedef short __v4hi __attribute__ ((__vector_size__ (8)));
+typedef char __v8qi __attribute__ ((__vector_size__ (8)));
/* Empty the multimedia state. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_empty (void)
{
__builtin_ia32_emms ();
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_m_empty (void)
{
_mm_empty ();
}
/* Convert I to a __m64 object. The integer is zero-extended to 64-bits. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtsi32_si64 (int __i)
{
- long long __tmp = (unsigned int)__i;
- return (__m64) __tmp;
+ return (__m64) __builtin_ia32_vec_init_v2si (__i, 0);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_from_int (int __i)
{
return _mm_cvtsi32_si64 (__i);
@@ -70,14 +71,28 @@ _m_from_int (int __i)
#ifdef __x86_64__
/* Convert I to a __m64 object. */
-static __inline __m64
+
+/* Intel intrinsic. */
+static __inline __m64 __attribute__((__always_inline__))
+_m_from_int64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+static __inline __m64 __attribute__((__always_inline__))
+_mm_cvtsi64_m64 (long long __i)
+{
+ return (__m64) __i;
+}
+
+/* Microsoft intrinsic. */
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtsi64x_si64 (long long __i)
{
return (__m64) __i;
}
-/* Convert I to a __m64 object. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set_pi64x (long long __i)
{
return (__m64) __i;
@@ -85,22 +100,36 @@ _mm_set_pi64x (long long __i)
#endif
/* Convert the lower 32 bits of the __m64 object into an integer. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvtsi64_si32 (__m64 __i)
{
- long long __tmp = (long long)__i;
- return __tmp;
+ return __builtin_ia32_vec_ext_v2si ((__v2si)__i, 0);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_m_to_int (__m64 __i)
{
return _mm_cvtsi64_si32 (__i);
}
#ifdef __x86_64__
-/* Convert the lower 32 bits of the __m64 object into an integer. */
-static __inline long long
+/* Convert the __m64 object to a 64bit integer. */
+
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_m_to_int64 (__m64 __i)
+{
+ return (long long)__i;
+}
+
+static __inline long long __attribute__((__always_inline__))
+_mm_cvtm64_si64 (__m64 __i)
+{
+ return (long long)__i;
+}
+
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
_mm_cvtsi64_si64x (__m64 __i)
{
return (long long)__i;
@@ -110,13 +139,13 @@ _mm_cvtsi64_si64x (__m64 __i)
/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
the result, and the four 16-bit values from M2 into the upper four 8-bit
values of the result, all with signed saturation. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_packs_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_packsswb ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_packsswb (__m64 __m1, __m64 __m2)
{
return _mm_packs_pi16 (__m1, __m2);
@@ -125,13 +154,13 @@ _m_packsswb (__m64 __m1, __m64 __m2)
/* Pack the two 32-bit values from M1 in to the lower two 16-bit values of
the result, and the two 32-bit values from M2 into the upper two 16-bit
values of the result, all with signed saturation. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_packs_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_packssdw ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_packssdw (__m64 __m1, __m64 __m2)
{
return _mm_packs_pi32 (__m1, __m2);
@@ -140,13 +169,13 @@ _m_packssdw (__m64 __m1, __m64 __m2)
/* Pack the four 16-bit values from M1 into the lower four 8-bit values of
the result, and the four 16-bit values from M2 into the upper four 8-bit
values of the result, all with unsigned saturation. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_packs_pu16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_packuswb ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_packuswb (__m64 __m1, __m64 __m2)
{
return _mm_packs_pu16 (__m1, __m2);
@@ -154,13 +183,13 @@ _m_packuswb (__m64 __m1, __m64 __m2)
/* Interleave the four 8-bit values from the high half of M1 with the four
8-bit values from the high half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpackhi_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpckhbw ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpckhbw (__m64 __m1, __m64 __m2)
{
return _mm_unpackhi_pi8 (__m1, __m2);
@@ -168,13 +197,13 @@ _m_punpckhbw (__m64 __m1, __m64 __m2)
/* Interleave the two 16-bit values from the high half of M1 with the two
16-bit values from the high half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpackhi_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpckhwd ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpckhwd (__m64 __m1, __m64 __m2)
{
return _mm_unpackhi_pi16 (__m1, __m2);
@@ -182,13 +211,13 @@ _m_punpckhwd (__m64 __m1, __m64 __m2)
/* Interleave the 32-bit value from the high half of M1 with the 32-bit
value from the high half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpackhi_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpckhdq ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpckhdq (__m64 __m1, __m64 __m2)
{
return _mm_unpackhi_pi32 (__m1, __m2);
@@ -196,13 +225,13 @@ _m_punpckhdq (__m64 __m1, __m64 __m2)
/* Interleave the four 8-bit values from the low half of M1 with the four
8-bit values from the low half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpacklo_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpcklbw ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpcklbw (__m64 __m1, __m64 __m2)
{
return _mm_unpacklo_pi8 (__m1, __m2);
@@ -210,13 +239,13 @@ _m_punpcklbw (__m64 __m1, __m64 __m2)
/* Interleave the two 16-bit values from the low half of M1 with the two
16-bit values from the low half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpacklo_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpcklwd ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpcklwd (__m64 __m1, __m64 __m2)
{
return _mm_unpacklo_pi16 (__m1, __m2);
@@ -224,73 +253,75 @@ _m_punpcklwd (__m64 __m1, __m64 __m2)
/* Interleave the 32-bit value from the low half of M1 with the 32-bit
value from the low half of M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_unpacklo_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_punpckldq ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_punpckldq (__m64 __m1, __m64 __m2)
{
return _mm_unpacklo_pi32 (__m1, __m2);
}
/* Add the 8-bit values in M1 to the 8-bit values in M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_add_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddb (__m64 __m1, __m64 __m2)
{
return _mm_add_pi8 (__m1, __m2);
}
/* Add the 16-bit values in M1 to the 16-bit values in M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_add_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddw (__m64 __m1, __m64 __m2)
{
return _mm_add_pi16 (__m1, __m2);
}
/* Add the 32-bit values in M1 to the 32-bit values in M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_add_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddd ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddd (__m64 __m1, __m64 __m2)
{
return _mm_add_pi32 (__m1, __m2);
}
/* Add the 64-bit values in M1 to the 64-bit values in M2. */
-static __inline __m64
+#ifdef __SSE2__
+static __inline __m64 __attribute__((__always_inline__))
_mm_add_si64 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddq ((long long)__m1, (long long)__m2);
}
+#endif
/* Add the 8-bit values in M1 to the 8-bit values in M2 using signed
saturated arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_adds_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddsb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddsb (__m64 __m1, __m64 __m2)
{
return _mm_adds_pi8 (__m1, __m2);
@@ -298,13 +329,13 @@ _m_paddsb (__m64 __m1, __m64 __m2)
/* Add the 16-bit values in M1 to the 16-bit values in M2 using signed
saturated arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_adds_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddsw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddsw (__m64 __m1, __m64 __m2)
{
return _mm_adds_pi16 (__m1, __m2);
@@ -312,13 +343,13 @@ _m_paddsw (__m64 __m1, __m64 __m2)
/* Add the 8-bit values in M1 to the 8-bit values in M2 using unsigned
saturated arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_adds_pu8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddusb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddusb (__m64 __m1, __m64 __m2)
{
return _mm_adds_pu8 (__m1, __m2);
@@ -326,73 +357,75 @@ _m_paddusb (__m64 __m1, __m64 __m2)
/* Add the 16-bit values in M1 to the 16-bit values in M2 using unsigned
saturated arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_adds_pu16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_paddusw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_paddusw (__m64 __m1, __m64 __m2)
{
return _mm_adds_pu16 (__m1, __m2);
}
/* Subtract the 8-bit values in M2 from the 8-bit values in M1. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sub_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubb (__m64 __m1, __m64 __m2)
{
return _mm_sub_pi8 (__m1, __m2);
}
/* Subtract the 16-bit values in M2 from the 16-bit values in M1. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sub_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubw (__m64 __m1, __m64 __m2)
{
return _mm_sub_pi16 (__m1, __m2);
}
/* Subtract the 32-bit values in M2 from the 32-bit values in M1. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sub_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubd ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubd (__m64 __m1, __m64 __m2)
{
return _mm_sub_pi32 (__m1, __m2);
}
/* Add the 64-bit values in M1 to the 64-bit values in M2. */
-static __inline __m64
+#ifdef __SSE2__
+static __inline __m64 __attribute__((__always_inline__))
_mm_sub_si64 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubq ((long long)__m1, (long long)__m2);
}
+#endif
/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using signed
saturating arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_subs_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubsb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubsb (__m64 __m1, __m64 __m2)
{
return _mm_subs_pi8 (__m1, __m2);
@@ -400,13 +433,13 @@ _m_psubsb (__m64 __m1, __m64 __m2)
/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
signed saturating arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_subs_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubsw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubsw (__m64 __m1, __m64 __m2)
{
return _mm_subs_pi16 (__m1, __m2);
@@ -414,13 +447,13 @@ _m_psubsw (__m64 __m1, __m64 __m2)
/* Subtract the 8-bit values in M2 from the 8-bit values in M1 using
unsigned saturating arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_subs_pu8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubusb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubusb (__m64 __m1, __m64 __m2)
{
return _mm_subs_pu8 (__m1, __m2);
@@ -428,13 +461,13 @@ _m_psubusb (__m64 __m1, __m64 __m2)
/* Subtract the 16-bit values in M2 from the 16-bit values in M1 using
unsigned saturating arithmetic. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_subs_pu16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_psubusw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psubusw (__m64 __m1, __m64 __m2)
{
return _mm_subs_pu16 (__m1, __m2);
@@ -443,13 +476,13 @@ _m_psubusw (__m64 __m1, __m64 __m2)
/* Multiply four 16-bit values in M1 by four 16-bit values in M2 producing
four 32-bit intermediate results, which are then summed by pairs to
produce two 32-bit results. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_madd_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pmaddwd ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmaddwd (__m64 __m1, __m64 __m2)
{
return _mm_madd_pi16 (__m1, __m2);
@@ -457,13 +490,13 @@ _m_pmaddwd (__m64 __m1, __m64 __m2)
/* Multiply four signed 16-bit values in M1 by four signed 16-bit values in
M2 and produce the high 16 bits of the 32-bit results. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_mulhi_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pmulhw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmulhw (__m64 __m1, __m64 __m2)
{
return _mm_mulhi_pi16 (__m1, __m2);
@@ -471,226 +504,226 @@ _m_pmulhw (__m64 __m1, __m64 __m2)
/* Multiply four 16-bit values in M1 by four 16-bit values in M2 and produce
the low 16 bits of the results. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_mullo_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pmullw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmullw (__m64 __m1, __m64 __m2)
{
return _mm_mullo_pi16 (__m1, __m2);
}
/* Shift four 16-bit values in M left by COUNT. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sll_pi16 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psllw ((__v4hi)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psllw (__m64 __m, __m64 __count)
{
return _mm_sll_pi16 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_slli_pi16 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psllw ((__v4hi)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psllwi (__m64 __m, int __count)
{
return _mm_slli_pi16 (__m, __count);
}
/* Shift two 32-bit values in M left by COUNT. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sll_pi32 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_pslld ((__v2si)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pslld (__m64 __m, __m64 __count)
{
return _mm_sll_pi32 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_slli_pi32 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_pslld ((__v2si)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pslldi (__m64 __m, int __count)
{
return _mm_slli_pi32 (__m, __count);
}
/* Shift the 64-bit value in M left by COUNT. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sll_si64 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psllq ((long long)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psllq (__m64 __m, __m64 __count)
{
return _mm_sll_si64 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_slli_si64 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psllq ((long long)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psllqi (__m64 __m, int __count)
{
return _mm_slli_si64 (__m, __count);
}
/* Shift four 16-bit values in M right by COUNT; shift in the sign bit. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sra_pi16 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psraw ((__v4hi)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psraw (__m64 __m, __m64 __count)
{
return _mm_sra_pi16 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srai_pi16 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psraw ((__v4hi)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrawi (__m64 __m, int __count)
{
return _mm_srai_pi16 (__m, __count);
}
/* Shift two 32-bit values in M right by COUNT; shift in the sign bit. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sra_pi32 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psrad ((__v2si)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrad (__m64 __m, __m64 __count)
{
return _mm_sra_pi32 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srai_pi32 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psrad ((__v2si)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psradi (__m64 __m, int __count)
{
return _mm_srai_pi32 (__m, __count);
}
/* Shift four 16-bit values in M right by COUNT; shift in zeros. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srl_pi16 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psrlw ((__v4hi)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrlw (__m64 __m, __m64 __count)
{
return _mm_srl_pi16 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srli_pi16 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psrlw ((__v4hi)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrlwi (__m64 __m, int __count)
{
return _mm_srli_pi16 (__m, __count);
}
/* Shift two 32-bit values in M right by COUNT; shift in zeros. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srl_pi32 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psrld ((__v2si)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrld (__m64 __m, __m64 __count)
{
return _mm_srl_pi32 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srli_pi32 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psrld ((__v2si)__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrldi (__m64 __m, int __count)
{
return _mm_srli_pi32 (__m, __count);
}
/* Shift the 64-bit value in M left by COUNT; shift in zeros. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srl_si64 (__m64 __m, __m64 __count)
{
return (__m64) __builtin_ia32_psrlq ((long long)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrlq (__m64 __m, __m64 __count)
{
return _mm_srl_si64 (__m, __count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_srli_si64 (__m64 __m, int __count)
{
return (__m64) __builtin_ia32_psrlq ((long long)__m, (long long)__count);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psrlqi (__m64 __m, int __count)
{
return _mm_srli_si64 (__m, __count);
}
/* Bit-wise AND the 64-bit values in M1 and M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_and_si64 (__m64 __m1, __m64 __m2)
{
- return (__m64) __builtin_ia32_pand ((long long)__m1, (long long)__m2);
+ return __builtin_ia32_pand (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pand (__m64 __m1, __m64 __m2)
{
return _mm_and_si64 (__m1, __m2);
@@ -698,39 +731,39 @@ _m_pand (__m64 __m1, __m64 __m2)
/* Bit-wise complement the 64-bit value in M1 and bit-wise AND it with the
64-bit value in M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_andnot_si64 (__m64 __m1, __m64 __m2)
{
- return (__m64) __builtin_ia32_pandn ((long long)__m1, (long long)__m2);
+ return __builtin_ia32_pandn (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pandn (__m64 __m1, __m64 __m2)
{
return _mm_andnot_si64 (__m1, __m2);
}
/* Bit-wise inclusive OR the 64-bit values in M1 and M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_or_si64 (__m64 __m1, __m64 __m2)
{
- return (__m64)__builtin_ia32_por ((long long)__m1, (long long)__m2);
+ return __builtin_ia32_por (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_por (__m64 __m1, __m64 __m2)
{
return _mm_or_si64 (__m1, __m2);
}
/* Bit-wise exclusive OR the 64-bit values in M1 and M2. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_xor_si64 (__m64 __m1, __m64 __m2)
{
- return (__m64)__builtin_ia32_pxor ((long long)__m1, (long long)__m2);
+ return __builtin_ia32_pxor (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pxor (__m64 __m1, __m64 __m2)
{
return _mm_xor_si64 (__m1, __m2);
@@ -738,25 +771,25 @@ _m_pxor (__m64 __m1, __m64 __m2)
/* Compare eight 8-bit values. The result of the comparison is 0xFF if the
test is true and zero if false. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpeq_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpeqb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpeqb (__m64 __m1, __m64 __m2)
{
return _mm_cmpeq_pi8 (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpgt_pi8 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpgtb ((__v8qi)__m1, (__v8qi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpgtb (__m64 __m1, __m64 __m2)
{
return _mm_cmpgt_pi8 (__m1, __m2);
@@ -764,25 +797,25 @@ _m_pcmpgtb (__m64 __m1, __m64 __m2)
/* Compare four 16-bit values. The result of the comparison is 0xFFFF if
the test is true and zero if false. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpeq_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpeqw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpeqw (__m64 __m1, __m64 __m2)
{
return _mm_cmpeq_pi16 (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpgt_pi16 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpgtw ((__v4hi)__m1, (__v4hi)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpgtw (__m64 __m1, __m64 __m2)
{
return _mm_cmpgt_pi16 (__m1, __m2);
@@ -790,99 +823,74 @@ _m_pcmpgtw (__m64 __m1, __m64 __m2)
/* Compare two 32-bit values. The result of the comparison is 0xFFFFFFFF if
the test is true and zero if false. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpeq_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpeqd ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpeqd (__m64 __m1, __m64 __m2)
{
return _mm_cmpeq_pi32 (__m1, __m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cmpgt_pi32 (__m64 __m1, __m64 __m2)
{
return (__m64) __builtin_ia32_pcmpgtd ((__v2si)__m1, (__v2si)__m2);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pcmpgtd (__m64 __m1, __m64 __m2)
{
return _mm_cmpgt_pi32 (__m1, __m2);
}
/* Creates a 64-bit zero. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_setzero_si64 (void)
{
- return (__m64)__builtin_ia32_mmx_zero ();
+ return (__m64)0LL;
}
/* Creates a vector of two 32-bit values; I0 is least significant. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set_pi32 (int __i1, int __i0)
{
- union {
- __m64 __q;
- struct {
- unsigned int __i0;
- unsigned int __i1;
- } __s;
- } __u;
-
- __u.__s.__i0 = __i0;
- __u.__s.__i1 = __i1;
-
- return __u.__q;
+ return (__m64) __builtin_ia32_vec_init_v2si (__i0, __i1);
}
/* Creates a vector of four 16-bit values; W0 is least significant. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set_pi16 (short __w3, short __w2, short __w1, short __w0)
{
- unsigned int __i1 = (unsigned short)__w3 << 16 | (unsigned short)__w2;
- unsigned int __i0 = (unsigned short)__w1 << 16 | (unsigned short)__w0;
- return _mm_set_pi32 (__i1, __i0);
-
+ return (__m64) __builtin_ia32_vec_init_v4hi (__w0, __w1, __w2, __w3);
}
/* Creates a vector of eight 8-bit values; B0 is least significant. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set_pi8 (char __b7, char __b6, char __b5, char __b4,
char __b3, char __b2, char __b1, char __b0)
{
- unsigned int __i1, __i0;
-
- __i1 = (unsigned char)__b7;
- __i1 = __i1 << 8 | (unsigned char)__b6;
- __i1 = __i1 << 8 | (unsigned char)__b5;
- __i1 = __i1 << 8 | (unsigned char)__b4;
-
- __i0 = (unsigned char)__b3;
- __i0 = __i0 << 8 | (unsigned char)__b2;
- __i0 = __i0 << 8 | (unsigned char)__b1;
- __i0 = __i0 << 8 | (unsigned char)__b0;
-
- return _mm_set_pi32 (__i1, __i0);
+ return (__m64) __builtin_ia32_vec_init_v8qi (__b0, __b1, __b2, __b3,
+ __b4, __b5, __b6, __b7);
}
/* Similar, but with the arguments in reverse order. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_setr_pi32 (int __i0, int __i1)
{
return _mm_set_pi32 (__i1, __i0);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_setr_pi16 (short __w0, short __w1, short __w2, short __w3)
{
return _mm_set_pi16 (__w3, __w2, __w1, __w0);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_setr_pi8 (char __b0, char __b1, char __b2, char __b3,
char __b4, char __b5, char __b6, char __b7)
{
@@ -890,27 +898,24 @@ _mm_setr_pi8 (char __b0, char __b1, char __b2, char __b3,
}
/* Creates a vector of two 32-bit values, both elements containing I. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set1_pi32 (int __i)
{
return _mm_set_pi32 (__i, __i);
}
/* Creates a vector of four 16-bit values, all elements containing W. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set1_pi16 (short __w)
{
- unsigned int __i = (unsigned short)__w << 16 | (unsigned short)__w;
- return _mm_set1_pi32 (__i);
+ return _mm_set_pi16 (__w, __w, __w, __w);
}
/* Creates a vector of eight 8-bit values, all elements containing B. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_set1_pi8 (char __b)
{
- unsigned int __w = (unsigned char)__b << 8 | (unsigned char)__b;
- unsigned int __i = __w << 16 | __w;
- return _mm_set1_pi32 (__i);
+ return _mm_set_pi8 (__b, __b, __b, __b, __b, __b, __b, __b);
}
#endif /* __MMX__ */
diff --git a/contrib/gcc/config/i386/mmx.md b/contrib/gcc/config/i386/mmx.md
new file mode 100644
index 0000000..4f0ab2c
--- /dev/null
+++ b/contrib/gcc/config/i386/mmx.md
@@ -0,0 +1,1433 @@
+;; GCC machine description for MMX and 3dNOW! instructions
+;; Copyright (C) 2005
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; The MMX and 3dNOW! patterns are in the same file because they use
+;; the same register file, and 3dNOW! adds a number of extensions to
+;; the base integer MMX isa.
+
+;; Note! Except for the basic move instructions, *all* of these
+;; patterns are outside the normal optabs namespace. This is because
+;; use of these registers requires the insertion of emms or femms
+;; instructions to return to normal fpu mode. The compiler doesn't
+;; know how to do that itself, which means it's up to the user. Which
+;; means that we should never use any of these patterns except at the
+;; direction of the user via a builtin.
+
+;; 8 byte integral modes handled by MMX (and by extension, SSE)
+(define_mode_macro MMXMODEI [V8QI V4HI V2SI])
+
+;; All 8-byte vector modes handled by MMX
+(define_mode_macro MMXMODE [V8QI V4HI V2SI V2SF])
+
+;; Mix-n-match
+(define_mode_macro MMXMODE12 [V8QI V4HI])
+(define_mode_macro MMXMODE24 [V4HI V2SI])
+
+;; Mapping from integer vector mode to mnemonic suffix
+(define_mode_attr mmxvecsize [(V8QI "b") (V4HI "w") (V2SI "d") (DI "q")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Move patterns
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; All of these patterns are enabled for MMX as well as 3dNOW.
+;; This is essential for maintaining stable calling conventions.
+
+(define_expand "mov<mode>"
+ [(set (match_operand:MMXMODEI 0 "nonimmediate_operand" "")
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" ""))]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_move (<MODE>mode, operands);
+ DONE;
+})
+
+(define_insn "*mov<mode>_internal_rex64"
+ [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
+ "=rm,r,*y,*y ,m ,*y,Y ,x,x ,m,r,x")
+ (match_operand:MMXMODEI 1 "vector_move_operand"
+ "Cr ,m,C ,*ym,*y,Y ,*y,C,xm,x,x,r"))]
+ "TARGET_64BIT && TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*")
+ (set_attr "mode" "DI")])
+
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:MMXMODEI 0 "nonimmediate_operand"
+ "=*y,*y ,m ,*y,*Y,*Y,*Y ,m ,*x,*x,*x,m ,?r ,?m")
+ (match_operand:MMXMODEI 1 "vector_move_operand"
+ "C ,*ym,*y,*Y,*y,C ,*Ym,*Y,C ,*x,m ,*x,irm,r"))]
+ "TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ #
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+(define_expand "movv2sf"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "")
+ (match_operand:V2SF 1 "nonimmediate_operand" ""))]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_move (V2SFmode, operands);
+ DONE;
+})
+
+(define_insn "*movv2sf_internal_rex64"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand"
+ "=rm,r,*y ,*y ,m ,*y,Y ,x,x,x,m,r,x")
+ (match_operand:V2SF 1 "vector_move_operand"
+ "Cr ,m ,C ,*ym,*y,Y ,*y,C,x,m,x,x,r"))]
+ "TARGET_64BIT && TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+(define_insn "*movv2sf_internal"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand"
+ "=*y,*y ,m,*y,*Y,*x,*x,*x,m ,?r ,?m")
+ (match_operand:V2SF 1 "vector_move_operand"
+ "C ,*ym,*y,*Y,*y,C ,*x,m ,*x,irm,r"))]
+ "TARGET_MMX
+ && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "@
+ pxor\t%0, %0
+ movq\t{%1, %0|%0, %1}
+ movq\t{%1, %0|%0, %1}
+ movdq2q\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ xorps\t%0, %0
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}
+ #
+ #"
+ [(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
+ (set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
+
+;; %%% This multiword shite has got to go.
+(define_split
+ [(set (match_operand:MMXMODE 0 "nonimmediate_operand" "")
+ (match_operand:MMXMODE 1 "general_operand" ""))]
+ "!TARGET_64BIT && reload_completed
+ && (!MMX_REG_P (operands[0]) && !SSE_REG_P (operands[0]))
+ && (!MMX_REG_P (operands[1]) && !SSE_REG_P (operands[1]))"
+ [(const_int 0)]
+ "ix86_split_long_move (operands); DONE;")
+
+(define_expand "push<mode>1"
+ [(match_operand:MMXMODE 0 "register_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_push (<MODE>mode, operands[0]);
+ DONE;
+})
+
+(define_expand "movmisalign<mode>"
+ [(set (match_operand:MMXMODE 0 "nonimmediate_operand" "")
+ (match_operand:MMXMODE 1 "nonimmediate_operand" ""))]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_move (<MODE>mode, operands);
+ DONE;
+})
+
+(define_insn "sse_movntdi"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "y")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "movntq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxmov")
+ (set_attr "mode" "DI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_addv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (plus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (PLUS, V2SFmode, operands)"
+ "pfadd\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_subv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y,y")
+ (minus:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "0,ym")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym,0")))]
+ "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ pfsub\\t{%2, %0|%0, %2}
+ pfsubr\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_expand "mmx_subrv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "")
+ (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "")
+ (match_operand:V2SF 1 "nonimmediate_operand" "")))]
+ "TARGET_3DNOW && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "")
+
+(define_insn "mmx_mulv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (mult:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V2SFmode, operands)"
+ "pfmul\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_smaxv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (smax:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (SMAX, V2SFmode, operands)"
+ "pfmax\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_sminv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (smin:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (SMIN, V2SFmode, operands)"
+ "pfmin\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_rcpv2sf2"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCP))]
+ "TARGET_3DNOW"
+ "pfrcp\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_rcpit1v2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCPIT1))]
+ "TARGET_3DNOW"
+ "pfrcpit1\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_rcpit2v2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRCPIT2))]
+ "TARGET_3DNOW"
+ "pfrcpit2\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_rsqrtv2sf2"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRSQRT))]
+ "TARGET_3DNOW"
+ "pfrsqrt\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_rsqit1v2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PFRSQIT1))]
+ "TARGET_3DNOW"
+ "pfrsqit1\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmx")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_haddv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (vec_concat:V2SF
+ (plus:SF
+ (vec_select:SF
+ (match_operand:V2SF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
+ (plus:SF
+ (vec_select:SF
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
+ "TARGET_3DNOW"
+ "pfacc\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_hsubv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (vec_concat:V2SF
+ (minus:SF
+ (vec_select:SF
+ (match_operand:V2SF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
+ (minus:SF
+ (vec_select:SF
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))))]
+ "TARGET_3DNOW_A"
+ "pfnacc\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_addsubv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (vec_merge:V2SF
+ (plus:V2SF
+ (match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym"))
+ (minus:V2SF (match_dup 1) (match_dup 2))
+ (const_int 1)))]
+ "TARGET_3DNOW_A"
+ "pfpnacc\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "V2SF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point comparisons
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_gtv2sf3"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (gt:V2SI (match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW"
+ "pfcmpgt\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_gev2sf3"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (ge:V2SI (match_operand:V2SF 1 "register_operand" "0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW"
+ "pfcmpge\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_eqv2sf3"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (eq:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2SF 2 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
+ "pfcmpeq\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "V2SF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point conversion operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_pf2id"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW"
+ "pf2id\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_pf2iw"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (sign_extend:V2SI
+ (ss_truncate:V2HI
+ (fix:V2SI
+ (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))]
+ "TARGET_3DNOW_A"
+ "pf2iw\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_pi2fw"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (float:V2SF
+ (sign_extend:V2SI
+ (truncate:V2HI
+ (match_operand:V2SI 1 "nonimmediate_operand" "ym")))))]
+ "TARGET_3DNOW_A"
+ "pi2fw\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "mmx_floatv2si2"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))]
+ "TARGET_3DNOW"
+ "pi2fd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point element swizzling
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_pswapdv2sf2"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "TARGET_3DNOW_A"
+ "pswapd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "V2SF")])
+
+(define_insn "*vec_dupv2sf"
+ [(set (match_operand:V2SF 0 "register_operand" "=y")
+ (vec_duplicate:V2SF
+ (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_MMX"
+ "punpckldq\t%0, %0"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "*mmx_concatv2sf"
+ [(set (match_operand:V2SF 0 "register_operand" "=y,y")
+ (vec_concat:V2SF
+ (match_operand:SF 1 "nonimmediate_operand" " 0,rm")
+ (match_operand:SF 2 "vector_move_operand" "ym,C")))]
+ "TARGET_MMX && !TARGET_SSE"
+ "@
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt,mmxmov")
+ (set_attr "mode" "DI")])
+
+(define_expand "vec_setv2sf"
+ [(match_operand:V2SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_insn_and_split "*vec_extractv2sf_0"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,y,m,m,frxy")
+ (vec_select:SF
+ (match_operand:V2SF 1 "nonimmediate_operand" " x,y,x,y,m")
+ (parallel [(const_int 0)])))]
+ "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (SFmode, REGNO (op1));
+ else
+ op1 = gen_lowpart (SFmode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_insn "*vec_extractv2sf_1"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=y,x,frxy")
+ (vec_select:SF
+ (match_operand:V2SF 1 "nonimmediate_operand" " 0,0,o")
+ (parallel [(const_int 1)])))]
+ "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ punpckhdq\t%0, %0
+ unpckhps\t%0, %0
+ #"
+ [(set_attr "type" "mmxcvt,sselog1,*")
+ (set_attr "mode" "DI,V4SF,SI")])
+
+(define_split
+ [(set (match_operand:SF 0 "register_operand" "")
+ (vec_select:SF
+ (match_operand:V2SF 1 "memory_operand" "")
+ (parallel [(const_int 1)])))]
+ "TARGET_MMX && reload_completed"
+ [(const_int 0)]
+{
+ operands[1] = adjust_address (operands[1], SFmode, 4);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_extractv2sf"
+ [(match_operand:SF 0 "register_operand" "")
+ (match_operand:V2SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv2sf"
+ [(match_operand:V2SF 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_add<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (plus:MMXMODEI
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+ "padd<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_adddi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, DImode, operands)"
+ "paddq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ssadd<mode>3"
+ [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
+ (ss_plus:MMXMODE12
+ (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "padds<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_usadd<mode>3"
+ [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
+ (us_plus:MMXMODE12
+ (match_operand:MMXMODE12 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "paddus<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_sub<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (minus:MMXMODEI
+ (match_operand:MMXMODEI 1 "register_operand" "0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "psub<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_subdi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(minus:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonimmediate_operand" "ym"))]
+ UNSPEC_NOP))]
+ "TARGET_SSE2"
+ "psubq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_sssub<mode>3"
+ [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
+ (ss_minus:MMXMODE12
+ (match_operand:MMXMODE12 1 "register_operand" "0")
+ (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "psubs<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ussub<mode>3"
+ [(set (match_operand:MMXMODE12 0 "register_operand" "=y")
+ (us_minus:MMXMODE12
+ (match_operand:MMXMODE12 1 "register_operand" "0")
+ (match_operand:MMXMODE12 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "psubus<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_mulv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (mult:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmullw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_smulv4hi3_highpart"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (mult:V4SI (sign_extend:V4SI
+ (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (const_int 16))))]
+ "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmulhw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_umulv4hi3_highpart"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (mult:V4SI (zero_extend:V4SI
+ (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V4SI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (const_int 16))))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmulhuw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_pmaddwd"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (plus:V2SI
+ (mult:V2SI
+ (sign_extend:V2SI
+ (vec_select:V2HI
+ (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+ (parallel [(const_int 0) (const_int 2)])))
+ (sign_extend:V2SI
+ (vec_select:V2HI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")
+ (parallel [(const_int 0) (const_int 2)]))))
+ (mult:V2SI
+ (sign_extend:V2SI
+ (vec_select:V2HI (match_dup 1)
+ (parallel [(const_int 1) (const_int 3)])))
+ (sign_extend:V2SI
+ (vec_select:V2HI (match_dup 2)
+ (parallel [(const_int 1) (const_int 3)]))))))]
+ "TARGET_MMX && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmaddwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_pmulhrwv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (plus:V4SI
+ (mult:V4SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (const_vector:V4SI [(const_int 32768) (const_int 32768)
+ (const_int 32768) (const_int 32768)]))
+ (const_int 16))))]
+ "TARGET_3DNOW && ix86_binary_operator_ok (MULT, V4HImode, operands)"
+ "pmulhrw\\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse2_umulsidi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (mult:DI
+ (zero_extend:DI
+ (vec_select:SI
+ (match_operand:V2SI 1 "nonimmediate_operand" "%0")
+ (parallel [(const_int 0)])))
+ (zero_extend:DI
+ (vec_select:SI
+ (match_operand:V2SI 2 "nonimmediate_operand" "ym")
+ (parallel [(const_int 0)])))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2SImode, operands)"
+ "pmuludq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxmul")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_umaxv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (umax:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (UMAX, V8QImode, operands)"
+ "pmaxub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_smaxv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (smax:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (SMAX, V4HImode, operands)"
+ "pmaxsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_uminv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (umin:V8QI (match_operand:V8QI 1 "nonimmediate_operand" "%0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (UMIN, V8QImode, operands)"
+ "pminub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_sminv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (smin:V4HI (match_operand:V4HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (SMIN, V4HImode, operands)"
+ "pminsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ashr<mode>3"
+ [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
+ (ashiftrt:MMXMODE24
+ (match_operand:MMXMODE24 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ "TARGET_MMX"
+ "psra<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_lshr<mode>3"
+ [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
+ (lshiftrt:MMXMODE24
+ (match_operand:MMXMODE24 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ "TARGET_MMX"
+ "psrl<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_lshrdi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))]
+ UNSPEC_NOP))]
+ "TARGET_MMX"
+ "psrlq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ashl<mode>3"
+ [(set (match_operand:MMXMODE24 0 "register_operand" "=y")
+ (ashift:MMXMODE24
+ (match_operand:MMXMODE24 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ "TARGET_MMX"
+ "psll<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ashldi3"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI
+ [(ashift:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))]
+ UNSPEC_NOP))]
+ "TARGET_MMX"
+ "psllq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral comparisons
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_eq<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (eq:MMXMODEI
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+ "pcmpeq<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_gt<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (gt:MMXMODEI
+ (match_operand:MMXMODEI 1 "register_operand" "0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "pcmpgt<mmxvecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcmp")
+ (set_attr "mode" "DI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral logical operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_and<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (and:MMXMODEI
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
+ "pand\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_nand<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (and:MMXMODEI
+ (not:MMXMODEI (match_operand:MMXMODEI 1 "register_operand" "0"))
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX"
+ "pandn\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_ior<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (ior:MMXMODEI
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (IOR, <MODE>mode, operands)"
+ "por\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_xor<mode>3"
+ [(set (match_operand:MMXMODEI 0 "register_operand" "=y")
+ (xor:MMXMODEI
+ (match_operand:MMXMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:MMXMODEI 2 "nonimmediate_operand" "ym")))]
+ "TARGET_MMX && ix86_binary_operator_ok (XOR, <MODE>mode, operands)"
+ "pxor\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxadd")
+ (set_attr "mode" "DI")
+ (set_attr "memory" "none")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral element swizzling
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_packsswb"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (vec_concat:V8QI
+ (ss_truncate:V4QI
+ (match_operand:V4HI 1 "register_operand" "0"))
+ (ss_truncate:V4QI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
+ "TARGET_MMX"
+ "packsswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_packssdw"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_concat:V4HI
+ (ss_truncate:V2HI
+ (match_operand:V2SI 1 "register_operand" "0"))
+ (ss_truncate:V2HI
+ (match_operand:V2SI 2 "nonimmediate_operand" "ym"))))]
+ "TARGET_MMX"
+ "packssdw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_packuswb"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (vec_concat:V8QI
+ (us_truncate:V4QI
+ (match_operand:V4HI 1 "register_operand" "0"))
+ (us_truncate:V4QI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym"))))]
+ "TARGET_MMX"
+ "packuswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpckhbw"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "register_operand" "0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_MMX"
+ "punpckhbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpcklbw"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "register_operand" "0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)])))]
+ "TARGET_MMX"
+ "punpcklbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpckhwd"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "register_operand" "0")
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
+ "TARGET_MMX"
+ "punpckhwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpcklwd"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "register_operand" "0")
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
+ "TARGET_MMX"
+ "punpcklwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpckhdq"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "register_operand" "0")
+ (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 1)
+ (const_int 3)])))]
+ "TARGET_MMX"
+ "punpckhdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_punpckldq"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "register_operand" "0")
+ (match_operand:V2SI 2 "nonimmediate_operand" "ym"))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ "TARGET_MMX"
+ "punpckldq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_expand "mmx_pinsrw"
+ [(set (match_operand:V4HI 0 "register_operand" "")
+ (vec_merge:V4HI
+ (vec_duplicate:V4HI
+ (match_operand:SI 2 "nonimmediate_operand" ""))
+ (match_operand:V4HI 1 "register_operand" "")
+ (match_operand:SI 3 "const_0_to_3_operand" "")))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ operands[2] = gen_lowpart (HImode, operands[2]);
+ operands[3] = GEN_INT (1 << INTVAL (operands[3]));
+})
+
+(define_insn "*mmx_pinsrw"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_merge:V4HI
+ (vec_duplicate:V4HI
+ (match_operand:HI 2 "nonimmediate_operand" "rm"))
+ (match_operand:V4HI 1 "register_operand" "0")
+ (match_operand:SI 3 "const_pow2_1_to_8_operand" "n")))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
+ return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+}
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_pextrw"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (vec_select:HI
+ (match_operand:V4HI 1 "register_operand" "y")
+ (parallel [(match_operand:SI 2 "const_0_to_3_operand" "n")]))))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "pextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_expand "mmx_pshufw"
+ [(match_operand:V4HI 0 "register_operand" "")
+ (match_operand:V4HI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_mmx_pshufw_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
+ DONE;
+})
+
+(define_insn "mmx_pshufw_1"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_select:V4HI
+ (match_operand:V4HI 1 "nonimmediate_operand" "ym")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
+ (match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_0_to_3_operand" "")])))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+
+ return "pshufw\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_pswapdv2si2"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_select:V2SI
+ (match_operand:V2SI 1 "nonimmediate_operand" "ym")
+ (parallel [(const_int 1) (const_int 0)])))]
+ "TARGET_3DNOW_A"
+ "pswapd\\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "*vec_dupv4hi"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (vec_duplicate:V4HI
+ (truncate:HI
+ (match_operand:SI 1 "register_operand" "0"))))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "pshufw\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "*vec_dupv2si"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_duplicate:V2SI
+ (match_operand:SI 1 "register_operand" "0")))]
+ "TARGET_MMX"
+ "punpckldq\t%0, %0"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "*mmx_concatv2si"
+ [(set (match_operand:V2SI 0 "register_operand" "=y,y")
+ (vec_concat:V2SI
+ (match_operand:SI 1 "nonimmediate_operand" " 0,rm")
+ (match_operand:SI 2 "vector_move_operand" "ym,C")))]
+ "TARGET_MMX && !TARGET_SSE"
+ "@
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt,mmxmov")
+ (set_attr "mode" "DI")])
+
+(define_expand "vec_setv2si"
+ [(match_operand:V2SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_insn_and_split "*vec_extractv2si_0"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=x,y,m,m,frxy")
+ (vec_select:SI
+ (match_operand:V2SI 1 "nonimmediate_operand" " x,y,x,y,m")
+ (parallel [(const_int 0)])))]
+ "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (SImode, REGNO (op1));
+ else
+ op1 = gen_lowpart (SImode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_insn "*vec_extractv2si_1"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=y,Y,Y,x,frxy")
+ (vec_select:SI
+ (match_operand:V2SI 1 "nonimmediate_operand" " 0,0,Y,0,o")
+ (parallel [(const_int 1)])))]
+ "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ punpckhdq\t%0, %0
+ punpckhdq\t%0, %0
+ pshufd\t{$85, %1, %0|%0, %1, 85}
+ unpckhps\t%0, %0
+ #"
+ [(set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,*")
+ (set_attr "mode" "DI,TI,TI,V4SF,SI")])
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand" "")
+ (vec_select:SI
+ (match_operand:V2SI 1 "memory_operand" "")
+ (parallel [(const_int 1)])))]
+ "TARGET_MMX && reload_completed"
+ [(const_int 0)]
+{
+ operands[1] = adjust_address (operands[1], SImode, 4);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_extractv2si"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:V2SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv2si"
+ [(match_operand:V2SI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv4hi"
+ [(match_operand:V4HI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv4hi"
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand:V4HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv4hi"
+ [(match_operand:V4HI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand:QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv8qi"
+ [(match_operand:QI 0 "register_operand" "")
+ (match_operand:V8QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_MMX"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv8qi"
+ [(match_operand:V8QI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Miscellaneous
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "mmx_uavgv8qi3"
+ [(set (match_operand:V8QI 0 "register_operand" "=y")
+ (truncate:V8QI
+ (lshiftrt:V8HI
+ (plus:V8HI
+ (plus:V8HI
+ (zero_extend:V8HI
+ (match_operand:V8QI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V8HI
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")))
+ (const_vector:V8HI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "(TARGET_SSE || TARGET_3DNOW)
+ && ix86_binary_operator_ok (PLUS, V8QImode, operands)"
+{
+ /* These two instructions have the same operation, but their encoding
+ is different. Prefer the one that is de facto standard. */
+ if (TARGET_SSE || TARGET_3DNOW_A)
+ return "pavgb\t{%2, %0|%0, %2}";
+ else
+ return "pavgusb\\t{%2, %0|%0, %2}";
+}
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_uavgv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=y")
+ (truncate:V4HI
+ (lshiftrt:V4SI
+ (plus:V4SI
+ (plus:V4SI
+ (zero_extend:V4SI
+ (match_operand:V4HI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V4SI
+ (match_operand:V4HI 2 "nonimmediate_operand" "ym")))
+ (const_vector:V4SI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "(TARGET_SSE || TARGET_3DNOW_A)
+ && ix86_binary_operator_ok (PLUS, V4HImode, operands)"
+ "pavgw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_psadbw"
+ [(set (match_operand:DI 0 "register_operand" "=y")
+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "0")
+ (match_operand:V8QI 2 "nonimmediate_operand" "ym")]
+ UNSPEC_PSADBW))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "psadbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "mmxshft")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_pmovmskb"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "pmovmskb\t{%1, %0|%0, %1}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_expand "mmx_maskmovq"
+ [(set (match_operand:V8QI 0 "memory_operand" "")
+ (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
+ (match_operand:V8QI 2 "register_operand" "y")
+ (match_dup 0)]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "")
+
+(define_insn "*mmx_maskmovq"
+ [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D"))
+ (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
+ (match_operand:V8QI 2 "register_operand" "y")
+ (mem:V8QI (match_dup 0))]
+ UNSPEC_MASKMOV))]
+ "(TARGET_SSE || TARGET_3DNOW_A) && !TARGET_64BIT"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovq\t{%2, %1|%1, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "*mmx_maskmovq_rex"
+ [(set (mem:V8QI (match_operand:DI 0 "register_operand" "D"))
+ (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y")
+ (match_operand:V8QI 2 "register_operand" "y")
+ (mem:V8QI (match_dup 0))]
+ UNSPEC_MASKMOV))]
+ "(TARGET_SSE || TARGET_3DNOW_A) && TARGET_64BIT"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovq\t{%2, %1|%1, %2}"
+ [(set_attr "type" "mmxcvt")
+ (set_attr "mode" "DI")])
+
+(define_insn "mmx_emms"
+ [(unspec_volatile [(const_int 0)] UNSPECV_EMMS)
+ (clobber (reg:XF 8))
+ (clobber (reg:XF 9))
+ (clobber (reg:XF 10))
+ (clobber (reg:XF 11))
+ (clobber (reg:XF 12))
+ (clobber (reg:XF 13))
+ (clobber (reg:XF 14))
+ (clobber (reg:XF 15))
+ (clobber (reg:DI 29))
+ (clobber (reg:DI 30))
+ (clobber (reg:DI 31))
+ (clobber (reg:DI 32))
+ (clobber (reg:DI 33))
+ (clobber (reg:DI 34))
+ (clobber (reg:DI 35))
+ (clobber (reg:DI 36))]
+ "TARGET_MMX"
+ "emms"
+ [(set_attr "type" "mmx")
+ (set_attr "memory" "unknown")])
+
+(define_insn "mmx_femms"
+ [(unspec_volatile [(const_int 0)] UNSPECV_FEMMS)
+ (clobber (reg:XF 8))
+ (clobber (reg:XF 9))
+ (clobber (reg:XF 10))
+ (clobber (reg:XF 11))
+ (clobber (reg:XF 12))
+ (clobber (reg:XF 13))
+ (clobber (reg:XF 14))
+ (clobber (reg:XF 15))
+ (clobber (reg:DI 29))
+ (clobber (reg:DI 30))
+ (clobber (reg:DI 31))
+ (clobber (reg:DI 32))
+ (clobber (reg:DI 33))
+ (clobber (reg:DI 34))
+ (clobber (reg:DI 35))
+ (clobber (reg:DI 36))]
+ "TARGET_3DNOW"
+ "femms"
+ [(set_attr "type" "mmx")
+ (set_attr "memory" "none")])
diff --git a/contrib/gcc/config/i386/netbsd-elf.h b/contrib/gcc/config/i386/netbsd-elf.h
index bd2e9de..d03afa8 100644
--- a/contrib/gcc/config/i386/netbsd-elf.h
+++ b/contrib/gcc/config/i386/netbsd-elf.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GCC,
for i386/ELF NetBSD systems.
- Copyright (C) 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2004 Free Software Foundation, Inc.
Contributed by matthew green <mrg@eterna.com.au>
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
diff --git a/contrib/gcc/config/i386/netbsd64.h b/contrib/gcc/config/i386/netbsd64.h
index 66f31e0..df72e70 100644
--- a/contrib/gcc/config/i386/netbsd64.h
+++ b/contrib/gcc/config/i386/netbsd64.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GCC,
for x86-64/ELF NetBSD systems.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
Contributed by Wasabi Systems, Inc.
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
diff --git a/contrib/gcc/config/i386/netware-crt0.c b/contrib/gcc/config/i386/netware-crt0.c
new file mode 100644
index 0000000..3b4a115
--- /dev/null
+++ b/contrib/gcc/config/i386/netware-crt0.c
@@ -0,0 +1,80 @@
+/* Startup routines for NetWare.
+ Contributed by Jan Beulich (jbeulich@novell.com)
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "unwind-dw2-fde.h"
+
+int __init_environment (void *);
+int __deinit_environment (void *);
+
+
+#define SECTION_DECL(name, decl) decl __attribute__((__section__(name)))
+
+SECTION_DECL(".ctors", void(*const __CTOR_LIST__)(void))
+ = (void(*)(void))(intptr_t)-1;
+SECTION_DECL(".ctors$_", void(*const __CTOR_END__)(void)) = NULL;
+
+SECTION_DECL(".dtors", void(*const __DTOR_LIST__)(void))
+ = (void(*)(void))(intptr_t)-1;
+SECTION_DECL(".dtors$_", void(*const __DTOR_END__)(void)) = NULL;
+
+/* No need to use the __[de]register_frame_info_bases functions since
+ for us the bases are NULL always anyway. */
+void __register_frame_info (const void *, struct object *)
+ __attribute__((__weak__));
+void *__deregister_frame_info (const void *) __attribute__((__weak__));
+
+SECTION_DECL(".eh_frame", /*const*/ uint32_t __EH_FRAME_BEGIN__[]) = { };
+SECTION_DECL(".eh_frame$_", /*const*/ uint32_t __EH_FRAME_END__[]) = {0};
+
+int
+__init_environment (void *unused __attribute__((__unused__)))
+{
+ void (* const * pctor)(void);
+ static struct object object;
+
+ if (__register_frame_info)
+ __register_frame_info (__EH_FRAME_BEGIN__, &object);
+
+ for (pctor = &__CTOR_END__ - 1; pctor > &__CTOR_LIST__; --pctor)
+ if (*pctor != NULL)
+ (*pctor)();
+
+ return 0;
+}
+
+int
+__deinit_environment (void *unused __attribute__((__unused__)))
+{
+ /* This should be static to prevent calling the same destructor
+ twice (just in case where we get here multiple times). */
+ static void (* const * pdtor)(void) = &__DTOR_LIST__ + 1;
+
+ while (pdtor < &__DTOR_END__)
+ if (*pdtor++ != NULL)
+ pdtor[-1] ();
+
+ if (__deregister_frame_info)
+ __deregister_frame_info(__EH_FRAME_BEGIN__);
+
+ return 0;
+}
diff --git a/contrib/gcc/config/i386/netware-libgcc.c b/contrib/gcc/config/i386/netware-libgcc.c
new file mode 100644
index 0000000..6ad9669
--- /dev/null
+++ b/contrib/gcc/config/i386/netware-libgcc.c
@@ -0,0 +1,59 @@
+/* Startup code for libgcc_s.nlm, necessary because we can't allow
+ libgcc_s to use libc's malloc & Co., which associate allocations
+ with the NLM owning the current (application) thread.
+ Contributed by Jan Beulich (jbeulich@novell.com)
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include <netware.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <windows.h>
+
+static rtag_t allocRTag;
+
+BOOL
+DllMain (HINSTANCE libraryId __attribute__ ((__unused__)),
+ DWORD reason, void *hModule)
+{
+ switch (reason)
+ {
+ case DLL_NLM_STARTUP:
+ allocRTag = AllocateResourceTag (hModule,
+ "libgcc memory", AllocSignature);
+ return allocRTag != NULL;
+ case DLL_NLM_SHUTDOWN:
+ /* This does not recover resources associated with the tag...
+ ReturnResourceTag (allocRTag, 0); */
+ break;
+ }
+ return 1;
+}
+
+void *
+malloc (size_t size)
+{
+ return AllocSleepOK (size, allocRTag, NULL);
+}
+
+void
+free (void *ptr)
+{
+ Free (ptr);
+}
diff --git a/contrib/gcc/config/i386/netware-libgcc.def b/contrib/gcc/config/i386/netware-libgcc.def
new file mode 100644
index 0000000..a545631
--- /dev/null
+++ b/contrib/gcc/config/i386/netware-libgcc.def
@@ -0,0 +1,2 @@
+description "gcc runtime and intrinsics support"
+copyright "Copyright (C) 1989-2005 Free Software Foundation, Inc."
diff --git a/contrib/gcc/config/i386/netware-libgcc.exp b/contrib/gcc/config/i386/netware-libgcc.exp
new file mode 100644
index 0000000..a3498c0
--- /dev/null
+++ b/contrib/gcc/config/i386/netware-libgcc.exp
@@ -0,0 +1,74 @@
+# libgcc_s.nlm exports
+ (libgcc2),
+ __absvdi2,
+ __absvsi2,
+ __addvdi3,
+ __addvsi3,
+# __ashldi3,
+# __ashrdi3,
+ __clzdi2,
+ __clzsi2,
+ __ctzdi2,
+ __ctzsi2,
+ __deregister_frame,
+ __deregister_frame_info,
+ __deregister_frame_info_bases,
+ __divdc3,
+# __divdi3,
+ __divsc3,
+# __divtc3,
+ __divxc3,
+ __ffsdi2,
+ __ffssi2,
+ __fixunsdfdi,
+ __fixunssfdi,
+# __fixunstfdi,
+ __fixunsxfdi,
+ __gcc_bcmp,
+ __gcc_personality_v0,
+# __lshrdi3,
+# __moddi3,
+ __muldc3,
+# __muldi3,
+ __mulsc3,
+# __multc3,
+ __mulvdi3,
+ __mulvsi3,
+ __mulxc3,
+ __negvdi2,
+ __negvsi2,
+ __paritydi2,
+ __paritysi2,
+ __popcountdi2,
+ __popcountsi2,
+ __powidf2
+ __powisf2
+# __powitf2
+ __powixf2
+ __register_frame,
+ __register_frame_info,
+ __register_frame_info_bases,
+ __register_frame_info_table,
+ __register_frame_info_table_bases,
+ __register_frame_table,
+ __subvdi3,
+ __subvsi3,
+# __umoddi3,
+# __udivdi3,
+ _Unwind_Backtrace,
+ _Unwind_DeleteException,
+ _Unwind_FindEnclosingFunction,
+ _Unwind_Find_FDE,
+ _Unwind_ForcedUnwind,
+ _Unwind_GetCFA,
+ _Unwind_GetDataRelBase,
+ _Unwind_GetGR,
+ _Unwind_GetIP,
+ _Unwind_GetLanguageSpecificData,
+ _Unwind_GetRegionStart,
+ _Unwind_GetTextRelBase,
+ _Unwind_RaiseException,
+ _Unwind_Resume,
+ _Unwind_Resume_or_Rethrow,
+ _Unwind_SetGR,
+ _Unwind_SetIP
diff --git a/contrib/gcc/config/i386/netware.c b/contrib/gcc/config/i386/netware.c
new file mode 100644
index 0000000..c26d634
--- /dev/null
+++ b/contrib/gcc/config/i386/netware.c
@@ -0,0 +1,194 @@
+/* Subroutines for insn-output.c for NetWare.
+ Contributed by Jan Beulich (jbeulich@novell.com)
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "ggc.h"
+
+
+/* Return string which is the former assembler name modified with an
+ underscore prefix and a suffix consisting of an atsign (@) followed
+ by the number of bytes of arguments */
+
+static tree
+gen_stdcall_or_fastcall_decoration (tree decl, char prefix)
+{
+ unsigned total = 0;
+ /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
+ of DECL_ASSEMBLER_NAME. */
+ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *newsym;
+ tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
+
+ if (formal_type != NULL_TREE)
+ {
+ /* These attributes are ignored for variadic functions in
+ i386.c:ix86_return_pops_args. For compatibility with MS
+ compiler do not add @0 suffix here. */
+ if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
+ return NULL_TREE;
+
+ /* Quit if we hit an incomplete type. Error is reported
+ by convert_arguments in c-typeck.c or cp/typeck.c. */
+ while (TREE_VALUE (formal_type) != void_type_node
+ && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
+ {
+ unsigned parm_size
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+
+ /* Must round up to include padding. This is done the same
+ way as in store_one_arg. */
+ parm_size = ((parm_size + PARM_BOUNDARY - 1)
+ / PARM_BOUNDARY * PARM_BOUNDARY);
+ total += parm_size;
+ formal_type = TREE_CHAIN (formal_type);
+ }
+ }
+
+ newsym = alloca (1 + strlen (asmname) + 1 + 10 + 1);
+ return get_identifier_with_length (newsym,
+ sprintf (newsym,
+ "%c%s@%u",
+ prefix,
+ asmname,
+ total / BITS_PER_UNIT));
+}
+
+/* Return string which is the former assembler name modified with an
+ _n@ prefix where n represents the number of arguments passed in
+ registers */
+
+static tree
+gen_regparm_prefix (tree decl, unsigned nregs)
+{
+ unsigned total = 0;
+ /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
+ of DECL_ASSEMBLER_NAME. */
+ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ char *newsym;
+ tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
+
+ if (formal_type != NULL_TREE)
+ {
+ /* This attribute is ignored for variadic functions. */
+ if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
+ return NULL_TREE;
+
+ /* Quit if we hit an incomplete type. Error is reported
+ by convert_arguments in c-typeck.c or cp/typeck.c. */
+ while (TREE_VALUE (formal_type) != void_type_node
+ && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
+ {
+ unsigned parm_size
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+
+ /* Must round up to include padding. This is done the same
+ way as in store_one_arg. */
+ parm_size = ((parm_size + PARM_BOUNDARY - 1)
+ / PARM_BOUNDARY * PARM_BOUNDARY);
+ total += parm_size;
+ formal_type = TREE_CHAIN (formal_type);
+ }
+ }
+
+ if (nregs > total / BITS_PER_WORD)
+ nregs = total / BITS_PER_WORD;
+ gcc_assert (nregs <= 9);
+ newsym = alloca (3 + strlen (asmname) + 1);
+ return get_identifier_with_length (newsym,
+ sprintf (newsym,
+ "_%u@%s",
+ nregs,
+ asmname));
+}
+
+void
+i386_nlm_encode_section_info (tree decl, rtx rtl, int first)
+{
+ default_encode_section_info (decl, rtl, first);
+
+ if (first
+ && TREE_CODE (decl) == FUNCTION_DECL
+ && *IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)) != '*'
+ && !strchr (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), '@'))
+ {
+ tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+ tree newid;
+
+ if (lookup_attribute ("stdcall", type_attributes))
+ newid = gen_stdcall_or_fastcall_decoration (decl, '_');
+ else if (lookup_attribute ("fastcall", type_attributes))
+ newid = gen_stdcall_or_fastcall_decoration (decl, FASTCALL_PREFIX);
+ else if ((newid = lookup_attribute ("regparm", type_attributes)) != NULL_TREE)
+ newid = gen_regparm_prefix (decl,
+ TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (newid))));
+ if (newid != NULL_TREE)
+ {
+ rtx rtlname = XEXP (rtl, 0);
+
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
+ /* These attributes must be present on first declaration,
+ change_decl_assembler_name will warn if they are added
+ later and the decl has been referenced, but duplicate_decls
+ should catch the mismatch before this is called. */
+ change_decl_assembler_name (decl, newid);
+ }
+ }
+}
+
+/* Strip the stdcall/fastcall/regparm pre-/suffix. */
+
+const char *
+i386_nlm_strip_name_encoding (const char *str)
+{
+ const char *name = default_strip_name_encoding (str);
+
+ if (*str != '*' && (*name == '_' || *name == '@'))
+ {
+ const char *p = strchr (name + 1, '@');
+
+ if (p)
+ {
+ ++name;
+ if (ISDIGIT (p[1]))
+ name = ggc_alloc_string (name, p - name);
+ else
+ {
+ gcc_assert (ISDIGIT (*name));
+ name++;
+ gcc_assert (name == p);
+ }
+ }
+ }
+ return name;
+}
diff --git a/contrib/gcc/config/i386/nto.h b/contrib/gcc/config/i386/nto.h
index 8860c8b..1095a63 100644
--- a/contrib/gcc/config/i386/nto.h
+++ b/contrib/gcc/config/i386/nto.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef DEFAULT_PCC_STRUCT_RETURN
#define DEFAULT_PCC_STRUCT_RETURN 1
@@ -37,11 +37,6 @@ Boston, MA 02111-1307, USA. */
builtin_assert ("system=qnxnto"); \
builtin_assert ("system=nto"); \
builtin_assert ("system=unix"); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
diff --git a/contrib/gcc/config/i386/nwld.c b/contrib/gcc/config/i386/nwld.c
new file mode 100644
index 0000000..4688ca0
--- /dev/null
+++ b/contrib/gcc/config/i386/nwld.c
@@ -0,0 +1,74 @@
+/* Subroutines for insn-output.c for NetWare.
+ Contributed by Jan Beulich (jbeulich@novell.com)
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+
+void
+nwld_named_section_asm_out_constructor (rtx symbol, int priority)
+{
+#if !SUPPORTS_INIT_PRIORITY
+ const char section[] = ".ctors"TARGET_SUB_SECTION_SEPARATOR;
+#else
+ char section[20];
+
+ sprintf (section,
+ ".ctors"TARGET_SUB_SECTION_SEPARATOR"%.5u",
+ /* Invert the numbering so the linker puts us in the proper
+ order; constructors are run from right to left, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - priority);
+#endif
+
+ switch_to_section (get_section (section, 0, NULL));
+ assemble_align (POINTER_SIZE);
+ assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+}
+
+void
+nwld_named_section_asm_out_destructor (rtx symbol, int priority)
+{
+#if !SUPPORTS_INIT_PRIORITY
+ const char section[] = ".dtors"TARGET_SUB_SECTION_SEPARATOR;
+#else
+ char section[20];
+
+ sprintf (section, ".dtors"TARGET_SUB_SECTION_SEPARATOR"%.5u",
+ /* Invert the numbering so the linker puts us in the proper
+ order; destructors are run from left to right, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - priority);
+#endif
+
+ switch_to_section (get_section (section, 0, NULL));
+ assemble_align (POINTER_SIZE);
+ assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+}
diff --git a/contrib/gcc/config/i386/nwld.h b/contrib/gcc/config/i386/nwld.h
new file mode 100644
index 0000000..fe132af
--- /dev/null
+++ b/contrib/gcc/config/i386/nwld.h
@@ -0,0 +1,63 @@
+/* nwld.h -- defines to be used when targeting GCC for some generic NetWare
+ system while using the Novell linker.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ Written by Jan Beulich (jbeulich@novell.com)
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "-lc --def-file libc.def%s"
+
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC "-lgcc %{!static-libgcc:--def-file libgcc.def%s}"
+
+#undef LINKER_NAME
+#define LINKER_NAME "nwld"
+
+#undef LINK_SPEC
+#define LINK_SPEC "--format:NLM --extensions:GNU" \
+ " %{static:%{!nostdlib:%{!nodefaultlib:%eStatic linking is not supported.\n}}}"
+
+#undef LINK_GCC_C_SEQUENCE_SPEC
+#define LINK_GCC_C_SEQUENCE_SPEC "%L %G"
+
+/* In order to permit the linker to derive the output filename from the first
+ input file, put the common startup code as the last object. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC ""
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crt0%O%s ../imports/%{!posix:libc}%{posix:posix}pre.gcc%O%s" \
+ " --def-file %{!posix:libc}%{posix:posix}pre.def%s"
+
+#define DRIVER_SELF_SPECS "%{!static-libgcc:-shared-libgcc}"
+
+#define TARGET_SUB_SECTION_SEPARATOR "$"
+
+void nwld_named_section_asm_out_constructor (rtx, int);
+void nwld_named_section_asm_out_destructor (rtx, int);
+
+#define TARGET_ASM_CONSTRUCTOR nwld_named_section_asm_out_constructor
+#define TARGET_ASM_DESTRUCTOR nwld_named_section_asm_out_destructor
+
+#undef EH_FRAME_SECTION_NAME
+#define EH_FRAME_SECTION_NAME ".eh_frame"TARGET_SUB_SECTION_SEPARATOR
+
+/* nwld does not currently support stabs debug info */
+#undef DBX_DEBUGGING_INFO
diff --git a/contrib/gcc/config/i386/openbsd.h b/contrib/gcc/config/i386/openbsd.h
index 14de018..6c5be72 100644
--- a/contrib/gcc/config/i386/openbsd.h
+++ b/contrib/gcc/config/i386/openbsd.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (OpenBSD/i386)");
diff --git a/contrib/gcc/config/i386/openbsdelf.h b/contrib/gcc/config/i386/openbsdelf.h
new file mode 100644
index 0000000..9323121
--- /dev/null
+++ b/contrib/gcc/config/i386/openbsdelf.h
@@ -0,0 +1,132 @@
+/* Configuration for an OpenBSD i386 target.
+
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* This gets defined in tm.h->linux.h->svr4.h, and keeps us from using
+ libraries compiled with the native cc, so undef it. */
+#undef NO_DOLLAR_IN_LABEL
+
+/* Override the default comment-starter of "/". */
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START "#"
+
+#undef DBX_REGISTER_NUMBER
+#define DBX_REGISTER_NUMBER(n) svr4_dbx_register_map[n]
+
+/* This goes away when the math-emulator is fixed */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_NO_FANCY_MATH_387)
+
+/* Run-time target specifications */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ OPENBSD_OS_CPP_BUILTINS(); \
+ } \
+ while (0)
+
+/* As an elf system, we need crtbegin/crtend stuff. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "\
+ %{!shared: %{pg:gcrt0%O%s} %{!pg:%{p:gcrt0%O%s} %{!p:crt0%O%s}} \
+ crtbegin%O%s} %{shared:crtbeginS%O%s}"
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "%{!shared:crtend%O%s} %{shared:crtendS%O%s}"
+
+/* Layout of source language data types. */
+
+/* This must agree with <machine/ansi.h> */
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+/* Assembler format: overall framework. */
+
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+#undef SET_ASM_OP
+#define SET_ASM_OP "\t.set\t"
+
+/* The following macros were originally stolen from i386v4.h.
+ These have to be defined to get PIC code correct. */
+
+/* Assembler format: dispatch tables. */
+
+/* Assembler format: sections. */
+
+/* Stack & calling: aggregate returns. */
+
+/* Don't default to pcc-struct-return, because gcc is the only compiler, and
+ we want to retain compatibility with older gcc versions. */
+#define DEFAULT_PCC_STRUCT_RETURN 0
+
+/* Assembler format: alignment output. */
+
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ if ((LOG) != 0) {\
+ if ((MAX_SKIP) == 0) fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
+#endif
+
+/* Stack & calling: profiling. */
+
+/* OpenBSD's profiler recovers all information from the stack pointer.
+ The icky part is not here, but in machine/profile.h. */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ fputs (flag_pic ? "\tcall __mcount@PLT\n": "\tcall __mcount\n", FILE);
+
+/* Assembler format: exception region output. */
+
+/* our configuration still doesn't handle dwarf2 correctly */
+#define DWARF2_UNWIND_INFO 0
+
+/* Assembler format: alignment output. */
+
+/* Note that we pick up ASM_OUTPUT_MAX_SKIP_ALIGN from i386/gas.h */
+
+/* Note that we pick up ASM_OUTPUT_MI_THUNK from unix.h. */
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{!shared:%{!nostdlib:%{!r*:%{!e*:-e __start}}}} \
+ %{shared:-shared} %{R*} \
+ %{static:-Bstatic} \
+ %{!static:-Bdynamic} \
+ %{assert*} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.so}"
+
+#define OBSD_HAS_CORRECT_SPECS
diff --git a/contrib/gcc/config/i386/pentium.md b/contrib/gcc/config/i386/pentium.md
index 5fec811..1f994dd 100644
--- a/contrib/gcc/config/i386/pentium.md
+++ b/contrib/gcc/config/i386/pentium.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
;; The Pentium is an in-order core with two integer pipelines.
diff --git a/contrib/gcc/config/i386/pmm_malloc.h b/contrib/gcc/config/i386/pmm_malloc.h
new file mode 100644
index 0000000..744ac6d
--- /dev/null
+++ b/contrib/gcc/config/i386/pmm_malloc.h
@@ -0,0 +1,60 @@
+/* Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, if you include this header file into source
+ files compiled by GCC, this header file does not by itself cause
+ the resulting executable to be covered by the GNU General Public
+ License. This exception does not however invalidate any other
+ reasons why the executable file might be covered by the GNU General
+ Public License. */
+
+#ifndef _MM_MALLOC_H_INCLUDED
+#define _MM_MALLOC_H_INCLUDED
+
+#include <stdlib.h>
+
+/* We can't depend on <stdlib.h> since the prototype of posix_memalign
+ may not be visible. */
+#ifndef __cplusplus
+extern int posix_memalign (void **, size_t, size_t);
+#else
+extern "C" int posix_memalign (void **, size_t, size_t) throw ();
+#endif
+
+static __inline void *
+_mm_malloc (size_t size, size_t alignment)
+{
+ void *ptr;
+ if (alignment == 1)
+ return malloc (size);
+ if (alignment == 2 || (sizeof (void *) == 8 && alignment == 4))
+ alignment = sizeof (void *);
+ if (posix_memalign (&ptr, alignment, size) == 0)
+ return ptr;
+ else
+ return NULL;
+}
+
+static __inline void
+_mm_free (void * ptr)
+{
+ free (ptr);
+}
+
+#endif /* _MM_MALLOC_H_INCLUDED */
diff --git a/contrib/gcc/config/i386/pmmintrin.h b/contrib/gcc/config/i386/pmmintrin.h
index 3b18e2a..7dbf030 100644
--- a/contrib/gcc/config/i386/pmmintrin.h
+++ b/contrib/gcc/config/i386/pmmintrin.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +14,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -25,7 +25,7 @@
Public License. */
/* Implemented from the specification included in the Intel C++ Compiler
- User Guide and Reference, version 8.0. */
+ User Guide and Reference, version 9.0. */
#ifndef _PMMINTRIN_H_INCLUDED
#define _PMMINTRIN_H_INCLUDED
@@ -44,88 +44,83 @@
#define _MM_GET_DENORMALS_ZERO_MODE() \
(_mm_getcsr() & _MM_DENORMALS_ZERO_MASK)
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_addsub_ps (__m128 __X, __m128 __Y)
{
return (__m128) __builtin_ia32_addsubps ((__v4sf)__X, (__v4sf)__Y);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_hadd_ps (__m128 __X, __m128 __Y)
{
return (__m128) __builtin_ia32_haddps ((__v4sf)__X, (__v4sf)__Y);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_hsub_ps (__m128 __X, __m128 __Y)
{
return (__m128) __builtin_ia32_hsubps ((__v4sf)__X, (__v4sf)__Y);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_movehdup_ps (__m128 __X)
{
return (__m128) __builtin_ia32_movshdup ((__v4sf)__X);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_moveldup_ps (__m128 __X)
{
return (__m128) __builtin_ia32_movsldup ((__v4sf)__X);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_addsub_pd (__m128d __X, __m128d __Y)
{
return (__m128d) __builtin_ia32_addsubpd ((__v2df)__X, (__v2df)__Y);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_hadd_pd (__m128d __X, __m128d __Y)
{
return (__m128d) __builtin_ia32_haddpd ((__v2df)__X, (__v2df)__Y);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_hsub_pd (__m128d __X, __m128d __Y)
{
return (__m128d) __builtin_ia32_hsubpd ((__v2df)__X, (__v2df)__Y);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_loaddup_pd (double const *__P)
{
- return (__m128d) __builtin_ia32_loadddup (__P);
+ return _mm_load1_pd (__P);
}
-static __inline __m128d
+static __inline __m128d __attribute__((__always_inline__))
_mm_movedup_pd (__m128d __X)
{
- return (__m128d) __builtin_ia32_movddup ((__v2df)__X);
+ return _mm_shuffle_pd (__X, __X, _MM_SHUFFLE2 (0,0));
}
-static __inline __m128i
+static __inline __m128i __attribute__((__always_inline__))
_mm_lddqu_si128 (__m128i const *__P)
{
return (__m128i) __builtin_ia32_lddqu ((char const *)__P);
}
-#if 0
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_monitor (void const * __P, unsigned int __E, unsigned int __H)
{
__builtin_ia32_monitor (__P, __E, __H);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_mwait (unsigned int __E, unsigned int __H)
{
__builtin_ia32_mwait (__E, __H);
}
-#else
-#define _mm_monitor(P, E, H) __builtin_ia32_monitor ((P), (E), (H))
-#define _mm_mwait(E, H) __builtin_ia32_mwait ((E), (H))
-#endif
#endif /* __SSE3__ */
diff --git a/contrib/gcc/config/i386/ppro.md b/contrib/gcc/config/i386/ppro.md
index 911bf3b..9f06989 100644
--- a/contrib/gcc/config/i386/ppro.md
+++ b/contrib/gcc/config/i386/ppro.md
@@ -1,5 +1,5 @@
-;; Pentium Pro/PII Scheduling
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Scheduling for the Intel P6 family of processors
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,136 +15,750 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
-
-;; Categorize how many uops an ia32 instruction evaluates to:
-;; one -- an instruction with 1 uop can be decoded by any of the
-;; three decoders.
-;; few -- an instruction with 1 to 4 uops can be decoded only by
-;; decoder 0.
-;; many -- a complex instruction may take an unspecified number of
-;; cycles to decode in decoder 0.
-
-(define_attr "ppro_uops" "one,few,many"
- (cond [(eq_attr "type" "other,multi,call,callv,fpspc,str")
- (const_string "many")
- (eq_attr "type" "icmov,fcmov,str,cld,leave")
- (const_string "few")
- (eq_attr "type" "imov")
- (if_then_else (eq_attr "memory" "store,both")
- (const_string "few")
- (const_string "one"))
- (eq_attr "memory" "!none")
- (const_string "few")
- ]
- (const_string "one")))
-
-;;
-;; The PPro has an out-of-order core, but the instruction decoders are
-;; naturally in-order and asymmetric. We get best performance by scheduling
-;; for the decoders, for in doing so we give the oo execution unit the
-;; most choices.
-;;
-;; Rough readiness numbers. Fine tuning happens in i386.c.
-;;
-;; p0 describes port 0.
-;; p01 describes ports 0 and 1 as a pair; alu insns can issue to either.
-;; p2 describes port 2 for loads.
-;; p34 describes ports 3 and 4 for stores.
-;; fpu describes the fpu accessed via port 0.
-;; ??? It is less than clear if there are separate fadd and fmul units
-;; that could operate in parallel.
-;;
-;; ??? fxch isn't handled; not an issue until sched3 after reg-stack is real.
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "ishift,rotate,ishift1,rotate1,lea,ibr,cld"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imul"))
- 4 1)
-
-;; ??? Does the divider lock out the pipe while it works,
-;; or is there a disconnected unit?
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "idiv"))
- 17 17)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fsgn,fistp"))
- 3 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fcmov"))
- 2 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fcmp"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmov"))
- 1 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmul"))
- 5 1)
-
-(define_function_unit "ppro_p0" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fdiv,fpspc"))
- 56 1)
-
-(define_function_unit "ppro_p01" 2 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "!imov,fmov"))
- 1 1)
-
-(define_function_unit "ppro_p01" 2 0
- (and (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imov,fmov"))
- (eq_attr "memory" "none"))
- 1 1)
-
-(define_function_unit "ppro_p2" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (ior (eq_attr "type" "pop,leave")
- (eq_attr "memory" "load,both")))
- 3 1)
-
-(define_function_unit "ppro_p34" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (ior (eq_attr "type" "push")
- (eq_attr "memory" "store,both")))
- 1 1)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fop,fsgn,fmov,fcmp,fcmov,fistp"))
- 1 1)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fmul"))
- 5 2)
-
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "fdiv,fpspc"))
- 56 56)
-
-;; imul uses the fpu. ??? does it have the same throughput as fmul?
-(define_function_unit "fpu" 1 0
- (and (eq_attr "cpu" "pentiumpro")
- (eq_attr "type" "imul"))
- 4 1)
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
+
+;; The P6 family includes the Pentium Pro, Pentium II, Pentium III, Celeron
+;; and Xeon lines of CPUs. The DFA scheduler description in this file is
+;; based on information that can be found in the following three documents:
+;;
+;; "P6 Family of Processors Hardware Developer's Manual",
+;; Intel, September 1999.
+;;
+;; "Intel Architecture Optimization Manual",
+;; Intel, 1999 (Order Number: 245127-001).
+;;
+;; "How to optimize for the Pentium family of microprocessors",
+;; by Agner Fog, PhD.
+;;
+;; The P6 pipeline has three major components:
+;; 1) the FETCH/DECODE unit, an in-order issue front-end
+;; 2) the DISPATCH/EXECUTE unit, which is the out-of-order core
+;; 3) the RETIRE unit, an in-order retirement unit
+;;
+;; So, the P6 CPUs have out-of-order cores, but the instruction decoder and
+;; retirement unit are naturally in-order.
+;;
+;; BUS INTERFACE UNIT
+;; / \
+;; L1 ICACHE L1 DCACHE
+;; / | \ | \
+;; DECODER0 DECODER1 DECODER2 DISP/EXEC RETIRE
+;; \ | / | |
+;; INSTRUCTION POOL __________|_______/
+;; (inc. reorder buffer)
+;;
+;; Since the P6 CPUs execute instructions out-of-order, the most important
+;; consideration in performance tuning is making sure enough micro-ops are
+;; ready for execution in the out-of-order core, while not stalling the
+;; decoder.
+;;
+;; TODO:
+;; - Find a less crude way to model complex instructions, in
+;; particular how many cycles they take to be decoded.
+;; - Include decoder latencies in the total reservation latencies.
+;; This isn't necessary right now because we assume for every
+;; instruction that it never blocks a decoder.
+;; - Figure out where the p0 and p1 reservations come from. These
+;; appear not to be in the manual (e.g. why is cld "(p0+p1)*2"
+;; better than "(p0|p1)*4" ???)
+;; - Lots more because I'm sure this is still far from optimal :-)
+
+;; The ppro_idiv and ppro_fdiv automata are used to model issue
+;; latencies of idiv and fdiv type insns.
+(define_automaton "ppro_decoder,ppro_core,ppro_idiv,ppro_fdiv,ppro_load,ppro_store")
+
+;; Simple instructions of the register-register form have only one uop.
+;; Load instructions are also only one uop. Store instructions decode to
+;; two uops, and simple read-modify instructions also take two uops.
+;; Simple instructions of the register-memory form have two to three uops.
+;; Simple read-modify-write instructions have four uops. The rules for
+;; the decoder are simple:
+;; - an instruction with 1 uop can be decoded by any of the three
+;; decoders in one cycle.
+;; - an instruction with 1 to 4 uops can be decoded only by decoder 0
+;; but still in only one cycle.
+;; - a complex (microcode) instruction can also only be decoded by
+;; decoder 0, and this takes an unspecified number of cycles.
+;;
+;; The goal is to schedule such that we have a few-one-one uops sequence
+;; in each cycle, to decode as many instructions per cycle as possible.
+(define_cpu_unit "decoder0" "ppro_decoder")
+(define_cpu_unit "decoder1" "ppro_decoder")
+(define_cpu_unit "decoder2" "ppro_decoder")
+
+;; We first wish to find an instruction for decoder0, so exclude
+;; decoder1 and decoder2 from being reserved until decoder 0 is
+;; reserved.
+(presence_set "decoder1" "decoder0")
+(presence_set "decoder2" "decoder0")
+
+;; Most instructions can be decoded on any of the three decoders.
+(define_reservation "decodern" "(decoder0|decoder1|decoder2)")
+
+;; The out-of-order core has five pipelines. During each cycle, the core
+;; may dispatch zero or one uop on the port of any of the five pipelines
+;; so the maximum number of dispatched uops per cycle is 5. In practicer,
+;; 3 uops per cycle is more realistic.
+;;
+;; Two of the five pipelines contain several execution units:
+;;
+;; Port 0 Port 1 Port 2 Port 3 Port 4
+;; ALU ALU LOAD SAC SDA
+;; FPU JUE
+;; AGU MMX
+;; MMX P3FPU
+;; P3FPU
+;;
+;; (SAC=Store Address Calculation, SDA=Store Data Unit, P3FPU = SSE unit,
+;; JUE = Jump Execution Unit, AGU = Address Generation Unit)
+;;
+(define_cpu_unit "p0,p1" "ppro_core")
+(define_cpu_unit "p2" "ppro_load")
+(define_cpu_unit "p3,p4" "ppro_store")
+(define_cpu_unit "idiv" "ppro_idiv")
+(define_cpu_unit "fdiv" "ppro_fdiv")
+
+;; Only the irregular instructions have to be modeled here. A load
+;; increases the latency by 2 or 3, or by nothing if the manual gives
+;; a latency already. Store latencies are not accounted for.
+;;
+;; The simple instructions follow a very regular pattern of 1 uop per
+;; reg-reg operation, 1 uop per load on port 2. and 2 uops per store
+;; on port 4 and port 3. These instructions are modelled at the bottom
+;; of this file.
+;;
+;; For microcoded instructions we don't know how many uops are produced.
+;; These instructions are the "complex" ones in the Intel manuals. All
+;; we _do_ know is that they typically produce four or more uops, so
+;; they can only be decoded on decoder0. Modelling their latencies
+;; doesn't make sense because we don't know how these instructions are
+;; executed in the core. So we just model that they can only be decoded
+;; on decoder 0, and say that it takes a little while before the result
+;; is available.
+(define_insn_reservation "ppro_complex_insn" 6
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "other,multi,call,callv,str"))
+ "decoder0")
+
+;; imov with memory operands does not use the integer units.
+(define_insn_reservation "ppro_imov" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "imov")))
+ "decodern,(p0|p1)")
+
+(define_insn_reservation "ppro_imov_load" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "imov")))
+ "decodern,p2")
+
+(define_insn_reservation "ppro_imov_store" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (eq_attr "type" "imov")))
+ "decoder0,p4+p3")
+
+;; imovx always decodes to one uop, and also doesn't use the integer
+;; units if it has memory operands.
+(define_insn_reservation "ppro_imovx" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "imovx")))
+ "decodern,(p0|p1)")
+
+(define_insn_reservation "ppro_imovx_load" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "imovx")))
+ "decodern,p2")
+
+;; lea executes on port 0 with latency one and throughput 1.
+(define_insn_reservation "ppro_lea" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "lea")))
+ "decodern,p0")
+
+;; Shift and rotate execute on port 0 with latency and throughput 1.
+;; The load and store units need to be reserved when memory operands
+;; are involved.
+(define_insn_reservation "ppro_shift_rotate" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "ishift,ishift1,rotate,rotate1")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_shift_rotate_mem" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "!none")
+ (eq_attr "type" "ishift,ishift1,rotate,rotate1")))
+ "decoder0,p2+p0,p4+p3")
+
+(define_insn_reservation "ppro_cld" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "cld"))
+ "decoder0,(p0+p1)*2")
+
+;; The P6 has a sophisticated branch prediction mechanism to minimize
+;; latencies due to branching. In particular, it has a fast way to
+;; execute branches that are taken multiple times (such as in loops).
+;; Branches not taken suffer no penalty, and correctly predicted
+;; branches cost only one fetch cycle. Mispredicted branches are very
+;; costly: typically 15 cycles and possibly as many as 26 cycles.
+;;
+;; Unfortunately all this makes it quite difficult to properly model
+;; the latencies for the compiler. Here I've made the choice to be
+;; optimistic and assume branches are often predicted correctly, so
+;; they have latency 1, and the decoders are not blocked.
+;;
+;; In addition, the model assumes a branch always decodes to only 1 uop,
+;; which is not exactly true because there are a few instructions that
+;; decode to 2 uops or microcode. But this probably gives the best
+;; results because we can assume these instructions can decode on all
+;; decoders.
+(define_insn_reservation "ppro_branch" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "ibr")))
+ "decodern,p1")
+
+;; ??? Indirect branches probably have worse latency than this.
+(define_insn_reservation "ppro_indirect_branch" 6
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "!none")
+ (eq_attr "type" "ibr")))
+ "decoder0,p2+p1")
+
+(define_insn_reservation "ppro_leave" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "leave"))
+ "decoder0,p2+(p0|p1),(p0|p1)")
+
+;; imul has throughput one, but latency 4, and can only execute on port 0.
+(define_insn_reservation "ppro_imul" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "imul")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_imul_mem" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "!none")
+ (eq_attr "type" "imul")))
+ "decoder0,p2+p0")
+
+;; div and idiv are very similar, so we model them the same.
+;; QI, HI, and SI have issue latency 12, 21, and 37, respectively.
+;; These issue latencies are modelled via the ppro_div automaton.
+(define_insn_reservation "ppro_idiv_QI" 19
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "QI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,(p0+idiv)*2,(p0|p1)+idiv,idiv*9")
+
+(define_insn_reservation "ppro_idiv_QI_load" 19
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "QI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,p2+p0+idiv,p0+idiv,(p0|p1)+idiv,idiv*9")
+
+(define_insn_reservation "ppro_idiv_HI" 23
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "HI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,(p0+idiv)*3,(p0|p1)+idiv,idiv*17")
+
+(define_insn_reservation "ppro_idiv_HI_load" 23
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "HI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,p2+p0+idiv,p0+idiv,(p0|p1)+idiv,idiv*18")
+
+(define_insn_reservation "ppro_idiv_SI" 39
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,(p0+idiv)*3,(p0|p1)+idiv,idiv*33")
+
+(define_insn_reservation "ppro_idiv_SI_load" 39
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SI")
+ (eq_attr "type" "idiv"))))
+ "decoder0,p2+p0+idiv,p0+idiv,(p0|p1)+idiv,idiv*34")
+
+;; Floating point operations always execute on port 0.
+;; ??? where do these latencies come from? fadd has latency 3 and
+;; has throughput "1/cycle (align with FADD)". What do they
+;; mean and how can we model that?
+(define_insn_reservation "ppro_fop" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none,unknown")
+ (eq_attr "type" "fop")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_fop_load" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "fop")))
+ "decoder0,p2+p0,p0")
+
+(define_insn_reservation "ppro_fop_store" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (eq_attr "type" "fop")))
+ "decoder0,p0,p0,p0+p4+p3")
+
+(define_insn_reservation "ppro_fop_both" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "both")
+ (eq_attr "type" "fop")))
+ "decoder0,p2+p0,p0+p4+p3")
+
+(define_insn_reservation "ppro_fsgn" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "fsgn"))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_fistp" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "fistp"))
+ "decoder0,p0*2,p4+p3")
+
+(define_insn_reservation "ppro_fcmov" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (eq_attr "type" "fcmov"))
+ "decoder0,p0*2")
+
+(define_insn_reservation "ppro_fcmp" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "fcmp")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_fcmp_load" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "fcmp")))
+ "decoder0,p2+p0")
+
+(define_insn_reservation "ppro_fmov" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "fmov")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_fmov_load" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "!XF")
+ (eq_attr "type" "fmov"))))
+ "decodern,p2")
+
+(define_insn_reservation "ppro_fmov_XF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "XF")
+ (eq_attr "type" "fmov"))))
+ "decoder0,(p2+p0)*2")
+
+(define_insn_reservation "ppro_fmov_store" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (and (eq_attr "mode" "!XF")
+ (eq_attr "type" "fmov"))))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_fmov_XF_store" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (and (eq_attr "mode" "XF")
+ (eq_attr "type" "fmov"))))
+ "decoder0,(p0+p4),(p0+p3)")
+
+;; fmul executes on port 0 with latency 5. It has issue latency 2,
+;; but we don't model this.
+(define_insn_reservation "ppro_fmul" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "fmul")))
+ "decoder0,p0*2")
+
+(define_insn_reservation "ppro_fmul_load" 6
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "fmul")))
+ "decoder0,p2+p0,p0")
+
+;; fdiv latencies depend on the mode of the operands. XFmode gives
+;; a latency of 38 cycles, DFmode gives 32, and SFmode gives latency 18.
+;; Division by a power of 2 takes only 9 cycles, but we cannot model
+;; that. Throughput is equal to latency - 1, which we model using the
+;; ppro_div automaton.
+(define_insn_reservation "ppro_fdiv_SF" 18
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decodern,p0+fdiv,fdiv*16")
+
+(define_insn_reservation "ppro_fdiv_SF_load" 19
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decoder0,p2+p0+fdiv,fdiv*16")
+
+(define_insn_reservation "ppro_fdiv_DF" 32
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decodern,p0+fdiv,fdiv*30")
+
+(define_insn_reservation "ppro_fdiv_DF_load" 33
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decoder0,p2+p0+fdiv,fdiv*30")
+
+(define_insn_reservation "ppro_fdiv_XF" 38
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "XF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decodern,p0+fdiv,fdiv*36")
+
+(define_insn_reservation "ppro_fdiv_XF_load" 39
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "XF")
+ (eq_attr "type" "fdiv,fpspc"))))
+ "decoder0,p2+p0+fdiv,fdiv*36")
+
+;; MMX instructions can execute on either port 0 or port 1 with a
+;; throughput of 1/cycle.
+;; on port 0: - ALU (latency 1)
+;; - Multiplier Unit (latency 3)
+;; on port 1: - ALU (latency 1)
+;; - Shift Unit (latency 1)
+;;
+;; MMX instructions are either of the type reg-reg, or read-modify, and
+;; except for mmxshft and mmxmul they can execute on port 0 or port 1,
+;; so they behave as "simple" instructions that need no special modelling.
+;; We only have to model mmxshft and mmxmul.
+(define_insn_reservation "ppro_mmx_shft" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "mmxshft")))
+ "decodern,p1")
+
+(define_insn_reservation "ppro_mmx_shft_load" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "mmxshft")))
+ "decoder0,p2+p1")
+
+(define_insn_reservation "ppro_mmx_mul" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "mmxmul")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_mmx_mul_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (eq_attr "type" "mmxmul")))
+ "decoder0,p2+p0")
+
+(define_insn_reservation "ppro_sse_mmxcvt" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "mode" "DI")
+ (eq_attr "type" "mmxcvt")))
+ "decodern,p1")
+
+;; FIXME: These are Pentium III only, but we cannot tell here if
+;; we're generating code for PentiumPro/Pentium II or Pentium III
+;; (define_insn_reservation "ppro_sse_mmxshft" 2
+;; (and (eq_attr "cpu" "pentiumpro,generic32")
+;; (and (eq_attr "mode" "DI")
+;; (eq_attr "type" "mmxshft")))
+;; "decodern,p0")
+
+;; SSE is very complicated, and takes a bit more effort.
+;; ??? I assumed that all SSE instructions decode on decoder0,
+;; but is this correct?
+
+;; The sfence instruction.
+(define_insn_reservation "ppro_sse_sfence" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "unknown")
+ (eq_attr "type" "sse")))
+ "decoder0,p4+p3")
+
+;; FIXME: This reservation is all wrong when we're scheduling sqrtss.
+(define_insn_reservation "ppro_sse_SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "sse")))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_sse_add_SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "sseadd"))))
+ "decodern,p1")
+
+(define_insn_reservation "ppro_sse_add_SF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "sseadd"))))
+ "decoder0,p2+p1")
+
+(define_insn_reservation "ppro_sse_cmp_SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssecmp"))))
+ "decoder0,p1")
+
+(define_insn_reservation "ppro_sse_cmp_SF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssecmp"))))
+ "decoder0,p2+p1")
+
+(define_insn_reservation "ppro_sse_comi_SF" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssecomi"))))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_sse_comi_SF_load" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssecomi"))))
+ "decoder0,p2+p0")
+
+(define_insn_reservation "ppro_sse_mul_SF" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssemul"))))
+ "decodern,p0")
+
+(define_insn_reservation "ppro_sse_mul_SF_load" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssemul"))))
+ "decoder0,p2+p0")
+
+;; FIXME: ssediv doesn't close p0 for 17 cycles, surely???
+(define_insn_reservation "ppro_sse_div_SF" 18
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssediv"))))
+ "decoder0,p0*17")
+
+(define_insn_reservation "ppro_sse_div_SF_load" 18
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssediv"))))
+ "decoder0,(p2+p0),p0*16")
+
+(define_insn_reservation "ppro_sse_icvt_SF" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "sseicvt")))
+ "decoder0,(p2+p1)*2")
+
+(define_insn_reservation "ppro_sse_icvt_SI" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "mode" "SI")
+ (eq_attr "type" "sseicvt")))
+ "decoder0,(p2+p1)")
+
+(define_insn_reservation "ppro_sse_mov_SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,(p0|p1)")
+
+(define_insn_reservation "ppro_sse_mov_SF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,p2+(p0|p1)")
+
+(define_insn_reservation "ppro_sse_mov_SF_store" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,p4+p3")
+
+(define_insn_reservation "ppro_sse_V4SF" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "sse")))
+ "decoder0,p1*2")
+
+(define_insn_reservation "ppro_sse_add_V4SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "sseadd"))))
+ "decoder0,p1*2")
+
+(define_insn_reservation "ppro_sse_add_V4SF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "sseadd"))))
+ "decoder0,(p2+p1)*2")
+
+(define_insn_reservation "ppro_sse_cmp_V4SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssecmp"))))
+ "decoder0,p1*2")
+
+(define_insn_reservation "ppro_sse_cmp_V4SF_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssecmp"))))
+ "decoder0,(p2+p1)*2")
+
+(define_insn_reservation "ppro_sse_cvt_V4SF" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none,unknown")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssecvt"))))
+ "decoder0,p1*2")
+
+(define_insn_reservation "ppro_sse_cvt_V4SF_other" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "!none,unknown")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssecmp"))))
+ "decoder0,p1,p4+p3")
+
+(define_insn_reservation "ppro_sse_mul_V4SF" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssemul"))))
+ "decoder0,p0*2")
+
+(define_insn_reservation "ppro_sse_mul_V4SF_load" 5
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssemul"))))
+ "decoder0,(p2+p0)*2")
+
+;; FIXME: p0 really closed this long???
+(define_insn_reservation "ppro_sse_div_V4SF" 48
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssediv"))))
+ "decoder0,p0*34")
+
+(define_insn_reservation "ppro_sse_div_V4SF_load" 48
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssediv"))))
+ "decoder0,(p2+p0)*2,p0*32")
+
+(define_insn_reservation "ppro_sse_log_V4SF" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "sselog,sselog1"))))
+ "decodern,p1")
+
+(define_insn_reservation "ppro_sse_log_V4SF_load" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "sselog,sselog1"))))
+ "decoder0,(p2+p1)")
+
+(define_insn_reservation "ppro_sse_mov_V4SF" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,(p0|p1)*2")
+
+(define_insn_reservation "ppro_sse_mov_V4SF_load" 2
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,p2*2")
+
+(define_insn_reservation "ppro_sse_mov_V4SF_store" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (and (eq_attr "mode" "V4SF")
+ (eq_attr "type" "ssemov"))))
+ "decoder0,(p4+p3)*2")
+
+;; All other instructions are modelled as simple instructions.
+;; We have already modelled all i387 floating point instructions, so all
+;; other instructions execute on either port 0 or port 1. This includes
+;; the ALU units, and the MMX units.
+;;
+;; reg-reg instructions produce 1 uop so they can be decoded on any of
+;; the three decoders.
+(define_insn_reservation "ppro_insn" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "none,unknown")
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ "decodern,(p0|p1)")
+
+;; read-modify and register-memory instructions have 2 or three uops,
+;; so they have to be decoded on decoder0.
+(define_insn_reservation "ppro_insn_load" 3
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "load")
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ "decoder0,p2+(p0|p1)")
+
+(define_insn_reservation "ppro_insn_store" 1
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "store")
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ "decoder0,(p0|p1),p4+p3")
+
+;; read-modify-store instructions produce 4 uops so they have to be
+;; decoded on decoder0 as well.
+(define_insn_reservation "ppro_insn_both" 4
+ (and (eq_attr "cpu" "pentiumpro,generic32")
+ (and (eq_attr "memory" "both")
+ (eq_attr "type" "alu,alu1,negnot,incdec,icmp,test,setcc,icmov,push,pop,fxch,sseiadd,sseishft,sseimul,mmx,mmxadd,mmxcmp")))
+ "decoder0,p2+(p0|p1),p4+p3")
+
diff --git a/contrib/gcc/config/i386/predicates.md b/contrib/gcc/config/i386/predicates.md
new file mode 100644
index 0000000..5201191
--- /dev/null
+++ b/contrib/gcc/config/i386/predicates.md
@@ -0,0 +1,990 @@
+;; Predicate definitions for IA-32 and x86-64.
+;; Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Return nonzero if OP is either a i387 or SSE fp register.
+(define_predicate "any_fp_register_operand"
+ (and (match_code "reg")
+ (match_test "ANY_FP_REGNO_P (REGNO (op))")))
+
+;; Return nonzero if OP is an i387 fp register.
+(define_predicate "fp_register_operand"
+ (and (match_code "reg")
+ (match_test "FP_REGNO_P (REGNO (op))")))
+
+;; Return nonzero if OP is a non-fp register_operand.
+(define_predicate "register_and_not_any_fp_reg_operand"
+ (and (match_code "reg")
+ (not (match_test "ANY_FP_REGNO_P (REGNO (op))"))))
+
+;; Return nonzero if OP is a register operand other than an i387 fp register.
+(define_predicate "register_and_not_fp_reg_operand"
+ (and (match_code "reg")
+ (not (match_test "FP_REGNO_P (REGNO (op))"))))
+
+;; True if the operand is an MMX register.
+(define_predicate "mmx_reg_operand"
+ (and (match_code "reg")
+ (match_test "MMX_REGNO_P (REGNO (op))")))
+
+;; True if the operand is a Q_REGS class register.
+(define_predicate "q_regs_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return ANY_QI_REG_P (op);
+})
+
+;; Return true if op is a NON_Q_REGS class register.
+(define_predicate "non_q_regs_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return NON_QI_REG_P (op);
+})
+
+;; Match an SI or HImode register for a zero_extract.
+(define_special_predicate "ext_register_operand"
+ (match_operand 0 "register_operand")
+{
+ if ((!TARGET_64BIT || GET_MODE (op) != DImode)
+ && GET_MODE (op) != SImode && GET_MODE (op) != HImode)
+ return 0;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ /* Be careful to accept only registers having upper parts. */
+ return REGNO (op) > LAST_VIRTUAL_REGISTER || REGNO (op) < 4;
+})
+
+;; Return true if op is the AX register.
+(define_predicate "ax_reg_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == 0")))
+
+;; Return true if op is the flags register.
+(define_predicate "flags_reg_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == FLAGS_REG")))
+
+;; Return 1 if VALUE can be stored in a sign extended immediate field.
+(define_predicate "x86_64_immediate_operand"
+ (match_code "const_int,symbol_ref,label_ref,const")
+{
+ if (!TARGET_64BIT)
+ return immediate_operand (op, mode);
+
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ /* CONST_DOUBLES never match, since HOST_BITS_PER_WIDE_INT is known
+ to be at least 32 and this all acceptable constants are
+ represented as CONST_INT. */
+ if (HOST_BITS_PER_WIDE_INT == 32)
+ return 1;
+ else
+ {
+ HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (op), DImode);
+ return trunc_int_for_mode (val, SImode) == val;
+ }
+ break;
+
+ case SYMBOL_REF:
+ /* For certain code models, the symbolic references are known to fit.
+ in CM_SMALL_PIC model we know it fits if it is local to the shared
+ library. Don't count TLS SYMBOL_REFs here, since they should fit
+ only if inside of UNSPEC handled below. */
+ /* TLS symbols are not constant. */
+ if (SYMBOL_REF_TLS_MODEL (op))
+ return false;
+ return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_KERNEL
+ || (ix86_cmodel == CM_MEDIUM && !SYMBOL_REF_FAR_ADDR_P (op)));
+
+ case LABEL_REF:
+ /* For certain code models, the code is near as well. */
+ return (ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM
+ || ix86_cmodel == CM_KERNEL);
+
+ case CONST:
+ /* We also may accept the offsetted memory references in certain
+ special cases. */
+ if (GET_CODE (XEXP (op, 0)) == UNSPEC)
+ switch (XINT (XEXP (op, 0), 1))
+ {
+ case UNSPEC_GOTPCREL:
+ case UNSPEC_DTPOFF:
+ case UNSPEC_GOTNTPOFF:
+ case UNSPEC_NTPOFF:
+ return 1;
+ default:
+ break;
+ }
+
+ if (GET_CODE (XEXP (op, 0)) == PLUS)
+ {
+ rtx op1 = XEXP (XEXP (op, 0), 0);
+ rtx op2 = XEXP (XEXP (op, 0), 1);
+ HOST_WIDE_INT offset;
+
+ if (ix86_cmodel == CM_LARGE)
+ return 0;
+ if (GET_CODE (op2) != CONST_INT)
+ return 0;
+ offset = trunc_int_for_mode (INTVAL (op2), DImode);
+ switch (GET_CODE (op1))
+ {
+ case SYMBOL_REF:
+ /* TLS symbols are not constant. */
+ if (SYMBOL_REF_TLS_MODEL (op1))
+ return 0;
+ /* For CM_SMALL assume that latest object is 16MB before
+ end of 31bits boundary. We may also accept pretty
+ large negative constants knowing that all objects are
+ in the positive half of address space. */
+ if ((ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op1)))
+ && offset < 16*1024*1024
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ /* For CM_KERNEL we know that all object resist in the
+ negative half of 32bits address space. We may not
+ accept negative offsets, since they may be just off
+ and we may accept pretty large positive ones. */
+ if (ix86_cmodel == CM_KERNEL
+ && offset > 0
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ break;
+
+ case LABEL_REF:
+ /* These conditions are similar to SYMBOL_REF ones, just the
+ constraints for code models differ. */
+ if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
+ && offset < 16*1024*1024
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ if (ix86_cmodel == CM_KERNEL
+ && offset > 0
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ break;
+
+ case UNSPEC:
+ switch (XINT (op1, 1))
+ {
+ case UNSPEC_DTPOFF:
+ case UNSPEC_NTPOFF:
+ if (offset > 0
+ && trunc_int_for_mode (offset, SImode) == offset)
+ return 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return 0;
+})
+
+;; Return 1 if VALUE can be stored in the zero extended immediate field.
+(define_predicate "x86_64_zext_immediate_operand"
+ (match_code "const_double,const_int,symbol_ref,label_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST_DOUBLE:
+ if (HOST_BITS_PER_WIDE_INT == 32)
+ return (GET_MODE (op) == VOIDmode && !CONST_DOUBLE_HIGH (op));
+ else
+ return 0;
+
+ case CONST_INT:
+ if (HOST_BITS_PER_WIDE_INT == 32)
+ return INTVAL (op) >= 0;
+ else
+ return !(INTVAL (op) & ~(HOST_WIDE_INT) 0xffffffff);
+
+ case SYMBOL_REF:
+ /* For certain code models, the symbolic references are known to fit. */
+ /* TLS symbols are not constant. */
+ if (SYMBOL_REF_TLS_MODEL (op))
+ return false;
+ return (ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op)));
+
+ case LABEL_REF:
+ /* For certain code models, the code is near as well. */
+ return ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM;
+
+ case CONST:
+ /* We also may accept the offsetted memory references in certain
+ special cases. */
+ if (GET_CODE (XEXP (op, 0)) == PLUS)
+ {
+ rtx op1 = XEXP (XEXP (op, 0), 0);
+ rtx op2 = XEXP (XEXP (op, 0), 1);
+
+ if (ix86_cmodel == CM_LARGE)
+ return 0;
+ switch (GET_CODE (op1))
+ {
+ case SYMBOL_REF:
+ /* TLS symbols are not constant. */
+ if (SYMBOL_REF_TLS_MODEL (op1))
+ return 0;
+ /* For small code model we may accept pretty large positive
+ offsets, since one bit is available for free. Negative
+ offsets are limited by the size of NULL pointer area
+ specified by the ABI. */
+ if ((ix86_cmodel == CM_SMALL
+ || (ix86_cmodel == CM_MEDIUM
+ && !SYMBOL_REF_FAR_ADDR_P (op1)))
+ && GET_CODE (op2) == CONST_INT
+ && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
+ && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
+ return 1;
+ /* ??? For the kernel, we may accept adjustment of
+ -0x10000000, since we know that it will just convert
+ negative address space to positive, but perhaps this
+ is not worthwhile. */
+ break;
+
+ case LABEL_REF:
+ /* These conditions are similar to SYMBOL_REF ones, just the
+ constraints for code models differ. */
+ if ((ix86_cmodel == CM_SMALL || ix86_cmodel == CM_MEDIUM)
+ && GET_CODE (op2) == CONST_INT
+ && trunc_int_for_mode (INTVAL (op2), DImode) > -0x10000
+ && trunc_int_for_mode (INTVAL (op2), SImode) == INTVAL (op2))
+ return 1;
+ break;
+
+ default:
+ return 0;
+ }
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ return 0;
+})
+
+;; Return nonzero if OP is general operand representable on x86_64.
+(define_predicate "x86_64_general_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (ior (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "x86_64_immediate_operand"))
+ (match_operand 0 "general_operand")))
+
+;; Return nonzero if OP is general operand representable on x86_64
+;; as either sign extended or zero extended constant.
+(define_predicate "x86_64_szext_general_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (ior (match_operand 0 "nonimmediate_operand")
+ (ior (match_operand 0 "x86_64_immediate_operand")
+ (match_operand 0 "x86_64_zext_immediate_operand")))
+ (match_operand 0 "general_operand")))
+
+;; Return nonzero if OP is nonmemory operand representable on x86_64.
+(define_predicate "x86_64_nonmemory_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "x86_64_immediate_operand"))
+ (match_operand 0 "nonmemory_operand")))
+
+;; Return nonzero if OP is nonmemory operand representable on x86_64.
+(define_predicate "x86_64_szext_nonmemory_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (ior (match_operand 0 "register_operand")
+ (ior (match_operand 0 "x86_64_immediate_operand")
+ (match_operand 0 "x86_64_zext_immediate_operand")))
+ (match_operand 0 "nonmemory_operand")))
+
+;; Return true when operand is PIC expression that can be computed by lea
+;; operation.
+(define_predicate "pic_32bit_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ if (!flag_pic)
+ return 0;
+ /* Rule out relocations that translate into 64bit constants. */
+ if (TARGET_64BIT && GET_CODE (op) == CONST)
+ {
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == UNSPEC
+ && (XINT (op, 1) == UNSPEC_GOTOFF
+ || XINT (op, 1) == UNSPEC_GOT))
+ return 0;
+ }
+ return symbolic_operand (op, mode);
+})
+
+
+;; Return nonzero if OP is nonmemory operand acceptable by movabs patterns.
+(define_predicate "x86_64_movabs_operand"
+ (if_then_else (match_test "!TARGET_64BIT || !flag_pic")
+ (match_operand 0 "nonmemory_operand")
+ (ior (match_operand 0 "register_operand")
+ (and (match_operand 0 "const_double_operand")
+ (match_test "GET_MODE_SIZE (mode) <= 8")))))
+
+;; Returns nonzero if OP is either a symbol reference or a sum of a symbol
+;; reference and a constant.
+(define_predicate "symbolic_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return 1;
+
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF
+ || (GET_CODE (op) == UNSPEC
+ && (XINT (op, 1) == UNSPEC_GOT
+ || XINT (op, 1) == UNSPEC_GOTOFF
+ || XINT (op, 1) == UNSPEC_GOTPCREL)))
+ return 1;
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return 0;
+
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF)
+ return 1;
+ /* Only @GOTOFF gets offsets. */
+ if (GET_CODE (op) != UNSPEC
+ || XINT (op, 1) != UNSPEC_GOTOFF)
+ return 0;
+
+ op = XVECEXP (op, 0, 0);
+ if (GET_CODE (op) == SYMBOL_REF
+ || GET_CODE (op) == LABEL_REF)
+ return 1;
+ return 0;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if the operand contains a @GOT or @GOTOFF reference.
+(define_predicate "pic_symbolic_operand"
+ (match_code "const")
+{
+ op = XEXP (op, 0);
+ if (TARGET_64BIT)
+ {
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == UNSPEC_GOTPCREL)
+ return 1;
+ if (GET_CODE (op) == PLUS
+ && GET_CODE (XEXP (op, 0)) == UNSPEC
+ && XINT (XEXP (op, 0), 1) == UNSPEC_GOTPCREL)
+ return 1;
+ }
+ else
+ {
+ if (GET_CODE (op) == UNSPEC)
+ return 1;
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return 0;
+ op = XEXP (op, 0);
+ if (GET_CODE (op) == UNSPEC)
+ return 1;
+ }
+ return 0;
+})
+
+;; Return true if OP is a symbolic operand that resolves locally.
+(define_predicate "local_symbolic_operand"
+ (match_code "const,label_ref,symbol_ref")
+{
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ op = XEXP (XEXP (op, 0), 0);
+
+ if (GET_CODE (op) == LABEL_REF)
+ return 1;
+
+ if (GET_CODE (op) != SYMBOL_REF)
+ return 0;
+
+ if (SYMBOL_REF_TLS_MODEL (op) != 0)
+ return 0;
+
+ if (SYMBOL_REF_LOCAL_P (op))
+ return 1;
+
+ /* There is, however, a not insubstantial body of code in the rest of
+ the compiler that assumes it can just stick the results of
+ ASM_GENERATE_INTERNAL_LABEL in a symbol_ref and have done. */
+ /* ??? This is a hack. Should update the body of the compiler to
+ always create a DECL an invoke targetm.encode_section_info. */
+ if (strncmp (XSTR (op, 0), internal_label_prefix,
+ internal_label_prefix_len) == 0)
+ return 1;
+
+ return 0;
+})
+
+;; Test for various thread-local symbols.
+(define_predicate "tls_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) != 0")))
+
+(define_predicate "tls_modbase_operand"
+ (and (match_code "symbol_ref")
+ (match_test "op == ix86_tls_module_base ()")))
+
+(define_predicate "tp_or_register_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "unspec")
+ (match_test "XINT (op, 1) == UNSPEC_TP"))))
+
+;; Test for a pc-relative call operand
+(define_predicate "constant_call_address_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "local_symbolic_operand")))
+
+;; True for any non-virtual or eliminable register. Used in places where
+;; instantiation of such a register may cause the pattern to not be recognized.
+(define_predicate "register_no_elim_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ return !(op == arg_pointer_rtx
+ || op == frame_pointer_rtx
+ || (REGNO (op) >= FIRST_PSEUDO_REGISTER
+ && REGNO (op) <= LAST_VIRTUAL_REGISTER));
+})
+
+;; Similarly, but include the stack pointer. This is used to prevent esp
+;; from being used as an index reg.
+(define_predicate "index_register_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+ if (reload_in_progress || reload_completed)
+ return REG_OK_FOR_INDEX_STRICT_P (op);
+ else
+ return REG_OK_FOR_INDEX_NONSTRICT_P (op);
+})
+
+;; Return false if this is any eliminable register. Otherwise general_operand.
+(define_predicate "general_no_elim_operand"
+ (if_then_else (match_code "reg,subreg")
+ (match_operand 0 "register_no_elim_operand")
+ (match_operand 0 "general_operand")))
+
+;; Return false if this is any eliminable register. Otherwise
+;; register_operand or a constant.
+(define_predicate "nonmemory_no_elim_operand"
+ (ior (match_operand 0 "register_no_elim_operand")
+ (match_operand 0 "immediate_operand")))
+
+;; Test for a valid operand for a call instruction.
+(define_predicate "call_insn_operand"
+ (ior (match_operand 0 "constant_call_address_operand")
+ (ior (match_operand 0 "register_no_elim_operand")
+ (match_operand 0 "memory_operand"))))
+
+;; Similarly, but for tail calls, in which we cannot allow memory references.
+(define_predicate "sibcall_insn_operand"
+ (ior (match_operand 0 "constant_call_address_operand")
+ (match_operand 0 "register_no_elim_operand")))
+
+;; Match exactly zero.
+(define_predicate "const0_operand"
+ (match_code "const_int,const_double,const_vector")
+{
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+ return op == CONST0_RTX (mode);
+})
+
+;; Match exactly one.
+(define_predicate "const1_operand"
+ (and (match_code "const_int")
+ (match_test "op == const1_rtx")))
+
+;; Match exactly eight.
+(define_predicate "const8_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 8")))
+
+;; Match 2, 4, or 8. Used for leal multiplicands.
+(define_predicate "const248_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT i = INTVAL (op);
+ return i == 2 || i == 4 || i == 8;
+})
+
+;; Match 0 or 1.
+(define_predicate "const_0_to_1_operand"
+ (and (match_code "const_int")
+ (match_test "op == const0_rtx || op == const1_rtx")))
+
+;; Match 0 to 3.
+(define_predicate "const_0_to_3_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3")))
+
+;; Match 0 to 7.
+(define_predicate "const_0_to_7_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 7")))
+
+;; Match 0 to 15.
+(define_predicate "const_0_to_15_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 15")))
+
+;; Match 0 to 63.
+(define_predicate "const_0_to_63_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 63")))
+
+;; Match 0 to 255.
+(define_predicate "const_0_to_255_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 255")))
+
+;; Match (0 to 255) * 8
+(define_predicate "const_0_to_255_mul_8_operand"
+ (match_code "const_int")
+{
+ unsigned HOST_WIDE_INT val = INTVAL (op);
+ return val <= 255*8 && val % 8 == 0;
+})
+
+;; Return nonzero if OP is CONST_INT >= 1 and <= 31 (a valid operand
+;; for shift & compare patterns, as shifting by 0 does not change flags).
+(define_predicate "const_1_to_31_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 1 && INTVAL (op) <= 31")))
+
+;; Match 2 or 3.
+(define_predicate "const_2_to_3_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 2 || INTVAL (op) == 3")))
+
+;; Match 4 to 7.
+(define_predicate "const_4_to_7_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 4 && INTVAL (op) <= 7")))
+
+;; Match exactly one bit in 4-bit mask.
+(define_predicate "const_pow2_1_to_8_operand"
+ (match_code "const_int")
+{
+ unsigned int log = exact_log2 (INTVAL (op));
+ return log <= 3;
+})
+
+;; Match exactly one bit in 8-bit mask.
+(define_predicate "const_pow2_1_to_128_operand"
+ (match_code "const_int")
+{
+ unsigned int log = exact_log2 (INTVAL (op));
+ return log <= 7;
+})
+
+;; True if this is a constant appropriate for an increment or decrement.
+(define_predicate "incdec_operand"
+ (match_code "const_int")
+{
+ /* On Pentium4, the inc and dec operations causes extra dependency on flag
+ registers, since carry flag is not set. */
+ if (!TARGET_USE_INCDEC && !optimize_size)
+ return 0;
+ return op == const1_rtx || op == constm1_rtx;
+})
+
+;; True for registers, or 1 or -1. Used to optimize double-word shifts.
+(define_predicate "reg_or_pm1_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "const_int")
+ (match_test "op == const1_rtx || op == constm1_rtx"))))
+
+;; True if OP is acceptable as operand of DImode shift expander.
+(define_predicate "shiftdi_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "ashldi_input_operand"
+ (if_then_else (match_test "TARGET_64BIT")
+ (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "reg_or_pm1_operand")))
+
+;; Return true if OP is a vector load from the constant pool with just
+;; the first element nonzero.
+(define_predicate "zero_extended_scalar_load_operand"
+ (match_code "mem")
+{
+ unsigned n_elts;
+ op = maybe_get_pool_constant (op);
+ if (!op)
+ return 0;
+ if (GET_CODE (op) != CONST_VECTOR)
+ return 0;
+ n_elts =
+ (GET_MODE_SIZE (GET_MODE (op)) /
+ GET_MODE_SIZE (GET_MODE_INNER (GET_MODE (op))));
+ for (n_elts--; n_elts > 0; n_elts--)
+ {
+ rtx elt = CONST_VECTOR_ELT (op, n_elts);
+ if (elt != CONST0_RTX (GET_MODE_INNER (GET_MODE (op))))
+ return 0;
+ }
+ return 1;
+})
+
+/* Return true if operand is a vector constant that is all ones. */
+(define_predicate "vector_all_ones_operand"
+ (match_code "const_vector")
+{
+ int nunits = GET_MODE_NUNITS (mode);
+
+ if (GET_CODE (op) == CONST_VECTOR
+ && CONST_VECTOR_NUNITS (op) == nunits)
+ {
+ int i;
+ for (i = 0; i < nunits; ++i)
+ {
+ rtx x = CONST_VECTOR_ELT (op, i);
+ if (x != constm1_rtx)
+ return 0;
+ }
+ return 1;
+ }
+
+ return 0;
+})
+
+; Return 1 when OP is operand acceptable for standard SSE move.
+(define_predicate "vector_move_operand"
+ (ior (match_operand 0 "nonimmediate_operand")
+ (match_operand 0 "const0_operand")))
+
+;; Return 1 when OP is nonimmediate or standard SSE constant.
+(define_predicate "nonimmediate_or_sse_const_operand"
+ (match_operand 0 "general_operand")
+{
+ if (nonimmediate_operand (op, mode))
+ return 1;
+ if (standard_sse_constant_p (op) > 0)
+ return 1;
+ return 0;
+})
+
+;; Return true if OP is a register or a zero.
+(define_predicate "reg_or_0_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "const0_operand")))
+
+;; Return true if op if a valid address, and does not contain
+;; a segment override.
+(define_special_predicate "no_seg_address_operand"
+ (match_operand 0 "address_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+ return parts.seg == SEG_DEFAULT;
+})
+
+;; Return nonzero if the rtx is known to be at least 32 bits aligned.
+(define_predicate "aligned_operand"
+ (match_operand 0 "general_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ /* Registers and immediate operands are always "aligned". */
+ if (GET_CODE (op) != MEM)
+ return 1;
+
+ /* All patterns using aligned_operand on memory operands ends up
+ in promoting memory operand to 64bit and thus causing memory mismatch. */
+ if (TARGET_MEMORY_MISMATCH_STALL && !optimize_size)
+ return 0;
+
+ /* Don't even try to do any aligned optimizations with volatiles. */
+ if (MEM_VOLATILE_P (op))
+ return 0;
+
+ if (MEM_ALIGN (op) >= 32)
+ return 1;
+
+ op = XEXP (op, 0);
+
+ /* Pushes and pops are only valid on the stack pointer. */
+ if (GET_CODE (op) == PRE_DEC
+ || GET_CODE (op) == POST_INC)
+ return 1;
+
+ /* Decode the address. */
+ ok = ix86_decompose_address (op, &parts);
+ gcc_assert (ok);
+
+ /* Look for some component that isn't known to be aligned. */
+ if (parts.index)
+ {
+ if (REGNO_POINTER_ALIGN (REGNO (parts.index)) * parts.scale < 32)
+ return 0;
+ }
+ if (parts.base)
+ {
+ if (REGNO_POINTER_ALIGN (REGNO (parts.base)) < 32)
+ return 0;
+ }
+ if (parts.disp)
+ {
+ if (GET_CODE (parts.disp) != CONST_INT
+ || (INTVAL (parts.disp) & 3) != 0)
+ return 0;
+ }
+
+ /* Didn't find one -- this must be an aligned address. */
+ return 1;
+})
+
+;; Returns 1 if OP is memory operand with a displacement.
+(define_predicate "memory_displacement_operand"
+ (match_operand 0 "memory_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (XEXP (op, 0), &parts);
+ gcc_assert (ok);
+ return parts.disp != NULL_RTX;
+})
+
+;; Returns 1 if OP is memory operand with a displacement only.
+(define_predicate "memory_displacement_only_operand"
+ (match_operand 0 "memory_operand")
+{
+ struct ix86_address parts;
+ int ok;
+
+ ok = ix86_decompose_address (XEXP (op, 0), &parts);
+ gcc_assert (ok);
+
+ if (parts.base || parts.index)
+ return 0;
+
+ return parts.disp != NULL_RTX;
+})
+
+;; Returns 1 if OP is memory operand that cannot be represented
+;; by the modRM array.
+(define_predicate "long_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "memory_address_length (op) != 0")))
+
+;; Return 1 if OP is a comparison operator that can be issued by fcmov.
+(define_predicate "fcmov_comparison_operator"
+ (match_operand 0 "comparison_operator")
+{
+ enum machine_mode inmode = GET_MODE (XEXP (op, 0));
+ enum rtx_code code = GET_CODE (op);
+
+ if (inmode == CCFPmode || inmode == CCFPUmode)
+ {
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ if (bypass_code != UNKNOWN || second_code != UNKNOWN)
+ return 0;
+ code = ix86_fp_compare_code_to_integer (code);
+ }
+ /* i387 supports just limited amount of conditional codes. */
+ switch (code)
+ {
+ case LTU: case GTU: case LEU: case GEU:
+ if (inmode == CCmode || inmode == CCFPmode || inmode == CCFPUmode)
+ return 1;
+ return 0;
+ case ORDERED: case UNORDERED:
+ case EQ: case NE:
+ return 1;
+ default:
+ return 0;
+ }
+})
+
+;; Return 1 if OP is a comparison that can be used in the CMPSS/CMPPS insns.
+;; The first set are supported directly; the second set can't be done with
+;; full IEEE support, i.e. NaNs.
+;;
+;; ??? It would seem that we have a lot of uses of this predicate that pass
+;; it the wrong mode. We got away with this because the old function didn't
+;; check the mode at all. Mirror that for now by calling this a special
+;; predicate.
+
+(define_special_predicate "sse_comparison_operator"
+ (match_code "eq,lt,le,unordered,ne,unge,ungt,ordered"))
+
+;; Return 1 if OP is a valid comparison operator in valid mode.
+(define_predicate "ix86_comparison_operator"
+ (match_operand 0 "comparison_operator")
+{
+ enum machine_mode inmode = GET_MODE (XEXP (op, 0));
+ enum rtx_code code = GET_CODE (op);
+
+ if (inmode == CCFPmode || inmode == CCFPUmode)
+ {
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ return (bypass_code == UNKNOWN && second_code == UNKNOWN);
+ }
+ switch (code)
+ {
+ case EQ: case NE:
+ return 1;
+ case LT: case GE:
+ if (inmode == CCmode || inmode == CCGCmode
+ || inmode == CCGOCmode || inmode == CCNOmode)
+ return 1;
+ return 0;
+ case LTU: case GTU: case LEU: case ORDERED: case UNORDERED: case GEU:
+ if (inmode == CCmode)
+ return 1;
+ return 0;
+ case GT: case LE:
+ if (inmode == CCmode || inmode == CCGCmode || inmode == CCNOmode)
+ return 1;
+ return 0;
+ default:
+ return 0;
+ }
+})
+
+;; Return 1 if OP is a valid comparison operator testing carry flag to be set.
+(define_predicate "ix86_carry_flag_operator"
+ (match_code "ltu,lt,unlt,gt,ungt,le,unle,ge,unge,ltgt,uneq")
+{
+ enum machine_mode inmode = GET_MODE (XEXP (op, 0));
+ enum rtx_code code = GET_CODE (op);
+
+ if (GET_CODE (XEXP (op, 0)) != REG
+ || REGNO (XEXP (op, 0)) != FLAGS_REG
+ || XEXP (op, 1) != const0_rtx)
+ return 0;
+
+ if (inmode == CCFPmode || inmode == CCFPUmode)
+ {
+ enum rtx_code second_code, bypass_code;
+ ix86_fp_comparison_codes (code, &bypass_code, &code, &second_code);
+ if (bypass_code != UNKNOWN || second_code != UNKNOWN)
+ return 0;
+ code = ix86_fp_compare_code_to_integer (code);
+ }
+ else if (inmode != CCmode)
+ return 0;
+
+ return code == LTU;
+})
+
+;; Nearly general operand, but accept any const_double, since we wish
+;; to be able to drop them into memory rather than have them get pulled
+;; into registers.
+(define_predicate "cmp_fp_expander_operand"
+ (ior (match_code "const_double")
+ (match_operand 0 "general_operand")))
+
+;; Return true if this is a valid binary floating-point operation.
+(define_predicate "binary_fp_operator"
+ (match_code "plus,minus,mult,div"))
+
+;; Return true if this is a multiply operation.
+(define_predicate "mult_operator"
+ (match_code "mult"))
+
+;; Return true if this is a division operation.
+(define_predicate "div_operator"
+ (match_code "div"))
+
+;; Return true if this is a float extend operation.
+(define_predicate "float_operator"
+ (match_code "float"))
+
+;; Return true for ARITHMETIC_P.
+(define_predicate "arith_or_logical_operator"
+ (match_code "plus,mult,and,ior,xor,smin,smax,umin,umax,compare,minus,div,
+ mod,udiv,umod,ashift,rotate,ashiftrt,lshiftrt,rotatert"))
+
+;; Return 1 if OP is a binary operator that can be promoted to wider mode.
+;; Modern CPUs have same latency for HImode and SImode multiply,
+;; but 386 and 486 do HImode multiply faster. */
+(define_predicate "promotable_binary_operator"
+ (ior (match_code "plus,and,ior,xor,ashift")
+ (and (match_code "mult")
+ (match_test "ix86_tune > PROCESSOR_I486"))))
+
+;; To avoid problems when jump re-emits comparisons like testqi_ext_ccno_0,
+;; re-recognize the operand to avoid a copy_to_mode_reg that will fail.
+;;
+;; ??? It seems likely that this will only work because cmpsi is an
+;; expander, and no actual insns use this.
+
+(define_predicate "cmpsi_operand"
+ (ior (match_operand 0 "nonimmediate_operand")
+ (and (match_code "and")
+ (match_code "zero_extract" "0")
+ (match_code "const_int" "1")
+ (match_code "const_int" "01")
+ (match_code "const_int" "02")
+ (match_test "INTVAL (XEXP (XEXP (op, 0), 1)) == 8")
+ (match_test "INTVAL (XEXP (XEXP (op, 0), 2)) == 8")
+ )))
+
+(define_predicate "compare_operator"
+ (match_code "compare"))
+
+(define_predicate "absneg_operator"
+ (match_code "abs,neg"))
diff --git a/contrib/gcc/config/i386/ptx4-i.h b/contrib/gcc/config/i386/ptx4-i.h
index 5fcd074..d17cb87 100644
--- a/contrib/gcc/config/i386/ptx4-i.h
+++ b/contrib/gcc/config/i386/ptx4-i.h
@@ -19,8 +19,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (i386 Sequent Dynix/ptx Version 4)");
diff --git a/contrib/gcc/config/i386/rtemself.h b/contrib/gcc/config/i386/rtemself.h
index 6f5299d..b468f1a 100644
--- a/contrib/gcc/config/i386/rtemself.h
+++ b/contrib/gcc/config/i386/rtemself.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Specify predefined symbols in preprocessor. */
diff --git a/contrib/gcc/config/i386/sco5.h b/contrib/gcc/config/i386/sco5.h
index bb872d5..026ffd8 100644
--- a/contrib/gcc/config/i386/sco5.h
+++ b/contrib/gcc/config/i386/sco5.h
@@ -1,5 +1,5 @@
/* Definitions for Intel 386 running SCO Unix System V 3.2 Version 5.
- Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003
+ Copyright (C) 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004
Free Software Foundation, Inc.
Contributed by Kean Johnston (jkj@sco.com)
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (i386, SCO OpenServer 5 Syntax)");
@@ -96,13 +96,11 @@ Boston, MA 02111-1307, USA. */
#undef WCHAR_TYPE
#undef WCHAR_TYPE_SIZE
#undef WINT_TYPE
-#undef LONG_DOUBLE_TYPE_SIZE
#define SIZE_TYPE "unsigned int"
#define PTRDIFF_TYPE "int"
#define WCHAR_TYPE "long int"
#define WCHAR_TYPE_SIZE BITS_PER_WORD
#define WINT_TYPE "long int"
-#define LONG_DOUBLE_TYPE_SIZE 96
/*
* New for multilib support. Set the default switches for multilib,
@@ -223,11 +221,6 @@ Boston, MA 02111-1307, USA. */
builtin_assert ("system=svr3"); \
if (flag_iso) \
cpp_define (pfile, "_STRICT_ANSI"); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
@@ -260,7 +253,7 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#define LINK_SPEC \
"%{!shared:%{!symbolic:%{!G:-E%{Xa:a}%{!Xa:%{Xc:c}%{!Xc:%{Xk:k}%{!Xk:%{Xt:t}%{!Xt:a}}}},%{ansi:ansi}%{!ansi:%{posix:posix}%{!posix:%{Xpg4:xpg4}%{!Xpg4:%{Xpg4plus:XPG4PLUS}%{!Xpg4plus:%{Xods30:ods30}%{!Xods30:XPG4PLUS}}}}},ELF}}} \
- %{Wl,*:%*} %{YP,*} %{YL,*} %{YU,*} \
+ %{YP,*} %{YL,*} %{YU,*} \
%{!YP,*:%{p:-YP,/usr/ccs/libp:/lib/libp:/usr/lib/libp:/usr/ccs/lib:/lib:/usr/lib} \
%{!p:-YP,/usr/ccs/lib:/lib:/usr/lib}} \
%{h*} %{static:-dn -Bstatic %{G:%e-G and -static are mutually exclusive}} \
@@ -283,14 +276,6 @@ Boston, MA 02111-1307, USA. */
#define LIBGCC_SPEC \
"%{!shared:%{!G:-lgcc}}"
-/* Here for legacy support only so we still accept -melf flag */
-#define MASK_COFF 010000000000 /* Mask for COFF generation */
-#define TARGET_ELF (1)
-
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- { "elf", -MASK_COFF, N_("Generate ELF output") },
-
/* 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) \
diff --git a/contrib/gcc/config/i386/sco5.opt b/contrib/gcc/config/i386/sco5.opt
new file mode 100644
index 0000000..03780ca
--- /dev/null
+++ b/contrib/gcc/config/i386/sco5.opt
@@ -0,0 +1,25 @@
+; SCO Unix-specific options.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+;; Legacy option
+melf
+Target RejectNegative
+Generate ELF output
diff --git a/contrib/gcc/config/i386/sol2-10.h b/contrib/gcc/config/i386/sol2-10.h
new file mode 100644
index 0000000..af51b4c
--- /dev/null
+++ b/contrib/gcc/config/i386/sol2-10.h
@@ -0,0 +1,114 @@
+/* Solaris 10 configuration.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef ASM_COMMENT_START
+#define ASM_COMMENT_START "/"
+
+/* binutils' GNU as understands --32 and --64, but the native Solaris
+ assembler requires -xarch=generic or -xarch=generic64 instead. */
+#undef ASM_SPEC
+#ifdef USE_GAS
+#define ASM_SPEC "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} " \
+ "%{Wa,*:%*} %{m32:--32} %{m64:--64} -s %(asm_cpu)"
+#else
+#define ASM_SPEC "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} " \
+ "%{Wa,*:%*} %{m32:-xarch=generic} %{m64:-xarch=generic64} " \
+ "-s %(asm_cpu)"
+#endif
+
+#undef NO_PROFILE_COUNTERS
+
+#undef MCOUNT_NAME
+#define MCOUNT_NAME "_mcount"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (TARGET_64BIT ? "int" : "long int")
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+#undef WINT_TYPE
+#define WINT_TYPE (TARGET_64BIT ? "int" : "long int")
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
+#define SUBTARGET_OVERRIDE_OPTIONS \
+ do \
+ { \
+ if (flag_omit_frame_pointer == 2) \
+ flag_omit_frame_pointer = 0; \
+ } \
+ while (0)
+
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP \
+ | MASK_FLOAT_RETURNS)
+
+#define SUBTARGET_OPTIMIZATION_OPTIONS \
+ do \
+ { \
+ if (optimize >= 1) \
+ target_flags |= MASK_OMIT_LEAF_FRAME_POINTER; \
+ } \
+ while (0)
+
+#define MULTILIB_DEFAULTS { "m32" }
+
+#undef LINK_ARCH64_SPEC_BASE
+#define LINK_ARCH64_SPEC_BASE \
+ "%{G:-G} \
+ %{YP,*} \
+ %{R*} \
+ %{compat-bsd: \
+ %{!YP,*:%{p|pg:-Y P,/usr/ucblib/64:/usr/lib/libp/64:/lib/64:/usr/lib/64} \
+ %{!p:%{!pg:-Y P,/usr/ucblib/64:/lib:/usr/lib/64}}} \
+ -R /usr/ucblib/64} \
+ %{!compat-bsd: \
+ %{!YP,*:%{p|pg:-Y P,/usr/lib/libp/64:/lib/64:/usr/lib/64} \
+ %{!p:%{!pg:-Y P,/lib/64:/usr/lib/64}}}}"
+
+#undef LINK_ARCH64_SPEC
+#define LINK_ARCH64_SPEC LINK_ARCH64_SPEC_BASE
+
+#ifdef TARGET_GNU_LD
+#define TARGET_LD_EMULATION "%{m64:-m elf_x86_64}%{!m64:-m elf_i386} "
+#else
+#define TARGET_LD_EMULATION ""
+#endif
+
+#undef LINK_ARCH_SPEC
+#define LINK_ARCH_SPEC TARGET_LD_EMULATION \
+ "%{m64:" LINK_ARCH64_SPEC "}%{!m64:" LINK_ARCH32_SPEC "}"
+
+/* We do not need to search a special directory for startup files. */
+#undef MD_STARTFILE_PREFIX
+
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION i386_solaris_elf_named_section
+
+/* In 32-bit mode, follow the SVR4 ABI definition; in 64-bit mode, use
+ the AMD64 ABI definition. */
+#undef RETURN_IN_MEMORY
+#define RETURN_IN_MEMORY(TYPE) \
+ (TARGET_64BIT \
+ ? ix86_return_in_memory (TYPE) \
+ : (TYPE_MODE (TYPE) == BLKmode \
+ || (VECTOR_MODE_P (TYPE_MODE (TYPE)) \
+ && int_size_in_bytes (TYPE) == 8)))
diff --git a/contrib/gcc/config/i386/sol2-c1.asm b/contrib/gcc/config/i386/sol2-c1.asm
index b17f57d9..af1ab31 100644
--- a/contrib/gcc/config/i386/sol2-c1.asm
+++ b/contrib/gcc/config/i386/sol2-c1.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/i386/sol2-ci.asm b/contrib/gcc/config/i386/sol2-ci.asm
index 439c709..c7a1744 100644
--- a/contrib/gcc/config/i386/sol2-ci.asm
+++ b/contrib/gcc/config/i386/sol2-ci.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/i386/sol2-cn.asm b/contrib/gcc/config/i386/sol2-cn.asm
index 3f3bad9..acd266a 100644
--- a/contrib/gcc/config/i386/sol2-cn.asm
+++ b/contrib/gcc/config/i386/sol2-cn.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/i386/sol2-gc1.asm b/contrib/gcc/config/i386/sol2-gc1.asm
index 81b56d4..abe9ed6 100644
--- a/contrib/gcc/config/i386/sol2-gc1.asm
+++ b/contrib/gcc/config/i386/sol2-gc1.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/i386/sol2.h b/contrib/gcc/config/i386/sol2.h
index 78b2985..7593071 100644
--- a/contrib/gcc/config/i386/sol2.h
+++ b/contrib/gcc/config/i386/sol2.h
@@ -1,5 +1,6 @@
/* Target definitions for GCC for Intel 80386 running Solaris 2
- Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004
Free Software Foundation, Inc.
Contributed by Fred Fish (fnf@cygnus.com).
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* The Solaris 2.0 x86 linker botches alignment of code sections.
It tries to align to a 16 byte boundary by padding with 0x00000090
@@ -30,14 +31,24 @@ Boston, MA 02111-1307, USA. */
it knows what it is doing. */
#define FORCE_CODE_SECTION_ALIGN asm(ALIGN_ASM_OP "16");
-/* 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. */
+/* Old versions of the Solaris assembler can not handle the difference of
+ labels in different sections, so force DW_EH_PE_datarel. */
#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 \
+ (flag_pic ? ((GLOBAL ? DW_EH_PE_indirect : 0) \
+ | (TARGET_64BIT ? DW_EH_PE_pcrel | DW_EH_PE_sdata4 \
+ : DW_EH_PE_datarel)) \
: DW_EH_PE_absptr)
+/* The Solaris linker will not merge a read-only .eh_frame section
+ with a read-write .eh_frame section. None of the encodings used
+ with non-PIC code require runtime relocations. In 64-bit mode,
+ since there is no backwards compatibility issue, we use a read-only
+ section for .eh_frame. In 32-bit mode, we use a writable .eh_frame
+ section in order to be compatible with G++ for Solaris x86. */
+#undef EH_TABLES_CAN_BE_READ_ONLY
+#define EH_TABLES_CAN_BE_READ_ONLY (TARGET_64BIT)
+
/* Solaris 2/Intel as chokes on #line directives. */
#undef CPP_SPEC
#define CPP_SPEC "%{.S:-P} %(cpp_subtarget)"
@@ -62,8 +73,10 @@ Boston, MA 02111-1307, USA. */
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* The Solaris assembler does not support .quad. Do not use it. */
+/* The 32-bit Solaris assembler does not support .quad. Do not use it. */
+#ifndef TARGET_BI_ARCH
#undef ASM_QUAD
+#endif
/* The Solaris assembler wants a .local for non-exported aliases. */
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET) \
@@ -79,3 +92,22 @@ Boston, MA 02111-1307, USA. */
fprintf ((FILE), "\n"); \
} \
} while (0)
+
+/* Solaris-specific #pragmas are implemented on top of attributes. Hook in
+ the bits from config/sol2.c. */
+#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+#define SUBTARGET_ATTRIBUTE_TABLE SOLARIS_ATTRIBUTE_TABLE
+
+/* Output a simple call for .init/.fini. */
+#define ASM_OUTPUT_CALL(FILE, FN) \
+ do \
+ { \
+ fprintf (FILE, "\tcall\t"); \
+ print_operand (FILE, XEXP (DECL_RTL (FN), 0), 'P'); \
+ fprintf (FILE, "\n"); \
+ } \
+ while (0)
+
+/* We do not need NT_VERSION notes. */
+#undef X86_FILE_START_VERSION_DIRECTIVE
+#define X86_FILE_START_VERSION_DIRECTIVE false
diff --git a/contrib/gcc/config/i386/sse.md b/contrib/gcc/config/i386/sse.md
new file mode 100644
index 0000000..96361e0
--- /dev/null
+++ b/contrib/gcc/config/i386/sse.md
@@ -0,0 +1,3950 @@
+;; GCC machine description for SSE instructions
+;; Copyright (C) 2005, 2006
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;; 16 byte integral modes handled by SSE, minus TImode, which gets
+;; special-cased for TARGET_64BIT.
+(define_mode_macro SSEMODEI [V16QI V8HI V4SI V2DI])
+
+;; All 16-byte vector modes handled by SSE
+(define_mode_macro SSEMODE [V16QI V8HI V4SI V2DI V4SF V2DF])
+
+;; Mix-n-match
+(define_mode_macro SSEMODE12 [V16QI V8HI])
+(define_mode_macro SSEMODE24 [V8HI V4SI])
+(define_mode_macro SSEMODE14 [V16QI V4SI])
+(define_mode_macro SSEMODE124 [V16QI V8HI V4SI])
+(define_mode_macro SSEMODE248 [V8HI V4SI V2DI])
+
+;; Mapping from integer vector mode to mnemonic suffix
+(define_mode_attr ssevecsize [(V16QI "b") (V8HI "w") (V4SI "d") (V2DI "q")])
+
+;; Patterns whose name begins with "sse{,2,3}_" are invoked by intrinsics.
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Move patterns
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; All of these patterns are enabled for SSE1 as well as SSE2.
+;; This is essential for maintaining stable calling conventions.
+
+(define_expand "mov<mode>"
+ [(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "")
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_move (<MODE>mode, operands);
+ DONE;
+})
+
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:SSEMODEI 0 "nonimmediate_operand" "=x,x ,m")
+ (match_operand:SSEMODEI 1 "nonimmediate_or_sse_const_operand" "C ,xm,x"))]
+ "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return standard_sse_constant_opcode (insn, operands[1]);
+ case 1:
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movdqa\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set (attr "mode")
+ (if_then_else
+ (ior (ior (ne (symbol_ref "optimize_size") (const_int 0))
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
+ (and (eq_attr "alternative" "2")
+ (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0))))
+ (const_string "V4SF")
+ (const_string "TI")))])
+
+(define_expand "movv4sf"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
+ (match_operand:V4SF 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_move (V4SFmode, operands);
+ DONE;
+})
+
+(define_insn "*movv4sf_internal"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V4SF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
+ "TARGET_SSE"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return standard_sse_constant_opcode (insn, operands[1]);
+ case 1:
+ case 2:
+ return "movaps\t{%1, %0|%0, %1}";
+ default:
+ abort();
+ }
+}
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_split
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "zero_extended_scalar_load_operand" ""))]
+ "TARGET_SSE && reload_completed"
+ [(set (match_dup 0)
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF (match_dup 1))
+ (match_dup 2)
+ (const_int 1)))]
+{
+ operands[1] = simplify_gen_subreg (SFmode, operands[1], V4SFmode, 0);
+ operands[2] = CONST0_RTX (V4SFmode);
+})
+
+(define_expand "movv2df"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "")
+ (match_operand:V2DF 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_move (V2DFmode, operands);
+ DONE;
+})
+
+(define_insn "*movv2df_internal"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
+ (match_operand:V2DF 1 "nonimmediate_or_sse_const_operand" "C,xm,x"))]
+ "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return standard_sse_constant_opcode (insn, operands[1]);
+ case 1:
+ case 2:
+ if (get_attr_mode (insn) == MODE_V4SF)
+ return "movaps\t{%1, %0|%0, %1}";
+ else
+ return "movapd\t{%1, %0|%0, %1}";
+ default:
+ gcc_unreachable ();
+ }
+}
+ [(set_attr "type" "sselog1,ssemov,ssemov")
+ (set (attr "mode")
+ (if_then_else
+ (ior (ior (ne (symbol_ref "optimize_size") (const_int 0))
+ (eq (symbol_ref "TARGET_SSE2") (const_int 0)))
+ (and (eq_attr "alternative" "2")
+ (ne (symbol_ref "TARGET_SSE_TYPELESS_STORES")
+ (const_int 0))))
+ (const_string "V4SF")
+ (const_string "V2DF")))])
+
+(define_split
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (match_operand:V2DF 1 "zero_extended_scalar_load_operand" ""))]
+ "TARGET_SSE2 && reload_completed"
+ [(set (match_dup 0) (vec_concat:V2DF (match_dup 1) (match_dup 2)))]
+{
+ operands[1] = simplify_gen_subreg (DFmode, operands[1], V2DFmode, 0);
+ operands[2] = CONST0_RTX (DFmode);
+})
+
+(define_expand "push<mode>1"
+ [(match_operand:SSEMODE 0 "register_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_push (<MODE>mode, operands[0]);
+ DONE;
+})
+
+(define_expand "movmisalign<mode>"
+ [(set (match_operand:SSEMODE 0 "nonimmediate_operand" "")
+ (match_operand:SSEMODE 1 "nonimmediate_operand" ""))]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_move_misalign (<MODE>mode, operands);
+ DONE;
+})
+
+(define_insn "sse_movups"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,m")
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "movups\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movupd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,m")
+ (unspec:V2DF [(match_operand:V2DF 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "movupd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movdqu"
+ [(set (match_operand:V16QI 0 "nonimmediate_operand" "=x,m")
+ (unspec:V16QI [(match_operand:V16QI 1 "nonimmediate_operand" "xm,x")]
+ UNSPEC_MOVU))]
+ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "movdqu\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse_movntv4sf"
+ [(set (match_operand:V4SF 0 "memory_operand" "=m")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE"
+ "movntps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse2_movntv2df"
+ [(set (match_operand:V2DF 0 "memory_operand" "=m")
+ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movntpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_movntv2di"
+ [(set (match_operand:V2DI 0 "memory_operand" "=m")
+ (unspec:V2DI [(match_operand:V2DI 1 "register_operand" "x")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movntdq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_movntsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "r")]
+ UNSPEC_MOVNT))]
+ "TARGET_SSE2"
+ "movnti\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse3_lddqu"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "m")]
+ UNSPEC_LDQQU))]
+ "TARGET_SSE3"
+ "lddqu\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "negv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (neg:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_expand_fp_absneg_operator (NEG, V4SFmode, operands); DONE;")
+
+(define_expand "absv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (abs:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_expand_fp_absneg_operator (ABS, V4SFmode, operands); DONE;")
+
+(define_expand "addv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (plus:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (PLUS, V4SFmode, operands);")
+
+(define_insn "*addv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (plus:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && ix86_binary_operator_ok (PLUS, V4SFmode, operands)"
+ "addps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmaddv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (plus:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE && ix86_binary_operator_ok (PLUS, V4SFmode, operands)"
+ "addss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
+
+(define_expand "subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (MINUS, V4SFmode, operands);")
+
+(define_insn "*subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "subps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmsubv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "subss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "SF")])
+
+(define_expand "mulv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (mult:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (MULT, V4SFmode, operands);")
+
+(define_insn "*mulv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (mult:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && ix86_binary_operator_ok (MULT, V4SFmode, operands)"
+ "mulps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmmulv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (mult:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE && ix86_binary_operator_ok (MULT, V4SFmode, operands)"
+ "mulss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "SF")])
+
+(define_expand "divv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (div:V4SF (match_operand:V4SF 1 "register_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (DIV, V4SFmode, operands);")
+
+(define_insn "*divv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (div:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "divps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmdivv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (div:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "divss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_rcpv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (unspec:V4SF
+ [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RCP))]
+ "TARGET_SSE"
+ "rcpps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmrcpv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_RCP)
+ (match_operand:V4SF 2 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "rcpss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_rsqrtv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (unspec:V4SF
+ [(match_operand:V4SF 1 "nonimmediate_operand" "xm")] UNSPEC_RSQRT))]
+ "TARGET_SSE"
+ "rsqrtps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmrsqrtv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (unspec:V4SF [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_RSQRT)
+ (match_operand:V4SF 2 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "rsqrtss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+(define_insn "sqrtv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "sqrtps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmsqrtv4sf2"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (sqrt:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
+ (match_operand:V4SF 2 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "sqrtss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
+;; isn't really correct, as those rtl operators aren't defined when
+;; applied to NaNs. Hopefully the optimizers won't get too smart on us.
+
+(define_expand "smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (smax:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+{
+ if (!flag_finite_math_only)
+ operands[1] = force_reg (V4SFmode, operands[1]);
+ ix86_fixup_binary_operands_no_copy (SMAX, V4SFmode, operands);
+})
+
+(define_insn "*smaxv4sf3_finite"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (smax:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && flag_finite_math_only
+ && ix86_binary_operator_ok (SMAX, V4SFmode, operands)"
+ "maxps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "maxps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmsmaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "maxss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+(define_expand "sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (smin:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+{
+ if (!flag_finite_math_only)
+ operands[1] = force_reg (V4SFmode, operands[1]);
+ ix86_fixup_binary_operands_no_copy (SMIN, V4SFmode, operands);
+})
+
+(define_insn "*sminv4sf3_finite"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (smin:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && flag_finite_math_only
+ && ix86_binary_operator_ok (SMIN, V4SFmode, operands)"
+ "minps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "minps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmsminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "minss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "SF")])
+
+;; These versions of the min/max patterns implement exactly the operations
+;; min = (op1 < op2 ? op1 : op2)
+;; max = (!(op1 < op2) ? op1 : op2)
+;; Their operands are not commutative, and thus they may be used in the
+;; presence of -0.0 and NaN.
+
+(define_insn "*ieee_sminv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MIN))]
+ "TARGET_SSE"
+ "minps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*ieee_smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MAX))]
+ "TARGET_SSE"
+ "maxps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*ieee_sminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MIN))]
+ "TARGET_SSE2"
+ "minpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*ieee_smaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (unspec:V2DF [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")]
+ UNSPEC_IEEE_MAX))]
+ "TARGET_SSE2"
+ "maxpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse3_addsubv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (plus:V4SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (minus:V4SF (match_dup 1) (match_dup 2))
+ (const_int 5)))]
+ "TARGET_SSE3"
+ "addsubps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse3_haddv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_concat:V4SF
+ (vec_concat:V2SF
+ (plus:SF
+ (vec_select:SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
+ (plus:SF
+ (vec_select:SF (match_dup 1) (parallel [(const_int 2)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 3)]))))
+ (vec_concat:V2SF
+ (plus:SF
+ (vec_select:SF
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))
+ (plus:SF
+ (vec_select:SF (match_dup 2) (parallel [(const_int 2)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 3)]))))))]
+ "TARGET_SSE3"
+ "haddps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse3_hsubv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_concat:V4SF
+ (vec_concat:V2SF
+ (minus:SF
+ (vec_select:SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 1)])))
+ (minus:SF
+ (vec_select:SF (match_dup 1) (parallel [(const_int 2)]))
+ (vec_select:SF (match_dup 1) (parallel [(const_int 3)]))))
+ (vec_concat:V2SF
+ (minus:SF
+ (vec_select:SF
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 1)])))
+ (minus:SF
+ (vec_select:SF (match_dup 2) (parallel [(const_int 2)]))
+ (vec_select:SF (match_dup 2) (parallel [(const_int 3)]))))))]
+ "TARGET_SSE3"
+ "hsubps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "reduc_splus_v4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")]
+ "TARGET_SSE"
+{
+ if (TARGET_SSE3)
+ {
+ rtx tmp = gen_reg_rtx (V4SFmode);
+ emit_insn (gen_sse3_haddv4sf3 (tmp, operands[1], operands[1]));
+ emit_insn (gen_sse3_haddv4sf3 (operands[0], tmp, tmp));
+ }
+ else
+ ix86_expand_reduc_v4sf (gen_addv4sf3, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "reduc_smax_v4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_reduc_v4sf (gen_smaxv4sf3, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "reduc_smin_v4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_reduc_v4sf (gen_sminv4sf3, operands[0], operands[1]);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point comparisons
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse_maskcmpv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (match_operator:V4SF 3 "sse_comparison_operator"
+ [(match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")]))]
+ "TARGET_SSE"
+ "cmp%D3ps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_vmmaskcmpv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (match_operator:V4SF 3 "sse_comparison_operator"
+ [(match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "register_operand" "x")])
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "cmp%D3ss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_comi"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (vec_select:SF
+ (match_operand:V4SF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE"
+ "comiss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_ucomi"
+ [(set (reg:CCFPU FLAGS_REG)
+ (compare:CCFPU
+ (vec_select:SF
+ (match_operand:V4SF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE"
+ "ucomiss\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "mode" "SF")])
+
+(define_expand "vcondv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (if_then_else:V4SF
+ (match_operator 3 ""
+ [(match_operand:V4SF 4 "nonimmediate_operand" "")
+ (match_operand:V4SF 5 "nonimmediate_operand" "")])
+ (match_operand:V4SF 1 "general_operand" "")
+ (match_operand:V4SF 2 "general_operand" "")))]
+ "TARGET_SSE"
+{
+ if (ix86_expand_fp_vcond (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point logical operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "andv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (and:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (AND, V4SFmode, operands);")
+
+(define_insn "*andv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (and:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && ix86_binary_operator_ok (AND, V4SFmode, operands)"
+ "andps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_nandv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (and:V4SF (not:V4SF (match_operand:V4SF 1 "register_operand" "0"))
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE"
+ "andnps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "iorv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (ior:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (IOR, V4SFmode, operands);")
+
+(define_insn "*iorv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (ior:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && ix86_binary_operator_ok (IOR, V4SFmode, operands)"
+ "orps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "xorv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (xor:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE"
+ "ix86_fixup_binary_operands_no_copy (XOR, V4SFmode, operands);")
+
+(define_insn "*xorv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (xor:V4SF (match_operand:V4SF 1 "nonimmediate_operand" "%0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE && ix86_binary_operator_ok (XOR, V4SFmode, operands)"
+ "xorps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+;; Also define scalar versions. These are used for abs, neg, and
+;; conditional move. Using subregs into vector modes causes register
+;; allocation lossage. These patterns do not allow memory operands
+;; because the native instructions read the full 128-bits.
+
+(define_insn "*andsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (and:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "register_operand" "x")))]
+ "TARGET_SSE"
+ "andps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*nandsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (and:SF (not:SF (match_operand:SF 1 "register_operand" "0"))
+ (match_operand:SF 2 "register_operand" "x")))]
+ "TARGET_SSE"
+ "andnps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*iorsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (ior:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "register_operand" "x")))]
+ "TARGET_SSE"
+ "orps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*xorsf3"
+ [(set (match_operand:SF 0 "register_operand" "=x")
+ (xor:SF (match_operand:SF 1 "register_operand" "0")
+ (match_operand:SF 2 "register_operand" "x")))]
+ "TARGET_SSE"
+ "xorps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point conversion operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse_cvtpi2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float:V2SF (match_operand:V2SI 2 "nonimmediate_operand" "ym")))
+ (match_operand:V4SF 1 "register_operand" "0")
+ (const_int 3)))]
+ "TARGET_SSE"
+ "cvtpi2ps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_cvtps2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_select:V2SI
+ (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX_NOTRUNC)
+ (parallel [(const_int 0) (const_int 1)])))]
+ "TARGET_SSE"
+ "cvtps2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse_cvttps2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (vec_select:V2SI
+ (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0) (const_int 1)])))]
+ "TARGET_SSE"
+ "cvttps2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_cvtsi2ss"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float:SF (match_operand:SI 2 "nonimmediate_operand" "r,m")))
+ (match_operand:V4SF 1 "register_operand" "0,0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "cvtsi2ss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "vector,double")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_cvtsi2ssq"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float:SF (match_operand:DI 2 "nonimmediate_operand" "r,rm")))
+ (match_operand:V4SF 1 "register_operand" "0,0")
+ (const_int 1)))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvtsi2ssq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "vector,double")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse_cvtss2si"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI
+ [(vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE"
+ "cvtss2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "SI")])
+
+(define_insn "sse_cvtss2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (unspec:DI
+ [(vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvtss2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse_cvttss2si"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (fix:SI
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE"
+ "cvttss2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "SI")])
+
+(define_insn "sse_cvttss2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (fix:DI
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE && TARGET_64BIT"
+ "cvttss2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse2_cvtdq2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (float:V4SF (match_operand:V4SI 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvtdq2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_cvtps2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (unspec:V4SI [(match_operand:V4SF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2"
+ "cvtps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_cvttps2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (fix:V4SI (match_operand:V4SF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvttps2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel single-precision floating point element swizzling
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse_movhlps"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
+ (match_operand:V4SF 2 "nonimmediate_operand" " x,o,x"))
+ (parallel [(const_int 6)
+ (const_int 7)
+ (const_int 2)
+ (const_int 3)])))]
+ "TARGET_SSE && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ movhlps\t{%2, %0|%0, %2}
+ movlps\t{%H2, %0|%0, %H2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF,V2SF,V2SF")])
+
+(define_insn "sse_movlhps"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "nonimmediate_operand" " 0,0,0")
+ (match_operand:V4SF 2 "nonimmediate_operand" " x,m,x"))
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 4)
+ (const_int 5)])))]
+ "TARGET_SSE && ix86_binary_operator_ok (UNKNOWN, V4SFmode, operands)"
+ "@
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}
+ movlps\t{%2, %H0|%H0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF,V2SF,V2SF")])
+
+(define_insn "sse_unpckhps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
+ "TARGET_SSE"
+ "unpckhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_unpcklps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
+ "TARGET_SSE"
+ "unpcklps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+;; These are modeled with the same vec_concat as the others so that we
+;; capture users of shufps that can use the new instructions
+(define_insn "sse3_movshdup"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (match_dup 1))
+ (parallel [(const_int 1)
+ (const_int 1)
+ (const_int 7)
+ (const_int 7)])))]
+ "TARGET_SSE3"
+ "movshdup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse3_movsldup"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (match_dup 1))
+ (parallel [(const_int 0)
+ (const_int 0)
+ (const_int 6)
+ (const_int 6)])))]
+ "TARGET_SSE3"
+ "movsldup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V4SF")])
+
+(define_expand "sse_shufps"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")
+ (match_operand:V4SF 2 "nonimmediate_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ int mask = INTVAL (operands[3]);
+ emit_insn (gen_sse_shufps_1 (operands[0], operands[1], operands[2],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT (((mask >> 4) & 3) + 4),
+ GEN_INT (((mask >> 6) & 3) + 4)));
+ DONE;
+})
+
+(define_insn "sse_shufps_1"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_select:V4SF
+ (vec_concat:V8SF
+ (match_operand:V4SF 1 "register_operand" "0")
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm"))
+ (parallel [(match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_4_to_7_operand" "")
+ (match_operand 6 "const_4_to_7_operand" "")])))]
+ "TARGET_SSE"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[3]) << 0;
+ mask |= INTVAL (operands[4]) << 2;
+ mask |= (INTVAL (operands[5]) - 4) << 4;
+ mask |= (INTVAL (operands[6]) - 4) << 6;
+ operands[3] = GEN_INT (mask);
+
+ return "shufps\t{%3, %2, %0|%0, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse_storehps"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:V2SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,x,o")
+ (parallel [(const_int 2) (const_int 3)])))]
+ "TARGET_SSE"
+ "@
+ movhps\t{%1, %0|%0, %1}
+ movhlps\t{%1, %0|%0, %1}
+ movlps\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "sse_loadhps"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,o")
+ (vec_concat:V4SF
+ (vec_select:V2SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "0,0,0")
+ (parallel [(const_int 0) (const_int 1)]))
+ (match_operand:V2SF 2 "nonimmediate_operand" "m,x,x")))]
+ "TARGET_SSE"
+ "@
+ movhps\t{%2, %0|%0, %2}
+ movlhps\t{%2, %0|%0, %2}
+ movlps\t{%2, %H0|%H0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "sse_storelps"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:V2SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,x,m")
+ (parallel [(const_int 0) (const_int 1)])))]
+ "TARGET_SSE"
+ "@
+ movlps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "sse_loadlps"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,m")
+ (vec_concat:V4SF
+ (match_operand:V2SF 2 "nonimmediate_operand" "0,m,x")
+ (vec_select:V2SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "x,0,0")
+ (parallel [(const_int 2) (const_int 3)]))))]
+ "TARGET_SSE"
+ "@
+ shufps\t{$0xe4, %1, %0|%0, %1, 0xe4}
+ movlps\t{%2, %0|%0, %2}
+ movlps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "mode" "V4SF,V2SF,V2SF")])
+
+(define_insn "sse_movss"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_merge:V4SF
+ (match_operand:V4SF 2 "register_operand" "x")
+ (match_operand:V4SF 1 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "movss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "SF")])
+
+(define_insn "*vec_dupv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_duplicate:V4SF
+ (match_operand:SF 1 "register_operand" "0")))]
+ "TARGET_SSE"
+ "shufps\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "V4SF")])
+
+;; ??? In theory we can match memory for the MMX alternative, but allowing
+;; nonimmediate_operand for operand 2 and *not* allowing memory for the SSE
+;; alternatives pretty much forces the MMX alternative to be chosen.
+(define_insn "*sse_concatv2sf"
+ [(set (match_operand:V2SF 0 "register_operand" "=x,x,*y,*y")
+ (vec_concat:V2SF
+ (match_operand:SF 1 "nonimmediate_operand" " 0,m, 0, m")
+ (match_operand:SF 2 "reg_or_0_operand" " x,C,*y, C")))]
+ "TARGET_SSE"
+ "@
+ unpcklps\t{%2, %0|%0, %2}
+ movss\t{%1, %0|%0, %1}
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "mode" "V4SF,SF,DI,DI")])
+
+(define_insn "*sse_concatv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "register_operand" " 0,0")
+ (match_operand:V2SF 2 "nonimmediate_operand" " x,m")))]
+ "TARGET_SSE"
+ "@
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V4SF,V2SF")])
+
+(define_expand "vec_initv4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_insn "*vec_setv4sf_0"
+ [(set (match_operand:V4SF 0 "nonimmediate_operand" "=x,x,Y ,m")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (match_operand:SF 2 "general_operand" " x,m,*r,x*rfF"))
+ (match_operand:V4SF 1 "vector_move_operand" " 0,C,C ,0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ movss\t{%2, %0|%0, %2}
+ movss\t{%2, %0|%0, %2}
+ movd\t{%2, %0|%0, %2}
+ #"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "SF")])
+
+(define_split
+ [(set (match_operand:V4SF 0 "memory_operand" "")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (match_operand:SF 1 "nonmemory_operand" ""))
+ (match_dup 0)
+ (const_int 1)))]
+ "TARGET_SSE && reload_completed"
+ [(const_int 0)]
+{
+ emit_move_insn (adjust_address (operands[0], SFmode, 0), operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_insn_and_split "*vec_extractv4sf_0"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=x,m,fr")
+ (vec_select:SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm,x,m")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (SFmode, REGNO (op1));
+ else
+ op1 = gen_lowpart (SFmode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_expand "vec_extractv4sf"
+ [(match_operand:SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel double-precision floating point arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "negv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (neg:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_expand_fp_absneg_operator (NEG, V2DFmode, operands); DONE;")
+
+(define_expand "absv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (abs:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_expand_fp_absneg_operator (ABS, V2DFmode, operands); DONE;")
+
+(define_expand "addv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (plus:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (PLUS, V2DFmode, operands);")
+
+(define_insn "*addv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (plus:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, V2DFmode, operands)"
+ "addpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmaddv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (plus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, V4SFmode, operands)"
+ "addsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_expand "subv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (minus:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (MINUS, V2DFmode, operands);")
+
+(define_insn "*subv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "subpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmsubv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (minus:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "subsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_expand "mulv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (mult:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (MULT, V2DFmode, operands);")
+
+(define_insn "*mulv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (mult:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2DFmode, operands)"
+ "mulpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmmulv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (mult:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V2DFmode, operands)"
+ "mulsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemul")
+ (set_attr "mode" "DF")])
+
+(define_expand "divv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (div:V2DF (match_operand:V2DF 1 "register_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (DIV, V2DFmode, operands);")
+
+(define_insn "*divv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "divpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmdivv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (div:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "divsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssediv")
+ (set_attr "mode" "DF")])
+
+(define_insn "sqrtv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (sqrt:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "sqrtpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmsqrtv2df2"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (sqrt:V2DF (match_operand:V2DF 1 "register_operand" "xm"))
+ (match_operand:V2DF 2 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "sqrtsd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sse")
+ (set_attr "mode" "DF")])
+
+;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
+;; isn't really correct, as those rtl operators aren't defined when
+;; applied to NaNs. Hopefully the optimizers won't get too smart on us.
+
+(define_expand "smaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (smax:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (!flag_finite_math_only)
+ operands[1] = force_reg (V2DFmode, operands[1]);
+ ix86_fixup_binary_operands_no_copy (SMAX, V2DFmode, operands);
+})
+
+(define_insn "*smaxv2df3_finite"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smax:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && flag_finite_math_only
+ && ix86_binary_operator_ok (SMAX, V2DFmode, operands)"
+ "maxpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*smaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "maxpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmsmaxv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (smax:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "maxsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_expand "sminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (smin:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (!flag_finite_math_only)
+ operands[1] = force_reg (V2DFmode, operands[1]);
+ ix86_fixup_binary_operands_no_copy (SMIN, V2DFmode, operands);
+})
+
+(define_insn "*sminv2df3_finite"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smin:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && flag_finite_math_only
+ && ix86_binary_operator_ok (SMIN, V2DFmode, operands)"
+ "minpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*sminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "minpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmsminv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (smin:V2DF (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "minsd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse3_addsubv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (plus:V2DF
+ (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (minus:V2DF (match_dup 1) (match_dup 2))
+ (const_int 1)))]
+ "TARGET_SSE3"
+ "addsubpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse3_haddv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_concat:V2DF
+ (plus:DF
+ (vec_select:DF
+ (match_operand:V2DF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:DF (match_dup 1) (parallel [(const_int 1)])))
+ (plus:DF
+ (vec_select:DF
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))
+ (vec_select:DF (match_dup 2) (parallel [(const_int 1)])))))]
+ "TARGET_SSE3"
+ "haddpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse3_hsubv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_concat:V2DF
+ (minus:DF
+ (vec_select:DF
+ (match_operand:V2DF 1 "register_operand" "0")
+ (parallel [(const_int 0)]))
+ (vec_select:DF (match_dup 1) (parallel [(const_int 1)])))
+ (minus:DF
+ (vec_select:DF
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))
+ (vec_select:DF (match_dup 2) (parallel [(const_int 1)])))))]
+ "TARGET_SSE3"
+ "hsubpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseadd")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "reduc_splus_v2df"
+ [(match_operand:V2DF 0 "register_operand" "")
+ (match_operand:V2DF 1 "register_operand" "")]
+ "TARGET_SSE3"
+{
+ emit_insn (gen_sse3_haddv2df3 (operands[0], operands[1], operands[1]));
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel double-precision floating point comparisons
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_maskcmpv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (match_operator:V2DF 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")]))]
+ "TARGET_SSE2"
+ "cmp%D3pd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_vmmaskcmpv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (match_operator:V2DF 3 "sse_comparison_operator"
+ [(match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")])
+ (match_dup 1)
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "cmp%D3sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_comi"
+ [(set (reg:CCFP FLAGS_REG)
+ (compare:CCFP
+ (vec_select:DF
+ (match_operand:V2DF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "comisd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "mode" "DF")])
+
+(define_insn "sse2_ucomi"
+ [(set (reg:CCFPU FLAGS_REG)
+ (compare:CCFPU
+ (vec_select:DF
+ (match_operand:V2DF 0 "register_operand" "x")
+ (parallel [(const_int 0)]))
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "ucomisd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecomi")
+ (set_attr "mode" "DF")])
+
+(define_expand "vcondv2df"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (if_then_else:V2DF
+ (match_operator 3 ""
+ [(match_operand:V2DF 4 "nonimmediate_operand" "")
+ (match_operand:V2DF 5 "nonimmediate_operand" "")])
+ (match_operand:V2DF 1 "general_operand" "")
+ (match_operand:V2DF 2 "general_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (ix86_expand_fp_vcond (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel double-precision floating point logical operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "andv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (and:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (AND, V2DFmode, operands);")
+
+(define_insn "*andv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (and:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (AND, V2DFmode, operands)"
+ "andpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_nandv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (and:V2DF (not:V2DF (match_operand:V2DF 1 "register_operand" "0"))
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "andnpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "iorv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (ior:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (IOR, V2DFmode, operands);")
+
+(define_insn "*iorv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (ior:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (IOR, V2DFmode, operands)"
+ "orpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "xorv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "")
+ (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (XOR, V2DFmode, operands);")
+
+(define_insn "*xorv2df3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (xor:V2DF (match_operand:V2DF 1 "nonimmediate_operand" "%0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (XOR, V2DFmode, operands)"
+ "xorpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+;; Also define scalar versions. These are used for abs, neg, and
+;; conditional move. Using subregs into vector modes causes register
+;; allocation lossage. These patterns do not allow memory operands
+;; because the native instructions read the full 128-bits.
+
+(define_insn "*anddf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (and:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "x")))]
+ "TARGET_SSE2"
+ "andpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*nanddf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (and:DF (not:DF (match_operand:DF 1 "register_operand" "0"))
+ (match_operand:DF 2 "register_operand" "x")))]
+ "TARGET_SSE2"
+ "andnpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*iordf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (ior:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "x")))]
+ "TARGET_SSE2"
+ "orpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "*xordf3"
+ [(set (match_operand:DF 0 "register_operand" "=x")
+ (xor:DF (match_operand:DF 1 "register_operand" "0")
+ (match_operand:DF 2 "register_operand" "x")))]
+ "TARGET_SSE2"
+ "xorpd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel double-precision floating point conversion operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_cvtpi2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x")
+ (float:V2DF (match_operand:V2SI 1 "nonimmediate_operand" "y,m")))]
+ "TARGET_SSE2"
+ "cvtpi2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx,*")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_cvtpd2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2"
+ "cvtpd2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse2_cvttpd2pi"
+ [(set (match_operand:V2SI 0 "register_operand" "=y")
+ (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "cvttpd2pi\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "unit" "mmx")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_cvtsi2sd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x")
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF
+ (float:DF (match_operand:SI 2 "nonimmediate_operand" "r,m")))
+ (match_operand:V2DF 1 "register_operand" "0,0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "cvtsi2sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "DF")
+ (set_attr "athlon_decode" "double,direct")])
+
+(define_insn "sse2_cvtsi2sdq"
+ [(set (match_operand:V2DF 0 "register_operand" "=x,x")
+ (vec_merge:V2DF
+ (vec_duplicate:V2DF
+ (float:DF (match_operand:DI 2 "nonimmediate_operand" "r,m")))
+ (match_operand:V2DF 1 "register_operand" "0,0")
+ (const_int 1)))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsi2sdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "DF")
+ (set_attr "athlon_decode" "double,direct")])
+
+(define_insn "sse2_cvtsd2si"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (unspec:SI
+ [(vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2"
+ "cvtsd2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "SI")])
+
+(define_insn "sse2_cvtsd2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (unspec:DI
+ [(vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))]
+ UNSPEC_FIX_NOTRUNC))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvtsd2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "athlon_decode" "double,vector")
+ (set_attr "mode" "DI")])
+
+(define_insn "sse2_cvttsd2si"
+ [(set (match_operand:SI 0 "register_operand" "=r,r")
+ (fix:SI
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2"
+ "cvttsd2si\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "SI")
+ (set_attr "athlon_decode" "double,vector")])
+
+(define_insn "sse2_cvttsd2siq"
+ [(set (match_operand:DI 0 "register_operand" "=r,r")
+ (fix:DI
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,m")
+ (parallel [(const_int 0)]))))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ "cvttsd2siq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sseicvt")
+ (set_attr "mode" "DI")
+ (set_attr "athlon_decode" "double,vector")])
+
+(define_insn "sse2_cvtdq2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (float:V2DF
+ (vec_select:V2SI
+ (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_SSE2"
+ "cvtdq2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "sse2_cvtpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (vec_concat:V4SI
+ (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "")]
+ UNSPEC_FIX_NOTRUNC)
+ (match_dup 2)))]
+ "TARGET_SSE2"
+ "operands[2] = CONST0_RTX (V2SImode);")
+
+(define_insn "*sse2_cvtpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_concat:V4SI
+ (unspec:V2SI [(match_operand:V2DF 1 "nonimmediate_operand" "xm")]
+ UNSPEC_FIX_NOTRUNC)
+ (match_operand:V2SI 2 "const0_operand" "")))]
+ "TARGET_SSE2"
+ "cvtpd2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_cvttpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (vec_concat:V4SI
+ (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" ""))
+ (match_dup 2)))]
+ "TARGET_SSE2"
+ "operands[2] = CONST0_RTX (V2SImode);")
+
+(define_insn "*sse2_cvttpd2dq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_concat:V4SI
+ (fix:V2SI (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
+ (match_operand:V2SI 2 "const0_operand" "")))]
+ "TARGET_SSE2"
+ "cvttpd2dq\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_cvtsd2ss"
+ [(set (match_operand:V4SF 0 "register_operand" "=x,x")
+ (vec_merge:V4SF
+ (vec_duplicate:V4SF
+ (float_truncate:V2SF
+ (match_operand:V2DF 2 "nonimmediate_operand" "x,m")))
+ (match_operand:V4SF 1 "register_operand" "0,0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "cvtsd2ss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "athlon_decode" "vector,double")
+ (set_attr "mode" "SF")])
+
+(define_insn "sse2_cvtss2sd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_merge:V2DF
+ (float_extend:V2DF
+ (vec_select:V2SF
+ (match_operand:V4SF 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0) (const_int 1)])))
+ (match_operand:V2DF 1 "register_operand" "0")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "cvtss2sd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "DF")])
+
+(define_expand "sse2_cvtpd2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "")
+ (vec_concat:V4SF
+ (float_truncate:V2SF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
+ (match_dup 2)))]
+ "TARGET_SSE2"
+ "operands[2] = CONST0_RTX (V2SFmode);")
+
+(define_insn "*sse2_cvtpd2ps"
+ [(set (match_operand:V4SF 0 "register_operand" "=x")
+ (vec_concat:V4SF
+ (float_truncate:V2SF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm"))
+ (match_operand:V2SF 2 "const0_operand" "")))]
+ "TARGET_SSE2"
+ "cvtpd2ps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse2_cvtps2pd"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (float_extend:V2DF
+ (vec_select:V2SF
+ (match_operand:V4SF 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0) (const_int 1)]))))]
+ "TARGET_SSE2"
+ "cvtps2pd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel double-precision floating point element swizzling
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_unpckhpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m")
+ (vec_select:V2DF
+ (vec_concat:V4DF
+ (match_operand:V2DF 1 "nonimmediate_operand" " 0,o,x")
+ (match_operand:V2DF 2 "nonimmediate_operand" " x,0,0"))
+ (parallel [(const_int 1)
+ (const_int 3)])))]
+ "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ unpckhpd\t{%2, %0|%0, %2}
+ movlpd\t{%H1, %0|%0, %H1}
+ movhpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "mode" "V2DF,V1DF,V1DF")])
+
+(define_insn "*sse3_movddup"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,o")
+ (vec_select:V2DF
+ (vec_concat:V4DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "xm,x")
+ (match_dup 1))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ "TARGET_SSE3 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ movddup\t{%1, %0|%0, %1}
+ #"
+ [(set_attr "type" "sselog,ssemov")
+ (set_attr "mode" "V2DF")])
+
+(define_split
+ [(set (match_operand:V2DF 0 "memory_operand" "")
+ (vec_select:V2DF
+ (vec_concat:V4DF
+ (match_operand:V2DF 1 "register_operand" "")
+ (match_dup 1))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ "TARGET_SSE3 && reload_completed"
+ [(const_int 0)]
+{
+ rtx low = gen_rtx_REG (DFmode, REGNO (operands[1]));
+ emit_move_insn (adjust_address (operands[0], DFmode, 0), low);
+ emit_move_insn (adjust_address (operands[0], DFmode, 8), low);
+ DONE;
+})
+
+(define_insn "sse2_unpcklpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,o")
+ (vec_select:V2DF
+ (vec_concat:V4DF
+ (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,0")
+ (match_operand:V2DF 2 "nonimmediate_operand" " x,m,x"))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ unpcklpd\t{%2, %0|%0, %2}
+ movhpd\t{%2, %0|%0, %2}
+ movlpd\t{%2, %H0|%H0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "mode" "V2DF,V1DF,V1DF")])
+
+(define_expand "sse2_shufpd"
+ [(match_operand:V2DF 0 "register_operand" "")
+ (match_operand:V2DF 1 "register_operand" "")
+ (match_operand:V2DF 2 "nonimmediate_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")]
+ "TARGET_SSE2"
+{
+ int mask = INTVAL (operands[3]);
+ emit_insn (gen_sse2_shufpd_1 (operands[0], operands[1], operands[2],
+ GEN_INT (mask & 1),
+ GEN_INT (mask & 2 ? 3 : 2)));
+ DONE;
+})
+
+(define_insn "sse2_shufpd_1"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_select:V2DF
+ (vec_concat:V4DF
+ (match_operand:V2DF 1 "register_operand" "0")
+ (match_operand:V2DF 2 "nonimmediate_operand" "xm"))
+ (parallel [(match_operand 3 "const_0_to_1_operand" "")
+ (match_operand 4 "const_2_to_3_operand" "")])))]
+ "TARGET_SSE2"
+{
+ int mask;
+ mask = INTVAL (operands[3]);
+ mask |= (INTVAL (operands[4]) - 2) << 1;
+ operands[3] = GEN_INT (mask);
+
+ return "shufpd\t{%3, %2, %0|%0, %2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_storehpd"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x*fr")
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" " x,0,o")
+ (parallel [(const_int 1)])))]
+ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movhpd\t{%1, %0|%0, %1}
+ unpckhpd\t%0, %0
+ #"
+ [(set_attr "type" "ssemov,sselog1,ssemov")
+ (set_attr "mode" "V1DF,V2DF,DF")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (vec_select:DF
+ (match_operand:V2DF 1 "memory_operand" "")
+ (parallel [(const_int 1)])))]
+ "TARGET_SSE2 && reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[1] = adjust_address (operands[1], DFmode, 8);
+})
+
+(define_insn "sse2_storelpd"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x*fr")
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" " x,x,m")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movlpd\t{%1, %0|%0, %1}
+ #
+ #"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V1DF,DF,DF")])
+
+(define_split
+ [(set (match_operand:DF 0 "register_operand" "")
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE2 && reload_completed"
+ [(const_int 0)]
+{
+ rtx op1 = operands[1];
+ if (REG_P (op1))
+ op1 = gen_rtx_REG (DFmode, REGNO (op1));
+ else
+ op1 = gen_lowpart (DFmode, op1);
+ emit_move_insn (operands[0], op1);
+ DONE;
+})
+
+(define_insn "sse2_loadhpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,x,o")
+ (vec_concat:V2DF
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,x,0")
+ (parallel [(const_int 0)]))
+ (match_operand:DF 2 "nonimmediate_operand" " m,x,0,x*fr")))]
+ "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ movhpd\t{%2, %0|%0, %2}
+ unpcklpd\t{%2, %0|%0, %2}
+ shufpd\t{$1, %1, %0|%0, %1, 1}
+ #"
+ [(set_attr "type" "ssemov,sselog,sselog,other")
+ (set_attr "mode" "V1DF,V2DF,V2DF,DF")])
+
+(define_split
+ [(set (match_operand:V2DF 0 "memory_operand" "")
+ (vec_concat:V2DF
+ (vec_select:DF (match_dup 0) (parallel [(const_int 0)]))
+ (match_operand:DF 1 "register_operand" "")))]
+ "TARGET_SSE2 && reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[0] = adjust_address (operands[0], DFmode, 8);
+})
+
+(define_insn "sse2_loadlpd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,x,x,x,m")
+ (vec_concat:V2DF
+ (match_operand:DF 2 "nonimmediate_operand" " m,m,x,0,0,x*fr")
+ (vec_select:DF
+ (match_operand:V2DF 1 "vector_move_operand" " C,0,0,x,o,0")
+ (parallel [(const_int 1)]))))]
+ "TARGET_SSE2 && !(MEM_P (operands[1]) && MEM_P (operands[2]))"
+ "@
+ movsd\t{%2, %0|%0, %2}
+ movlpd\t{%2, %0|%0, %2}
+ movsd\t{%2, %0|%0, %2}
+ shufpd\t{$2, %2, %0|%0, %2, 2}
+ movhpd\t{%H1, %0|%0, %H1}
+ #"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,other")
+ (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,DF")])
+
+(define_split
+ [(set (match_operand:V2DF 0 "memory_operand" "")
+ (vec_concat:V2DF
+ (match_operand:DF 1 "register_operand" "")
+ (vec_select:DF (match_dup 0) (parallel [(const_int 1)]))))]
+ "TARGET_SSE2 && reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[0] = adjust_address (operands[0], DFmode, 8);
+})
+
+;; Not sure these two are ever used, but it doesn't hurt to have
+;; them. -aoliva
+(define_insn "*vec_extractv2df_1_sse"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,x,o")
+ (parallel [(const_int 1)])))]
+ "!TARGET_SSE2 && TARGET_SSE
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movhps\t{%1, %0|%0, %1}
+ movhlps\t{%1, %0|%0, %1}
+ movlps\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "*vec_extractv2df_0_sse"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:DF
+ (match_operand:V2DF 1 "nonimmediate_operand" "x,x,m")
+ (parallel [(const_int 0)])))]
+ "!TARGET_SSE2 && TARGET_SSE
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movlps\t{%1, %0|%0, %1}
+ movaps\t{%1, %0|%0, %1}
+ movlps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "sse2_movsd"
+ [(set (match_operand:V2DF 0 "nonimmediate_operand" "=x,x,m,x,x,o")
+ (vec_merge:V2DF
+ (match_operand:V2DF 2 "nonimmediate_operand" " x,m,x,0,0,0")
+ (match_operand:V2DF 1 "nonimmediate_operand" " 0,0,0,x,o,x")
+ (const_int 1)))]
+ "TARGET_SSE2"
+ "@
+ movsd\t{%2, %0|%0, %2}
+ movlpd\t{%2, %0|%0, %2}
+ movlpd\t{%2, %0|%0, %2}
+ shufpd\t{$2, %2, %0|%0, %2, 2}
+ movhps\t{%H1, %0|%0, %H1}
+ movhps\t{%1, %H0|%H0, %1}"
+ [(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,V1DF")])
+
+(define_insn "*vec_dupv2df_sse3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_duplicate:V2DF
+ (match_operand:DF 1 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE3"
+ "movddup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "DF")])
+
+(define_insn "*vec_dupv2df"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_duplicate:V2DF
+ (match_operand:DF 1 "register_operand" "0")))]
+ "TARGET_SSE2"
+ "unpcklpd\t%0, %0"
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "*vec_concatv2df_sse3"
+ [(set (match_operand:V2DF 0 "register_operand" "=x")
+ (vec_concat:V2DF
+ (match_operand:DF 1 "nonimmediate_operand" "xm")
+ (match_dup 1)))]
+ "TARGET_SSE3"
+ "movddup\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "DF")])
+
+(define_insn "*vec_concatv2df"
+ [(set (match_operand:V2DF 0 "register_operand" "=Y,Y,Y,x,x")
+ (vec_concat:V2DF
+ (match_operand:DF 1 "nonimmediate_operand" " 0,0,m,0,0")
+ (match_operand:DF 2 "vector_move_operand" " Y,m,C,x,m")))]
+ "TARGET_SSE"
+ "@
+ unpcklpd\t{%2, %0|%0, %2}
+ movhpd\t{%2, %0|%0, %2}
+ movsd\t{%1, %0|%0, %1}
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "mode" "V2DF,V1DF,DF,V4SF,V2SF")])
+
+(define_expand "vec_setv2df"
+ [(match_operand:V2DF 0 "register_operand" "")
+ (match_operand:DF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv2df"
+ [(match_operand:DF 0 "register_operand" "")
+ (match_operand:V2DF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv2df"
+ [(match_operand:V2DF 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral arithmetic
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "neg<mode>2"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (minus:SSEMODEI
+ (match_dup 2)
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "operands[2] = force_reg (<MODE>mode, CONST0_RTX (<MODE>mode));")
+
+(define_expand "add<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (plus:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (PLUS, <MODE>mode, operands);")
+
+(define_insn "*add<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (plus:SSEMODEI
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+ "padd<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_ssadd<mode>3"
+ [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
+ (ss_plus:SSEMODE12
+ (match_operand:SSEMODE12 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (SS_PLUS, <MODE>mode, operands)"
+ "padds<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_usadd<mode>3"
+ [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
+ (us_plus:SSEMODE12
+ (match_operand:SSEMODE12 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (US_PLUS, <MODE>mode, operands)"
+ "paddus<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "sub<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (minus:SSEMODEI (match_operand:SSEMODEI 1 "register_operand" "")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (MINUS, <MODE>mode, operands);")
+
+(define_insn "*sub<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (minus:SSEMODEI
+ (match_operand:SSEMODEI 1 "register_operand" "0")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psub<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_sssub<mode>3"
+ [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
+ (ss_minus:SSEMODE12
+ (match_operand:SSEMODE12 1 "register_operand" "0")
+ (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubs<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_ussub<mode>3"
+ [(set (match_operand:SSEMODE12 0 "register_operand" "=x")
+ (us_minus:SSEMODE12
+ (match_operand:SSEMODE12 1 "register_operand" "0")
+ (match_operand:SSEMODE12 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "psubus<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "mulv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (mult:V16QI (match_operand:V16QI 1 "register_operand" "")
+ (match_operand:V16QI 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx t[12], op0;
+ int i;
+
+ for (i = 0; i < 12; ++i)
+ t[i] = gen_reg_rtx (V16QImode);
+
+ /* Unpack data such that we've got a source byte in each low byte of
+ each word. We don't care what goes into the high byte of each word.
+ Rather than trying to get zero in there, most convenient is to let
+ it be a copy of the low byte. */
+ emit_insn (gen_sse2_punpckhbw (t[0], operands[1], operands[1]));
+ emit_insn (gen_sse2_punpckhbw (t[1], operands[2], operands[2]));
+ emit_insn (gen_sse2_punpcklbw (t[2], operands[1], operands[1]));
+ emit_insn (gen_sse2_punpcklbw (t[3], operands[2], operands[2]));
+
+ /* Multiply words. The end-of-line annotations here give a picture of what
+ the output of that instruction looks like. Dot means don't care; the
+ letters are the bytes of the result with A being the most significant. */
+ emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[4]), /* .A.B.C.D.E.F.G.H */
+ gen_lowpart (V8HImode, t[0]),
+ gen_lowpart (V8HImode, t[1])));
+ emit_insn (gen_mulv8hi3 (gen_lowpart (V8HImode, t[5]), /* .I.J.K.L.M.N.O.P */
+ gen_lowpart (V8HImode, t[2]),
+ gen_lowpart (V8HImode, t[3])));
+
+ /* Extract the relevant bytes and merge them back together. */
+ emit_insn (gen_sse2_punpckhbw (t[6], t[5], t[4])); /* ..AI..BJ..CK..DL */
+ emit_insn (gen_sse2_punpcklbw (t[7], t[5], t[4])); /* ..EM..FN..GO..HP */
+ emit_insn (gen_sse2_punpckhbw (t[8], t[7], t[6])); /* ....AEIM....BFJN */
+ emit_insn (gen_sse2_punpcklbw (t[9], t[7], t[6])); /* ....CGKO....DHLP */
+ emit_insn (gen_sse2_punpckhbw (t[10], t[9], t[8])); /* ........ACEGIKMO */
+ emit_insn (gen_sse2_punpcklbw (t[11], t[9], t[8])); /* ........BDFHJLNP */
+
+ op0 = operands[0];
+ emit_insn (gen_sse2_punpcklbw (op0, t[11], t[10])); /* ABCDEFGHIJKLMNOP */
+ DONE;
+})
+
+(define_expand "mulv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "")
+ (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:V8HI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (MULT, V8HImode, operands);")
+
+(define_insn "*mulv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (mult:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
+ "pmullw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_smulv8hi3_highpart"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (truncate:V8HI
+ (lshiftrt:V8SI
+ (mult:V8SI
+ (sign_extend:V8SI
+ (match_operand:V8HI 1 "nonimmediate_operand" "%0"))
+ (sign_extend:V8SI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (const_int 16))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
+ "pmulhw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_umulv8hi3_highpart"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (truncate:V8HI
+ (lshiftrt:V8SI
+ (mult:V8SI
+ (zero_extend:V8SI
+ (match_operand:V8HI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V8SI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (const_int 16))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
+ "pmulhuw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_umulv2siv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (mult:V2DI
+ (zero_extend:V2DI
+ (vec_select:V2SI
+ (match_operand:V4SI 1 "nonimmediate_operand" "%0")
+ (parallel [(const_int 0) (const_int 2)])))
+ (zero_extend:V2DI
+ (vec_select:V2SI
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0) (const_int 2)])))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (MULT, V8HImode, operands)"
+ "pmuludq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseimul")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pmaddwd"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (plus:V4SI
+ (mult:V4SI
+ (sign_extend:V4SI
+ (vec_select:V4HI
+ (match_operand:V8HI 1 "nonimmediate_operand" "%0")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)])))
+ (sign_extend:V4SI
+ (vec_select:V4HI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)]))))
+ (mult:V4SI
+ (sign_extend:V4SI
+ (vec_select:V4HI (match_dup 1)
+ (parallel [(const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)])))
+ (sign_extend:V4SI
+ (vec_select:V4HI (match_dup 2)
+ (parallel [(const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)]))))))]
+ "TARGET_SSE2"
+ "pmaddwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "mulv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (mult:V4SI (match_operand:V4SI 1 "register_operand" "")
+ (match_operand:V4SI 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx t1, t2, t3, t4, t5, t6, thirtytwo;
+ rtx op0, op1, op2;
+
+ op0 = operands[0];
+ op1 = operands[1];
+ op2 = operands[2];
+ t1 = gen_reg_rtx (V4SImode);
+ t2 = gen_reg_rtx (V4SImode);
+ t3 = gen_reg_rtx (V4SImode);
+ t4 = gen_reg_rtx (V4SImode);
+ t5 = gen_reg_rtx (V4SImode);
+ t6 = gen_reg_rtx (V4SImode);
+ thirtytwo = GEN_INT (32);
+
+ /* Multiply elements 2 and 0. */
+ emit_insn (gen_sse2_umulv2siv2di3 (gen_lowpart (V2DImode, t1), op1, op2));
+
+ /* Shift both input vectors down one element, so that elements 3 and 1
+ are now in the slots for elements 2 and 0. For K8, at least, this is
+ faster than using a shuffle. */
+ emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t2),
+ gen_lowpart (TImode, op1), thirtytwo));
+ emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t3),
+ gen_lowpart (TImode, op2), thirtytwo));
+
+ /* Multiply elements 3 and 1. */
+ emit_insn (gen_sse2_umulv2siv2di3 (gen_lowpart (V2DImode, t4), t2, t3));
+
+ /* Move the results in element 2 down to element 1; we don't care what
+ goes in elements 2 and 3. */
+ emit_insn (gen_sse2_pshufd_1 (t5, t1, const0_rtx, const2_rtx,
+ const0_rtx, const0_rtx));
+ emit_insn (gen_sse2_pshufd_1 (t6, t4, const0_rtx, const2_rtx,
+ const0_rtx, const0_rtx));
+
+ /* Merge the parts back together. */
+ emit_insn (gen_sse2_punpckldq (op0, t5, t6));
+ DONE;
+})
+
+(define_expand "mulv2di3"
+ [(set (match_operand:V2DI 0 "register_operand" "")
+ (mult:V2DI (match_operand:V2DI 1 "register_operand" "")
+ (match_operand:V2DI 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx t1, t2, t3, t4, t5, t6, thirtytwo;
+ rtx op0, op1, op2;
+
+ op0 = operands[0];
+ op1 = operands[1];
+ op2 = operands[2];
+ t1 = gen_reg_rtx (V2DImode);
+ t2 = gen_reg_rtx (V2DImode);
+ t3 = gen_reg_rtx (V2DImode);
+ t4 = gen_reg_rtx (V2DImode);
+ t5 = gen_reg_rtx (V2DImode);
+ t6 = gen_reg_rtx (V2DImode);
+ thirtytwo = GEN_INT (32);
+
+ /* Multiply low parts. */
+ emit_insn (gen_sse2_umulv2siv2di3 (t1, gen_lowpart (V4SImode, op1),
+ gen_lowpart (V4SImode, op2)));
+
+ /* Shift input vectors left 32 bits so we can multiply high parts. */
+ emit_insn (gen_lshrv2di3 (t2, op1, thirtytwo));
+ emit_insn (gen_lshrv2di3 (t3, op2, thirtytwo));
+
+ /* Multiply high parts by low parts. */
+ emit_insn (gen_sse2_umulv2siv2di3 (t4, gen_lowpart (V4SImode, op1),
+ gen_lowpart (V4SImode, t3)));
+ emit_insn (gen_sse2_umulv2siv2di3 (t5, gen_lowpart (V4SImode, op2),
+ gen_lowpart (V4SImode, t2)));
+
+ /* Shift them back. */
+ emit_insn (gen_ashlv2di3 (t4, t4, thirtytwo));
+ emit_insn (gen_ashlv2di3 (t5, t5, thirtytwo));
+
+ /* Add the three parts together. */
+ emit_insn (gen_addv2di3 (t6, t1, t4));
+ emit_insn (gen_addv2di3 (op0, t6, t5));
+ DONE;
+})
+
+(define_expand "sdot_prodv8hi"
+ [(match_operand:V4SI 0 "register_operand" "")
+ (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:V8HI 2 "nonimmediate_operand" "")
+ (match_operand:V4SI 3 "register_operand" "")]
+ "TARGET_SSE2"
+{
+ rtx t = gen_reg_rtx (V4SImode);
+ emit_insn (gen_sse2_pmaddwd (t, operands[1], operands[2]));
+ emit_insn (gen_addv4si3 (operands[0], operands[3], t));
+ DONE;
+})
+
+(define_expand "udot_prodv4si"
+ [(match_operand:V2DI 0 "register_operand" "")
+ (match_operand:V4SI 1 "register_operand" "")
+ (match_operand:V4SI 2 "register_operand" "")
+ (match_operand:V2DI 3 "register_operand" "")]
+ "TARGET_SSE2"
+{
+ rtx t1, t2, t3, t4;
+
+ t1 = gen_reg_rtx (V2DImode);
+ emit_insn (gen_sse2_umulv2siv2di3 (t1, operands[1], operands[2]));
+ emit_insn (gen_addv2di3 (t1, t1, operands[3]));
+
+ t2 = gen_reg_rtx (V4SImode);
+ t3 = gen_reg_rtx (V4SImode);
+ emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t2),
+ gen_lowpart (TImode, operands[1]),
+ GEN_INT (32)));
+ emit_insn (gen_sse2_lshrti3 (gen_lowpart (TImode, t3),
+ gen_lowpart (TImode, operands[2]),
+ GEN_INT (32)));
+
+ t4 = gen_reg_rtx (V2DImode);
+ emit_insn (gen_sse2_umulv2siv2di3 (t4, t2, t3));
+
+ emit_insn (gen_addv2di3 (operands[0], t1, t4));
+ DONE;
+})
+
+(define_insn "ashr<mode>3"
+ [(set (match_operand:SSEMODE24 0 "register_operand" "=x")
+ (ashiftrt:SSEMODE24
+ (match_operand:SSEMODE24 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xn")))]
+ "TARGET_SSE2"
+ "psra<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "lshr<mode>3"
+ [(set (match_operand:SSEMODE248 0 "register_operand" "=x")
+ (lshiftrt:SSEMODE248
+ (match_operand:SSEMODE248 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xn")))]
+ "TARGET_SSE2"
+ "psrl<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "ashl<mode>3"
+ [(set (match_operand:SSEMODE248 0 "register_operand" "=x")
+ (ashift:SSEMODE248
+ (match_operand:SSEMODE248 1 "register_operand" "0")
+ (match_operand:TI 2 "nonmemory_operand" "xn")))]
+ "TARGET_SSE2"
+ "psll<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_ashlti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (ashift:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))]
+ "TARGET_SSE2"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
+ return "pslldq\t{%2, %0|%0, %2}";
+}
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_expand "vec_shl_<mode>"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (ashift:TI (match_operand:SSEMODEI 1 "register_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (!const_0_to_255_mul_8_operand (operands[2], SImode))
+ FAIL;
+ operands[0] = gen_lowpart (TImode, operands[0]);
+ operands[1] = gen_lowpart (TImode, operands[1]);
+})
+
+(define_insn "sse2_lshrti3"
+ [(set (match_operand:TI 0 "register_operand" "=x")
+ (lshiftrt:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:SI 2 "const_0_to_255_mul_8_operand" "n")))]
+ "TARGET_SSE2"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) / 8);
+ return "psrldq\t{%2, %0|%0, %2}";
+}
+ [(set_attr "type" "sseishft")
+ (set_attr "mode" "TI")])
+
+(define_expand "vec_shr_<mode>"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (lshiftrt:TI (match_operand:SSEMODEI 1 "register_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (!const_0_to_255_mul_8_operand (operands[2], SImode))
+ FAIL;
+ operands[0] = gen_lowpart (TImode, operands[0]);
+ operands[1] = gen_lowpart (TImode, operands[1]);
+})
+
+(define_expand "umaxv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (umax:V16QI (match_operand:V16QI 1 "nonimmediate_operand" "")
+ (match_operand:V16QI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (UMAX, V16QImode, operands);")
+
+(define_insn "*umaxv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (umax:V16QI (match_operand:V16QI 1 "nonimmediate_operand" "%0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (UMAX, V16QImode, operands)"
+ "pmaxub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "smaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "")
+ (smax:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:V8HI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (SMAX, V8HImode, operands);")
+
+(define_insn "*smaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (smax:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (SMAX, V8HImode, operands)"
+ "pmaxsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "umaxv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (us_minus:V8HI (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (set (match_dup 3)
+ (plus:V8HI (match_dup 0) (match_dup 2)))]
+ "TARGET_SSE2"
+{
+ operands[3] = operands[0];
+ if (rtx_equal_p (operands[0], operands[2]))
+ operands[0] = gen_reg_rtx (V8HImode);
+})
+
+(define_expand "smax<mode>3"
+ [(set (match_operand:SSEMODE14 0 "register_operand" "")
+ (smax:SSEMODE14 (match_operand:SSEMODE14 1 "register_operand" "")
+ (match_operand:SSEMODE14 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx xops[6];
+ bool ok;
+
+ xops[0] = operands[0];
+ xops[1] = operands[1];
+ xops[2] = operands[2];
+ xops[3] = gen_rtx_GT (VOIDmode, operands[1], operands[2]);
+ xops[4] = operands[1];
+ xops[5] = operands[2];
+ ok = ix86_expand_int_vcond (xops);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "umaxv4si3"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (umax:V4SI (match_operand:V4SI 1 "register_operand" "")
+ (match_operand:V4SI 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx xops[6];
+ bool ok;
+
+ xops[0] = operands[0];
+ xops[1] = operands[1];
+ xops[2] = operands[2];
+ xops[3] = gen_rtx_GTU (VOIDmode, operands[1], operands[2]);
+ xops[4] = operands[1];
+ xops[5] = operands[2];
+ ok = ix86_expand_int_vcond (xops);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "uminv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (umin:V16QI (match_operand:V16QI 1 "nonimmediate_operand" "")
+ (match_operand:V16QI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (UMIN, V16QImode, operands);")
+
+(define_insn "*uminv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (umin:V16QI (match_operand:V16QI 1 "nonimmediate_operand" "%0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (UMIN, V16QImode, operands)"
+ "pminub\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "sminv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "")
+ (smin:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:V8HI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (SMIN, V8HImode, operands);")
+
+(define_insn "*sminv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (smin:V8HI (match_operand:V8HI 1 "nonimmediate_operand" "%0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (SMIN, V8HImode, operands)"
+ "pminsw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:SSEMODE14 0 "register_operand" "")
+ (smin:SSEMODE14 (match_operand:SSEMODE14 1 "register_operand" "")
+ (match_operand:SSEMODE14 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx xops[6];
+ bool ok;
+
+ xops[0] = operands[0];
+ xops[1] = operands[2];
+ xops[2] = operands[1];
+ xops[3] = gen_rtx_GT (VOIDmode, operands[1], operands[2]);
+ xops[4] = operands[1];
+ xops[5] = operands[2];
+ ok = ix86_expand_int_vcond (xops);
+ gcc_assert (ok);
+ DONE;
+})
+
+(define_expand "umin<mode>3"
+ [(set (match_operand:SSEMODE24 0 "register_operand" "")
+ (umin:SSEMODE24 (match_operand:SSEMODE24 1 "register_operand" "")
+ (match_operand:SSEMODE24 2 "register_operand" "")))]
+ "TARGET_SSE2"
+{
+ rtx xops[6];
+ bool ok;
+
+ xops[0] = operands[0];
+ xops[1] = operands[2];
+ xops[2] = operands[1];
+ xops[3] = gen_rtx_GTU (VOIDmode, operands[1], operands[2]);
+ xops[4] = operands[1];
+ xops[5] = operands[2];
+ ok = ix86_expand_int_vcond (xops);
+ gcc_assert (ok);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral comparisons
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_eq<mode>3"
+ [(set (match_operand:SSEMODE124 0 "register_operand" "=x")
+ (eq:SSEMODE124
+ (match_operand:SSEMODE124 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODE124 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
+ "pcmpeq<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_gt<mode>3"
+ [(set (match_operand:SSEMODE124 0 "register_operand" "=x")
+ (gt:SSEMODE124
+ (match_operand:SSEMODE124 1 "register_operand" "0")
+ (match_operand:SSEMODE124 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pcmpgt<ssevecsize>\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssecmp")
+ (set_attr "mode" "TI")])
+
+(define_expand "vcond<mode>"
+ [(set (match_operand:SSEMODE124 0 "register_operand" "")
+ (if_then_else:SSEMODE124
+ (match_operator 3 ""
+ [(match_operand:SSEMODE124 4 "nonimmediate_operand" "")
+ (match_operand:SSEMODE124 5 "nonimmediate_operand" "")])
+ (match_operand:SSEMODE124 1 "general_operand" "")
+ (match_operand:SSEMODE124 2 "general_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (ix86_expand_int_vcond (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "vcondu<mode>"
+ [(set (match_operand:SSEMODE124 0 "register_operand" "")
+ (if_then_else:SSEMODE124
+ (match_operator 3 ""
+ [(match_operand:SSEMODE124 4 "nonimmediate_operand" "")
+ (match_operand:SSEMODE124 5 "nonimmediate_operand" "")])
+ (match_operand:SSEMODE124 1 "general_operand" "")
+ (match_operand:SSEMODE124 2 "general_operand" "")))]
+ "TARGET_SSE2"
+{
+ if (ix86_expand_int_vcond (operands))
+ DONE;
+ else
+ FAIL;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral logical operations
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_expand "one_cmpl<mode>2"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (xor:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
+ (match_dup 2)))]
+ "TARGET_SSE2"
+{
+ int i, n = GET_MODE_NUNITS (<MODE>mode);
+ rtvec v = rtvec_alloc (n);
+
+ for (i = 0; i < n; ++i)
+ RTVEC_ELT (v, i) = constm1_rtx;
+
+ operands[2] = force_reg (<MODE>mode, gen_rtx_CONST_VECTOR (<MODE>mode, v));
+})
+
+(define_expand "and<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (and:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (AND, <MODE>mode, operands);")
+
+(define_insn "*and<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (and:SSEMODEI
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (AND, <MODE>mode, operands)"
+ "pand\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_nand<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (and:SSEMODEI
+ (not:SSEMODEI (match_operand:SSEMODEI 1 "register_operand" "0"))
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2"
+ "pandn\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "ior<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (ior:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (IOR, <MODE>mode, operands);")
+
+(define_insn "*ior<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (ior:SSEMODEI
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (IOR, <MODE>mode, operands)"
+ "por\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "xor<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "")
+ (xor:SSEMODEI (match_operand:SSEMODEI 1 "nonimmediate_operand" "")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "")))]
+ "TARGET_SSE2"
+ "ix86_fixup_binary_operands_no_copy (XOR, <MODE>mode, operands);")
+
+(define_insn "*xor<mode>3"
+ [(set (match_operand:SSEMODEI 0 "register_operand" "=x")
+ (xor:SSEMODEI
+ (match_operand:SSEMODEI 1 "nonimmediate_operand" "%0")
+ (match_operand:SSEMODEI 2 "nonimmediate_operand" "xm")))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (XOR, <MODE>mode, operands)"
+ "pxor\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Parallel integral element swizzling
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_packsswb"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_concat:V16QI
+ (ss_truncate:V8QI
+ (match_operand:V8HI 1 "register_operand" "0"))
+ (ss_truncate:V8QI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm"))))]
+ "TARGET_SSE2"
+ "packsswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_packssdw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_concat:V8HI
+ (ss_truncate:V4HI
+ (match_operand:V4SI 1 "register_operand" "0"))
+ (ss_truncate:V4HI
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm"))))]
+ "TARGET_SSE2"
+ "packssdw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_packuswb"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_concat:V16QI
+ (us_truncate:V8QI
+ (match_operand:V8HI 1 "register_operand" "0"))
+ (us_truncate:V8QI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm"))))]
+ "TARGET_SSE2"
+ "packuswb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhbw"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_select:V16QI
+ (vec_concat:V32QI
+ (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 8) (const_int 24)
+ (const_int 9) (const_int 25)
+ (const_int 10) (const_int 26)
+ (const_int 11) (const_int 27)
+ (const_int 12) (const_int 28)
+ (const_int 13) (const_int 29)
+ (const_int 14) (const_int 30)
+ (const_int 15) (const_int 31)])))]
+ "TARGET_SSE2"
+ "punpckhbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklbw"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (vec_select:V16QI
+ (vec_concat:V32QI
+ (match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0) (const_int 16)
+ (const_int 1) (const_int 17)
+ (const_int 2) (const_int 18)
+ (const_int 3) (const_int 19)
+ (const_int 4) (const_int 20)
+ (const_int 5) (const_int 21)
+ (const_int 6) (const_int 22)
+ (const_int 7) (const_int 23)])))]
+ "TARGET_SSE2"
+ "punpcklbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhwd"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 4) (const_int 12)
+ (const_int 5) (const_int 13)
+ (const_int 6) (const_int 14)
+ (const_int 7) (const_int 15)])))]
+ "TARGET_SSE2"
+ "punpckhwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklwd"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_select:V8HI
+ (vec_concat:V16HI
+ (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0) (const_int 8)
+ (const_int 1) (const_int 9)
+ (const_int 2) (const_int 10)
+ (const_int 3) (const_int 11)])))]
+ "TARGET_SSE2"
+ "punpcklwd\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhdq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_select:V4SI
+ (vec_concat:V8SI
+ (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 2) (const_int 6)
+ (const_int 3) (const_int 7)])))]
+ "TARGET_SSE2"
+ "punpckhdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckldq"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_select:V4SI
+ (vec_concat:V8SI
+ (match_operand:V4SI 1 "register_operand" "0")
+ (match_operand:V4SI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0) (const_int 4)
+ (const_int 1) (const_int 5)])))]
+ "TARGET_SSE2"
+ "punpckldq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpckhqdq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_select:V2DI
+ (vec_concat:V4DI
+ (match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 1)
+ (const_int 3)])))]
+ "TARGET_SSE2"
+ "punpckhqdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_punpcklqdq"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (vec_select:V2DI
+ (vec_concat:V4DI
+ (match_operand:V2DI 1 "register_operand" "0")
+ (match_operand:V2DI 2 "nonimmediate_operand" "xm"))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ "TARGET_SSE2"
+ "punpcklqdq\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_pinsrw"
+ [(set (match_operand:V8HI 0 "register_operand" "")
+ (vec_merge:V8HI
+ (vec_duplicate:V8HI
+ (match_operand:SI 2 "nonimmediate_operand" ""))
+ (match_operand:V8HI 1 "register_operand" "")
+ (match_operand:SI 3 "const_0_to_7_operand" "")))]
+ "TARGET_SSE2"
+{
+ operands[2] = gen_lowpart (HImode, operands[2]);
+ operands[3] = GEN_INT ((1 << INTVAL (operands[3])));
+})
+
+(define_insn "*sse2_pinsrw"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_merge:V8HI
+ (vec_duplicate:V8HI
+ (match_operand:HI 2 "nonimmediate_operand" "rm"))
+ (match_operand:V8HI 1 "register_operand" "0")
+ (match_operand:SI 3 "const_pow2_1_to_128_operand" "n")))]
+ "TARGET_SSE2"
+{
+ operands[3] = GEN_INT (exact_log2 (INTVAL (operands[3])));
+ return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_pextrw"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (zero_extend:SI
+ (vec_select:HI
+ (match_operand:V8HI 1 "register_operand" "x")
+ (parallel [(match_operand:SI 2 "const_0_to_7_operand" "n")]))))]
+ "TARGET_SSE2"
+ "pextrw\t{%2, %1, %0|%0, %1, %2}"
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_pshufd"
+ [(match_operand:V4SI 0 "register_operand" "")
+ (match_operand:V4SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_SSE2"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_sse2_pshufd_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
+ DONE;
+})
+
+(define_insn "sse2_pshufd_1"
+ [(set (match_operand:V4SI 0 "register_operand" "=x")
+ (vec_select:V4SI
+ (match_operand:V4SI 1 "nonimmediate_operand" "xm")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
+ (match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_0_to_3_operand" "")])))]
+ "TARGET_SSE2"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+
+ return "pshufd\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_pshuflw"
+ [(match_operand:V8HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_SSE2"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_sse2_pshuflw_1 (operands[0], operands[1],
+ GEN_INT ((mask >> 0) & 3),
+ GEN_INT ((mask >> 2) & 3),
+ GEN_INT ((mask >> 4) & 3),
+ GEN_INT ((mask >> 6) & 3)));
+ DONE;
+})
+
+(define_insn "sse2_pshuflw_1"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+ (parallel [(match_operand 2 "const_0_to_3_operand" "")
+ (match_operand 3 "const_0_to_3_operand" "")
+ (match_operand 4 "const_0_to_3_operand" "")
+ (match_operand 5 "const_0_to_3_operand" "")
+ (const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)])))]
+ "TARGET_SSE2"
+{
+ int mask = 0;
+ mask |= INTVAL (operands[2]) << 0;
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+
+ return "pshuflw\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_pshufhw"
+ [(match_operand:V8HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")]
+ "TARGET_SSE2"
+{
+ int mask = INTVAL (operands[2]);
+ emit_insn (gen_sse2_pshufhw_1 (operands[0], operands[1],
+ GEN_INT (((mask >> 0) & 3) + 4),
+ GEN_INT (((mask >> 2) & 3) + 4),
+ GEN_INT (((mask >> 4) & 3) + 4),
+ GEN_INT (((mask >> 6) & 3) + 4)));
+ DONE;
+})
+
+(define_insn "sse2_pshufhw_1"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (vec_select:V8HI
+ (match_operand:V8HI 1 "nonimmediate_operand" "xm")
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (match_operand 2 "const_4_to_7_operand" "")
+ (match_operand 3 "const_4_to_7_operand" "")
+ (match_operand 4 "const_4_to_7_operand" "")
+ (match_operand 5 "const_4_to_7_operand" "")])))]
+ "TARGET_SSE2"
+{
+ int mask = 0;
+ mask |= (INTVAL (operands[2]) - 4) << 0;
+ mask |= (INTVAL (operands[3]) - 4) << 2;
+ mask |= (INTVAL (operands[4]) - 4) << 4;
+ mask |= (INTVAL (operands[5]) - 4) << 6;
+ operands[2] = GEN_INT (mask);
+
+ return "pshufhw\t{%2, %1, %0|%0, %1, %2}";
+}
+ [(set_attr "type" "sselog")
+ (set_attr "mode" "TI")])
+
+(define_expand "sse2_loadd"
+ [(set (match_operand:V4SI 0 "register_operand" "")
+ (vec_merge:V4SI
+ (vec_duplicate:V4SI
+ (match_operand:SI 1 "nonimmediate_operand" ""))
+ (match_dup 2)
+ (const_int 1)))]
+ "TARGET_SSE"
+ "operands[2] = CONST0_RTX (V4SImode);")
+
+(define_insn "sse2_loadld"
+ [(set (match_operand:V4SI 0 "register_operand" "=Y,x,x")
+ (vec_merge:V4SI
+ (vec_duplicate:V4SI
+ (match_operand:SI 2 "nonimmediate_operand" "mr,m,x"))
+ (match_operand:V4SI 1 "reg_or_0_operand" " C,C,0")
+ (const_int 1)))]
+ "TARGET_SSE"
+ "@
+ movd\t{%2, %0|%0, %2}
+ movss\t{%2, %0|%0, %2}
+ movss\t{%2, %0|%0, %2}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "TI,V4SF,SF")])
+
+;; ??? The hardware supports more, but TARGET_INTER_UNIT_MOVES must
+;; be taken into account, and movdi isn't fully populated even without.
+(define_insn_and_split "sse2_stored"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=mx")
+ (vec_select:SI
+ (match_operand:V4SI 1 "register_operand" "x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]));
+})
+
+(define_expand "sse_storeq"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (vec_select:DI
+ (match_operand:V2DI 1 "register_operand" "")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE"
+ "")
+
+;; ??? The hardware supports more, but TARGET_INTER_UNIT_MOVES must
+;; be taken into account, and movdi isn't fully populated even without.
+(define_insn "*sse2_storeq"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=mx")
+ (vec_select:DI
+ (match_operand:V2DI 1 "register_operand" "x")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE"
+ "#")
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
+ (vec_select:DI
+ (match_operand:V2DI 1 "register_operand" "")
+ (parallel [(const_int 0)])))]
+ "TARGET_SSE && reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+})
+
+(define_insn "*vec_extractv2di_1_sse2"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:DI
+ (match_operand:V2DI 1 "nonimmediate_operand" "x,0,o")
+ (parallel [(const_int 1)])))]
+ "TARGET_SSE2 && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movhps\t{%1, %0|%0, %1}
+ psrldq\t{$4, %0|%0, 4}
+ movq\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov,sseishft,ssemov")
+ (set_attr "mode" "V2SF,TI,TI")])
+
+;; Not sure this is ever used, but it doesn't hurt to have it. -aoliva
+(define_insn "*vec_extractv2di_1_sse"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=m,x,x")
+ (vec_select:DI
+ (match_operand:V2DI 1 "nonimmediate_operand" "x,x,o")
+ (parallel [(const_int 1)])))]
+ "!TARGET_SSE2 && TARGET_SSE
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ movhps\t{%1, %0|%0, %1}
+ movhlps\t{%1, %0|%0, %1}
+ movlps\t{%H1, %0|%0, %H1}"
+ [(set_attr "type" "ssemov")
+ (set_attr "mode" "V2SF,V4SF,V2SF")])
+
+(define_insn "*vec_dupv4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=Y,x")
+ (vec_duplicate:V4SI
+ (match_operand:SI 1 "register_operand" " Y,0")))]
+ "TARGET_SSE"
+ "@
+ pshufd\t{$0, %1, %0|%0, %1, 0}
+ shufps\t{$0, %0, %0|%0, %0, 0}"
+ [(set_attr "type" "sselog1")
+ (set_attr "mode" "TI,V4SF")])
+
+(define_insn "*vec_dupv2di"
+ [(set (match_operand:V2DI 0 "register_operand" "=Y,x")
+ (vec_duplicate:V2DI
+ (match_operand:DI 1 "register_operand" " 0,0")))]
+ "TARGET_SSE"
+ "@
+ punpcklqdq\t%0, %0
+ movlhps\t%0, %0"
+ [(set_attr "type" "sselog1,ssemov")
+ (set_attr "mode" "TI,V4SF")])
+
+;; ??? In theory we can match memory for the MMX alternative, but allowing
+;; nonimmediate_operand for operand 2 and *not* allowing memory for the SSE
+;; alternatives pretty much forces the MMX alternative to be chosen.
+(define_insn "*sse2_concatv2si"
+ [(set (match_operand:V2SI 0 "register_operand" "=Y, Y,*y,*y")
+ (vec_concat:V2SI
+ (match_operand:SI 1 "nonimmediate_operand" " 0,rm, 0,rm")
+ (match_operand:SI 2 "reg_or_0_operand" " Y, C,*y, C")))]
+ "TARGET_SSE2"
+ "@
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "mode" "TI,TI,DI,DI")])
+
+(define_insn "*sse1_concatv2si"
+ [(set (match_operand:V2SI 0 "register_operand" "=x,x,*y,*y")
+ (vec_concat:V2SI
+ (match_operand:SI 1 "nonimmediate_operand" " 0,m, 0,*rm")
+ (match_operand:SI 2 "reg_or_0_operand" " x,C,*y,C")))]
+ "TARGET_SSE"
+ "@
+ unpcklps\t{%2, %0|%0, %2}
+ movss\t{%1, %0|%0, %1}
+ punpckldq\t{%2, %0|%0, %2}
+ movd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "mode" "V4SF,V4SF,DI,DI")])
+
+(define_insn "*vec_concatv4si_1"
+ [(set (match_operand:V4SI 0 "register_operand" "=Y,x,x")
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "register_operand" " 0,0,0")
+ (match_operand:V2SI 2 "nonimmediate_operand" " Y,x,m")))]
+ "TARGET_SSE"
+ "@
+ punpcklqdq\t{%2, %0|%0, %2}
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "mode" "TI,V4SF,V2SF")])
+
+(define_insn "*vec_concatv2di"
+ [(set (match_operand:V2DI 0 "register_operand" "=Y,?Y,Y,x,x,x")
+ (vec_concat:V2DI
+ (match_operand:DI 1 "nonimmediate_operand" " m,*y,0,0,0,m")
+ (match_operand:DI 2 "vector_move_operand" " C, C,Y,x,m,0")))]
+ "TARGET_SSE"
+ "@
+ movq\t{%1, %0|%0, %1}
+ movq2dq\t{%1, %0|%0, %1}
+ punpcklqdq\t{%2, %0|%0, %2}
+ movlhps\t{%2, %0|%0, %2}
+ movhps\t{%2, %0|%0, %2}
+ movlps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssemov,ssemov,sselog,ssemov,ssemov,ssemov")
+ (set_attr "mode" "TI,TI,TI,V4SF,V2SF,V2SF")])
+
+(define_expand "vec_setv2di"
+ [(match_operand:V2DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv2di"
+ [(match_operand:DI 0 "register_operand" "")
+ (match_operand:V2DI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv2di"
+ [(match_operand:V2DI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv4si"
+ [(match_operand:V4SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv4si"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:V4SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv4si"
+ [(match_operand:V4SI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv8hi"
+ [(match_operand:V8HI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv8hi"
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv8hi"
+ [(match_operand:V8HI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "vec_setv16qi"
+ [(match_operand:V16QI 0 "register_operand" "")
+ (match_operand:QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_set (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv16qi"
+ [(match_operand:QI 0 "register_operand" "")
+ (match_operand:V16QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_extract (false, operands[0], operands[1],
+ INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_initv16qi"
+ [(match_operand:V16QI 0 "register_operand" "")
+ (match_operand 1 "" "")]
+ "TARGET_SSE"
+{
+ ix86_expand_vector_init (false, operands[0], operands[1]);
+ DONE;
+})
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;
+;; Miscellaneous
+;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(define_insn "sse2_uavgv16qi3"
+ [(set (match_operand:V16QI 0 "register_operand" "=x")
+ (truncate:V16QI
+ (lshiftrt:V16HI
+ (plus:V16HI
+ (plus:V16HI
+ (zero_extend:V16HI
+ (match_operand:V16QI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V16HI
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")))
+ (const_vector:V16QI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, V16QImode, operands)"
+ "pavgb\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse2_uavgv8hi3"
+ [(set (match_operand:V8HI 0 "register_operand" "=x")
+ (truncate:V8HI
+ (lshiftrt:V8SI
+ (plus:V8SI
+ (plus:V8SI
+ (zero_extend:V8SI
+ (match_operand:V8HI 1 "nonimmediate_operand" "%0"))
+ (zero_extend:V8SI
+ (match_operand:V8HI 2 "nonimmediate_operand" "xm")))
+ (const_vector:V8HI [(const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)
+ (const_int 1) (const_int 1)]))
+ (const_int 1))))]
+ "TARGET_SSE2 && ix86_binary_operator_ok (PLUS, V8HImode, operands)"
+ "pavgw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+;; The correct representation for this is absolutely enormous, and
+;; surely not generally useful.
+(define_insn "sse2_psadbw"
+ [(set (match_operand:V2DI 0 "register_operand" "=x")
+ (unspec:V2DI [(match_operand:V16QI 1 "register_operand" "0")
+ (match_operand:V16QI 2 "nonimmediate_operand" "xm")]
+ UNSPEC_PSADBW))]
+ "TARGET_SSE2"
+ "psadbw\t{%2, %0|%0, %2}"
+ [(set_attr "type" "sseiadd")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse_movmskps"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V4SF 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE"
+ "movmskps\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V4SF")])
+
+(define_insn "sse2_movmskpd"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V2DF 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2"
+ "movmskpd\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_insn "sse2_pmovmskb"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:V16QI 1 "register_operand" "x")]
+ UNSPEC_MOVMSK))]
+ "TARGET_SSE2"
+ "pmovmskb\t{%1, %0|%0, %1}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "V2DF")])
+
+(define_expand "sse2_maskmovdqu"
+ [(set (match_operand:V16QI 0 "memory_operand" "")
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
+ (match_operand:V16QI 2 "register_operand" "x")
+ (match_dup 0)]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE2"
+ "")
+
+(define_insn "*sse2_maskmovdqu"
+ [(set (mem:V16QI (match_operand:SI 0 "register_operand" "D"))
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
+ (match_operand:V16QI 2 "register_operand" "x")
+ (mem:V16QI (match_dup 0))]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE2 && !TARGET_64BIT"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "*sse2_maskmovdqu_rex64"
+ [(set (mem:V16QI (match_operand:DI 0 "register_operand" "D"))
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "x")
+ (match_operand:V16QI 2 "register_operand" "x")
+ (mem:V16QI (match_dup 0))]
+ UNSPEC_MASKMOV))]
+ "TARGET_SSE2 && TARGET_64BIT"
+ ;; @@@ check ordering of operands in intel/nonintel syntax
+ "maskmovdqu\t{%2, %1|%1, %2}"
+ [(set_attr "type" "ssecvt")
+ (set_attr "mode" "TI")])
+
+(define_insn "sse_ldmxcsr"
+ [(unspec_volatile [(match_operand:SI 0 "memory_operand" "m")]
+ UNSPECV_LDMXCSR)]
+ "TARGET_SSE"
+ "ldmxcsr\t%0"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "load")])
+
+(define_insn "sse_stmxcsr"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec_volatile:SI [(const_int 0)] UNSPECV_STMXCSR))]
+ "TARGET_SSE"
+ "stmxcsr\t%0"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "store")])
+
+(define_expand "sse_sfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sse_sfence"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
+ "TARGET_SSE || TARGET_3DNOW_A"
+ "sfence"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_insn "sse2_clflush"
+ [(unspec_volatile [(match_operand 0 "address_operand" "p")]
+ UNSPECV_CLFLUSH)]
+ "TARGET_SSE2"
+ "clflush\t%a0"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse2_mfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_SSE2"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sse2_mfence"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
+ "TARGET_SSE2"
+ "mfence"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_expand "sse2_lfence"
+ [(set (match_dup 0)
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sse2_lfence"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
+ "TARGET_SSE2"
+ "lfence"
+ [(set_attr "type" "sse")
+ (set_attr "memory" "unknown")])
+
+(define_insn "sse3_mwait"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
+ (match_operand:SI 1 "register_operand" "c")]
+ UNSPECV_MWAIT)]
+ "TARGET_SSE3"
+;; 64bit version is "mwait %rax,%rcx". But only lower 32bits are used.
+;; Since 32bit register operands are implicitly zero extended to 64bit,
+;; we only need to set up 32bit registers.
+ "mwait"
+ [(set_attr "length" "3")])
+
+(define_insn "sse3_monitor"
+ [(unspec_volatile [(match_operand:SI 0 "register_operand" "a")
+ (match_operand:SI 1 "register_operand" "c")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPECV_MONITOR)]
+ "TARGET_SSE3 && !TARGET_64BIT"
+ "monitor\t%0, %1, %2"
+ [(set_attr "length" "3")])
+
+(define_insn "sse3_monitor64"
+ [(unspec_volatile [(match_operand:DI 0 "register_operand" "a")
+ (match_operand:SI 1 "register_operand" "c")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPECV_MONITOR)]
+ "TARGET_SSE3 && TARGET_64BIT"
+;; 64bit version is "monitor %rax,%rcx,%rdx". But only lower 32bits in
+;; RCX and RDX are used. Since 32bit register operands are implicitly
+;; zero extended to 64bit, we only need to set up 32bit registers.
+ "monitor"
+ [(set_attr "length" "3")])
diff --git a/contrib/gcc/config/i386/sync.md b/contrib/gcc/config/i386/sync.md
new file mode 100644
index 0000000..8c2fdb2
--- /dev/null
+++ b/contrib/gcc/config/i386/sync.md
@@ -0,0 +1,291 @@
+;; GCC machine description for i386 synchronization instructions.
+;; Copyright (C) 2005, 2006
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_mode_macro IMODE [QI HI SI (DI "TARGET_64BIT")])
+(define_mode_attr modesuffix [(QI "b") (HI "w") (SI "l") (DI "q")])
+(define_mode_attr modeconstraint [(QI "q") (HI "r") (SI "r") (DI "r")])
+(define_mode_attr immconstraint [(QI "i") (HI "i") (SI "i") (DI "e")])
+
+(define_mode_macro CASMODE [QI HI SI (DI "TARGET_64BIT || TARGET_CMPXCHG8B")
+ (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
+(define_mode_macro DCASMODE
+ [(DI "!TARGET_64BIT && TARGET_CMPXCHG8B && !flag_pic")
+ (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
+(define_mode_attr doublemodesuffix [(DI "8") (TI "16")])
+(define_mode_attr DCASHMODE [(DI "SI") (TI "DI")])
+
+;; ??? It would be possible to use cmpxchg8b on pentium for DImode
+;; changes. It's complicated because the insn uses ecx:ebx as the
+;; new value; note that the registers are reversed from the order
+;; that they'd be in with (reg:DI 2 ecx). Similarly for TImode
+;; data in 64-bit mode.
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(parallel
+ [(set (match_operand:CASMODE 0 "register_operand" "")
+ (match_operand:CASMODE 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:CASMODE
+ [(match_dup 1)
+ (match_operand:CASMODE 2 "register_operand" "")
+ (match_operand:CASMODE 3 "register_operand" "")]
+ UNSPECV_CMPXCHG_1))
+ (clobber (reg:CC FLAGS_REG))])]
+ "TARGET_CMPXCHG"
+{
+ if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode)
+ {
+ enum machine_mode hmode = <MODE>mode == DImode ? SImode : DImode;
+ rtx low = simplify_gen_subreg (hmode, operands[3], <MODE>mode, 0);
+ rtx high = simplify_gen_subreg (hmode, operands[3], <MODE>mode,
+ GET_MODE_SIZE (hmode));
+ low = force_reg (hmode, low);
+ high = force_reg (hmode, high);
+ if (<MODE>mode == DImode)
+ emit_insn (gen_sync_double_compare_and_swapdi
+ (operands[0], operands[1], operands[2], low, high));
+ else if (<MODE>mode == TImode)
+ emit_insn (gen_sync_double_compare_and_swapti
+ (operands[0], operands[1], operands[2], low, high));
+ else
+ gcc_unreachable ();
+ DONE;
+ }
+})
+
+(define_insn "*sync_compare_and_swap<mode>"
+ [(set (match_operand:IMODE 0 "register_operand" "=a")
+ (match_operand:IMODE 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:IMODE
+ [(match_dup 1)
+ (match_operand:IMODE 2 "register_operand" "a")
+ (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
+ UNSPECV_CMPXCHG_1))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_CMPXCHG"
+ "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
+
+(define_insn "sync_double_compare_and_swap<mode>"
+ [(set (match_operand:DCASMODE 0 "register_operand" "=A")
+ (match_operand:DCASMODE 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:DCASMODE
+ [(match_dup 1)
+ (match_operand:DCASMODE 2 "register_operand" "A")
+ (match_operand:<DCASHMODE> 3 "register_operand" "b")
+ (match_operand:<DCASHMODE> 4 "register_operand" "c")]
+ UNSPECV_CMPXCHG_1))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;cmpxchg<doublemodesuffix>b\t%1")
+
+;; Theoretically we'd like to use constraint "r" (any reg) for operand
+;; 3, but that includes ecx. If operand 3 and 4 are the same (like when
+;; the input is -1LL) GCC might chose to allocate operand 3 to ecx, like
+;; operand 4. This breaks, as the xchg will move the PIC register contents
+;; to %ecx then --> boom. Operands 3 and 4 really need to be different
+;; registers, which in this case means operand 3 must not be ecx.
+;; Instead of playing tricks with fake early clobbers or the like we
+;; just enumerate all regs possible here, which (as this is !TARGET_64BIT)
+;; are just esi and edi.
+(define_insn "*sync_double_compare_and_swapdi_pic"
+ [(set (match_operand:DI 0 "register_operand" "=A")
+ (match_operand:DI 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:DI
+ [(match_dup 1)
+ (match_operand:DI 2 "register_operand" "A")
+ (match_operand:SI 3 "register_operand" "SD")
+ (match_operand:SI 4 "register_operand" "c")]
+ UNSPECV_CMPXCHG_1))
+ (clobber (reg:CC FLAGS_REG))]
+ "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic"
+ "xchg{l}\t%%ebx, %3\;lock\;cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3")
+
+(define_expand "sync_compare_and_swap_cc<mode>"
+ [(parallel
+ [(set (match_operand:CASMODE 0 "register_operand" "")
+ (match_operand:CASMODE 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:CASMODE
+ [(match_dup 1)
+ (match_operand:CASMODE 2 "register_operand" "")
+ (match_operand:CASMODE 3 "register_operand" "")]
+ UNSPECV_CMPXCHG_1))
+ (set (match_dup 4)
+ (compare:CCZ
+ (unspec_volatile:CASMODE
+ [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
+ (match_dup 2)))])]
+ "TARGET_CMPXCHG"
+{
+ operands[4] = gen_rtx_REG (CCZmode, FLAGS_REG);
+ ix86_compare_op0 = operands[3];
+ ix86_compare_op1 = NULL;
+ ix86_compare_emitted = operands[4];
+ if ((<MODE>mode == DImode && !TARGET_64BIT) || <MODE>mode == TImode)
+ {
+ enum machine_mode hmode = <MODE>mode == DImode ? SImode : DImode;
+ rtx low = simplify_gen_subreg (hmode, operands[3], <MODE>mode, 0);
+ rtx high = simplify_gen_subreg (hmode, operands[3], <MODE>mode,
+ GET_MODE_SIZE (hmode));
+ low = force_reg (hmode, low);
+ high = force_reg (hmode, high);
+ if (<MODE>mode == DImode)
+ emit_insn (gen_sync_double_compare_and_swap_ccdi
+ (operands[0], operands[1], operands[2], low, high));
+ else if (<MODE>mode == TImode)
+ emit_insn (gen_sync_double_compare_and_swap_ccti
+ (operands[0], operands[1], operands[2], low, high));
+ else
+ gcc_unreachable ();
+ DONE;
+ }
+})
+
+(define_insn "*sync_compare_and_swap_cc<mode>"
+ [(set (match_operand:IMODE 0 "register_operand" "=a")
+ (match_operand:IMODE 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:IMODE
+ [(match_dup 1)
+ (match_operand:IMODE 2 "register_operand" "a")
+ (match_operand:IMODE 3 "register_operand" "<modeconstraint>")]
+ UNSPECV_CMPXCHG_1))
+ (set (reg:CCZ FLAGS_REG)
+ (compare:CCZ
+ (unspec_volatile:IMODE
+ [(match_dup 1) (match_dup 2) (match_dup 3)] UNSPECV_CMPXCHG_2)
+ (match_dup 2)))]
+ "TARGET_CMPXCHG"
+ "lock\;cmpxchg{<modesuffix>}\t{%3, %1|%1, %3}")
+
+(define_insn "sync_double_compare_and_swap_cc<mode>"
+ [(set (match_operand:DCASMODE 0 "register_operand" "=A")
+ (match_operand:DCASMODE 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:DCASMODE
+ [(match_dup 1)
+ (match_operand:DCASMODE 2 "register_operand" "A")
+ (match_operand:<DCASHMODE> 3 "register_operand" "b")
+ (match_operand:<DCASHMODE> 4 "register_operand" "c")]
+ UNSPECV_CMPXCHG_1))
+ (set (reg:CCZ FLAGS_REG)
+ (compare:CCZ
+ (unspec_volatile:DCASMODE
+ [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
+ UNSPECV_CMPXCHG_2)
+ (match_dup 2)))]
+ ""
+ "lock\;cmpxchg<doublemodesuffix>b\t%1")
+
+;; See above for the explanation of using the constraint "SD" for
+;; operand 3.
+(define_insn "*sync_double_compare_and_swap_ccdi_pic"
+ [(set (match_operand:DI 0 "register_operand" "=A")
+ (match_operand:DI 1 "memory_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:DI
+ [(match_dup 1)
+ (match_operand:DI 2 "register_operand" "A")
+ (match_operand:SI 3 "register_operand" "SD")
+ (match_operand:SI 4 "register_operand" "c")]
+ UNSPECV_CMPXCHG_1))
+ (set (reg:CCZ FLAGS_REG)
+ (compare:CCZ
+ (unspec_volatile:DI
+ [(match_dup 1) (match_dup 2) (match_dup 3) (match_dup 4)]
+ UNSPECV_CMPXCHG_2)
+ (match_dup 2)))]
+ "!TARGET_64BIT && TARGET_CMPXCHG8B && flag_pic"
+ "xchg{l}\t%%ebx, %3\;lock\;cmpxchg8b\t%1\;xchg{l}\t%%ebx, %3")
+
+(define_insn "sync_old_add<mode>"
+ [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>")
+ (unspec_volatile:IMODE
+ [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG))
+ (set (match_dup 1)
+ (plus:IMODE (match_dup 1)
+ (match_operand:IMODE 2 "register_operand" "0")))
+ (clobber (reg:CC FLAGS_REG))]
+ "TARGET_XADD"
+ "lock\;xadd{<modesuffix>}\t{%0, %1|%1, %0}")
+
+;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
+(define_insn "sync_lock_test_and_set<mode>"
+ [(set (match_operand:IMODE 0 "register_operand" "=<modeconstraint>")
+ (unspec_volatile:IMODE
+ [(match_operand:IMODE 1 "memory_operand" "+m")] UNSPECV_XCHG))
+ (set (match_dup 1)
+ (match_operand:IMODE 2 "register_operand" "0"))]
+ ""
+ "xchg{<modesuffix>}\t{%1, %0|%0, %1}")
+
+(define_insn "sync_add<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "+m")
+ (unspec_volatile:IMODE
+ [(plus:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
+ UNSPECV_LOCK))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;add{<modesuffix>}\t{%1, %0|%0, %1}")
+
+(define_insn "sync_sub<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "+m")
+ (unspec_volatile:IMODE
+ [(minus:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
+ UNSPECV_LOCK))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;sub{<modesuffix>}\t{%1, %0|%0, %1}")
+
+(define_insn "sync_ior<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "+m")
+ (unspec_volatile:IMODE
+ [(ior:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
+ UNSPECV_LOCK))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;or{<modesuffix>}\t{%1, %0|%0, %1}")
+
+(define_insn "sync_and<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "+m")
+ (unspec_volatile:IMODE
+ [(and:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
+ UNSPECV_LOCK))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;and{<modesuffix>}\t{%1, %0|%0, %1}")
+
+(define_insn "sync_xor<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "+m")
+ (unspec_volatile:IMODE
+ [(xor:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "nonmemory_operand" "<modeconstraint><immconstraint>"))]
+ UNSPECV_LOCK))
+ (clobber (reg:CC FLAGS_REG))]
+ ""
+ "lock\;xor{<modesuffix>}\t{%1, %0|%0, %1}")
diff --git a/contrib/gcc/config/i386/sysv4-cpp.h b/contrib/gcc/config/i386/sysv4-cpp.h
index 6ec751a..c53b1da 100644
--- a/contrib/gcc/config/i386/sysv4-cpp.h
+++ b/contrib/gcc/config/i386/sysv4-cpp.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
diff --git a/contrib/gcc/config/i386/sysv4.h b/contrib/gcc/config/i386/sysv4.h
index 2447006..acbd69e 100644
--- a/contrib/gcc/config/i386/sysv4.h
+++ b/contrib/gcc/config/i386/sysv4.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_VERSION fprintf (stderr, " (i386 System V Release 4)");
diff --git a/contrib/gcc/config/i386/sysv5.h b/contrib/gcc/config/i386/sysv5.h
index c4edd71..34b00c6 100644
--- a/contrib/gcc/config/i386/sysv5.h
+++ b/contrib/gcc/config/i386/sysv5.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Dwarf2 is supported by native debuggers */
diff --git a/contrib/gcc/config/i386/t-crtfm b/contrib/gcc/config/i386/t-crtfm
new file mode 100644
index 0000000..fc4b587
--- /dev/null
+++ b/contrib/gcc/config/i386/t-crtfm
@@ -0,0 +1,6 @@
+EXTRA_PARTS += crtfastmath.o
+
+$(T)crtfastmath.o: $(srcdir)/config/i386/crtfastmath.c $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -msse -c \
+ $(srcdir)/config/i386/crtfastmath.c \
+ -o $(T)crtfastmath$(objext)
diff --git a/contrib/gcc/config/i386/t-cygming b/contrib/gcc/config/i386/t-cygming
index aa6ff61..c001a8b 100644
--- a/contrib/gcc/config/i386/t-cygming
+++ b/contrib/gcc/config/i386/t-cygming
@@ -16,4 +16,17 @@ winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt.c
+winnt-cxx.o: $(srcdir)/config/i386/winnt-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+ $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/winnt-cxx.c
+
+
+winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
+ $(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/winnt-stubs.c
+
STMP_FIXINC=stmp-fixinc
diff --git a/contrib/gcc/config/i386/t-darwin b/contrib/gcc/config/i386/t-darwin
new file mode 100644
index 0000000..e79f335
--- /dev/null
+++ b/contrib/gcc/config/i386/t-darwin
@@ -0,0 +1,5 @@
+SHLIB_VERPFX = $(srcdir)/config/i386/darwin-libgcc
+MULTILIB_OPTIONS = m64
+MULTILIB_DIRNAMES = x86_64
+LIB2_SIDITI_CONV_FUNCS=yes
+LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c
diff --git a/contrib/gcc/config/i386/t-darwin64 b/contrib/gcc/config/i386/t-darwin64
new file mode 100644
index 0000000..e787586
--- /dev/null
+++ b/contrib/gcc/config/i386/t-darwin64
@@ -0,0 +1,3 @@
+SHLIB_VERPFX = $(srcdir)/config/i386/darwin-libgcc
+LIB2_SIDITI_CONV_FUNCS=yes
+LIB2FUNCS_EXTRA = $(srcdir)/config/darwin-64.c
diff --git a/contrib/gcc/config/i386/t-gmm_malloc b/contrib/gcc/config/i386/t-gmm_malloc
new file mode 100644
index 0000000..c37f8a7
--- /dev/null
+++ b/contrib/gcc/config/i386/t-gmm_malloc
@@ -0,0 +1,6 @@
+# Install gmm_malloc.h as mm_malloc.h.
+
+EXTRA_HEADERS += mm_malloc.h
+mm_malloc.h: $(srcdir)/config/i386/gmm_malloc.h
+ rm -f $@
+ cat $^ > $@
diff --git a/contrib/gcc/config/i386/t-gthr-win32 b/contrib/gcc/config/i386/t-gthr-win32
new file mode 100644
index 0000000..204a485
--- /dev/null
+++ b/contrib/gcc/config/i386/t-gthr-win32
@@ -0,0 +1,3 @@
+# We hide calls to w32api needed for w32 thread support here:
+LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
+
diff --git a/contrib/gcc/config/i386/t-linux64 b/contrib/gcc/config/i386/t-linux64
index 3b109d8..aac59a0 100644
--- a/contrib/gcc/config/i386/t-linux64
+++ b/contrib/gcc/config/i386/t-linux64
@@ -11,7 +11,8 @@ MULTILIB_OSDIRNAMES = ../lib64 ../lib
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
-EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \
+ crtbeginT.o crtfastmath.o
# The pushl in CTOR initialization interferes with frame pointer elimination.
# crtend*.o cannot be compiled without -fno-asynchronous-unwind-tables,
diff --git a/contrib/gcc/config/i386/t-mingw32 b/contrib/gcc/config/i386/t-mingw32
index 28096f8..6d043a3 100644
--- a/contrib/gcc/config/i386/t-mingw32
+++ b/contrib/gcc/config/i386/t-mingw32
@@ -1,7 +1,2 @@
-#
-# collect2 doesn't work for i386-mingw32* yet.
-#
-USE_COLLECT2=
-
-# We hide calls to w32api needed for w32 thread support here:
-LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
+# Match SYSTEM_INCLUDE_DIR
+NATIVE_SYSTEM_HEADER_DIR = /mingw/include
diff --git a/contrib/gcc/config/i386/t-nwld b/contrib/gcc/config/i386/t-nwld
new file mode 100644
index 0000000..6f69055
--- /dev/null
+++ b/contrib/gcc/config/i386/t-nwld
@@ -0,0 +1,61 @@
+CRTSTUFF_T_CFLAGS = -mpreferred-stack-boundary=2
+CRT0STUFF_T_CFLAGS = -mpreferred-stack-boundary=2 $(INCLUDES)
+# this is a slight misuse (it's not an assembler file)
+CRT0_S = $(srcdir)/config/i386/netware-crt0.c
+MCRT0_S = $(srcdir)/config/i386/netware-crt0.c
+
+libgcc.def: $(srcdir)/config/i386/t-nwld
+ echo "module libgcc_s" >$@
+
+libc.def: $(srcdir)/config/i386/t-nwld
+ echo "module libc" >$@
+
+libcpre.def: $(srcdir)/config/i386/t-nwld
+ echo "start _LibCPrelude" >$@
+ echo "exit _LibCPostlude" >>$@
+ echo "check _LibCCheckUnload" >>$@
+
+posixpre.def: $(srcdir)/config/i386/t-nwld
+ echo "start POSIX_Start" >$@
+ echo "exit POSIX_Stop" >>$@
+ echo "check POSIX_CheckUnload" >>$@
+
+nwld.o: $(srcdir)/config/i386/nwld.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_P_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/nwld.c
+
+
+s-crt0: $(srcdir)/unwind-dw2-fde.h
+
+# Build a shared libgcc library for NetWare.
+
+SHLIB_EXT = .nlm
+SHLIB_NAME = @shlib_base_name@.nlm
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+SHLIB_DEF = $(srcdir)/config/i386/netware-libgcc.def
+SHLIB_MAP = $(srcdir)/config/i386/netware-libgcc.exp
+SHLIB_SRC = $(srcdir)/config/i386/netware-libgcc.c
+
+SHLIB_LINK = set -e; \
+ cat $(SHLIB_DEF) >@shlib_base_name@.def; \
+ echo "name $(SHLIB_NAME)" >>@shlib_base_name@.def; \
+ echo "version $(version)" | sed "s!\.!,!g" >>@shlib_base_name@.def; \
+ touch libgcc/build; \
+ echo "build $$$$(expr $$$$(<libgcc/build) + 0)" >>@shlib_base_name@.def; \
+ echo "export @$(SHLIB_MAP)" >>@shlib_base_name@.def; \
+ if mpkxdc -n -p @shlib_base_name@.xdc; \
+ then echo "xdcdata @shlib_base_name@.xdc" >>@shlib_base_name@.def; \
+ else echo "WARNING: $(SHLIB_NAME) built without XDC data will not work well." 1>&2; \
+ fi; \
+ $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -o $(SHLIB_NAME) \
+ $(SHLIB_SRC) -posix -static-libgcc -lnetware \
+ -Wl,--Map,--map-info,full,--strip-all,--def-file,@shlib_base_name@.def; \
+ rm -f @shlib_base_name@.imp; $(LN_S) $(SHLIB_MAP) @shlib_base_name@.imp; \
+ rm -f libgcc.imp; $(LN_S) @shlib_base_name@.imp libgcc.imp; \
+ expr $$$$(<libgcc/build) + 1 >libgcc/build
+
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk. We want this delayed until actual install time.
+SHLIB_INSTALL = \
+ $$(SHELL) $(srcdir)/mkinstalldirs $$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+ $$(INSTALL_DATA) $(SHLIB_NAME) $$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_NAME); \
+ $$(INSTALL_DATA) @shlib_base_name@.imp $$(DESTDIR)$$(libsubdir)/
diff --git a/contrib/gcc/config/i386/t-pmm_malloc b/contrib/gcc/config/i386/t-pmm_malloc
new file mode 100644
index 0000000..109009f
--- /dev/null
+++ b/contrib/gcc/config/i386/t-pmm_malloc
@@ -0,0 +1,6 @@
+# Install pmm_malloc.h as mm_malloc.h.
+
+EXTRA_HEADERS += mm_malloc.h
+mm_malloc.h: $(srcdir)/config/i386/pmm_malloc.h
+ rm -f $@
+ cat $^ > $@
diff --git a/contrib/gcc/config/i386/t-rtems-i386 b/contrib/gcc/config/i386/t-rtems-i386
index d32928c..9400be8 100644
--- a/contrib/gcc/config/i386/t-rtems-i386
+++ b/contrib/gcc/config/i386/t-rtems-i386
@@ -36,17 +36,14 @@ xp-bit.c: $(srcdir)/config/fp-bit.c
echo '#define EXTENDED_FLOAT_STUBS' > xp-bit.c
cat $(srcdir)/config/fp-bit.c >> xp-bit.c
-MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro/mtune=k6/mtune=athlon \
-msoft-float mno-fp-ret-in-387
-MULTILIB_DIRNAMES= m486 mpentium mpentiumpro k6 athlon soft-float nofp
+MULTILIB_OPTIONS = mtune=i486/mtune=pentium/mtune=pentiumpro \
+msoft-float
+MULTILIB_DIRNAMES= m486 mpentium mpentiumpro soft-float
MULTILIB_MATCHES = msoft-float=mno-m80387
+MULTILIB_MATCHES += mtune?pentium=mtune?k6 mtune?pentiumpro=mtune?mathlon
MULTILIB_EXCEPTIONS = \
-mno-fp-ret-in-387 \
-mtune=i486/*mno-fp-ret-in-387* \
-mtune=pentium/*msoft-float* mtune=pentium/*mno-fp-ret-in-387* \
-mtune=pentiumpro/*msoft-float* mtune=pentiumpro/*mno-fp-ret-in-387* \
-mtune=k6/*msoft-float* mtune=k6/*mno-fp-ret-in-387* \
-mtune=athlon/*msoft-float* mtune=athlon/*mno-fp-ret-in-387*
+mtune=pentium/*msoft-float* \
+mtune=pentiumpro/*msoft-float*
EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
diff --git a/contrib/gcc/config/i386/t-sol2 b/contrib/gcc/config/i386/t-sol2
index 5d7522c..0eec96f 100644
--- a/contrib/gcc/config/i386/t-sol2
+++ b/contrib/gcc/config/i386/t-sol2
@@ -1,24 +1,24 @@
# gmon build rule:
-gmon.o: $(srcdir)/config/i386/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H)
- $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) \
- -c $(srcdir)/config/i386/gmon-sol2.c -o gmon.o
+$(T)gmon.o: $(srcdir)/config/i386/gmon-sol2.c $(GCC_PASSES) $(CONFIG_H)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+ -c $(srcdir)/config/i386/gmon-sol2.c -o $(T)gmon.o
# Assemble startup files.
# Apparently Sun believes that assembler files don't need comments, because no
# single ASCII character is valid (tried them all). So we manually strip out
# the comments with sed. This bug may only be in the Early Access releases.
-gcrt1.o: $(srcdir)/config/i386/sol2-gc1.asm
+$(T)gcrt1.o: $(srcdir)/config/i386/sol2-gc1.asm $(GCC_PASSES)
sed -e '/^!/d' <$(srcdir)/config/i386/sol2-gc1.asm >gcrt1.s
- $(AS) -o gcrt1.o gcrt1.s
-crt1.o: $(srcdir)/config/i386/sol2-c1.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)gcrt1.o gcrt1.s
+$(T)crt1.o: $(srcdir)/config/i386/sol2-c1.asm $(GCC_PASSES)
sed -e '/^!/d' <$(srcdir)/config/i386/sol2-c1.asm >crt1.s
- $(GCC_FOR_TARGET) -c -o crt1.o crt1.s
-crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crt1.o crt1.s
+$(T)crti.o: $(srcdir)/config/i386/sol2-ci.asm $(GCC_PASSES)
sed -e '/^!/d' <$(srcdir)/config/i386/sol2-ci.asm >crti.s
- $(GCC_FOR_TARGET) -c -o crti.o crti.s
-crtn.o: $(srcdir)/config/i386/sol2-cn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crti.o crti.s
+$(T)crtn.o: $(srcdir)/config/i386/sol2-cn.asm $(GCC_PASSES)
sed -e '/^!/d' <$(srcdir)/config/i386/sol2-cn.asm >crtn.s
- $(GCC_FOR_TARGET) -c -o crtn.o crtn.s
+ $(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) -c -o $(T)crtn.o crtn.s
# We need to use -fPIC when we are using gcc to compile the routines in
# crtstuff.c. This is only really needed when we are going to use gcc/g++
diff --git a/contrib/gcc/config/i386/t-sol2-10 b/contrib/gcc/config/i386/t-sol2-10
new file mode 100644
index 0000000..64e5928
--- /dev/null
+++ b/contrib/gcc/config/i386/t-sol2-10
@@ -0,0 +1,11 @@
+MULTILIB_OPTIONS = m32/m64
+MULTILIB_DIRNAMES = 32 amd64
+MULTILIB_OSDIRNAMES = . amd64
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+# GCC contains i386 assembler sources for some of the startfiles
+# which aren't appropriate for amd64. Just use the installed
+# versions of: crt1.o crti.o crtn.o gcrt1.o
+EXTRA_MULTILIB_PARTS=gmon.o crtbegin.o crtend.o
diff --git a/contrib/gcc/config/i386/t-vxworks b/contrib/gcc/config/i386/t-vxworks
index 6093995..c440b1f 100644
--- a/contrib/gcc/config/i386/t-vxworks
+++ b/contrib/gcc/config/i386/t-vxworks
@@ -1,8 +1,8 @@
# Multilibs for VxWorks.
-#GCC does not have an arch=pentium3 setting, so we cannot build PENTIUM3gnu
-MULTILIB_OPTIONS = \
- march=i486/march=pentium/march=pentiumpro/march=pentium4
-MULTILIB_DIRNAMES = \
- I80486 PENTIUMgnu PENTIUM2gnu PENTIUM4gnu
+# Build multilibs for normal, -mrtp, and -mrtp -fPIC.
+MULTILIB_OPTIONS = mrtp fPIC
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = fPIC=fpic
+MULTILIB_EXCEPTIONS = fPIC
diff --git a/contrib/gcc/config/i386/t-vxworksae b/contrib/gcc/config/i386/t-vxworksae
new file mode 100644
index 0000000..0cea2bb
--- /dev/null
+++ b/contrib/gcc/config/i386/t-vxworksae
@@ -0,0 +1,5 @@
+# Multilibs for VxWorks AE.
+
+MULTILIB_OPTIONS = mvthreads
+MULTILIB_MATCHES =
+MULTILIB_EXCEPTIONS =
diff --git a/contrib/gcc/config/i386/unix.h b/contrib/gcc/config/i386/unix.h
index 102afe0..abb4e05 100644
--- a/contrib/gcc/config/i386/unix.h
+++ b/contrib/gcc/config/i386/unix.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file defines the aspects of assembler syntax
that are the same for all the i386 Unix systems
diff --git a/contrib/gcc/config/i386/uwin.h b/contrib/gcc/config/i386/uwin.h
index d2553c9..38d218e 100644
--- a/contrib/gcc/config/i386/uwin.h
+++ b/contrib/gcc/config/i386/uwin.h
@@ -2,7 +2,7 @@
hosting on U/WIN (Windows32), using GNU tools and the Windows32 API
Library, 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) 1999, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Mumit Khan <khan@xraylith.wisc.edu>.
This file is part of GCC.
@@ -19,8 +19,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Most of this is the same as for Cygwin32, except for changing some
specs. */
@@ -55,9 +55,6 @@ Boston, MA 02111-1307, USA. */
#define LIB_SPEC \
"%{pg:-lgmon} %{mwindows:-luser32 -lgdi32 -lcomdlg32} -lkernel32 -ladvapi32"
-/* This is needed in g77spec.c for now. Will be removed in the future. */
-#define WIN32_UWIN_TARGET 1
-
/* Include in the mingw32 libraries with libgcc */
#undef LIBGCC_SPEC
#define LIBGCC_SPEC "-lgnuwin -lposix -lgcc -last -lmoldname -lmsvcrt"
diff --git a/contrib/gcc/config/i386/vxworks.h b/contrib/gcc/config/i386/vxworks.h
index 5ded098..dd4164e 100644
--- a/contrib/gcc/config/i386/vxworks.h
+++ b/contrib/gcc/config/i386/vxworks.h
@@ -1,5 +1,6 @@
-/* Definitions of target machine for GCC. VxWorks i586 version.
- Copyright (C) 2003 Free Software Foundation, Inc.
+/* IA32 VxWorks target definitions for GNU compiler.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+ Updated by CodeSourcery, LLC.
This file is part of GCC.
@@ -15,60 +16,70 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define HANDLE_SYSV_PRAGMA 1
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (80586, VxWorks syntax)");
-/* Prefix for internally generated assembler labels. If we aren't using
- underscores, we are using prefix `.'s to identify labels that should
- be ignored, as in `i386/gas.h' --karl@cs.umb.edu */
-
-#define LPREFIX "L"
-
-/* Assembler pseudos to introduce constants of various size. */
-
-#define ASM_SHORT "\t.word\t"
-#define ASM_LONG "\t.long\t"
-#define ASM_QUAD "\t.quad\t" /* Should not be used for 32bit compilation. */
-
-
-#define ASM_OUTPUT_ALIGN(FILE,LOG) \
- if ((LOG)!=0) fprintf ((FILE), "\t.balign %d\n", 1<<(LOG))
-
#undef ASM_SPEC
-#define ASM_SPEC "%{v:-V} %{Qy:} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("__vxworks"); \
- builtin_assert ("system=unix"); \
- \
- if (TARGET_386) \
- builtin_define ("CPU=I80386"); \
- else if (TARGET_486) \
- builtin_define ("CPU=I80486"); \
- else if (TARGET_PENTIUM) \
- { \
- builtin_define ("CPU=PENTIUM"); \
- builtin_define ("CPU_VARIANT=PENTIUM"); \
- } \
- else if (TARGET_PENTIUMPRO) \
- { \
- builtin_define ("CPU=PENTIUM2"); \
- builtin_define ("CPU_VARIANT=PENTIUMPRO"); \
- } \
- else if (TARGET_PENTIUM4) \
- { \
- builtin_define ("CPU=PENTIUM4"); \
- builtin_define ("CPU_VARIANT=PENTIUM4"); \
- } \
- } \
+#define ASM_SPEC "%{v:-v} %{Qy:} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*}"
+
+#define VXWORKS_CPU_DEFINE() \
+ do \
+ { \
+ if (TARGET_386) \
+ builtin_define ("CPU=I80386"); \
+ else if (TARGET_486) \
+ builtin_define ("CPU=I80486"); \
+ else if (TARGET_PENTIUM) \
+ { \
+ builtin_define ("CPU=PENTIUM"); \
+ builtin_define ("CPU_VARIANT=PENTIUM"); \
+ } \
+ else if (TARGET_PENTIUMPRO) \
+ { \
+ builtin_define ("CPU=PENTIUM2"); \
+ builtin_define ("CPU_VARIANT=PENTIUMPRO"); \
+ } \
+ else if (TARGET_PENTIUM4) \
+ { \
+ builtin_define ("CPU=PENTIUM4"); \
+ builtin_define ("CPU_VARIANT=PENTIUM4"); \
+ } \
+ } \
while (0)
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_define ("__VXWORKS__"); \
+ builtin_assert ("system=unix"); \
+ \
+ VXWORKS_CPU_DEFINE(); \
+ } \
+ while (0)
+#undef CPP_SPEC
+#define CPP_SPEC VXWORKS_ADDITIONAL_CPP_SPEC
+#undef LIB_SPEC
+#define LIB_SPEC VXWORKS_LIB_SPEC
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC
+#undef LINK_SPEC
+#define LINK_SPEC VXWORKS_LINK_SPEC
+
+#undef SUBTARGET_SWITCHES
+#define SUBTARGET_SWITCHES EXTRA_SUBTARGET_SWITCHES
+
+#undef SUBTARGET_OVERRIDE_OPTIONS
+#define SUBTARGET_OVERRIDE_OPTIONS VXWORKS_OVERRIDE_OPTIONS
+
+/* No _mcount profiling on VxWorks. */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE,LABELNO) VXWORKS_FUNCTION_PROFILER(FILE,LABELNO)
diff --git a/contrib/gcc/config/i386/vxworksae.h b/contrib/gcc/config/i386/vxworksae.h
new file mode 100644
index 0000000..0fd80c4
--- /dev/null
+++ b/contrib/gcc/config/i386/vxworksae.h
@@ -0,0 +1,27 @@
+/* IA32 VxWorks AE target definitions for GNU compiler.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* On VxWorks AE, we only want SIMNT. */
+#undef VXWORKS_CPU_DEFINE
+#define VXWORKS_CPU_DEFINE() \
+ do \
+ builtin_define ("CPU=SIMNT"); \
+ while (0)
diff --git a/contrib/gcc/config/i386/winnt-cxx.c b/contrib/gcc/config/i386/winnt-cxx.c
new file mode 100755
index 0000000..6123ebb
--- /dev/null
+++ b/contrib/gcc/config/i386/winnt-cxx.c
@@ -0,0 +1,167 @@
+/* Target support for C++ classes on Windows.
+ Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+ Copyright (C) 2005
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "cp/cp-tree.h" /* this is why we're a separate module */
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "hashtab.h"
+
+bool
+i386_pe_type_dllimport_p (tree decl)
+{
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL);
+
+ if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+
+ /* We ignore the dllimport attribute for inline member functions.
+ This differs from MSVC behavior which treats it like GNUC
+ 'extern inline' extension. Also ignore for template
+ instantiations with linkonce semantics and artificial methods. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && (DECL_DECLARED_INLINE_P (decl)
+ || DECL_TEMPLATE_INSTANTIATION (decl)
+ || DECL_ARTIFICIAL (decl)))
+ return false;
+
+ /* Since we can't treat a pointer to a dllimport'd symbol as a
+ constant address, we turn off the attribute on C++ virtual
+ methods to allow creation of vtables using thunks. */
+ else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
+ && DECL_VIRTUAL_P (decl))
+ {
+ /* Even though we ignore the attribute from the start, warn if we later see
+ an out-of class definition, as we do for other member functions in
+ tree.c:merge_dllimport_decl_attributes. If this is the key method, the
+ definition may affect the import-export status of vtables, depending
+ on how we handle MULTIPLE_SYMBOL_SPACES in cp/decl2.c. */
+ if (DECL_INITIAL (decl))
+ {
+ warning (OPT_Wattributes, "%q+D redeclared without dllimport attribute: "
+ "previous dllimport ignored", decl);
+#ifdef PE_DLL_DEBUG
+ if (decl == CLASSTYPE_KEY_METHOD (DECL_CONTEXT (decl)))
+ warning (OPT_Wattributes, "key method %q+D of dllimport'd class defined"
+ decl);
+#endif
+ }
+ return false;
+ }
+
+ /* Don't mark defined functions as dllimport. This code will only be
+ reached if we see a non-inline function defined out-of-class. */
+ else if (TREE_CODE (decl) == FUNCTION_DECL
+ && (DECL_INITIAL (decl)))
+ return false;
+
+ /* Don't allow definitions of static data members in dllimport class,
+ If vtable data is marked as DECL_EXTERNAL, import it; otherwise just
+ ignore the class attribute. */
+ else if (TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl) && TREE_PUBLIC (decl)
+ && !DECL_EXTERNAL (decl))
+ {
+ if (!DECL_VIRTUAL_P (decl))
+ error ("definition of static data member %q+D of "
+ "dllimport'd class", decl);
+ return false;
+ }
+
+ return true;
+}
+
+
+bool
+i386_pe_type_dllexport_p (tree decl)
+{
+ gcc_assert (TREE_CODE (decl) == VAR_DECL
+ || TREE_CODE (decl) == FUNCTION_DECL);
+ /* Avoid exporting compiler-generated default dtors and copy ctors.
+ The only artificial methods that need to be exported are virtual
+ and non-virtual thunks. */
+ if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
+ && DECL_ARTIFICIAL (decl) && !DECL_THUNK_P (decl))
+ return false;
+ return true;
+}
+
+static inline void maybe_add_dllimport (tree decl)
+{
+ if (i386_pe_type_dllimport_p (decl))
+ DECL_DLLIMPORT_P (decl) = 1;
+}
+
+void
+i386_pe_adjust_class_at_definition (tree t)
+{
+ tree member;
+
+ gcc_assert (CLASS_TYPE_P (t));
+
+ /* We only look at dllimport. The only thing that dllexport does is
+ add stuff to a '.drectiv' section at end-of-file, so no need to do
+ anything for dllexport'd classes until we generate RTL. */
+ if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (t)) == NULL_TREE)
+ return;
+
+ /* We don't actually add the attribute to the decl, just set the flag
+ that signals that the address of this symbol is not a compile-time
+ constant. Any subsequent out-of-class declaration of members wil
+ cause the DECL_DLLIMPORT_P flag to be unset.
+ (See tree.c: merge_dllimport_decl_attributes).
+ That is just right since out-of class declarations can only be a
+ definition. We recheck the class members at RTL generation to
+ emit warnings if this has happened. Definition of static data member
+ of dllimport'd class always causes an error (as per MS compiler).
+ */
+
+ /* Check static VAR_DECL's. */
+ for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))
+ if (TREE_CODE (member) == VAR_DECL)
+ maybe_add_dllimport (member);
+
+ /* Check FUNCTION_DECL's. */
+ for (member = TYPE_METHODS (t); member; member = TREE_CHAIN (member))
+ if (TREE_CODE (member) == FUNCTION_DECL)
+ maybe_add_dllimport (member);
+
+ /* Check vtables */
+ for (member = CLASSTYPE_VTABLES (t); member; member = TREE_CHAIN (member))
+ if (TREE_CODE (member) == VAR_DECL)
+ maybe_add_dllimport (member);
+
+/* We leave typeinfo tables alone. We can't mark TI objects as
+ dllimport, since the address of a secondary VTT may be needed
+ for static initialization of a primary VTT. VTT's of
+ dllimport'd classes should always be link-once COMDAT. */
+}
diff --git a/contrib/gcc/config/i386/winnt-stubs.c b/contrib/gcc/config/i386/winnt-stubs.c
new file mode 100755
index 0000000..c196f75
--- /dev/null
+++ b/contrib/gcc/config/i386/winnt-stubs.c
@@ -0,0 +1,53 @@
+/* Dummy subroutines for language-specific support on Windows.
+ Contributed by Danny Smith (dannysmith@users.sourceforge.net)
+ Copyright (C) 2005
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "output.h"
+#include "tree.h"
+#include "flags.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "hashtab.h"
+
+bool
+i386_pe_type_dllimport_p (tree decl ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+
+bool
+i386_pe_type_dllexport_p (tree decl ATTRIBUTE_UNUSED)
+{
+ return false;
+}
+
+
+void
+i386_pe_adjust_class_at_definition (tree t ATTRIBUTE_UNUSED)
+{ }
diff --git a/contrib/gcc/config/i386/winnt.c b/contrib/gcc/config/i386/winnt.c
index f8621b4..a46fc5b 100644
--- a/contrib/gcc/config/i386/winnt.c
+++ b/contrib/gcc/config/i386/winnt.c
@@ -1,7 +1,7 @@
/* Subroutines for insn-output.c for Windows NT.
Contributed by Douglas Rupp (drupp@cs.washington.edu)
- Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
- Free Software Foundation, Inc.
+ Copyright (C) 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -47,10 +47,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
*/
static tree associated_type (tree);
-static const char * gen_stdcall_suffix (tree);
-static const char * gen_fastcall_suffix (tree);
-static int i386_pe_dllexport_p (tree);
-static int i386_pe_dllimport_p (tree);
+static tree gen_stdcall_or_fastcall_suffix (tree, bool);
+static bool i386_pe_dllexport_p (tree);
+static bool i386_pe_dllimport_p (tree);
static void i386_pe_mark_dllexport (tree);
static void i386_pe_mark_dllimport (tree);
@@ -63,96 +62,45 @@ static void i386_pe_mark_dllimport (tree);
#define DLL_EXPORT_PREFIX "#e."
#endif
-/* Handle a "dllimport" or "dllexport" attribute;
+/* Handle a "shared" attribute;
arguments as in struct attribute_spec.handler. */
tree
-ix86_handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
- bool *no_add_attrs)
+ix86_handle_shared_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
{
- tree node = *pnode;
-
- /* These attributes may apply to structure and union types being created,
- but otherwise should pass to the declaration involved. */
- if (!DECL_P (node))
- {
- if (flags & ((int) ATTR_FLAG_DECL_NEXT | (int) ATTR_FLAG_FUNCTION_NEXT
- | (int) ATTR_FLAG_ARRAY_NEXT))
- {
- *no_add_attrs = true;
- return tree_cons (name, args, NULL_TREE);
- }
- if (TREE_CODE (node) != RECORD_TYPE && TREE_CODE (node) != UNION_TYPE)
- {
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- *no_add_attrs = true;
- }
-
- return NULL_TREE;
- }
-
- /* Report error on dllimport ambiguities seen now before they cause
- any damage. */
- else if (is_attribute_p ("dllimport", name))
- {
- /* Like MS, treat definition of dllimported variables and
- non-inlined functions on declaration as syntax errors.
- We allow the attribute for function definitions if declared
- inline, but just ignore it in i386_pe_dllimport_p. */
- if (TREE_CODE (node) == FUNCTION_DECL && DECL_INITIAL (node)
- && !DECL_INLINE (node))
- {
- error ("%Jfunction `%D' definition is marked dllimport.", node, node);
- *no_add_attrs = true;
- }
-
- else if (TREE_CODE (node) == VAR_DECL)
- {
- if (DECL_INITIAL (node))
- {
- error ("%Jvariable `%D' definition is marked dllimport.",
- node, node);
- *no_add_attrs = true;
- }
-
- /* `extern' needn't be specified with dllimport.
- Specify `extern' now and hope for the best. Sigh. */
- DECL_EXTERNAL (node) = 1;
- /* Also, implicitly give dllimport'd variables declared within
- a function global scope, unless declared static. */
- if (current_function_decl != NULL_TREE && !TREE_STATIC (node))
- TREE_PUBLIC (node) = 1;
- }
- }
-
- /* Report error if symbol is not accessible at global scope. */
- if (!TREE_PUBLIC (node)
- && (TREE_CODE (node) == VAR_DECL
- || TREE_CODE (node) == FUNCTION_DECL))
+ if (TREE_CODE (*node) != VAR_DECL)
{
- error ("%Jexternal linkage required for symbol '%D' because of "
- "'%s' attribute.", node, node, IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute only applies to variables",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return NULL_TREE;
}
-/* Handle a "shared" attribute;
+/* Handle a "selectany" attribute;
arguments as in struct attribute_spec.handler. */
tree
-ix86_handle_shared_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ix86_handle_selectany_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
+ bool *no_add_attrs)
{
- if (TREE_CODE (*node) != VAR_DECL)
- {
- warning ("`%s' attribute only applies to variables",
- IDENTIFIER_POINTER (name));
+ /* The attribute applies only to objects that are initialized and have
+ external linkage. However, we may not know about initialization
+ until the language frontend has processed the decl. We'll check for
+ initialization later in encode_section_info. */
+ if (TREE_CODE (*node) != VAR_DECL || !TREE_PUBLIC (*node))
+ {
+ error ("%qs attribute applies only to initialized variables"
+ " with external linkage", IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
return NULL_TREE;
}
+
/* Return the type that we should use to determine if DECL is
imported or exported. */
@@ -160,132 +108,73 @@ ix86_handle_shared_attribute (tree *node, tree name,
static tree
associated_type (tree decl)
{
- tree t = NULL_TREE;
-
- /* In the C++ frontend, DECL_CONTEXT for a method doesn't actually refer
- to the containing class. So we look at the 'this' arg. */
- if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
- {
- /* Artificial methods are not affected by the import/export status
- of their class unless they are COMDAT. Implicit copy ctor's and
- dtor's are not affected by class status but virtual and
- non-virtual thunks are. */
- if (!DECL_ARTIFICIAL (decl) || DECL_COMDAT (decl))
- t = TYPE_MAIN_VARIANT
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
- }
- else if (DECL_CONTEXT (decl)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (decl))) == 't')
- t = DECL_CONTEXT (decl);
-
- return t;
+ return (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl)))
+ ? DECL_CONTEXT (decl) : NULL_TREE;
}
-/* Return nonzero if DECL is a dllexport'd object. */
-static int
+/* Return true if DECL is a dllexport'd object. */
+
+static bool
i386_pe_dllexport_p (tree decl)
{
- tree exp;
-
if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return 0;
- exp = lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl));
- if (exp)
- return 1;
-
- /* Class members get the dllexport status of their class. */
- if (associated_type (decl))
- {
- exp = lookup_attribute ("dllexport",
- TYPE_ATTRIBUTES (associated_type (decl)));
- if (exp)
- return 1;
- }
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
- return 0;
-}
+ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ return true;
+
+ /* Also mark class members of exported classes with dllexport. */
+ if (associated_type (decl)
+ && lookup_attribute ("dllexport",
+ TYPE_ATTRIBUTES (associated_type (decl))))
+ return i386_pe_type_dllexport_p (decl);
-/* Return nonzero if DECL is a dllimport'd object. */
+ return false;
+}
-static int
+static bool
i386_pe_dllimport_p (tree decl)
{
- tree imp;
- int context_imp = 0;
-
- if (TREE_CODE (decl) == FUNCTION_DECL
- && TARGET_NOP_FUN_DLLIMPORT)
- return 0;
-
if (TREE_CODE (decl) != VAR_DECL
- && TREE_CODE (decl) != FUNCTION_DECL)
- return 0;
+ && TREE_CODE (decl) != FUNCTION_DECL)
+ return false;
- imp = lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl));
-
- /* Class members get the dllimport status of their class. */
- if (!imp && associated_type (decl))
- {
- imp = lookup_attribute ("dllimport",
- TYPE_ATTRIBUTES (associated_type (decl)));
- if (imp)
- context_imp = 1;
- }
-
- if (imp)
+ /* Lookup the attribute in addition to checking the DECL_DLLIMPORT_P flag.
+ We may need to override an earlier decision. */
+ if (DECL_DLLIMPORT_P (decl)
+ && lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)))
{
- /* Don't mark defined functions as dllimport. If the definition
- itself was marked with dllimport, than ix86_handle_dll_attribute
- reports an error. This handles the case when the definition
- overrides an earlier declaration. */
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)
- && !DECL_INLINE (decl))
+ /* Make a final check to see if this is a definition before we generate
+ RTL for an indirect reference. */
+ if (!DECL_EXTERNAL (decl))
{
- /* Don't warn about artificial methods. */
- if (!DECL_ARTIFICIAL (decl))
- warning ("%Jfunction '%D' is defined after prior declaration "
- "as dllimport: attribute ignored", decl, decl);
- return 0;
- }
-
- /* We ignore the dllimport attribute for inline member functions.
- This differs from MSVC behavior which treats it like GNUC
- 'extern inline' extension. */
- else if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))
- {
- if (extra_warnings)
- warning ("%Jinline function '%D' is declared as dllimport: "
- "attribute ignored.", decl, decl);
- return 0;
- }
-
- /* Don't allow definitions of static data members in dllimport class,
- Just ignore attribute for vtable data. */
- else if (TREE_CODE (decl) == VAR_DECL
- && TREE_STATIC (decl) && TREE_PUBLIC (decl)
- && !DECL_EXTERNAL (decl) && context_imp)
- {
- if (!DECL_VIRTUAL_P (decl))
- error ("%Jdefinition of static data member '%D' of "
- "dllimport'd class.", decl, decl);
- return 0;
- }
-
- /* Since we can't treat a pointer to a dllimport'd symbol as a
- constant address, we turn off the attribute on C++ virtual
- methods to allow creation of vtables using thunks. Don't mark
- artificial methods either (in associated_type, only COMDAT
- artificial method get import status from class context). */
- else if (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE
- && (DECL_VIRTUAL_P (decl) || DECL_ARTIFICIAL (decl)))
- return 0;
-
- return 1;
+ error ("%q+D: definition is marked as dllimport", decl);
+ DECL_DLLIMPORT_P (decl) = 0;
+ return false;
+ }
+ return true;
}
+ /* The DECL_DLLIMPORT_P flag was set for decls in the class definition
+ by targetm.cxx.adjust_class_at_definition. Check again to emit
+ warnings if the class attribute has been overridden by an
+ out-of-class definition. */
+ else if (associated_type (decl)
+ && lookup_attribute ("dllimport",
+ TYPE_ATTRIBUTES (associated_type (decl))))
+ return i386_pe_type_dllimport_p (decl);
+
+ return false;
+}
- return 0;
+/* Handle the -mno-fun-dllimport target switch. */
+bool
+i386_pe_valid_dllimport_attribute_p (tree decl)
+{
+ if (TARGET_NOP_FUN_DLLIMPORT && TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+ return true;
}
/* Return nonzero if SYMBOL is marked as being dllexport'd. */
@@ -307,7 +196,7 @@ i386_pe_dllimport_name_p (const char *symbol)
}
/* Mark a DECL as being dllexport'd.
- Note that we override the previous setting (eg: dllimport). */
+ Note that we override the previous setting (e.g.: dllimport). */
static void
i386_pe_mark_dllexport (tree decl)
@@ -315,23 +204,20 @@ i386_pe_mark_dllexport (tree decl)
const char *oldname;
char *newname;
rtx rtlname;
+ rtx symref;
tree idp;
rtlname = XEXP (DECL_RTL (decl), 0);
- if (GET_CODE (rtlname) == SYMBOL_REF)
- oldname = XSTR (rtlname, 0);
- else if (GET_CODE (rtlname) == MEM
- && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
- oldname = XSTR (XEXP (rtlname, 0), 0);
- else
- abort ();
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
if (i386_pe_dllimport_name_p (oldname))
{
- warning ("%Jinconsistent dll linkage for '%D', dllexport assumed.",
- decl, decl);
+ warning (0, "inconsistent dll linkage for %q+D, dllexport assumed",
+ decl);
/* Remove DLL_IMPORT_PREFIX. */
oldname += strlen (DLL_IMPORT_PREFIX);
- DECL_NON_ADDR_CONST_P (decl) = 0;
}
else if (i386_pe_dllexport_name_p (oldname))
return; /* already done */
@@ -345,8 +231,9 @@ i386_pe_mark_dllexport (tree decl)
identical. */
idp = get_identifier (newname);
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
+ symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+ SET_SYMBOL_REF_DECL (symref, decl);
+ XEXP (DECL_RTL (decl), 0) = symref;
}
/* Mark a DECL as being dllimport'd. */
@@ -358,30 +245,25 @@ i386_pe_mark_dllimport (tree decl)
char *newname;
tree idp;
rtx rtlname, newrtl;
+ rtx symref;
rtlname = XEXP (DECL_RTL (decl), 0);
- if (GET_CODE (rtlname) == SYMBOL_REF)
- oldname = XSTR (rtlname, 0);
- else if (GET_CODE (rtlname) == MEM
- && GET_CODE (XEXP (rtlname, 0)) == SYMBOL_REF)
- oldname = XSTR (XEXP (rtlname, 0), 0);
- else
- abort ();
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ gcc_assert (GET_CODE (rtlname) == SYMBOL_REF);
+ oldname = XSTR (rtlname, 0);
if (i386_pe_dllexport_name_p (oldname))
{
- error ("`%s' declared as both exported to and imported from a DLL",
+ error ("%qs declared as both exported to and imported from a DLL",
IDENTIFIER_POINTER (DECL_NAME (decl)));
return;
}
else if (i386_pe_dllimport_name_p (oldname))
{
- /* Already done, but do a sanity check to prevent assembler errors. */
- if (!DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
- {
- error ("%Jfailure in redeclaration of '%D': dllimport'd "
- "symbol lacks external linkage.", decl, decl);
- abort();
- }
+ /* Already done, but do a sanity check to prevent assembler
+ errors. */
+ gcc_assert (DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
+ && DECL_DLLIMPORT_P (decl));
return;
}
@@ -394,93 +276,65 @@ i386_pe_mark_dllimport (tree decl)
identical. */
idp = get_identifier (newname);
- newrtl = gen_rtx (MEM, Pmode,
- gen_rtx (SYMBOL_REF, Pmode,
- IDENTIFIER_POINTER (idp)));
+ symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
+ SET_SYMBOL_REF_DECL (symref, decl);
+ newrtl = gen_rtx_MEM (Pmode,symref);
XEXP (DECL_RTL (decl), 0) = newrtl;
- /* Can't treat a pointer to this as a constant address */
- DECL_NON_ADDR_CONST_P (decl) = 1;
-}
-
-/* Return string which is the former assembler name modified with a
- prefix consisting of FASTCALL_PREFIX and a suffix consisting of an
- atsign (@) followed by the number of bytes of arguments. */
-
-static const char *
-gen_fastcall_suffix (tree decl)
-{
- int total = 0;
- const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- char *newsym;
-
- if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
- if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
- == void_type_node)
- {
- tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
-
- /* Quit if we hit an incomplete type. Error is reported
- by convert_arguments in c-typeck.c or cp/typeck.c. */
- while (TREE_VALUE (formal_type) != void_type_node
- && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
- {
- int parm_size
- = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
- /* Must round up to include padding. This is done the same
- way as in store_one_arg. */
- parm_size = ((parm_size + PARM_BOUNDARY - 1)
- / PARM_BOUNDARY * PARM_BOUNDARY);
- total += parm_size;
- formal_type = TREE_CHAIN (formal_type);
- }
- }
-
- /* Assume max of 8 base 10 digits in the suffix. */
- newsym = xmalloc (1 + strlen (asmname) + 1 + 8 + 1);
- sprintf (newsym, "%c%s@%d", FASTCALL_PREFIX, asmname, total/BITS_PER_UNIT);
- return IDENTIFIER_POINTER (get_identifier (newsym));
+ DECL_DLLIMPORT_P (decl) = 1;
}
/* Return string which is the former assembler name modified with a
suffix consisting of an atsign (@) followed by the number of bytes of
- arguments */
+ arguments. If FASTCALL is true, also add the FASTCALL_PREFIX. */
-static const char *
-gen_stdcall_suffix (tree decl)
+static tree
+gen_stdcall_or_fastcall_suffix (tree decl, bool fastcall)
{
int total = 0;
/* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
of DECL_ASSEMBLER_NAME. */
- const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+ const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
char *newsym;
+ char *p;
+ tree formal_type;
+
+ /* Do not change the identifier if a verbatim asmspec or already done. */
+ if (*asmname == '*' || strchr (asmname, '@'))
+ return DECL_ASSEMBLER_NAME (decl);
- if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
- if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
- == void_type_node)
- {
- tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
-
- /* Quit if we hit an incomplete type. Error is reported
- by convert_arguments in c-typeck.c or cp/typeck.c. */
- while (TREE_VALUE (formal_type) != void_type_node
- && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
- {
- int parm_size
- = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+ formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
+ if (formal_type != NULL_TREE)
+ {
+ /* These attributes are ignored for variadic functions in
+ i386.c:ix86_return_pops_args. For compatibility with MS
+ compiler do not add @0 suffix here. */
+ if (TREE_VALUE (tree_last (formal_type)) != void_type_node)
+ return DECL_ASSEMBLER_NAME (decl);
+
+ /* Quit if we hit an incomplete type. Error is reported
+ by convert_arguments in c-typeck.c or cp/typeck.c. */
+ while (TREE_VALUE (formal_type) != void_type_node
+ && COMPLETE_TYPE_P (TREE_VALUE (formal_type)))
+ {
+ int parm_size
+ = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
/* Must round up to include padding. This is done the same
way as in store_one_arg. */
- parm_size = ((parm_size + PARM_BOUNDARY - 1)
- / PARM_BOUNDARY * PARM_BOUNDARY);
- total += parm_size;
- formal_type = TREE_CHAIN (formal_type);
- }
- }
+ parm_size = ((parm_size + PARM_BOUNDARY - 1)
+ / PARM_BOUNDARY * PARM_BOUNDARY);
+ total += parm_size;
+ formal_type = TREE_CHAIN (formal_type);\
+ }
+ }
/* Assume max of 8 base 10 digits in the suffix. */
- newsym = xmalloc (strlen (asmname) + 1 + 8 + 1);
- sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
- return IDENTIFIER_POINTER (get_identifier (newsym));
+ newsym = alloca (1 + strlen (asmname) + 1 + 8 + 1);
+ p = newsym;
+ if (fastcall)
+ *p++ = FASTCALL_PREFIX;
+ sprintf (p, "%s@%d", asmname, total/BITS_PER_UNIT);
+ return get_identifier (newsym);
}
void
@@ -488,58 +342,65 @@ i386_pe_encode_section_info (tree decl, rtx rtl, int first)
{
default_encode_section_info (decl, rtl, first);
- if (TREE_CODE (decl) == FUNCTION_DECL)
+ if (first && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ tree type_attributes = TYPE_ATTRIBUTES (TREE_TYPE (decl));
+ tree newid = NULL_TREE;
+
+ if (lookup_attribute ("stdcall", type_attributes))
+ newid = gen_stdcall_or_fastcall_suffix (decl, false);
+ else if (lookup_attribute ("fastcall", type_attributes))
+ newid = gen_stdcall_or_fastcall_suffix (decl, true);
+ if (newid != NULL_TREE)
+ {
+ rtx rtlname = XEXP (rtl, 0);
+ if (GET_CODE (rtlname) == MEM)
+ rtlname = XEXP (rtlname, 0);
+ XSTR (rtlname, 0) = IDENTIFIER_POINTER (newid);
+ /* These attributes must be present on first declaration,
+ change_decl_assembler_name will warn if they are added
+ later and the decl has been referenced, but duplicate_decls
+ should catch the mismatch before this is called. */
+ change_decl_assembler_name (decl, newid);
+ }
+ }
+
+ else if (TREE_CODE (decl) == VAR_DECL
+ && lookup_attribute ("selectany", DECL_ATTRIBUTES (decl)))
{
- if (lookup_attribute ("stdcall",
- TYPE_ATTRIBUTES (TREE_TYPE (decl))))
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
- else if (lookup_attribute ("fastcall",
- TYPE_ATTRIBUTES (TREE_TYPE (decl))))
- XEXP (DECL_RTL (decl), 0) =
- gen_rtx (SYMBOL_REF, Pmode, gen_fastcall_suffix (decl));
+ if (DECL_INITIAL (decl)
+ /* If an object is initialized with a ctor, the static
+ initialization and destruction code for it is present in
+ each unit defining the object. The code that calls the
+ ctor is protected by a link-once guard variable, so that
+ the object still has link-once semantics, */
+ || TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
+ make_decl_one_only (decl);
+ else
+ error ("%q+D:'selectany' attribute applies only to initialized objects",
+ decl);
}
/* Mark the decl so we can tell from the rtl whether the object is
- dllexport'd or dllimport'd. This also handles dllexport/dllimport
- override semantics. */
+ dllexport'd or dllimport'd. tree.c: merge_dllimport_decl_attributes
+ handles dllexport/dllimport override semantics. */
if (i386_pe_dllexport_p (decl))
i386_pe_mark_dllexport (decl);
else if (i386_pe_dllimport_p (decl))
i386_pe_mark_dllimport (decl);
- /* It might be that DECL has already been marked as dllimport, but a
- subsequent definition nullified that. The attribute is gone but
- DECL_RTL still has (DLL_IMPORT_PREFIX) prefixed. We need to remove
- that. Ditto for the DECL_NON_ADDR_CONST_P flag. */
- else if ((TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == VAR_DECL)
- && DECL_RTL (decl) != NULL_RTX
- && GET_CODE (DECL_RTL (decl)) == MEM
- && GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM
- && 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)))
- {
- const char *oldname = XSTR (XEXP (XEXP (DECL_RTL (decl), 0), 0), 0);
-
- /* Remove DLL_IMPORT_PREFIX. */
- tree idp = get_identifier (oldname + strlen (DLL_IMPORT_PREFIX));
- rtx newrtl = gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (idp));
-
- if (DECL_INITIAL (decl) || !DECL_EXTERNAL (decl))
- warning ("%J'%D' defined locally after being "
- "referenced with dllimport linkage", decl, decl);
- else
- warning ("%J'%D' redeclared without dllimport attribute "
- "after being referenced with dllimport linkage", decl, decl);
-
- XEXP (DECL_RTL (decl), 0) = newrtl;
-
- DECL_NON_ADDR_CONST_P (decl) = 0;
-
- /* We previously set TREE_PUBLIC and DECL_EXTERNAL.
- We leave these alone for now. */
- }
+ /* It might be that DECL has been declared as dllimport, but a
+ subsequent definition nullified that. Assert that
+ tree.c: merge_dllimport_decl_attributes has removed the attribute
+ before the RTL name was marked with the DLL_IMPORT_PREFIX. */
+ else
+ gcc_assert (!((TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && rtl != NULL_RTX
+ && GET_CODE (rtl) == MEM
+ && GET_CODE (XEXP (rtl, 0)) == MEM
+ && GET_CODE (XEXP (XEXP (rtl, 0), 0)) == SYMBOL_REF
+ && i386_pe_dllimport_name_p (XSTR (XEXP (XEXP (rtl, 0), 0), 0))));
}
/* Strip only the leading encoding, leaving the stdcall suffix and fastcall
@@ -559,7 +420,7 @@ i386_pe_strip_name_encoding (const char *str)
return str;
}
-/* Also strip the stdcall suffix. */
+/* Also strip the fastcall prefix and stdcall suffix. */
const char *
i386_pe_strip_name_encoding_full (const char *str)
@@ -567,6 +428,11 @@ i386_pe_strip_name_encoding_full (const char *str)
const char *p;
const char *name = i386_pe_strip_name_encoding (str);
+ /* Strip leading '@' on fastcall symbols. */
+ if (*name == '@')
+ name++;
+
+ /* Strip trailing "@n". */
p = strchr (name, '@');
if (p)
return ggc_alloc_string (name, p - name);
@@ -598,9 +464,9 @@ void i386_pe_output_labelref (FILE *stream, const char *name)
}
}
else if ((name[0] == FASTCALL_PREFIX)
- || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX)
+ || (strncmp (name, DLL_EXPORT_PREFIX, strlen (DLL_EXPORT_PREFIX))
== 0
- && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX)))
+ && name[strlen (DLL_EXPORT_PREFIX)] == FASTCALL_PREFIX))
/* A fastcall symbol. */
{
fprintf (stream, "%s",
@@ -668,7 +534,7 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc)
unsigned int **slot;
/* The names we put in the hashtable will always be the unique
- versions gived to us by the stringtable, so we can just use
+ versions given to us by the stringtable, so we can just use
their addresses as the keys. */
if (!htab)
htab = htab_create (31, htab_hash_pointer, htab_eq_pointer, NULL);
@@ -699,14 +565,15 @@ i386_pe_section_type_flags (tree decl, const char *name, int reloc)
else
{
if (decl && **slot != flags)
- error ("%J'%D' causes a section type conflict", decl, decl);
+ error ("%q+D causes a section type conflict", decl);
}
return flags;
}
void
-i386_pe_asm_named_section (const char *name, unsigned int flags)
+i386_pe_asm_named_section (const char *name, unsigned int flags,
+ tree decl)
{
char flagchars[8], *f = flagchars;
@@ -733,10 +600,16 @@ i386_pe_asm_named_section (const char *name, unsigned int flags)
if (flags & SECTION_LINKONCE)
{
/* 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, without warning.
+ If 'selectany' attribute has been specified, MS compiler
+ sets 'discard' characteristic, rather than telling linker
+ to warn of size or content mismatch, so do the same. */
+ bool discard = (flags & SECTION_CODE)
+ || lookup_attribute ("selectany",
+ DECL_ATTRIBUTES (decl));
fprintf (asm_out_file, "\t.linkonce %s\n",
- (flags & SECTION_CODE ? "discard" : "same_size"));
+ (discard ? "discard" : "same_size"));
}
}
@@ -764,13 +637,14 @@ i386_pe_declare_function_type (FILE *file, const char *name, int public)
/* Keep a list of external functions. */
-struct extern_list
+struct extern_list GTY(())
{
struct extern_list *next;
+ tree decl;
const char *name;
};
-static struct extern_list *extern_head;
+static GTY(()) struct extern_list *extern_head;
/* Assemble an external function reference. We need to keep a list of
these, so that we can output the function types at the end of the
@@ -779,26 +653,27 @@ static struct extern_list *extern_head;
for it then. */
void
-i386_pe_record_external_function (const char *name)
+i386_pe_record_external_function (tree decl, const char *name)
{
struct extern_list *p;
- p = (struct extern_list *) xmalloc (sizeof *p);
+ p = (struct extern_list *) ggc_alloc (sizeof *p);
p->next = extern_head;
+ p->decl = decl;
p->name = name;
extern_head = p;
}
/* Keep a list of exported symbols. */
-struct export_list
+struct export_list GTY(())
{
struct export_list *next;
const char *name;
int is_data; /* used to type tag exported symbols. */
};
-static struct export_list *export_head;
+static GTY(()) struct export_list *export_head;
/* Assemble an export symbol entry. We need to keep a list of
these, so that we can output the export list at the end of the
@@ -811,7 +686,7 @@ i386_pe_record_exported_symbol (const char *name, int is_data)
{
struct export_list *p;
- p = (struct export_list *) xmalloc (sizeof *p);
+ p = (struct export_list *) ggc_alloc (sizeof *p);
p->next = export_head;
p->name = name;
p->is_data = is_data;
@@ -833,10 +708,11 @@ i386_pe_file_end (void)
{
tree decl;
- decl = get_identifier (p->name);
+ decl = p->decl;
/* Positively ensure only one declaration for any given symbol. */
- if (! TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (decl))
+ if (! TREE_ASM_WRITTEN (decl)
+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
{
TREE_ASM_WRITTEN (decl) = 1;
i386_pe_declare_function_type (asm_out_file, p->name,
@@ -856,3 +732,5 @@ i386_pe_file_end (void)
}
}
}
+
+#include "gt-winnt.h"
diff --git a/contrib/gcc/config/i386/x-darwin b/contrib/gcc/config/i386/x-darwin
new file mode 100644
index 0000000..9a3b0f2
--- /dev/null
+++ b/contrib/gcc/config/i386/x-darwin
@@ -0,0 +1,4 @@
+host-i386-darwin.o : $(srcdir)/config/i386/host-i386-darwin.c \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) \
+ config/host-darwin.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/contrib/gcc/config/i386/x-i386 b/contrib/gcc/config/i386/x-i386
new file mode 100644
index 0000000..e156bcd
--- /dev/null
+++ b/contrib/gcc/config/i386/x-i386
@@ -0,0 +1,3 @@
+driver-i386.o : $(srcdir)/config/i386/driver-i386.c \
+ $(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/contrib/gcc/config/i386/x-mingw32 b/contrib/gcc/config/i386/x-mingw32
index 04593aa..7ae6152 100644
--- a/contrib/gcc/config/i386/x-mingw32
+++ b/contrib/gcc/config/i386/x-mingw32
@@ -2,3 +2,12 @@
# Make local_includedir relative to EXEC_PREFIX
#
local_includedir=$(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include
+
+# On MinGW, we use "%IA64d" to print 64-bit integers, and the format-checking
+# code does not handle that, so we have to disable checking here.
+WERROR_FLAGS += -Wno-format
+
+host-mingw32.o : $(srcdir)/config/i386/host-mingw32.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h hosthooks.h hosthooks-def.h toplev.h diagnostic.h $(HOOKS_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/host-mingw32.c
diff --git a/contrib/gcc/config/i386/xm-cygwin.h b/contrib/gcc/config/i386/xm-cygwin.h
index 1ecb00c..c3d6a2c 100644
--- a/contrib/gcc/config/i386/xm-cygwin.h
+++ b/contrib/gcc/config/i386/xm-cygwin.h
@@ -16,7 +16,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define HOST_EXECUTABLE_SUFFIX ".exe"
diff --git a/contrib/gcc/config/i386/xm-djgpp.h b/contrib/gcc/config/i386/xm-djgpp.h
index 9bb520d..a93befc 100644
--- a/contrib/gcc/config/i386/xm-djgpp.h
+++ b/contrib/gcc/config/i386/xm-djgpp.h
@@ -1,5 +1,6 @@
/* Configuration for GCC for Intel 80386 running DJGPP.
- Copyright (C) 1988, 1996, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1996, 1998, 1999, 2000, 2001, 2004
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Use semicolons to separate elements of a path. */
#define PATH_SEPARATOR ';'
diff --git a/contrib/gcc/config/i386/xm-mingw32.h b/contrib/gcc/config/i386/xm-mingw32.h
index 8881966..053947e 100644
--- a/contrib/gcc/config/i386/xm-mingw32.h
+++ b/contrib/gcc/config/i386/xm-mingw32.h
@@ -17,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#define HOST_EXECUTABLE_SUFFIX ".exe"
@@ -27,3 +27,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* This is the name of the null device on windows. */
#define HOST_BIT_BUCKET "nul"
+
+/* The st_ino field of struct stat is always 0. */
+#define HOST_LACKS_INODE_NUMBERS
+
+/* MSVCRT does not support the "ll" format specifier for printing
+ "long long" values. Instead, we use "I64". */
+#define HOST_LONG_LONG_FORMAT "I64"
diff --git a/contrib/gcc/config/i386/xmmintrin.h b/contrib/gcc/config/i386/xmmintrin.h
index 921806f..87ec195 100644
--- a/contrib/gcc/config/i386/xmmintrin.h
+++ b/contrib/gcc/config/i386/xmmintrin.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -14,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -25,7 +26,7 @@
Public License. */
/* Implemented from the specification included in the Intel C++ Compiler
- User Guide and Reference, version 8.0. */
+ User Guide and Reference, version 9.0. */
#ifndef _XMMINTRIN_H_INCLUDED
#define _XMMINTRIN_H_INCLUDED
@@ -37,11 +38,15 @@
/* We need type definitions from the MMX header file. */
#include <mmintrin.h>
-/* The data type intended for user use. */
-typedef float __m128 __attribute__ ((__mode__(__V4SF__)));
+/* Get _mm_malloc () and _mm_free (). */
+#include <mm_malloc.h>
+
+/* The Intel API is flexible enough that we must allow aliasing with other
+ vector types, and their scalar components. */
+typedef float __m128 __attribute__ ((__vector_size__ (16), __may_alias__));
/* Internal data types for implementing the intrinsics. */
-typedef float __v4sf __attribute__ ((__mode__(__V4SF__)));
+typedef float __v4sf __attribute__ ((__vector_size__ (16)));
/* Create a selector for use with the SHUFPS instruction. */
#define _MM_SHUFFLE(fp3,fp2,fp1,fp0) \
@@ -83,59 +88,66 @@ enum _mm_hint
#define _MM_FLUSH_ZERO_ON 0x8000
#define _MM_FLUSH_ZERO_OFF 0x0000
+/* Create a vector of zeros. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_setzero_ps (void)
+{
+ return __extension__ (__m128){ 0.0f, 0.0f, 0.0f, 0.0f };
+}
+
/* Perform the respective operation on the lower SPFP (single-precision
floating-point) values of A and B; the upper three SPFP values are
passed through from A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_add_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_addss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_sub_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_subss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_mul_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_mulss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_div_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_divss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_sqrt_ss (__m128 __A)
{
return (__m128) __builtin_ia32_sqrtss ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_rcp_ss (__m128 __A)
{
return (__m128) __builtin_ia32_rcpss ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_rsqrt_ss (__m128 __A)
{
return (__m128) __builtin_ia32_rsqrtss ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_min_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_minss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_max_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_maxss ((__v4sf)__A, (__v4sf)__B);
@@ -143,55 +155,55 @@ _mm_max_ss (__m128 __A, __m128 __B)
/* Perform the respective operation on the four SPFP values in A and B. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_add_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_addps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_sub_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_subps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_mul_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_mulps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_div_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_divps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_sqrt_ps (__m128 __A)
{
return (__m128) __builtin_ia32_sqrtps ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_rcp_ps (__m128 __A)
{
return (__m128) __builtin_ia32_rcpps ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_rsqrt_ps (__m128 __A)
{
return (__m128) __builtin_ia32_rsqrtps ((__v4sf)__A);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_min_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_minps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_max_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_maxps ((__v4sf)__A, (__v4sf)__B);
@@ -199,25 +211,25 @@ _mm_max_ps (__m128 __A, __m128 __B)
/* Perform logical bit-wise operations on 128-bit values. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_and_ps (__m128 __A, __m128 __B)
{
return __builtin_ia32_andps (__A, __B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_andnot_ps (__m128 __A, __m128 __B)
{
return __builtin_ia32_andnps (__A, __B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_or_ps (__m128 __A, __m128 __B)
{
return __builtin_ia32_orps (__A, __B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_xor_ps (__m128 __A, __m128 __B)
{
return __builtin_ia32_xorps (__A, __B);
@@ -227,25 +239,25 @@ _mm_xor_ps (__m128 __A, __m128 __B)
comparison is true, place a mask of all ones in the result, otherwise a
mask of zeros. The upper three SPFP values are passed through from A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpeq_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpeqss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmplt_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpltss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmple_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpless ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpgt_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movss ((__v4sf) __A,
@@ -255,7 +267,7 @@ _mm_cmpgt_ss (__m128 __A, __m128 __B)
__A));
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpge_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movss ((__v4sf) __A,
@@ -265,25 +277,25 @@ _mm_cmpge_ss (__m128 __A, __m128 __B)
__A));
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpneq_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpneqss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnlt_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpnltss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnle_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpnless ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpngt_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movss ((__v4sf) __A,
@@ -293,7 +305,7 @@ _mm_cmpngt_ss (__m128 __A, __m128 __B)
__A));
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnge_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movss ((__v4sf) __A,
@@ -303,13 +315,13 @@ _mm_cmpnge_ss (__m128 __A, __m128 __B)
__A));
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpord_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpordss ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpunord_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpunordss ((__v4sf)__A, (__v4sf)__B);
@@ -319,73 +331,73 @@ _mm_cmpunord_ss (__m128 __A, __m128 __B)
element, if the comparison is true, place a mask of all ones in the
result, otherwise a mask of zeros. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpeq_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpeqps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmplt_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpltps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmple_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpleps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpgt_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpgtps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpge_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpgeps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpneq_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpneqps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnlt_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpnltps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnle_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpnleps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpngt_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpngtps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpnge_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpngeps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpord_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpordps ((__v4sf)__A, (__v4sf)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cmpunord_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_cmpunordps ((__v4sf)__A, (__v4sf)__B);
@@ -394,73 +406,73 @@ _mm_cmpunord_ps (__m128 __A, __m128 __B)
/* Compare the lower SPFP values of A and B and return 1 if true
and 0 if false. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comieq_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comieq ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comilt_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comilt ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comile_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comile ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comigt_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comigt ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comige_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comige ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_comineq_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_comineq ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomieq_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomieq ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomilt_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomilt ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomile_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomile ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomigt_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomigt ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomige_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomige ((__v4sf)__A, (__v4sf)__B);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_ucomineq_ss (__m128 __A, __m128 __B)
{
return __builtin_ia32_ucomineq ((__v4sf)__A, (__v4sf)__B);
@@ -468,22 +480,31 @@ _mm_ucomineq_ss (__m128 __A, __m128 __B)
/* Convert the lower SPFP value to a 32-bit integer according to the current
rounding mode. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvtss_si32 (__m128 __A)
{
return __builtin_ia32_cvtss2si ((__v4sf) __A);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvt_ss2si (__m128 __A)
{
return _mm_cvtss_si32 (__A);
}
#ifdef __x86_64__
-/* Convert the lower SPFP value to a 32-bit integer according to the current
- rounding mode. */
-static __inline long long
+/* Convert the lower SPFP value to a 32-bit integer according to the
+ current rounding mode. */
+
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvtss_si64 (__m128 __A)
+{
+ return __builtin_ia32_cvtss2si64 ((__v4sf) __A);
+}
+
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
_mm_cvtss_si64x (__m128 __A)
{
return __builtin_ia32_cvtss2si64 ((__v4sf) __A);
@@ -492,26 +513,26 @@ _mm_cvtss_si64x (__m128 __A)
/* Convert the two lower SPFP values to 32-bit integers according to the
current rounding mode. Return the integers in packed form. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi32 (__m128 __A)
{
return (__m64) __builtin_ia32_cvtps2pi ((__v4sf) __A);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvt_ps2pi (__m128 __A)
{
return _mm_cvtps_pi32 (__A);
}
/* Truncate the lower SPFP value to a 32-bit integer. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvttss_si32 (__m128 __A)
{
return __builtin_ia32_cvttss2si ((__v4sf) __A);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_cvtt_ss2si (__m128 __A)
{
return _mm_cvttss_si32 (__A);
@@ -519,7 +540,16 @@ _mm_cvtt_ss2si (__m128 __A)
#ifdef __x86_64__
/* Truncate the lower SPFP value to a 32-bit integer. */
-static __inline long long
+
+/* Intel intrinsic. */
+static __inline long long __attribute__((__always_inline__))
+_mm_cvttss_si64 (__m128 __A)
+{
+ return __builtin_ia32_cvttss2si64 ((__v4sf) __A);
+}
+
+/* Microsoft intrinsic. */
+static __inline long long __attribute__((__always_inline__))
_mm_cvttss_si64x (__m128 __A)
{
return __builtin_ia32_cvttss2si64 ((__v4sf) __A);
@@ -528,26 +558,26 @@ _mm_cvttss_si64x (__m128 __A)
/* Truncate the two lower SPFP values to 32-bit integers. Return the
integers in packed form. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvttps_pi32 (__m128 __A)
{
return (__m64) __builtin_ia32_cvttps2pi ((__v4sf) __A);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtt_ps2pi (__m128 __A)
{
return _mm_cvttps_pi32 (__A);
}
/* Convert B to a SPFP value and insert it as element zero in A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsi32_ss (__m128 __A, int __B)
{
return (__m128) __builtin_ia32_cvtsi2ss ((__v4sf) __A, __B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvt_si2ss (__m128 __A, int __B)
{
return _mm_cvtsi32_ss (__A, __B);
@@ -555,7 +585,16 @@ _mm_cvt_si2ss (__m128 __A, int __B)
#ifdef __x86_64__
/* Convert B to a SPFP value and insert it as element zero in A. */
-static __inline __m128
+
+/* Intel intrinsic. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_cvtsi64_ss (__m128 __A, long long __B)
+{
+ return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B);
+}
+
+/* Microsoft intrinsic. */
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtsi64x_ss (__m128 __A, long long __B)
{
return (__m128) __builtin_ia32_cvtsi642ss ((__v4sf) __A, __B);
@@ -564,20 +603,20 @@ _mm_cvtsi64x_ss (__m128 __A, long long __B)
/* Convert the two 32-bit values in B to SPFP form and insert them
as the two lower elements in A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi32_ps (__m128 __A, __m64 __B)
{
return (__m128) __builtin_ia32_cvtpi2ps ((__v4sf) __A, (__v2si)__B);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvt_pi2ps (__m128 __A, __m64 __B)
{
return _mm_cvtpi32_ps (__A, __B);
}
/* Convert the four signed 16-bit values in A to SPFP form. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi16_ps (__m64 __A)
{
__v4hi __sign;
@@ -587,15 +626,14 @@ _mm_cvtpi16_ps (__m64 __A)
/* This comparison against zero gives us a mask that can be used to
fill in the missing sign bits in the unpack operations below, so
that we get signed values after unpacking. */
- __sign = (__v4hi) __builtin_ia32_mmx_zero ();
- __sign = __builtin_ia32_pcmpgtw (__sign, (__v4hi)__A);
+ __sign = __builtin_ia32_pcmpgtw ((__v4hi)0LL, (__v4hi)__A);
/* Convert the four words to doublewords. */
__hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, __sign);
__losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, __sign);
/* Convert the doublewords to floating point two at a time. */
- __r = (__v4sf) __builtin_ia32_setzerops ();
+ __r = (__v4sf) _mm_setzero_ps ();
__r = __builtin_ia32_cvtpi2ps (__r, __hisi);
__r = __builtin_ia32_movlhps (__r, __r);
__r = __builtin_ia32_cvtpi2ps (__r, __losi);
@@ -604,19 +642,18 @@ _mm_cvtpi16_ps (__m64 __A)
}
/* Convert the four unsigned 16-bit values in A to SPFP form. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpu16_ps (__m64 __A)
{
- __v4hi __zero = (__v4hi) __builtin_ia32_mmx_zero ();
__v2si __hisi, __losi;
__v4sf __r;
/* Convert the four words to doublewords. */
- __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, __zero);
- __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, __zero);
+ __hisi = (__v2si) __builtin_ia32_punpckhwd ((__v4hi)__A, (__v4hi)0LL);
+ __losi = (__v2si) __builtin_ia32_punpcklwd ((__v4hi)__A, (__v4hi)0LL);
/* Convert the doublewords to floating point two at a time. */
- __r = (__v4sf) __builtin_ia32_setzerops ();
+ __r = (__v4sf) _mm_setzero_ps ();
__r = __builtin_ia32_cvtpi2ps (__r, __hisi);
__r = __builtin_ia32_movlhps (__r, __r);
__r = __builtin_ia32_cvtpi2ps (__r, __losi);
@@ -625,7 +662,7 @@ _mm_cvtpu16_ps (__m64 __A)
}
/* Convert the low four signed 8-bit values in A to SPFP form. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi8_ps (__m64 __A)
{
__v8qi __sign;
@@ -633,8 +670,7 @@ _mm_cvtpi8_ps (__m64 __A)
/* This comparison against zero gives us a mask that can be used to
fill in the missing sign bits in the unpack operations below, so
that we get signed values after unpacking. */
- __sign = (__v8qi) __builtin_ia32_mmx_zero ();
- __sign = __builtin_ia32_pcmpgtb (__sign, (__v8qi)__A);
+ __sign = __builtin_ia32_pcmpgtb ((__v8qi)0LL, (__v8qi)__A);
/* Convert the four low bytes to words. */
__A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, __sign);
@@ -643,26 +679,25 @@ _mm_cvtpi8_ps (__m64 __A)
}
/* Convert the low four unsigned 8-bit values in A to SPFP form. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpu8_ps(__m64 __A)
{
- __v8qi __zero = (__v8qi) __builtin_ia32_mmx_zero ();
- __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, __zero);
+ __A = (__m64) __builtin_ia32_punpcklbw ((__v8qi)__A, (__v8qi)0LL);
return _mm_cvtpu16_ps(__A);
}
/* Convert the four signed 32-bit values in A and B to SPFP form. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_cvtpi32x2_ps(__m64 __A, __m64 __B)
{
- __v4sf __zero = (__v4sf) __builtin_ia32_setzerops ();
+ __v4sf __zero = (__v4sf) _mm_setzero_ps ();
__v4sf __sfa = __builtin_ia32_cvtpi2ps (__zero, (__v2si)__A);
__v4sf __sfb = __builtin_ia32_cvtpi2ps (__zero, (__v2si)__B);
return (__m128) __builtin_ia32_movlhps (__sfa, __sfb);
}
/* Convert the four SPFP values in A to four signed 16-bit integers. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi16(__m128 __A)
{
__v4sf __hisf = (__v4sf)__A;
@@ -673,17 +708,16 @@ _mm_cvtps_pi16(__m128 __A)
}
/* Convert the four SPFP values in A to four signed 8-bit integers. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_cvtps_pi8(__m128 __A)
{
__v4hi __tmp = (__v4hi) _mm_cvtps_pi16 (__A);
- __v4hi __zero = (__v4hi) __builtin_ia32_mmx_zero ();
- return (__m64) __builtin_ia32_packsswb (__tmp, __zero);
+ return (__m64) __builtin_ia32_packsswb (__tmp, (__v4hi)0LL);
}
/* Selects four specific SPFP values from A and B based on MASK. */
#if 0
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_shuffle_ps (__m128 __A, __m128 __B, int __mask)
{
return (__m128) __builtin_ia32_shufps ((__v4sf)__A, (__v4sf)__B, __mask);
@@ -695,14 +729,14 @@ _mm_shuffle_ps (__m128 __A, __m128 __B, int __mask)
/* Selects and interleaves the upper two SPFP values from A and B. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_unpackhi_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_unpckhps ((__v4sf)__A, (__v4sf)__B);
}
/* Selects and interleaves the lower two SPFP values from A and B. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_unpacklo_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_unpcklps ((__v4sf)__A, (__v4sf)__B);
@@ -710,28 +744,28 @@ _mm_unpacklo_ps (__m128 __A, __m128 __B)
/* Sets the upper two SPFP values with 64-bits of data loaded from P;
the lower two values are passed through from A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_loadh_pi (__m128 __A, __m64 const *__P)
{
return (__m128) __builtin_ia32_loadhps ((__v4sf)__A, (__v2si *)__P);
}
/* Stores the upper two SPFP values of A into P. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_storeh_pi (__m64 *__P, __m128 __A)
{
__builtin_ia32_storehps ((__v2si *)__P, (__v4sf)__A);
}
/* Moves the upper two values of B into the lower two values of A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_movehl_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movhlps ((__v4sf)__A, (__v4sf)__B);
}
/* Moves the lower two values of B into the upper two values of A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_movelh_ps (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movlhps ((__v4sf)__A, (__v4sf)__B);
@@ -739,222 +773,219 @@ _mm_movelh_ps (__m128 __A, __m128 __B)
/* Sets the lower two SPFP values with 64-bits of data loaded from P;
the upper two values are passed through from A. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_loadl_pi (__m128 __A, __m64 const *__P)
{
return (__m128) __builtin_ia32_loadlps ((__v4sf)__A, (__v2si *)__P);
}
/* Stores the lower two SPFP values of A into P. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_storel_pi (__m64 *__P, __m128 __A)
{
__builtin_ia32_storelps ((__v2si *)__P, (__v4sf)__A);
}
/* Creates a 4-bit mask from the most significant bits of the SPFP values. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_movemask_ps (__m128 __A)
{
return __builtin_ia32_movmskps ((__v4sf)__A);
}
/* Return the contents of the control register. */
-static __inline unsigned int
+static __inline unsigned int __attribute__((__always_inline__))
_mm_getcsr (void)
{
return __builtin_ia32_stmxcsr ();
}
/* Read exception bits from the control register. */
-static __inline unsigned int
+static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_EXCEPTION_STATE (void)
{
return _mm_getcsr() & _MM_EXCEPT_MASK;
}
-static __inline unsigned int
+static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_EXCEPTION_MASK (void)
{
return _mm_getcsr() & _MM_MASK_MASK;
}
-static __inline unsigned int
+static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_ROUNDING_MODE (void)
{
return _mm_getcsr() & _MM_ROUND_MASK;
}
-static __inline unsigned int
+static __inline unsigned int __attribute__((__always_inline__))
_MM_GET_FLUSH_ZERO_MODE (void)
{
return _mm_getcsr() & _MM_FLUSH_ZERO_MASK;
}
/* Set the control register to I. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_setcsr (unsigned int __I)
{
__builtin_ia32_ldmxcsr (__I);
}
/* Set exception bits in the control register. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_MM_SET_EXCEPTION_STATE(unsigned int __mask)
{
_mm_setcsr((_mm_getcsr() & ~_MM_EXCEPT_MASK) | __mask);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_MM_SET_EXCEPTION_MASK (unsigned int __mask)
{
_mm_setcsr((_mm_getcsr() & ~_MM_MASK_MASK) | __mask);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_MM_SET_ROUNDING_MODE (unsigned int __mode)
{
_mm_setcsr((_mm_getcsr() & ~_MM_ROUND_MASK) | __mode);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_MM_SET_FLUSH_ZERO_MODE (unsigned int __mode)
{
_mm_setcsr((_mm_getcsr() & ~_MM_FLUSH_ZERO_MASK) | __mode);
}
+/* Create a vector with element 0 as F and the rest zero. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_set_ss (float __F)
+{
+ return __extension__ (__m128)(__v4sf){ __F, 0, 0, 0 };
+}
+
+/* Create a vector with all four elements equal to F. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_set1_ps (float __F)
+{
+ return __extension__ (__m128)(__v4sf){ __F, __F, __F, __F };
+}
+
+static __inline __m128 __attribute__((__always_inline__))
+_mm_set_ps1 (float __F)
+{
+ return _mm_set1_ps (__F);
+}
+
/* Create a vector with element 0 as *P and the rest zero. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_load_ss (float const *__P)
{
- return (__m128) __builtin_ia32_loadss (__P);
+ return _mm_set_ss (*__P);
}
/* Create a vector with all four elements equal to *P. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_load1_ps (float const *__P)
{
- __v4sf __tmp = __builtin_ia32_loadss (__P);
- return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,0,0,0));
+ return _mm_set1_ps (*__P);
}
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_load_ps1 (float const *__P)
{
return _mm_load1_ps (__P);
}
/* Load four SPFP values from P. The address must be 16-byte aligned. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_load_ps (float const *__P)
{
- return (__m128) __builtin_ia32_loadaps (__P);
+ return (__m128) *(__v4sf *)__P;
}
/* Load four SPFP values from P. The address need not be 16-byte aligned. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_loadu_ps (float const *__P)
{
return (__m128) __builtin_ia32_loadups (__P);
}
/* Load four SPFP values in reverse order. The address must be aligned. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_loadr_ps (float const *__P)
{
- __v4sf __tmp = __builtin_ia32_loadaps (__P);
+ __v4sf __tmp = *(__v4sf *)__P;
return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,1,2,3));
}
-/* Create a vector with element 0 as F and the rest zero. */
-static __inline __m128
-_mm_set_ss (float __F)
-{
- return (__m128) __builtin_ia32_loadss (&__F);
-}
-
-/* Create a vector with all four elements equal to F. */
-static __inline __m128
-_mm_set1_ps (float __F)
+/* Create the vector [Z Y X W]. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W)
{
- __v4sf __tmp = __builtin_ia32_loadss (&__F);
- return (__m128) __builtin_ia32_shufps (__tmp, __tmp, _MM_SHUFFLE (0,0,0,0));
+ return __extension__ (__m128)(__v4sf){ __W, __X, __Y, __Z };
}
-static __inline __m128
-_mm_set_ps1 (float __F)
+/* Create the vector [W X Y Z]. */
+static __inline __m128 __attribute__((__always_inline__))
+_mm_setr_ps (float __Z, float __Y, float __X, float __W)
{
- return _mm_set1_ps (__F);
+ return __extension__ (__m128)(__v4sf){ __Z, __Y, __X, __W };
}
-/* Create the vector [Z Y X W]. */
-static __inline __m128
-_mm_set_ps (const float __Z, const float __Y, const float __X, const float __W)
+/* Stores the lower SPFP value. */
+static __inline void __attribute__((__always_inline__))
+_mm_store_ss (float *__P, __m128 __A)
{
- return (__v4sf) {__W, __X, __Y, __Z};
+ *__P = __builtin_ia32_vec_ext_v4sf ((__v4sf)__A, 0);
}
-/* Create the vector [W X Y Z]. */
-static __inline __m128
-_mm_setr_ps (float __Z, float __Y, float __X, float __W)
+static __inline float __attribute__((__always_inline__))
+_mm_cvtss_f32 (__m128 __A)
{
- return _mm_set_ps (__W, __X, __Y, __Z);
+ return __builtin_ia32_vec_ext_v4sf ((__v4sf)__A, 0);
}
-/* Create a vector of zeros. */
-static __inline __m128
-_mm_setzero_ps (void)
+/* Store four SPFP values. The address must be 16-byte aligned. */
+static __inline void __attribute__((__always_inline__))
+_mm_store_ps (float *__P, __m128 __A)
{
- return (__m128) __builtin_ia32_setzerops ();
+ *(__v4sf *)__P = (__v4sf)__A;
}
-/* Stores the lower SPFP value. */
-static __inline void
-_mm_store_ss (float *__P, __m128 __A)
+/* Store four SPFP values. The address need not be 16-byte aligned. */
+static __inline void __attribute__((__always_inline__))
+_mm_storeu_ps (float *__P, __m128 __A)
{
- __builtin_ia32_storess (__P, (__v4sf)__A);
+ __builtin_ia32_storeups (__P, (__v4sf)__A);
}
/* Store the lower SPFP value across four words. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_store1_ps (float *__P, __m128 __A)
{
__v4sf __va = (__v4sf)__A;
__v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,0,0,0));
- __builtin_ia32_storeaps (__P, __tmp);
+ _mm_storeu_ps (__P, __tmp);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_store_ps1 (float *__P, __m128 __A)
{
_mm_store1_ps (__P, __A);
}
-/* Store four SPFP values. The address must be 16-byte aligned. */
-static __inline void
-_mm_store_ps (float *__P, __m128 __A)
-{
- __builtin_ia32_storeaps (__P, (__v4sf)__A);
-}
-
-/* Store four SPFP values. The address need not be 16-byte aligned. */
-static __inline void
-_mm_storeu_ps (float *__P, __m128 __A)
-{
- __builtin_ia32_storeups (__P, (__v4sf)__A);
-}
-
/* Store four SPFP values in reverse order. The address must be aligned. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_storer_ps (float *__P, __m128 __A)
{
__v4sf __va = (__v4sf)__A;
__v4sf __tmp = __builtin_ia32_shufps (__va, __va, _MM_SHUFFLE (0,1,2,3));
- __builtin_ia32_storeaps (__P, __tmp);
+ _mm_store_ps (__P, __tmp);
}
/* Sets the low SPFP value of A from the low value of B. */
-static __inline __m128
+static __inline __m128 __attribute__((__always_inline__))
_mm_move_ss (__m128 __A, __m128 __B)
{
return (__m128) __builtin_ia32_movss ((__v4sf)__A, (__v4sf)__B);
@@ -962,103 +993,102 @@ _mm_move_ss (__m128 __A, __m128 __B)
/* Extracts one of the four words of A. The selector N must be immediate. */
#if 0
-static __inline int
-_mm_extract_pi16 (__m64 __A, int __N)
+static __inline int __attribute__((__always_inline__))
+_mm_extract_pi16 (__m64 const __A, int const __N)
{
- return __builtin_ia32_pextrw ((__v4hi)__A, __N);
+ return __builtin_ia32_vec_ext_v4hi ((__v4hi)__A, __N);
}
-static __inline int
-_m_pextrw (__m64 __A, int __N)
+static __inline int __attribute__((__always_inline__))
+_m_pextrw (__m64 const __A, int const __N)
{
return _mm_extract_pi16 (__A, __N);
}
#else
-#define _mm_extract_pi16(A, N) \
- __builtin_ia32_pextrw ((__v4hi)(A), (N))
+#define _mm_extract_pi16(A, N) __builtin_ia32_vec_ext_v4hi ((__v4hi)(A), (N))
#define _m_pextrw(A, N) _mm_extract_pi16((A), (N))
#endif
/* Inserts word D into one of four words of A. The selector N must be
immediate. */
#if 0
-static __inline __m64
-_mm_insert_pi16 (__m64 __A, int __D, int __N)
+static __inline __m64 __attribute__((__always_inline__))
+_mm_insert_pi16 (__m64 const __A, int const __D, int const __N)
{
- return (__m64)__builtin_ia32_pinsrw ((__v4hi)__A, __D, __N);
+ return (__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)__A, __D, __N);
}
-static __inline __m64
-_m_pinsrw (__m64 __A, int __D, int __N)
+static __inline __m64 __attribute__((__always_inline__))
+_m_pinsrw (__m64 const __A, int const __D, int const __N)
{
return _mm_insert_pi16 (__A, __D, __N);
}
#else
#define _mm_insert_pi16(A, D, N) \
- ((__m64) __builtin_ia32_pinsrw ((__v4hi)(A), (D), (N)))
+ ((__m64) __builtin_ia32_vec_set_v4hi ((__v4hi)(A), (D), (N)))
#define _m_pinsrw(A, D, N) _mm_insert_pi16((A), (D), (N))
#endif
/* Compute the element-wise maximum of signed 16-bit values. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_max_pi16 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pmaxsw ((__v4hi)__A, (__v4hi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmaxsw (__m64 __A, __m64 __B)
{
return _mm_max_pi16 (__A, __B);
}
/* Compute the element-wise maximum of unsigned 8-bit values. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_max_pu8 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pmaxub ((__v8qi)__A, (__v8qi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmaxub (__m64 __A, __m64 __B)
{
return _mm_max_pu8 (__A, __B);
}
/* Compute the element-wise minimum of signed 16-bit values. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_min_pi16 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pminsw ((__v4hi)__A, (__v4hi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pminsw (__m64 __A, __m64 __B)
{
return _mm_min_pi16 (__A, __B);
}
/* Compute the element-wise minimum of unsigned 8-bit values. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_min_pu8 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pminub ((__v8qi)__A, (__v8qi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pminub (__m64 __A, __m64 __B)
{
return _mm_min_pu8 (__A, __B);
}
/* Create an 8-bit mask of the signs of 8-bit values. */
-static __inline int
+static __inline int __attribute__((__always_inline__))
_mm_movemask_pi8 (__m64 __A)
{
return __builtin_ia32_pmovmskb ((__v8qi)__A);
}
-static __inline int
+static __inline int __attribute__((__always_inline__))
_m_pmovmskb (__m64 __A)
{
return _mm_movemask_pi8 (__A);
@@ -1066,13 +1096,13 @@ _m_pmovmskb (__m64 __A)
/* Multiply four unsigned 16-bit values in A by four unsigned 16-bit values
in B and produce the high 16 bits of the 32-bit results. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_mulhi_pu16 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pmulhuw ((__v4hi)__A, (__v4hi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pmulhuw (__m64 __A, __m64 __B)
{
return _mm_mulhi_pu16 (__A, __B);
@@ -1081,13 +1111,13 @@ _m_pmulhuw (__m64 __A, __m64 __B)
/* Return a combination of the four 16-bit values in A. The selector
must be an immediate. */
#if 0
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_shuffle_pi16 (__m64 __A, int __N)
{
return (__m64) __builtin_ia32_pshufw ((__v4hi)__A, __N);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pshufw (__m64 __A, int __N)
{
return _mm_shuffle_pi16 (__A, __N);
@@ -1101,39 +1131,39 @@ _m_pshufw (__m64 __A, int __N)
/* Conditionally store byte elements of A into P. The high bit of each
byte in the selector N determines whether the corresponding byte from
A is stored. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_maskmove_si64 (__m64 __A, __m64 __N, char *__P)
{
__builtin_ia32_maskmovq ((__v8qi)__A, (__v8qi)__N, __P);
}
-static __inline void
+static __inline void __attribute__((__always_inline__))
_m_maskmovq (__m64 __A, __m64 __N, char *__P)
{
_mm_maskmove_si64 (__A, __N, __P);
}
/* Compute the rounded averages of the unsigned 8-bit values in A and B. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_avg_pu8 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pavgb ((__v8qi)__A, (__v8qi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pavgb (__m64 __A, __m64 __B)
{
return _mm_avg_pu8 (__A, __B);
}
/* Compute the rounded averages of the unsigned 16-bit values in A and B. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_avg_pu16 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_pavgw ((__v4hi)__A, (__v4hi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_pavgw (__m64 __A, __m64 __B)
{
return _mm_avg_pu16 (__A, __B);
@@ -1142,13 +1172,13 @@ _m_pavgw (__m64 __A, __m64 __B)
/* Compute the sum of the absolute differences of the unsigned 8-bit
values in A and B. Return the value in the lower 16-bit word; the
upper words are cleared. */
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_mm_sad_pu8 (__m64 __A, __m64 __B)
{
return (__m64) __builtin_ia32_psadbw ((__v8qi)__A, (__v8qi)__B);
}
-static __inline __m64
+static __inline __m64 __attribute__((__always_inline__))
_m_psadbw (__m64 __A, __m64 __B)
{
return _mm_sad_pu8 (__A, __B);
@@ -1157,7 +1187,7 @@ _m_psadbw (__m64 __A, __m64 __B)
/* Loads one cache line from address P to a location "closer" to the
processor. The selector I specifies the type of prefetch operation. */
#if 0
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_prefetch (void *__P, enum _mm_hint __I)
{
__builtin_prefetch (__P, 0, __I);
@@ -1168,14 +1198,14 @@ _mm_prefetch (void *__P, enum _mm_hint __I)
#endif
/* Stores the data in A to the address P without polluting the caches. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_stream_pi (__m64 *__P, __m64 __A)
{
__builtin_ia32_movntq ((unsigned long long *)__P, (unsigned long long)__A);
}
/* Likewise. The address must be 16-byte aligned. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_stream_ps (float *__P, __m128 __A)
{
__builtin_ia32_movntps (__P, (__v4sf)__A);
@@ -1183,7 +1213,7 @@ _mm_stream_ps (float *__P, __m128 __A)
/* Guarantees that every preceding store is globally visible before
any subsequent store. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_sfence (void)
{
__builtin_ia32_sfence ();
@@ -1192,7 +1222,7 @@ _mm_sfence (void)
/* The execution of the next instruction is delayed by an implementation
specific amount of time. The instruction does not modify the
architectural state. */
-static __inline void
+static __inline void __attribute__((__always_inline__))
_mm_pause (void)
{
__asm__ __volatile__ ("rep; nop" : : );
@@ -1202,14 +1232,14 @@ _mm_pause (void)
#define _MM_TRANSPOSE4_PS(row0, row1, row2, row3) \
do { \
__v4sf __r0 = (row0), __r1 = (row1), __r2 = (row2), __r3 = (row3); \
- __v4sf __t0 = __builtin_ia32_shufps (__r0, __r1, 0x44); \
- __v4sf __t2 = __builtin_ia32_shufps (__r0, __r1, 0xEE); \
- __v4sf __t1 = __builtin_ia32_shufps (__r2, __r3, 0x44); \
- __v4sf __t3 = __builtin_ia32_shufps (__r2, __r3, 0xEE); \
- (row0) = __builtin_ia32_shufps (__t0, __t1, 0x88); \
- (row1) = __builtin_ia32_shufps (__t0, __t1, 0xDD); \
- (row2) = __builtin_ia32_shufps (__t2, __t3, 0x88); \
- (row3) = __builtin_ia32_shufps (__t2, __t3, 0xDD); \
+ __v4sf __t0 = __builtin_ia32_unpcklps (__r0, __r1); \
+ __v4sf __t1 = __builtin_ia32_unpcklps (__r2, __r3); \
+ __v4sf __t2 = __builtin_ia32_unpckhps (__r0, __r1); \
+ __v4sf __t3 = __builtin_ia32_unpckhps (__r2, __r3); \
+ (row0) = __builtin_ia32_movlhps (__t0, __t1); \
+ (row1) = __builtin_ia32_movhlps (__t1, __t0); \
+ (row2) = __builtin_ia32_movlhps (__t2, __t3); \
+ (row3) = __builtin_ia32_movhlps (__t3, __t2); \
} while (0)
/* For backward source compatibility. */
diff --git a/contrib/gcc/config/ia64/crtbegin.asm b/contrib/gcc/config/ia64/crtbegin.asm
index 494def7..e040916 100644
--- a/contrib/gcc/config/ia64/crtbegin.asm
+++ b/contrib/gcc/config/ia64/crtbegin.asm
@@ -1,20 +1,29 @@
-/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003, 2005 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
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library 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
- Library General Public License for more details.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, 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 "auto-host.h"
diff --git a/contrib/gcc/config/ia64/crtend.asm b/contrib/gcc/config/ia64/crtend.asm
index 8984d88..66eaa01 100644
--- a/contrib/gcc/config/ia64/crtend.asm
+++ b/contrib/gcc/config/ia64/crtend.asm
@@ -1,20 +1,29 @@
-/* Copyright (C) 2000, 2001, 2003 Free Software Foundation, Inc.
+/* Copyright (C) 2000, 2001, 2003, 2005 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
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library 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
- Library General Public License for more details.
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
- You should have received a copy of the GNU Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, 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 "auto-host.h"
diff --git a/contrib/gcc/config/ia64/crtfastmath.c b/contrib/gcc/config/ia64/crtfastmath.c
index aa0d120..e5b32cb 100644
--- a/contrib/gcc/config/ia64/crtfastmath.c
+++ b/contrib/gcc/config/ia64/crtfastmath.c
@@ -1,29 +1,29 @@
-/* Copyright (C) 2001 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2005 Free Software Foundation, Inc.
Contributed by David Mosberger <davidm@hpl.hp.com>.
- The GNU C Library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
+ This file is part of GCC.
- The GNU C Library is distributed in the hope that it will be useful,
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
+ 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 Library General Public
- License along with the GNU C Library; see the file COPYING.LIB. If not,
- write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
-/* 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.) */
+/* 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. */
/* We could call fesetenv() here but that would create a confusing
dependency on libm (since that is where fesetenv() gets defined.
diff --git a/contrib/gcc/config/ia64/crti.asm b/contrib/gcc/config/ia64/crti.asm
index 4b48e3d..a2d1e12 100644
--- a/contrib/gcc/config/ia64/crti.asm
+++ b/contrib/gcc/config/ia64/crti.asm
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/ia64/crtn.asm b/contrib/gcc/config/ia64/crtn.asm
index 48a9a03..52ec47c 100644
--- a/contrib/gcc/config/ia64/crtn.asm
+++ b/contrib/gcc/config/ia64/crtn.asm
@@ -21,8 +21,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/ia64/fde-glibc.c b/contrib/gcc/config/ia64/fde-glibc.c
index 15e1927..7506c17 100644
--- a/contrib/gcc/config/ia64/fde-glibc.c
+++ b/contrib/gcc/config/ia64/fde-glibc.c
@@ -15,8 +15,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
diff --git a/contrib/gcc/config/ia64/freebsd.h b/contrib/gcc/config/ia64/freebsd.h
index d5977ff..2373910 100644
--- a/contrib/gcc/config/ia64/freebsd.h
+++ b/contrib/gcc/config/ia64/freebsd.h
@@ -16,7 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
@@ -24,7 +25,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#define LINK_SPEC " \
%{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
- %{Wl,*:%*} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
%{shared:-Bshareable %{h*} %{soname*}} \
%{symbolic:-Bsymbolic} \
diff --git a/contrib/gcc/config/ia64/hpux.h b/contrib/gcc/config/ia64/hpux.h
index 09fb53f..996b7d2 100644
--- a/contrib/gcc/config/ia64/hpux.h
+++ b/contrib/gcc/config/ia64/hpux.h
@@ -1,5 +1,6 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+ Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com> and
Reva Cuthbertson <reva@cup.hp.com>
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This macro is a C statement to print on `stderr' a string describing the
particular machine description choice. */
@@ -29,6 +30,12 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_HPUX
#define TARGET_HPUX 1
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "unsigned int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
/* Target OS builtins. */
#define TARGET_OS_CPP_BUILTINS() \
do { \
@@ -46,6 +53,7 @@ do { \
builtin_define("_HPUX_SOURCE"); \
builtin_define("__STDC_EXT__"); \
builtin_define("__STDCPP__"); \
+ builtin_define("_INCLUDE__STDC_A1_SOURCE"); \
} \
if (TARGET_ILP32) \
builtin_define("_ILP32"); \
@@ -64,11 +72,13 @@ do { \
#undef ENDFILE_SPEC
#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s}}"
+#define STARTFILE_SPEC "%{!shared:%{static:crt0%O%s} \
+ %{mlp64:/usr/lib/hpux64/unix98%O%s} \
+ %{!mlp64:/usr/lib/hpux32/unix98%O%s}}"
#undef LINK_SPEC
#define LINK_SPEC \
- "+Accept TypeMismatch \
+ "-z +Accept TypeMismatch \
%{shared:-b} \
%{!shared: \
-u main \
@@ -84,11 +94,6 @@ do { \
%{mlp64:-L/usr/lib/hpux64/libp} -lgprof} \
%{!symbolic:-lc}}"
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- { "ilp32", MASK_ILP32, "Generate ILP32 code" }, \
- { "lp64", -MASK_ILP32, "Generate LP64 code" },
-
#define MULTILIB_DEFAULTS { "milp32" }
/* A C expression whose value is zero if pointers that need to be extended
@@ -101,16 +106,11 @@ do { \
#define JMP_BUF_SIZE (8 * 76)
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
-
-/* This needs to be set to force structure arguments with a single
- integer field to be treated as structures and not as the type of
- their field. Without this a structure with a single char will be
- returned just like a char variable, instead of being returned at the
- top of the register as specified for big-endian IA64. */
+#define TARGET_DEFAULT \
+ (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
-#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
- (!FLOAT_MODE_P (MODE) || (MODE) == TFmode)
+/* ??? Might not be needed anymore. */
+#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode)
/* ASM_OUTPUT_EXTERNAL_LIBCALL defaults to just a globalize_label call,
but that doesn't put out the @function type information which causes
@@ -178,19 +178,45 @@ do { \
/* It is illegal to have relocations in shared segments on HPUX.
Pretend flag_pic is always set. */
-#undef TARGET_ASM_SELECT_SECTION
-#define TARGET_ASM_SELECT_SECTION ia64_rwreloc_select_section
-#undef TARGET_ASM_UNIQUE_SECTION
-#define TARGET_ASM_UNIQUE_SECTION ia64_rwreloc_unique_section
-#undef TARGET_ASM_SELECT_RTX_SECTION
-#define TARGET_ASM_SELECT_RTX_SECTION ia64_rwreloc_select_rtx_section
-#undef TARGET_SECTION_TYPE_FLAGS
-#define TARGET_SECTION_TYPE_FLAGS ia64_rwreloc_section_type_flags
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK ia64_hpux_reloc_rw_mask
/* ia64 HPUX has the float and long double forms of math functions. */
#undef TARGET_C99_FUNCTIONS
#define TARGET_C99_FUNCTIONS 1
+#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS ia64_hpux_init_libfuncs
#define FLOAT_LIB_COMPARE_RETURNS_BOOL(MODE, COMPARISON) ((MODE) == TFmode)
+
+/* Put all *xf routines in libgcc, regardless of long double size. */
+#undef LIBGCC2_HAS_XF_MODE
+#define LIBGCC2_HAS_XF_MODE 1
+#define XF_SIZE 64
+
+/* Put all *tf routines in libgcc, regardless of long double size. */
+#undef LIBGCC2_HAS_TF_MODE
+#define LIBGCC2_HAS_TF_MODE 1
+#define TF_SIZE 113
+
+/* HP-UX headers are C++-compatible. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* HP-UX uses PROFILE_HOOK instead of FUNCTION_PROFILER but we need a
+ FUNCTION_PROFILER defined because its use is not ifdefed. When using
+ PROFILE_HOOK, the profile call comes after the prologue. */
+
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE, LABELNO) do { } while (0)
+
+#undef PROFILE_HOOK
+#define PROFILE_HOOK(LABEL) ia64_profile_hook (LABEL)
+
+#undef PROFILE_BEFORE_PROLOGUE
+
+#undef NO_PROFILE_COUNTERS
+#define NO_PROFILE_COUNTERS 0
+
+#undef HANDLE_PRAGMA_PACK_PUSH_POP
+#define HANDLE_PRAGMA_PACK_PUSH_POP
diff --git a/contrib/gcc/config/ia64/ia64-c.c b/contrib/gcc/config/ia64/ia64-c.c
index 422fc86..9bb2a80 100644
--- a/contrib/gcc/config/ia64/ia64-c.c
+++ b/contrib/gcc/config/ia64/ia64-c.c
@@ -1,5 +1,5 @@
/* Definitions of C specific functions for GNU compiler.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Steve Ellcey <sje@cup.hp.com>
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -40,16 +40,16 @@ ia64_hpux_handle_builtin_pragma (cpp_reader *pfile ATTRIBUTE_UNUSED)
enum cpp_ttype type;
tree x;
- type = c_lex (&x);
+ type = pragma_lex (&x);
while (type == CPP_NAME)
{
ia64_hpux_add_pragma_builtin (x);
- type = c_lex (&x);
+ type = pragma_lex (&x);
if (type == CPP_COMMA)
- type = c_lex (&x);
+ type = pragma_lex (&x);
}
if (type != CPP_EOF)
- warning ("malformed #pragma builtin");
+ warning (OPT_Wpragmas, "malformed #pragma builtin");
}
/* List of standard math functions which do not set matherr by default
@@ -60,7 +60,7 @@ ia64_hpux_handle_builtin_pragma (cpp_reader *pfile ATTRIBUTE_UNUSED)
typedef struct c89_mathlib_names
{
const char *realname; /* User visible function name. */
- const char *c89name; /* libm special name needed to set errno. */
+ const char *c89name; /* libm special name needed to set errno. */
} c89_mathlib_names;
static const c89_mathlib_names c89_mathlib_name_list [] =
diff --git a/contrib/gcc/config/ia64/ia64-modes.def b/contrib/gcc/config/ia64/ia64-modes.def
index 17688bd..c7e9927 100644
--- a/contrib/gcc/config/ia64/ia64-modes.def
+++ b/contrib/gcc/config/ia64/ia64-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -17,43 +17,52 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* IA64 requires both XF and TF modes.
XFmode is __float80 is IEEE extended; TFmode is __float128
- is IEEE quad.
+ is IEEE quad. Both these modes occupy 16 bytes, but XFmode
+ only has 80 significant bits. RFmode is __fpreg is IA64 internal
+ register format with 82 significant bits but otherwise handled like
+ XFmode. */
- IEEE extended is 128 bits wide, except in ILP32 mode, but we
- have to say it's 12 bytes so that the bitsize and wider_mode
- tables are correctly set up. We correct its size below. */
-
-FLOAT_MODE (XF, 12, ieee_extended_intel_128_format);
+FRACTIONAL_FLOAT_MODE (XF, 80, 16, ieee_extended_intel_128_format);
+FRACTIONAL_FLOAT_MODE (RF, 82, 16, ieee_extended_intel_128_format);
FLOAT_MODE (TF, 16, ieee_quad_format);
/* The above produces:
mode ILP32 size/align LP64 size/align
- XF 12/4 12/4
+ XF 16/16 16/16
TF 16/16 16/16
psABI expectations:
mode ILP32 size/align LP64 size/align
- XF - 16/16
+ XF 12/4 -
TF - -
HPUX expectations:
mode ILP32 size/align LP64 size/align
- XF 16/16 16/16
+ XF - -
TF 16/8 -
We fix this up here. */
+ADJUST_FLOAT_FORMAT (XF, (TARGET_ILP32 && !TARGET_HPUX)
+ ? &ieee_extended_intel_96_format
+ : &ieee_extended_intel_128_format);
ADJUST_BYTESIZE (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
ADJUST_ALIGNMENT (XF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
+ADJUST_FLOAT_FORMAT (RF, (TARGET_ILP32 && !TARGET_HPUX)
+ ? &ieee_extended_intel_96_format
+ : &ieee_extended_intel_128_format);
+ADJUST_BYTESIZE (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 12 : 16);
+ADJUST_ALIGNMENT (RF, (TARGET_ILP32 && !TARGET_HPUX) ? 4 : 16);
+
ADJUST_ALIGNMENT (TF, (TARGET_ILP32 && TARGET_HPUX) ? 8 : 16);
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
@@ -66,3 +75,13 @@ INT_MODE (OI, 32);
so that flow doesn't do something stupid. */
CC_MODE (CCI);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODE (INT, QI, 16);
+VECTOR_MODE (INT, HI, 8);
+VECTOR_MODE (INT, SI, 4);
+VECTOR_MODE (FLOAT, SF, 2);
+VECTOR_MODE (FLOAT, SF, 4);
+
diff --git a/contrib/gcc/config/ia64/ia64-protos.h b/contrib/gcc/config/ia64/ia64-protos.h
index 7825616..c4bf61d 100644
--- a/contrib/gcc/config/ia64/ia64-protos.h
+++ b/contrib/gcc/config/ia64/ia64-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler for IA-64.
- Copyright (C) 1999, 2000, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Variables defined in ia64.c. */
@@ -33,74 +33,44 @@ extern int bundling_p;
extern int ia64_st_address_bypass_p (rtx, rtx);
extern int ia64_ld_address_bypass_p (rtx, rtx);
extern int ia64_produce_address_p (rtx);
-extern int call_operand (rtx, enum machine_mode);
-extern int sdata_symbolic_operand (rtx, enum machine_mode);
-extern int got_symbolic_operand (rtx, enum machine_mode);
-extern int symbolic_operand (rtx, enum machine_mode);
-extern int tls_symbolic_operand (rtx, enum machine_mode);
-extern int function_operand (rtx, enum machine_mode);
-extern int setjmp_operand (rtx, enum machine_mode);
-extern int move_operand (rtx, enum machine_mode);
-extern int gr_register_operand (rtx, enum machine_mode);
-extern int fr_register_operand (rtx, enum machine_mode);
-extern int grfr_register_operand (rtx, enum machine_mode);
-extern int gr_nonimmediate_operand (rtx, enum machine_mode);
-extern int fr_nonimmediate_operand (rtx, enum machine_mode);
-extern int grfr_nonimmediate_operand (rtx, enum machine_mode);
-extern int gr_reg_or_0_operand (rtx, enum machine_mode);
-extern int gr_reg_or_5bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_6bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_operand (rtx, enum machine_mode);
-extern int grfr_reg_or_8bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_adjusted_operand (rtx, enum machine_mode);
-extern int gr_reg_or_8bit_and_adjusted_operand (rtx, enum machine_mode);
-extern int gr_reg_or_14bit_operand (rtx, enum machine_mode);
-extern int gr_reg_or_22bit_operand (rtx, enum machine_mode);
-extern int shift_count_operand (rtx, enum machine_mode);
-extern int shift_32bit_count_operand (rtx, enum machine_mode);
-extern int shladd_operand (rtx, enum machine_mode);
-extern int fetchadd_operand (rtx, enum machine_mode);
-extern int fr_reg_or_fp01_operand (rtx, enum machine_mode);
-extern int normal_comparison_operator (rtx, enum machine_mode);
-extern int adjusted_comparison_operator (rtx, enum machine_mode);
-extern int signed_inequality_operator (rtx, enum machine_mode);
-extern int destination_operand (rtx, enum machine_mode);
-extern int not_postinc_memory_operand (rtx, enum machine_mode);
-extern int predicate_operator (rtx, enum machine_mode);
-extern int ar_lc_reg_operand (rtx, enum machine_mode);
-extern int ar_ccv_reg_operand (rtx, enum machine_mode);
-extern int ar_pfs_reg_operand (rtx, enum machine_mode);
-extern int general_xfmode_operand (rtx, enum machine_mode);
-extern int destination_xfmode_operand (rtx, enum machine_mode);
-extern int xfreg_or_fp01_operand (rtx, enum machine_mode);
-extern int basereg_operand (rtx, enum machine_mode);
+
+extern bool ia64_const_ok_for_letter_p (HOST_WIDE_INT, char);
+extern bool ia64_const_double_ok_for_letter_p (rtx, char);
+extern bool ia64_extra_constraint (rtx, char);
+extern bool ia64_legitimate_constant_p (rtx);
extern rtx ia64_expand_move (rtx, rtx);
extern int ia64_move_ok (rtx, rtx);
+extern int ia64_load_pair_ok (rtx, rtx);
extern int addp4_optimize_ok (rtx, rtx);
extern void ia64_emit_cond_move (rtx, rtx, rtx);
extern int ia64_depz_field_mask (rtx, rtx);
extern void ia64_split_tmode_move (rtx[]);
-extern rtx spill_xfmode_operand (rtx, int);
+extern bool ia64_expand_movxf_movrf (enum machine_mode, rtx[]);
extern rtx ia64_expand_compare (enum rtx_code, enum machine_mode);
+extern void ia64_expand_vecint_cmov (rtx[]);
+extern bool ia64_expand_vecint_minmax (enum rtx_code, enum machine_mode, rtx[]);
+extern void ia64_expand_widen_sum (rtx[], bool);
+extern void ia64_expand_dot_prod_v8qi (rtx[], bool);
extern void ia64_expand_call (rtx, rtx, rtx, int);
extern void ia64_split_call (rtx, rtx, rtx, rtx, rtx, int, int);
extern void ia64_reload_gp (void);
+extern void ia64_expand_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx);
extern HOST_WIDE_INT ia64_initial_elimination_offset (int, int);
extern void ia64_expand_prologue (void);
extern void ia64_expand_epilogue (int);
extern int ia64_direct_return (void);
-extern void ia64_expand_load_address (rtx, rtx);
+extern bool ia64_expand_load_address (rtx, rtx);
extern int ia64_hard_regno_rename_ok (int, int);
extern void ia64_initialize_trampoline (rtx, rtx, rtx);
extern void ia64_print_operand_address (FILE *, rtx);
extern void ia64_print_operand (FILE *, rtx, int);
+extern enum reg_class ia64_preferred_reload_class (rtx, enum reg_class);
extern enum reg_class ia64_secondary_reload_class (enum reg_class,
enum machine_mode, rtx);
-extern void ia64_output_dwarf_dtprel (FILE*, int, rtx);
extern void process_for_unwind_directive (FILE *, rtx);
extern const char *get_bundle_name (int);
#endif /* RTX_CODE */
@@ -114,15 +84,9 @@ extern rtx ia64_va_arg (tree, tree);
extern rtx ia64_function_value (tree, tree);
#endif /* RTX_CODE */
-extern void ia64_setup_incoming_varargs (CUMULATIVE_ARGS, int, tree,
- int *, int);
-extern int ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
extern void ia64_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
tree, int);
-extern int ia64_function_arg_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern int ia64_return_in_memory (tree);
+extern int ia64_function_arg_boundary (enum machine_mode, tree);
extern void ia64_asm_output_external (FILE *, tree, const char *);
#endif /* TREE_CODE */
@@ -138,17 +102,13 @@ extern int ia64_dbx_register_number (int);
extern rtx ia64_return_addr_rtx (HOST_WIDE_INT, rtx);
extern void ia64_split_return_addr_rtx (rtx);
-#ifdef SDATA_SECTION_ASM_OP
-extern void sdata_section (void);
-#endif
-
-#ifdef SBSS_SECTION_ASM_OP
-extern void sbss_section (void);
-#endif
-
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction'. */
extern enum direction ia64_hpux_function_arg_padding (enum machine_mode, tree);
#endif /* ARGS_SIZE_RTX */
extern void ia64_hpux_handle_builtin_pragma (struct cpp_reader *);
+extern void ia64_output_function_profiler (FILE *, int);
+extern void ia64_profile_hook (int);
+
+extern void ia64_optimization_options (int, int);
diff --git a/contrib/gcc/config/ia64/ia64.c b/contrib/gcc/config/ia64/ia64.c
index c215b19..6ddff32 100644
--- a/contrib/gcc/config/ia64/ia64.c
+++ b/contrib/gcc/config/ia64/ia64.c
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler.
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -51,6 +51,10 @@ Boston, MA 02111-1307, USA. */
#include "hashtab.h"
#include "langhooks.h"
#include "cfglayout.h"
+#include "tree-gimple.h"
+#include "intl.h"
+#include "debug.h"
+#include "params.h"
/* This is used for communication between ASM_OUTPUT_LABEL and
ASM_OUTPUT_LABELREF. */
@@ -97,26 +101,17 @@ static const char * const ia64_local_reg_names[80] =
static const char * const ia64_output_reg_names[8] =
{ "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7" };
-/* String used with the -mfixed-range= option. */
-const char *ia64_fixed_range_string;
-
-/* Determines whether we use adds, addl, or movl to generate our
- TLS immediate offsets. */
-int ia64_tls_size = 22;
-
-/* String used with the -mtls-size= option. */
-const char *ia64_tls_size_string;
-
/* Which cpu are we scheduling for. */
-enum processor_type ia64_tune;
-
-/* String used with the -tune= option. */
-const char *ia64_tune_string;
+enum processor_type ia64_tune = PROCESSOR_ITANIUM2;
/* Determines whether we run our final scheduling pass or not. We always
avoid the normal second scheduling pass. */
static int ia64_flag_schedule_insns2;
+/* Determines whether we run variable tracking in machine dependent
+ reorganization. */
+static int ia64_flag_var_tracking;
+
/* Variables which are this size or smaller are put in the sdata/sbss
sections. */
@@ -159,16 +154,24 @@ struct ia64_frame_info
/* Current frame information calculated by ia64_compute_frame_size. */
static struct ia64_frame_info current_frame_info;
-static int ia64_use_dfa_pipeline_interface (void);
static int ia64_first_cycle_multipass_dfa_lookahead (void);
static void ia64_dependencies_evaluation_hook (rtx, rtx);
static void ia64_init_dfa_pre_cycle_insn (void);
static rtx ia64_dfa_pre_cycle_insn (void);
static int ia64_first_cycle_multipass_dfa_lookahead_guard (rtx);
+static bool ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx);
static int ia64_dfa_new_cycle (FILE *, int, rtx, int, int, int *);
+static void ia64_h_i_d_extended (void);
+static int ia64_mode_to_int (enum machine_mode);
+static void ia64_set_sched_flags (spec_info_t);
+static int ia64_speculate_insn (rtx, ds_t, rtx *);
+static rtx ia64_gen_spec_insn (rtx, ds_t, int, bool, bool);
+static bool ia64_needs_block_p (rtx);
+static rtx ia64_gen_check (rtx, rtx, bool);
+static int ia64_spec_check_p (rtx);
+static int ia64_spec_check_src_p (rtx);
static rtx gen_tls_get_addr (void);
static rtx gen_thread_pointer (void);
-static rtx ia64_expand_tls_address (enum tls_model, rtx, rtx);
static int find_gr_spill (int);
static int next_scratch_gr_reg (void);
static void mark_reg_gr_used_mask (rtx, void *);
@@ -182,10 +185,16 @@ static rtx gen_movdi_x (rtx, rtx, rtx);
static rtx gen_fr_spill_x (rtx, rtx, rtx);
static rtx gen_fr_restore_x (rtx, rtx, rtx);
-static enum machine_mode hfa_element_mode (tree, int);
+static enum machine_mode hfa_element_mode (tree, bool);
+static void ia64_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int *, int);
+static int ia64_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
static bool ia64_function_ok_for_sibcall (tree, tree);
+static bool ia64_return_in_memory (tree, tree);
static bool ia64_rtx_costs (rtx, int, int, int *);
static void fix_range (const char *);
+static bool ia64_handle_option (size_t, const char *, int);
static struct machine_function * ia64_init_machine_status (void);
static void emit_insn_group_barriers (FILE *);
static void emit_all_insn_group_barriers (FILE *);
@@ -193,23 +202,19 @@ static void final_emit_insn_group_barriers (FILE *);
static void emit_predicate_relation_info (void);
static void ia64_reorg (void);
static bool ia64_in_small_data_p (tree);
-static void process_epilogue (void);
-static int process_set (FILE *, rtx);
-
-static rtx ia64_expand_fetch_and_op (optab, enum machine_mode, tree, rtx);
-static rtx ia64_expand_op_and_fetch (optab, enum machine_mode, tree, rtx);
-static rtx ia64_expand_compare_and_swap (enum machine_mode, enum machine_mode,
- int, tree, rtx);
-static rtx ia64_expand_lock_test_and_set (enum machine_mode, tree, rtx);
-static rtx ia64_expand_lock_release (enum machine_mode, tree, rtx);
+static void process_epilogue (FILE *, rtx, bool, bool);
+static int process_set (FILE *, rtx, rtx, bool, bool);
+
static bool ia64_assemble_integer (rtx, unsigned int, int);
static void ia64_output_function_prologue (FILE *, HOST_WIDE_INT);
static void ia64_output_function_epilogue (FILE *, HOST_WIDE_INT);
static void ia64_output_function_end_prologue (FILE *);
static int ia64_issue_rate (void);
-static int ia64_adjust_cost (rtx, rtx, rtx, int);
+static int ia64_adjust_cost_2 (rtx, int, rtx, int);
static void ia64_sched_init (FILE *, int, int);
+static void ia64_sched_init_global (FILE *, int, int);
+static void ia64_sched_finish_global (FILE *, int);
static void ia64_sched_finish (FILE *, int);
static int ia64_dfa_sched_reorder (FILE *, int, rtx *, int *, int, int);
static int ia64_sched_reorder (FILE *, int, rtx *, int *, int);
@@ -238,31 +243,37 @@ static void ia64_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static void ia64_file_start (void);
-static void ia64_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
-static void ia64_rwreloc_select_section (tree, int, unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_unique_section (tree, int)
+static int ia64_hpux_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
+static int ia64_reloc_rw_mask (void) ATTRIBUTE_UNUSED;
+static section *ia64_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+static void ia64_output_dwarf_dtprel (FILE *, int, rtx)
ATTRIBUTE_UNUSED;
-static void ia64_rwreloc_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
-static unsigned int ia64_rwreloc_section_type_flags (tree, const char *, int)
- ATTRIBUTE_UNUSED;
-
+static unsigned int ia64_section_type_flags (tree, const char *, int);
static void ia64_hpux_add_extern_decl (tree decl)
ATTRIBUTE_UNUSED;
static void ia64_hpux_file_end (void)
ATTRIBUTE_UNUSED;
+static void ia64_init_libfuncs (void)
+ ATTRIBUTE_UNUSED;
static void ia64_hpux_init_libfuncs (void)
ATTRIBUTE_UNUSED;
+static void ia64_sysv4_init_libfuncs (void)
+ ATTRIBUTE_UNUSED;
static void ia64_vms_init_libfuncs (void)
ATTRIBUTE_UNUSED;
static tree ia64_handle_model_attribute (tree *, tree, tree, int, bool *);
static void ia64_encode_section_info (tree, rtx, int);
static rtx ia64_struct_value_rtx (tree, int);
-
+static tree ia64_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool ia64_scalar_mode_supported_p (enum machine_mode mode);
+static bool ia64_vector_mode_supported_p (enum machine_mode mode);
+static bool ia64_cannot_force_const_mem (rtx);
+static const char *ia64_mangle_fundamental_type (tree);
+static const char *ia64_invalid_conversion (tree, tree);
+static const char *ia64_invalid_unary_op (int, tree);
+static const char *ia64_invalid_binary_op (int, tree, tree);
/* Table of valid machine attributes. */
static const struct attribute_spec ia64_attribute_table[] =
@@ -310,8 +321,8 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_IN_SMALL_DATA_P
#define TARGET_IN_SMALL_DATA_P ia64_in_small_data_p
-#undef TARGET_SCHED_ADJUST_COST
-#define TARGET_SCHED_ADJUST_COST ia64_adjust_cost
+#undef TARGET_SCHED_ADJUST_COST_2
+#define TARGET_SCHED_ADJUST_COST_2 ia64_adjust_cost_2
#undef TARGET_SCHED_ISSUE_RATE
#define TARGET_SCHED_ISSUE_RATE ia64_issue_rate
#undef TARGET_SCHED_VARIABLE_ISSUE
@@ -320,6 +331,10 @@ static const struct attribute_spec ia64_attribute_table[] =
#define TARGET_SCHED_INIT ia64_sched_init
#undef TARGET_SCHED_FINISH
#define TARGET_SCHED_FINISH ia64_sched_finish
+#undef TARGET_SCHED_INIT_GLOBAL
+#define TARGET_SCHED_INIT_GLOBAL ia64_sched_init_global
+#undef TARGET_SCHED_FINISH_GLOBAL
+#define TARGET_SCHED_FINISH_GLOBAL ia64_sched_finish_global
#undef TARGET_SCHED_REORDER
#define TARGET_SCHED_REORDER ia64_sched_reorder
#undef TARGET_SCHED_REORDER2
@@ -328,9 +343,6 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK
#define TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK ia64_dependencies_evaluation_hook
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE ia64_use_dfa_pipeline_interface
-
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD ia64_first_cycle_multipass_dfa_lookahead
@@ -346,8 +358,29 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_SCHED_DFA_NEW_CYCLE
#define TARGET_SCHED_DFA_NEW_CYCLE ia64_dfa_new_cycle
+#undef TARGET_SCHED_H_I_D_EXTENDED
+#define TARGET_SCHED_H_I_D_EXTENDED ia64_h_i_d_extended
+
+#undef TARGET_SCHED_SET_SCHED_FLAGS
+#define TARGET_SCHED_SET_SCHED_FLAGS ia64_set_sched_flags
+
+#undef TARGET_SCHED_SPECULATE_INSN
+#define TARGET_SCHED_SPECULATE_INSN ia64_speculate_insn
+
+#undef TARGET_SCHED_NEEDS_BLOCK_P
+#define TARGET_SCHED_NEEDS_BLOCK_P ia64_needs_block_p
+
+#undef TARGET_SCHED_GEN_CHECK
+#define TARGET_SCHED_GEN_CHECK ia64_gen_check
+
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD_GUARD_SPEC\
+ ia64_first_cycle_multipass_dfa_lookahead_guard_spec
+
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL ia64_function_ok_for_sibcall
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES ia64_arg_partial_bytes
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK ia64_output_mi_thunk
@@ -368,639 +401,78 @@ static const struct attribute_spec ia64_attribute_table[] =
#undef TARGET_ENCODE_SECTION_INFO
#define TARGET_ENCODE_SECTION_INFO ia64_encode_section_info
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
-
-struct gcc_target targetm = TARGET_INITIALIZER;
-
-/* Return 1 if OP is a valid operand for the MEM of a CALL insn. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != GET_MODE (op) && mode != VOIDmode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG
- || (GET_CODE (op) == SUBREG && GET_CODE (XEXP (op, 0)) == REG));
-}
-
-/* Return 1 if OP refers to a symbol in the sdata section. */
-
-int
-sdata_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT offset = 0, size = 0;
-
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS
- || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
- || GET_CODE (XEXP (op, 1)) != CONST_INT)
- break;
- offset = INTVAL (XEXP (op, 1));
- op = XEXP (op, 0);
- /* FALLTHRU */
-
- case SYMBOL_REF:
- if (CONSTANT_POOL_ADDRESS_P (op))
- {
- size = GET_MODE_SIZE (get_pool_mode (op));
- if (size > ia64_section_threshold)
- return false;
- }
- else
- {
- tree t;
-
- if (!SYMBOL_REF_LOCAL_P (op) || !SYMBOL_REF_SMALL_P (op))
- return false;
-
- /* Note that in addition to DECLs, we can get various forms
- of constants here. */
- t = SYMBOL_REF_DECL (op);
- if (DECL_P (t))
- t = DECL_SIZE_UNIT (t);
- else
- t = TYPE_SIZE_UNIT (TREE_TYPE (t));
- if (t && host_integerp (t, 0))
- {
- size = tree_low_cst (t, 0);
- if (size < 0)
- size = 0;
- }
- }
-
- /* Deny the stupid user trick of addressing outside the object. Such
- things quickly result in GPREL22 relocation overflows. Of course,
- they're also highly undefined. From a pure pedant's point of view
- they deserve a slap on the wrist (such as provided by a relocation
- overflow), but that just leads to bugzilla noise. */
- return (offset >= 0 && offset <= size);
-
- default:
- break;
- }
-
- return 0;
-}
-
-int
-small_addr_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return SYMBOL_REF_SMALL_ADDR_P (op);
-}
-
-/* Return 1 if OP refers to a symbol, and is appropriate for a GOT load. */
-
-int
-got_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- op = XEXP (op, 0);
- if (GET_CODE (op) != PLUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- op = XEXP (op, 1);
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- return 1;
-
- /* Ok if we're not using GOT entries at all. */
- if (TARGET_NO_PIC || TARGET_AUTO_PIC)
- return 1;
-
- /* "Ok" while emitting rtl, since otherwise we won't be provided
- with the entire offset during emission, which makes it very
- hard to split the offset into high and low parts. */
- if (rtx_equal_function_value_matters)
- return 1;
-
- /* Force the low 14 bits of the constant to zero so that we do not
- use up so many GOT entries. */
- return (INTVAL (op) & 0x3fff) == 0;
-
- case SYMBOL_REF:
- if (SYMBOL_REF_SMALL_ADDR_P (op))
- return 0;
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return 1 if OP refers to a symbol. */
-
-int
-symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- default:
- break;
- }
- return 0;
-}
-
-/* Return tls_model if OP refers to a TLS symbol. */
-
-int
-tls_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-
-/* Return 1 if OP refers to a function. */
-
-int
-function_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (op))
- return 1;
- else
- return 0;
-}
-
-/* Return 1 if OP is setjmp or a similar function. */
-
-/* ??? This is an unsatisfying solution. Should rethink. */
-
-int
-setjmp_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- const char *name;
- int retval = 0;
-
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
-
- name = XSTR (op, 0);
-
- /* The following code is borrowed from special_function_p in calls.c. */
-
- /* Disregard prefix _, __ or __x. */
- if (name[0] == '_')
- {
- if (name[1] == '_' && name[2] == 'x')
- name += 3;
- else if (name[1] == '_')
- name += 2;
- else
- name += 1;
- }
-
- if (name[0] == 's')
- {
- retval
- = ((name[1] == 'e'
- && (! strcmp (name, "setjmp")
- || ! strcmp (name, "setjmp_syscall")))
- || (name[1] == 'i'
- && ! strcmp (name, "sigsetjmp"))
- || (name[1] == 'a'
- && ! strcmp (name, "savectx")));
- }
- else if ((name[0] == 'q' && name[1] == 's'
- && ! strcmp (name, "qsetjmp"))
- || (name[0] == 'v' && name[1] == 'f'
- && ! strcmp (name, "vfork")))
- retval = 1;
-
- return retval;
-}
-
-/* Return 1 if OP is a general operand, excluding tls symbolic operands. */
-
-int
-move_operand (rtx op, enum machine_mode mode)
-{
- return general_operand (op, mode) && !tls_symbolic_operand (op, mode);
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR reg. */
-
-int
-gr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) an FR reg. */
-
-int
-fr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a register operand that is (or could be) a GR/FR reg. */
-
-int
-grfr_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a GR reg. */
-
-int
-gr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is (or could be) a FR reg. */
-
-int
-fr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a nonimmediate operand that is a GR/FR reg. */
-
-int
-grfr_nonimmediate_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) == REG)
- {
- unsigned int regno = REGNO (op);
- if (regno < FIRST_PSEUDO_REGISTER)
- return GENERAL_REGNO_P (regno) || FR_REGNO_P (regno);
- }
- return 1;
-}
-
-/* Return 1 if OP is a GR register operand, or zero. */
-
-int
-gr_reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- return (op == const0_rtx || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 5 bit immediate operand. */
-
-int
-gr_reg_or_5bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && INTVAL (op) >= 0 && INTVAL (op) < 32)
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or a 6 bit immediate operand. */
-
-int
-gr_reg_or_6bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR register operand, or an 8 bit immediate operand. */
-
-int
-gr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a GR/FR register operand, or an 8 bit immediate. */
-
-int
-grfr_reg_or_8bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || grfr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or an 8 bit adjusted immediate
- operand. */
-
-int
-gr_reg_or_8bit_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_L (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or is valid for both an 8 bit
- immediate and an 8 bit adjusted immediate operand. This is necessary
- because when we emit a compare, we don't know what the condition will be,
- so we need the union of the immediates accepted by GT and LT. */
-
-int
-gr_reg_or_8bit_and_adjusted_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_K (INTVAL (op))
- && CONST_OK_FOR_L (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 14 bit immediate operand. */
-
-int
-gr_reg_or_14bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_I (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a register operand, or a 22 bit immediate operand. */
-
-int
-gr_reg_or_22bit_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_J (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX
- || gr_register_operand (op, mode));
-}
-
-/* Return 1 if OP is a 6 bit immediate operand. */
-
-int
-shift_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT && CONST_OK_FOR_M (INTVAL (op)))
- || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 5 bit immediate operand. */
-
-int
-shift_32bit_count_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= 0 && INTVAL (op) < 32))
- || GET_CODE (op) == CONSTANT_P_RTX);
-}
-
-/* Return 1 if OP is a 2, 4, 8, or 16 immediate operand. */
-
-int
-shladd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == 2 || INTVAL (op) == 4
- || INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a -16, -8, -4, -1, 1, 4, 8, or 16 immediate operand. */
-
-int
-fetchadd_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (INTVAL (op) == -16 || INTVAL (op) == -8 ||
- INTVAL (op) == -4 || INTVAL (op) == -1 ||
- INTVAL (op) == 1 || INTVAL (op) == 4 ||
- INTVAL (op) == 8 || INTVAL (op) == 16));
-}
-
-/* Return 1 if OP is a floating-point constant zero, one, or a register. */
-
-int
-fr_reg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (op))
- || fr_register_operand (op, mode));
-}
-
-/* Like nonimmediate_operand, but don't allow MEMs that try to use a
- POST_MODIFY with a REG as displacement. */
-
-int
-destination_operand (rtx op, enum machine_mode mode)
-{
- if (! nonimmediate_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM
- && GET_CODE (XEXP (op, 0)) == POST_MODIFY
- && GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) == REG)
- return 0;
- return 1;
-}
-
-/* Like memory_operand, but don't allow post-increments. */
-
-int
-not_postinc_memory_operand (rtx op, enum machine_mode mode)
-{
- return (memory_operand (op, mode)
- && GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != 'a');
-}
-
-/* Return 1 if this is a comparison operator, which accepts a normal 8-bit
- signed immediate operand. */
-
-int
-normal_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == EQ || code == NE
- || code == GT || code == LE || code == GTU || code == LEU));
-}
-
-/* Return 1 if this is a comparison operator, which accepts an adjusted 8-bit
- signed immediate operand. */
-
-int
-adjusted_comparison_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == LT || code == GE || code == LTU || code == GEU));
-}
-
-/* Return 1 if this is a signed inequality operator. */
-
-int
-signed_inequality_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((mode == VOIDmode || GET_MODE (op) == mode)
- && (code == GE || code == GT
- || code == LE || code == LT));
-}
-
-/* Return 1 if this operator is valid for predication. */
+#undef TARGET_SECTION_TYPE_FLAGS
+#define TARGET_SECTION_TYPE_FLAGS ia64_section_type_flags
-int
-predicate_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == EQ || code == NE));
-}
-
-/* Return 1 if this operator can be used in a conditional operation. */
-
-int
-condop_operator (register rtx op, enum machine_mode mode)
-{
- enum rtx_code code = GET_CODE (op);
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && (code == PLUS || code == MINUS || code == AND
- || code == IOR || code == XOR));
-}
-
-/* Return 1 if this is the ar.lc register. */
-
-int
-ar_lc_reg_operand (register rtx op, enum machine_mode mode)
-{
- return (GET_MODE (op) == DImode
- && (mode == DImode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_LC_REGNUM);
-}
-
-/* Return 1 if this is the ar.ccv register. */
-
-int
-ar_ccv_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_CCV_REGNUM);
-}
-
-/* Return 1 if this is the ar.pfs register. */
-
-int
-ar_pfs_reg_operand (register rtx op, enum machine_mode mode)
-{
- return ((GET_MODE (op) == mode || mode == VOIDmode)
- && GET_CODE (op) == REG
- && REGNO (op) == AR_PFS_REGNUM);
-}
-
-/* Like general_operand, but don't allow (mem (addressof)). */
-
-int
-general_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! general_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
-
-/* Similarly. */
-
-int
-destination_xfmode_operand (rtx op, enum machine_mode mode)
-{
- if (! destination_operand (op, mode))
- return 0;
- if (GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 0;
- return 1;
-}
+#ifdef HAVE_AS_TLS
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL ia64_output_dwarf_dtprel
+#endif
-/* Similarly. */
+/* ??? ABI doesn't allow us to define this. */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#endif
-int
-xfreg_or_fp01_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == SUBREG)
- return 0;
- return fr_reg_or_fp01_operand (op, mode);
-}
+/* ??? ABI doesn't allow us to define this. */
+#if 0
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#endif
-/* Return 1 if OP is valid as a base register in a reg + offset address. */
+/* ??? Investigate. */
+#if 0
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+#endif
-int
-basereg_operand (rtx op, enum machine_mode mode)
-{
- /* ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
- checks from pa.c basereg_operand as well? Seems to be OK without them
- in test runs. */
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX ia64_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY ia64_return_in_memory
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS ia64_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR ia64_gimplify_va_arg
+
+#undef TARGET_UNWIND_EMIT
+#define TARGET_UNWIND_EMIT process_for_unwind_directive
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P ia64_scalar_mode_supported_p
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p
+
+/* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur
+ in an order different from the specified program order. */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | TARGET_CPU_DEFAULT)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION ia64_handle_option
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM ia64_cannot_force_const_mem
+
+#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
+#define TARGET_MANGLE_FUNDAMENTAL_TYPE ia64_mangle_fundamental_type
+
+#undef TARGET_INVALID_CONVERSION
+#define TARGET_INVALID_CONVERSION ia64_invalid_conversion
+#undef TARGET_INVALID_UNARY_OP
+#define TARGET_INVALID_UNARY_OP ia64_invalid_unary_op
+#undef TARGET_INVALID_BINARY_OP
+#define TARGET_INVALID_BINARY_OP ia64_invalid_binary_op
- return (register_operand (op, mode) &&
- REG_POINTER ((GET_CODE (op) == SUBREG) ? SUBREG_REG (op) : op));
-}
+struct gcc_target targetm = TARGET_INITIALIZER;
typedef enum
{
@@ -1043,7 +515,8 @@ ia64_get_addr_area (tree decl)
}
static tree
-ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+ia64_handle_model_attribute (tree *node, tree name, tree args,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
{
ia64_addr_area addr_area = ADDR_AREA_NORMAL;
ia64_addr_area area;
@@ -1057,7 +530,7 @@ ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBU
}
else
{
- warning ("invalid argument of `%s' attribute",
+ warning (OPT_Wattributes, "invalid argument of %qs attribute",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
@@ -1070,26 +543,27 @@ ia64_handle_model_attribute (tree *node, tree name, tree args, int flags ATTRIBU
&& !TREE_STATIC (decl))
{
error ("%Jan address area attribute cannot be specified for "
- "local variables", decl, decl);
+ "local variables", decl);
*no_add_attrs = true;
}
area = ia64_get_addr_area (decl);
if (area != ADDR_AREA_NORMAL && addr_area != area)
{
- error ("%Jaddress area of '%s' conflicts with previous "
- "declaration", decl, decl);
+ error ("address area of %q+D conflicts with previous "
+ "declaration", decl);
*no_add_attrs = true;
}
break;
case FUNCTION_DECL:
error ("%Jaddress area attribute cannot be specified for functions",
- decl, decl);
+ decl);
*no_add_attrs = true;
break;
default:
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ warning (OPT_Wattributes, "%qs attribute ignored",
+ IDENTIFIER_POINTER (name));
*no_add_attrs = true;
break;
}
@@ -1107,7 +581,7 @@ ia64_encode_addr_area (tree decl, rtx symbol)
{
case ADDR_AREA_NORMAL: break;
case ADDR_AREA_SMALL: flags |= SYMBOL_FLAG_SMALL_ADDR; break;
- default: abort ();
+ default: gcc_unreachable ();
}
SYMBOL_REF_FLAGS (symbol) = flags;
}
@@ -1125,6 +599,102 @@ ia64_encode_section_info (tree decl, rtx rtl, int first)
ia64_encode_addr_area (decl, XEXP (rtl, 0));
}
+/* Implement CONST_OK_FOR_LETTER_P. */
+
+bool
+ia64_const_ok_for_letter_p (HOST_WIDE_INT value, char c)
+{
+ switch (c)
+ {
+ case 'I':
+ return CONST_OK_FOR_I (value);
+ case 'J':
+ return CONST_OK_FOR_J (value);
+ case 'K':
+ return CONST_OK_FOR_K (value);
+ case 'L':
+ return CONST_OK_FOR_L (value);
+ case 'M':
+ return CONST_OK_FOR_M (value);
+ case 'N':
+ return CONST_OK_FOR_N (value);
+ case 'O':
+ return CONST_OK_FOR_O (value);
+ case 'P':
+ return CONST_OK_FOR_P (value);
+ default:
+ return false;
+ }
+}
+
+/* Implement CONST_DOUBLE_OK_FOR_LETTER_P. */
+
+bool
+ia64_const_double_ok_for_letter_p (rtx value, char c)
+{
+ switch (c)
+ {
+ case 'G':
+ return CONST_DOUBLE_OK_FOR_G (value);
+ default:
+ return false;
+ }
+}
+
+/* Implement EXTRA_CONSTRAINT. */
+
+bool
+ia64_extra_constraint (rtx value, char c)
+{
+ switch (c)
+ {
+ case 'Q':
+ /* Non-volatile memory for FP_REG loads/stores. */
+ return memory_operand(value, VOIDmode) && !MEM_VOLATILE_P (value);
+
+ case 'R':
+ /* 1..4 for shladd arguments. */
+ return (GET_CODE (value) == CONST_INT
+ && INTVAL (value) >= 1 && INTVAL (value) <= 4);
+
+ case 'S':
+ /* Non-post-inc memory for asms and other unsavory creatures. */
+ return (GET_CODE (value) == MEM
+ && GET_RTX_CLASS (GET_CODE (XEXP (value, 0))) != RTX_AUTOINC
+ && (reload_in_progress || memory_operand (value, VOIDmode)));
+
+ case 'T':
+ /* Symbol ref to small-address-area. */
+ return small_addr_symbolic_operand (value, VOIDmode);
+
+ case 'U':
+ /* Vector zero. */
+ return value == CONST0_RTX (GET_MODE (value));
+
+ case 'W':
+ /* An integer vector, such that conversion to an integer yields a
+ value appropriate for an integer 'J' constraint. */
+ if (GET_CODE (value) == CONST_VECTOR
+ && GET_MODE_CLASS (GET_MODE (value)) == MODE_VECTOR_INT)
+ {
+ value = simplify_subreg (DImode, value, GET_MODE (value), 0);
+ return ia64_const_ok_for_letter_p (INTVAL (value), 'J');
+ }
+ return false;
+
+ case 'Y':
+ /* A V2SF vector containing elements that satisfy 'G'. */
+ return
+ (GET_CODE (value) == CONST_VECTOR
+ && GET_MODE (value) == V2SFmode
+ && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 0), 'G')
+ && ia64_const_double_ok_for_letter_p (XVECEXP (value, 0, 1), 'G'));
+
+ default:
+ return false;
+ }
+}
+
/* Return 1 if the operands of a move are ok. */
int
@@ -1148,6 +718,37 @@ ia64_move_ok (rtx dst, rtx src)
return GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src);
}
+/* Return 1 if the operands are ok for a floating point load pair. */
+
+int
+ia64_load_pair_ok (rtx dst, rtx src)
+{
+ if (GET_CODE (dst) != REG || !FP_REGNO_P (REGNO (dst)))
+ return 0;
+ if (GET_CODE (src) != MEM || MEM_VOLATILE_P (src))
+ return 0;
+ switch (GET_CODE (XEXP (src, 0)))
+ {
+ case REG:
+ case POST_INC:
+ break;
+ case POST_DEC:
+ return 0;
+ case POST_MODIFY:
+ {
+ rtx adjust = XEXP (XEXP (XEXP (src, 0), 1), 1);
+
+ if (GET_CODE (adjust) != CONST_INT
+ || INTVAL (adjust) != GET_MODE_SIZE (GET_MODE (src)))
+ return 0;
+ }
+ break;
+ default:
+ abort ();
+ }
+ return 1;
+}
+
int
addp4_optimize_ok (rtx op1, rtx op2)
{
@@ -1171,72 +772,158 @@ ia64_depz_field_mask (rtx rop, rtx rshift)
return exact_log2 (op + 1);
}
+/* Return the TLS model to use for ADDR. */
+
+static enum tls_model
+tls_symbolic_operand_type (rtx addr)
+{
+ enum tls_model tls_kind = 0;
+
+ if (GET_CODE (addr) == CONST)
+ {
+ if (GET_CODE (XEXP (addr, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addr, 0), 0)) == SYMBOL_REF)
+ tls_kind = SYMBOL_REF_TLS_MODEL (XEXP (XEXP (addr, 0), 0));
+ }
+ else if (GET_CODE (addr) == SYMBOL_REF)
+ tls_kind = SYMBOL_REF_TLS_MODEL (addr);
+
+ return tls_kind;
+}
+
+/* Return true if X is a constant that is valid for some immediate
+ field in an instruction. */
+
+bool
+ia64_legitimate_constant_p (rtx x)
+{
+ switch (GET_CODE (x))
+ {
+ case CONST_INT:
+ case LABEL_REF:
+ return true;
+
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode)
+ return true;
+ return CONST_DOUBLE_OK_FOR_G (x);
+
+ case CONST:
+ case SYMBOL_REF:
+ /* ??? Short term workaround for PR 28490. We must make the code here
+ match the code in ia64_expand_move and move_operand, even though they
+ are both technically wrong. */
+ if (tls_symbolic_operand_type (x) == 0)
+ {
+ HOST_WIDE_INT addend = 0;
+ rtx op = x;
+
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT)
+ {
+ addend = INTVAL (XEXP (XEXP (op, 0), 1));
+ op = XEXP (XEXP (op, 0), 0);
+ }
+
+ if (any_offset_symbol_operand (op, GET_MODE (op))
+ || function_operand (op, GET_MODE (op)))
+ return true;
+ if (aligned_offset_symbol_operand (op, GET_MODE (op)))
+ return (addend & 0x3fff) == 0;
+ return false;
+ }
+ return false;
+
+ case CONST_VECTOR:
+ {
+ enum machine_mode mode = GET_MODE (x);
+
+ if (mode == V2SFmode)
+ return ia64_extra_constraint (x, 'Y');
+
+ return (GET_MODE_CLASS (mode) == MODE_VECTOR_INT
+ && GET_MODE_SIZE (mode) <= 8);
+ }
+
+ default:
+ return false;
+ }
+}
+
+/* Don't allow TLS addresses to get spilled to memory. */
+
+static bool
+ia64_cannot_force_const_mem (rtx x)
+{
+ return tls_symbolic_operand_type (x) != 0;
+}
+
/* Expand a symbolic constant load. */
-void
+bool
ia64_expand_load_address (rtx dest, rtx src)
{
- if (tls_symbolic_operand (src, VOIDmode))
- abort ();
- if (GET_CODE (dest) != REG)
- abort ();
+ gcc_assert (GET_CODE (dest) == REG);
/* ILP32 mode still loads 64-bits of data from the GOT. This avoids
having to pointer-extend the value afterward. Other forms of address
computation below are also more natural to compute as 64-bit quantities.
If we've been given an SImode destination register, change it. */
if (GET_MODE (dest) != Pmode)
- dest = gen_rtx_REG (Pmode, REGNO (dest));
+ dest = gen_rtx_REG_offset (dest, Pmode, REGNO (dest), 0);
- if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (src))
- {
- emit_insn (gen_rtx_SET (VOIDmode, dest, src));
- return;
- }
- else if (TARGET_AUTO_PIC)
- {
- emit_insn (gen_load_gprel64 (dest, src));
- return;
- }
+ if (TARGET_NO_PIC)
+ return false;
+ if (small_addr_symbolic_operand (src, VOIDmode))
+ return false;
+
+ if (TARGET_AUTO_PIC)
+ emit_insn (gen_load_gprel64 (dest, src));
else if (GET_CODE (src) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (src))
- {
- emit_insn (gen_load_fptr (dest, src));
- return;
- }
+ emit_insn (gen_load_fptr (dest, src));
else if (sdata_symbolic_operand (src, VOIDmode))
+ emit_insn (gen_load_gprel (dest, src));
+ else
{
- emit_insn (gen_load_gprel (dest, src));
- return;
- }
+ HOST_WIDE_INT addend = 0;
+ rtx tmp;
- if (GET_CODE (src) == CONST
- && GET_CODE (XEXP (src, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (src, 0), 1)) == CONST_INT
- && (INTVAL (XEXP (XEXP (src, 0), 1)) & 0x1fff) != 0)
- {
- rtx sym = XEXP (XEXP (src, 0), 0);
- HOST_WIDE_INT ofs, hi, lo;
+ /* We did split constant offsets in ia64_expand_move, and we did try
+ to keep them split in move_operand, but we also allowed reload to
+ rematerialize arbitrary constants rather than spill the value to
+ the stack and reload it. So we have to be prepared here to split
+ them apart again. */
+ if (GET_CODE (src) == CONST)
+ {
+ HOST_WIDE_INT hi, lo;
- /* Split the offset into a sign extended 14-bit low part
- and a complementary high part. */
- ofs = INTVAL (XEXP (XEXP (src, 0), 1));
- lo = ((ofs & 0x3fff) ^ 0x2000) - 0x2000;
- hi = ofs - lo;
+ hi = INTVAL (XEXP (XEXP (src, 0), 1));
+ lo = ((hi & 0x3fff) ^ 0x2000) - 0x2000;
+ hi = hi - lo;
- ia64_expand_load_address (dest, plus_constant (sym, hi));
- emit_insn (gen_adddi3 (dest, dest, GEN_INT (lo)));
- }
- else
- {
- rtx tmp;
+ if (lo != 0)
+ {
+ addend = lo;
+ src = plus_constant (XEXP (XEXP (src, 0), 0), hi);
+ }
+ }
tmp = gen_rtx_HIGH (Pmode, src);
tmp = gen_rtx_PLUS (Pmode, tmp, pic_offset_table_rtx);
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
- tmp = gen_rtx_LO_SUM (GET_MODE (dest), dest, src);
+ tmp = gen_rtx_LO_SUM (Pmode, dest, src);
emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (Pmode, dest, GEN_INT (addend));
+ emit_insn (gen_rtx_SET (VOIDmode, dest, tmp));
+ }
}
+
+ return true;
}
static GTY(()) rtx gen_tls_tga;
@@ -1253,18 +940,17 @@ static rtx
gen_thread_pointer (void)
{
if (!thread_pointer_rtx)
- {
- thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
- RTX_UNCHANGING_P (thread_pointer_rtx) = 1;
- }
+ thread_pointer_rtx = gen_rtx_REG (Pmode, 13);
return thread_pointer_rtx;
}
static rtx
-ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
+ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1,
+ rtx orig_op1, HOST_WIDE_INT addend)
{
rtx tga_op1, tga_op2, tga_ret, tga_eqv, tmp, insns;
rtx orig_op0 = op0;
+ HOST_WIDE_INT addend_lo, addend_hi;
switch (tls_kind)
{
@@ -1272,14 +958,10 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
start_sequence ();
tga_op1 = gen_reg_rtx (Pmode);
- emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ emit_insn (gen_load_dtpmod (tga_op1, op1));
tga_op2 = gen_reg_rtx (Pmode);
- emit_insn (gen_load_ltoff_dtprel (tga_op2, op1));
- tga_op2 = gen_rtx_MEM (Pmode, tga_op2);
- RTX_UNCHANGING_P (tga_op2) = 1;
+ emit_insn (gen_load_dtprel (tga_op2, op1));
tga_ret = emit_library_call_value (gen_tls_get_addr (), NULL_RTX,
LCT_CONST, Pmode, 2, tga_op1,
@@ -1301,9 +983,7 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
start_sequence ();
tga_op1 = gen_reg_rtx (Pmode);
- emit_insn (gen_load_ltoff_dtpmod (tga_op1, op1));
- tga_op1 = gen_rtx_MEM (Pmode, tga_op1);
- RTX_UNCHANGING_P (tga_op1) = 1;
+ emit_insn (gen_load_dtpmod (tga_op1, op1));
tga_op2 = const0_rtx;
@@ -1327,15 +1007,18 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
emit_insn (gen_adddi3 (op0, tmp, op0));
}
else
- emit_insn (gen_add_dtprel (op0, tmp, op1));
+ emit_insn (gen_add_dtprel (op0, op1, tmp));
break;
case TLS_MODEL_INITIAL_EXEC:
+ addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
+ addend_hi = addend - addend_lo;
+
+ op1 = plus_constant (op1, addend_hi);
+ addend = addend_lo;
+
tmp = gen_reg_rtx (Pmode);
- emit_insn (gen_load_ltoff_tprel (tmp, op1));
- tmp = gen_rtx_MEM (Pmode, tmp);
- RTX_UNCHANGING_P (tmp) = 1;
- tmp = force_reg (Pmode, tmp);
+ emit_insn (gen_load_tprel (tmp, op1));
if (!register_operand (op0, Pmode))
op0 = gen_reg_rtx (Pmode);
@@ -1345,19 +1028,25 @@ ia64_expand_tls_address (enum tls_model tls_kind, rtx op0, rtx op1)
case TLS_MODEL_LOCAL_EXEC:
if (!register_operand (op0, Pmode))
op0 = gen_reg_rtx (Pmode);
+
+ op1 = orig_op1;
+ addend = 0;
if (TARGET_TLS64)
{
emit_insn (gen_load_tprel (op0, op1));
- emit_insn (gen_adddi3 (op0, gen_thread_pointer (), op0));
+ emit_insn (gen_adddi3 (op0, op0, gen_thread_pointer ()));
}
else
- emit_insn (gen_add_tprel (op0, gen_thread_pointer (), op1));
+ emit_insn (gen_add_tprel (op0, op1, gen_thread_pointer ()));
break;
default:
- abort ();
+ gcc_unreachable ();
}
+ if (addend)
+ op0 = expand_simple_binop (Pmode, PLUS, op0, GEN_INT (addend),
+ orig_op0, 1, OPTAB_DIRECT);
if (orig_op0 == op0)
return NULL_RTX;
if (GET_MODE (orig_op0) == Pmode)
@@ -1375,14 +1064,60 @@ ia64_expand_move (rtx op0, rtx op1)
if ((mode == Pmode || mode == ptr_mode) && symbolic_operand (op1, VOIDmode))
{
+ HOST_WIDE_INT addend = 0;
enum tls_model tls_kind;
- if ((tls_kind = tls_symbolic_operand (op1, VOIDmode)))
- return ia64_expand_tls_address (tls_kind, op0, op1);
+ rtx sym = op1;
- if (!TARGET_NO_PIC && reload_completed)
+ if (GET_CODE (op1) == CONST
+ && GET_CODE (XEXP (op1, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (op1, 0), 1)) == CONST_INT)
{
- ia64_expand_load_address (op0, op1);
- return NULL_RTX;
+ addend = INTVAL (XEXP (XEXP (op1, 0), 1));
+ sym = XEXP (XEXP (op1, 0), 0);
+ }
+
+ tls_kind = tls_symbolic_operand_type (sym);
+ if (tls_kind)
+ return ia64_expand_tls_address (tls_kind, op0, sym, op1, addend);
+
+ if (any_offset_symbol_operand (sym, mode))
+ addend = 0;
+ else if (aligned_offset_symbol_operand (sym, mode))
+ {
+ HOST_WIDE_INT addend_lo, addend_hi;
+
+ addend_lo = ((addend & 0x3fff) ^ 0x2000) - 0x2000;
+ addend_hi = addend - addend_lo;
+
+ if (addend_lo != 0)
+ {
+ op1 = plus_constant (sym, addend_hi);
+ addend = addend_lo;
+ }
+ else
+ addend = 0;
+ }
+ else
+ op1 = sym;
+
+ if (reload_completed)
+ {
+ /* We really should have taken care of this offset earlier. */
+ gcc_assert (addend == 0);
+ if (ia64_expand_load_address (op0, op1))
+ return NULL_RTX;
+ }
+
+ if (addend)
+ {
+ rtx subtarget = no_new_pseudos ? op0 : gen_reg_rtx (mode);
+
+ emit_insn (gen_rtx_SET (VOIDmode, subtarget, op1));
+
+ op1 = expand_simple_binop (mode, PLUS, subtarget,
+ GEN_INT (addend), op0, 1, OPTAB_DIRECT);
+ if (op0 == op1)
+ return NULL_RTX;
}
}
@@ -1434,7 +1169,7 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
case CONST_INT:
case CONST_DOUBLE:
/* Cannot occur reversed. */
- if (reversed) abort ();
+ gcc_assert (!reversed);
if (GET_MODE (in) != TFmode)
split_double (in, &out[0], &out[1]);
@@ -1491,14 +1226,16 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
break;
case POST_INC:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Just do the increment in two steps. */
out[0] = adjust_automodify_address (in, DImode, 0, 0);
out[1] = adjust_automodify_address (in, DImode, 0, 8);
break;
case POST_DEC:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Add 8, subtract 24. */
base = XEXP (base, 0);
out[0] = adjust_automodify_address
@@ -1510,7 +1247,8 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
break;
case POST_MODIFY:
- if (reversed || dead) abort ();
+ gcc_assert (!reversed && !dead);
+
/* Extract and adjust the modification. This case is
trickier than the others, because we might have an
index register, or we might have a combined offset that
@@ -1529,38 +1267,41 @@ ia64_split_tmode (rtx out[2], rtx in, bool reversed, bool dead)
out[1] = adjust_automodify_address (in, DImode, 0, 8);
fixup = gen_adddi3 (base, base, GEN_INT (-8));
}
- else if (GET_CODE (XEXP (offset, 1)) != CONST_INT)
- abort ();
- else if (INTVAL (XEXP (offset, 1)) < -256 + 8)
- {
- /* Again the postmodify cannot be made to match, but
- in this case it's more efficient to get rid of the
- postmodify entirely and fix up with an add insn. */
- out[1] = adjust_automodify_address (in, DImode, base, 8);
- fixup = gen_adddi3 (base, base,
- GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
- }
else
{
- /* Combined offset still fits in the displacement field.
- (We cannot overflow it at the high end.) */
- out[1] = adjust_automodify_address
- (in, DImode,
- gen_rtx_POST_MODIFY (Pmode, base,
- gen_rtx_PLUS (Pmode, base,
- GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
- 8);
+ gcc_assert (GET_CODE (XEXP (offset, 1)) == CONST_INT);
+ if (INTVAL (XEXP (offset, 1)) < -256 + 8)
+ {
+ /* Again the postmodify cannot be made to match,
+ but in this case it's more efficient to get rid
+ of the postmodify entirely and fix up with an
+ add insn. */
+ out[1] = adjust_automodify_address (in, DImode, base, 8);
+ fixup = gen_adddi3
+ (base, base, GEN_INT (INTVAL (XEXP (offset, 1)) - 8));
+ }
+ else
+ {
+ /* Combined offset still fits in the displacement field.
+ (We cannot overflow it at the high end.) */
+ out[1] = adjust_automodify_address
+ (in, DImode, gen_rtx_POST_MODIFY
+ (Pmode, base, gen_rtx_PLUS
+ (Pmode, base,
+ GEN_INT (INTVAL (XEXP (offset, 1)) - 8))),
+ 8);
+ }
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
}
default:
- abort ();
+ gcc_unreachable ();
}
return fixup;
@@ -1580,7 +1321,7 @@ ia64_split_tmode_move (rtx operands[])
the value it points to. In that case we have to do the loads in
the appropriate order so that the pointer is not destroyed too
early. Also we must not generate a postmodify for that second
- load, or rws_access_regno will abort. */
+ load, or rws_access_regno will die. */
if (GET_CODE (operands[1]) == MEM
&& reg_overlap_mentioned_p (operands[0], operands[1]))
{
@@ -1637,28 +1378,159 @@ ia64_split_tmode_move (rtx operands[])
This solution attempts to prevent this situation from occurring. When
we see something like the above, we spill the inner register to memory. */
-rtx
-spill_xfmode_operand (rtx in, int force)
+static rtx
+spill_xfmode_rfmode_operand (rtx in, int force, enum machine_mode mode)
{
if (GET_CODE (in) == SUBREG
&& GET_MODE (SUBREG_REG (in)) == TImode
&& GET_CODE (SUBREG_REG (in)) == REG)
{
- rtx mem = gen_mem_addressof (SUBREG_REG (in), NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memt = assign_stack_temp (TImode, 16, 0);
+ emit_move_insn (memt, SUBREG_REG (in));
+ return adjust_address (memt, mode, 0);
}
else if (force && GET_CODE (in) == REG)
{
- rtx mem = gen_mem_addressof (in, NULL_TREE, /*rescan=*/true);
- return gen_rtx_MEM (XFmode, copy_to_reg (XEXP (mem, 0)));
+ rtx memx = assign_stack_temp (mode, 16, 0);
+ emit_move_insn (memx, in);
+ return memx;
}
- else if (GET_CODE (in) == MEM
- && GET_CODE (XEXP (in, 0)) == ADDRESSOF)
- return change_address (in, XFmode, copy_to_reg (XEXP (in, 0)));
else
return in;
}
+/* Expand the movxf or movrf pattern (MODE says which) with the given
+ OPERANDS, returning true if the pattern should then invoke
+ DONE. */
+
+bool
+ia64_expand_movxf_movrf (enum machine_mode mode, rtx operands[])
+{
+ rtx op0 = operands[0];
+
+ if (GET_CODE (op0) == SUBREG)
+ op0 = SUBREG_REG (op0);
+
+ /* We must support XFmode loads into general registers for stdarg/vararg,
+ unprototyped calls, and a rare case where a long double is passed as
+ an argument after a float HFA fills the FP registers. We split them into
+ DImode loads for convenience. We also need to support XFmode stores
+ for the last case. This case does not happen for stdarg/vararg routines,
+ because we do a block store to memory of unnamed arguments. */
+
+ if (GET_CODE (op0) == REG && GR_REGNO_P (REGNO (op0)))
+ {
+ rtx out[2];
+
+ /* We're hoping to transform everything that deals with XFmode
+ quantities and GR registers early in the compiler. */
+ gcc_assert (!no_new_pseudos);
+
+ /* Struct to register can just use TImode instead. */
+ if ((GET_CODE (operands[1]) == SUBREG
+ && GET_MODE (SUBREG_REG (operands[1])) == TImode)
+ || (GET_CODE (operands[1]) == REG
+ && GR_REGNO_P (REGNO (operands[1]))))
+ {
+ rtx op1 = operands[1];
+
+ if (GET_CODE (op1) == SUBREG)
+ op1 = SUBREG_REG (op1);
+ else
+ op1 = gen_rtx_REG (TImode, REGNO (op1));
+
+ emit_move_insn (gen_rtx_REG (TImode, REGNO (op0)), op1);
+ return true;
+ }
+
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ /* Don't word-swap when reading in the constant. */
+ emit_move_insn (gen_rtx_REG (DImode, REGNO (op0)),
+ operand_subword (operands[1], WORDS_BIG_ENDIAN,
+ 0, mode));
+ emit_move_insn (gen_rtx_REG (DImode, REGNO (op0) + 1),
+ operand_subword (operands[1], !WORDS_BIG_ENDIAN,
+ 0, mode));
+ return true;
+ }
+
+ /* If the quantity is in a register not known to be GR, spill it. */
+ if (register_operand (operands[1], mode))
+ operands[1] = spill_xfmode_rfmode_operand (operands[1], 1, mode);
+
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+
+ /* Don't word-swap when reading in the value. */
+ out[0] = gen_rtx_REG (DImode, REGNO (op0));
+ out[1] = gen_rtx_REG (DImode, REGNO (op0) + 1);
+
+ emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
+ emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
+ return true;
+ }
+
+ if (GET_CODE (operands[1]) == REG && GR_REGNO_P (REGNO (operands[1])))
+ {
+ /* We're hoping to transform everything that deals with XFmode
+ quantities and GR registers early in the compiler. */
+ gcc_assert (!no_new_pseudos);
+
+ /* Op0 can't be a GR_REG here, as that case is handled above.
+ If op0 is a register, then we spill op1, so that we now have a
+ MEM operand. This requires creating an XFmode subreg of a TImode reg
+ to force the spill. */
+ if (register_operand (operands[0], mode))
+ {
+ rtx op1 = gen_rtx_REG (TImode, REGNO (operands[1]));
+ op1 = gen_rtx_SUBREG (mode, op1, 0);
+ operands[1] = spill_xfmode_rfmode_operand (op1, 0, mode);
+ }
+
+ else
+ {
+ rtx in[2];
+
+ gcc_assert (GET_CODE (operands[0]) == MEM);
+
+ /* Don't word-swap when writing out the value. */
+ in[0] = gen_rtx_REG (DImode, REGNO (operands[1]));
+ in[1] = gen_rtx_REG (DImode, REGNO (operands[1]) + 1);
+
+ emit_move_insn (adjust_address (operands[0], DImode, 0), in[0]);
+ emit_move_insn (adjust_address (operands[0], DImode, 8), in[1]);
+ return true;
+ }
+ }
+
+ if (!reload_in_progress && !reload_completed)
+ {
+ operands[1] = spill_xfmode_rfmode_operand (operands[1], 0, mode);
+
+ if (GET_MODE (op0) == TImode && GET_CODE (op0) == REG)
+ {
+ rtx memt, memx, in = operands[1];
+ if (CONSTANT_P (in))
+ in = validize_mem (force_const_mem (mode, in));
+ if (GET_CODE (in) == MEM)
+ memt = adjust_address (in, TImode, 0);
+ else
+ {
+ memt = assign_stack_temp (TImode, 16, 0);
+ memx = adjust_address (memt, mode, 0);
+ emit_move_insn (memx, in);
+ }
+ emit_move_insn (op0, memt);
+ return true;
+ }
+
+ if (!ia64_move_ok (operands[0], operands[1]))
+ operands[1] = force_reg (mode, operands[1]);
+ }
+
+ return false;
+}
+
/* Emit comparison instruction if necessary, returning the expression
that holds the compare result in the proper mode. */
@@ -1674,15 +1546,13 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
do not need to emit another comparison. */
if (GET_MODE (op0) == BImode)
{
- if ((code == NE || code == EQ) && op1 == const0_rtx)
- cmp = op0;
- else
- abort ();
+ gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
+ cmp = op0;
}
/* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
magic number as its third argument, that indicates what to do.
The return value is an integer to be compared against zero. */
- else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
+ else if (GET_MODE (op0) == TFmode)
{
enum qfcmp_magic {
QCMP_INV = 1, /* Raise FP_INVALID on SNaN as a side effect. */
@@ -1693,8 +1563,8 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
} magic;
enum rtx_code ncode;
rtx ret, insns;
- if (GET_MODE (op1) != TFmode)
- abort ();
+
+ gcc_assert (cmptf_libfunc && GET_MODE (op1) == TFmode);
switch (code)
{
/* 1 = equal, 0 = not equal. Equality operators do
@@ -1703,6 +1573,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
case NE: magic = QCMP_EQ; ncode = EQ; break;
/* isunordered() from C99. */
case UNORDERED: magic = QCMP_UNORD; ncode = NE; break;
+ case ORDERED: magic = QCMP_UNORD; ncode = EQ; break;
/* Relational operators raise FP_INVALID when given
an SNaN operand. */
case LT: magic = QCMP_LT |QCMP_INV; ncode = NE; break;
@@ -1712,7 +1583,7 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
/* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT.
Expanders for buneq etc. weuld have to be added to ia64.md
for this to be useful. */
- default: abort ();
+ default: gcc_unreachable ();
}
start_sequence ();
@@ -1743,6 +1614,316 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
return gen_rtx_fmt_ee (code, mode, cmp, const0_rtx);
}
+/* Generate an integral vector comparison. Return true if the condition has
+ been reversed, and so the sense of the comparison should be inverted. */
+
+static bool
+ia64_expand_vecint_compare (enum rtx_code code, enum machine_mode mode,
+ rtx dest, rtx op0, rtx op1)
+{
+ bool negate = false;
+ rtx x;
+
+ /* Canonicalize the comparison to EQ, GT, GTU. */
+ switch (code)
+ {
+ case EQ:
+ case GT:
+ case GTU:
+ break;
+
+ case NE:
+ case LE:
+ case LEU:
+ code = reverse_condition (code);
+ negate = true;
+ break;
+
+ case GE:
+ case GEU:
+ code = reverse_condition (code);
+ negate = true;
+ /* FALLTHRU */
+
+ case LT:
+ case LTU:
+ code = swap_condition (code);
+ x = op0, op0 = op1, op1 = x;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Unsigned parallel compare is not supported by the hardware. Play some
+ tricks to turn this into a signed comparison against 0. */
+ if (code == GTU)
+ {
+ switch (mode)
+ {
+ case V2SImode:
+ {
+ rtx t1, t2, mask;
+
+ /* Perform a parallel modulo subtraction. */
+ t1 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_subv2si3 (t1, op0, op1));
+
+ /* Extract the original sign bit of op0. */
+ mask = GEN_INT (-0x80000000);
+ mask = gen_rtx_CONST_VECTOR (V2SImode, gen_rtvec (2, mask, mask));
+ mask = force_reg (V2SImode, mask);
+ t2 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_andv2si3 (t2, op0, mask));
+
+ /* XOR it back into the result of the subtraction. This results
+ in the sign bit set iff we saw unsigned underflow. */
+ x = gen_reg_rtx (V2SImode);
+ emit_insn (gen_xorv2si3 (x, t1, t2));
+
+ code = GT;
+ op0 = x;
+ op1 = CONST0_RTX (mode);
+ }
+ break;
+
+ case V8QImode:
+ case V4HImode:
+ /* Perform a parallel unsigned saturating subtraction. */
+ x = gen_reg_rtx (mode);
+ emit_insn (gen_rtx_SET (VOIDmode, x,
+ gen_rtx_US_MINUS (mode, op0, op1)));
+
+ code = EQ;
+ op0 = x;
+ op1 = CONST0_RTX (mode);
+ negate = !negate;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ x = gen_rtx_fmt_ee (code, mode, op0, op1);
+ emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+
+ return negate;
+}
+
+/* Emit an integral vector conditional move. */
+
+void
+ia64_expand_vecint_cmov (rtx operands[])
+{
+ enum machine_mode mode = GET_MODE (operands[0]);
+ enum rtx_code code = GET_CODE (operands[3]);
+ bool negate;
+ rtx cmp, x, ot, of;
+
+ cmp = gen_reg_rtx (mode);
+ negate = ia64_expand_vecint_compare (code, mode, cmp,
+ operands[4], operands[5]);
+
+ ot = operands[1+negate];
+ of = operands[2-negate];
+
+ if (ot == CONST0_RTX (mode))
+ {
+ if (of == CONST0_RTX (mode))
+ {
+ emit_move_insn (operands[0], ot);
+ return;
+ }
+
+ x = gen_rtx_NOT (mode, cmp);
+ x = gen_rtx_AND (mode, x, of);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+ else if (of == CONST0_RTX (mode))
+ {
+ x = gen_rtx_AND (mode, cmp, ot);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+ else
+ {
+ rtx t, f;
+
+ t = gen_reg_rtx (mode);
+ x = gen_rtx_AND (mode, cmp, operands[1+negate]);
+ emit_insn (gen_rtx_SET (VOIDmode, t, x));
+
+ f = gen_reg_rtx (mode);
+ x = gen_rtx_NOT (mode, cmp);
+ x = gen_rtx_AND (mode, x, operands[2-negate]);
+ emit_insn (gen_rtx_SET (VOIDmode, f, x));
+
+ x = gen_rtx_IOR (mode, t, f);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ }
+}
+
+/* Emit an integral vector min or max operation. Return true if all done. */
+
+bool
+ia64_expand_vecint_minmax (enum rtx_code code, enum machine_mode mode,
+ rtx operands[])
+{
+ rtx xops[6];
+
+ /* These four combinations are supported directly. */
+ if (mode == V8QImode && (code == UMIN || code == UMAX))
+ return false;
+ if (mode == V4HImode && (code == SMIN || code == SMAX))
+ return false;
+
+ /* This combination can be implemented with only saturating subtraction. */
+ if (mode == V4HImode && code == UMAX)
+ {
+ rtx x, tmp = gen_reg_rtx (mode);
+
+ x = gen_rtx_US_MINUS (mode, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (VOIDmode, tmp, x));
+
+ emit_insn (gen_addv4hi3 (operands[0], tmp, operands[2]));
+ return true;
+ }
+
+ /* Everything else implemented via vector comparisons. */
+ xops[0] = operands[0];
+ xops[4] = xops[1] = operands[1];
+ xops[5] = xops[2] = operands[2];
+
+ switch (code)
+ {
+ case UMIN:
+ code = LTU;
+ break;
+ case UMAX:
+ code = GTU;
+ break;
+ case SMIN:
+ code = LT;
+ break;
+ case SMAX:
+ code = GT;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ xops[3] = gen_rtx_fmt_ee (code, VOIDmode, operands[1], operands[2]);
+
+ ia64_expand_vecint_cmov (xops);
+ return true;
+}
+
+/* Emit an integral vector widening sum operations. */
+
+void
+ia64_expand_widen_sum (rtx operands[3], bool unsignedp)
+{
+ rtx l, h, x, s;
+ enum machine_mode wmode, mode;
+ rtx (*unpack_l) (rtx, rtx, rtx);
+ rtx (*unpack_h) (rtx, rtx, rtx);
+ rtx (*plus) (rtx, rtx, rtx);
+
+ wmode = GET_MODE (operands[0]);
+ mode = GET_MODE (operands[1]);
+
+ switch (mode)
+ {
+ case V8QImode:
+ unpack_l = gen_unpack1_l;
+ unpack_h = gen_unpack1_h;
+ plus = gen_addv4hi3;
+ break;
+ case V4HImode:
+ unpack_l = gen_unpack2_l;
+ unpack_h = gen_unpack2_h;
+ plus = gen_addv2si3;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ /* Fill in x with the sign extension of each element in op1. */
+ if (unsignedp)
+ x = CONST0_RTX (mode);
+ else
+ {
+ bool neg;
+
+ x = gen_reg_rtx (mode);
+
+ neg = ia64_expand_vecint_compare (LT, mode, x, operands[1],
+ CONST0_RTX (mode));
+ gcc_assert (!neg);
+ }
+
+ l = gen_reg_rtx (wmode);
+ h = gen_reg_rtx (wmode);
+ s = gen_reg_rtx (wmode);
+
+ emit_insn (unpack_l (gen_lowpart (mode, l), operands[1], x));
+ emit_insn (unpack_h (gen_lowpart (mode, h), operands[1], x));
+ emit_insn (plus (s, l, operands[2]));
+ emit_insn (plus (operands[0], h, s));
+}
+
+/* Emit a signed or unsigned V8QI dot product operation. */
+
+void
+ia64_expand_dot_prod_v8qi (rtx operands[4], bool unsignedp)
+{
+ rtx l1, l2, h1, h2, x1, x2, p1, p2, p3, p4, s1, s2, s3;
+
+ /* Fill in x1 and x2 with the sign extension of each element. */
+ if (unsignedp)
+ x1 = x2 = CONST0_RTX (V8QImode);
+ else
+ {
+ bool neg;
+
+ x1 = gen_reg_rtx (V8QImode);
+ x2 = gen_reg_rtx (V8QImode);
+
+ neg = ia64_expand_vecint_compare (LT, V8QImode, x1, operands[1],
+ CONST0_RTX (V8QImode));
+ gcc_assert (!neg);
+ neg = ia64_expand_vecint_compare (LT, V8QImode, x2, operands[2],
+ CONST0_RTX (V8QImode));
+ gcc_assert (!neg);
+ }
+
+ l1 = gen_reg_rtx (V4HImode);
+ l2 = gen_reg_rtx (V4HImode);
+ h1 = gen_reg_rtx (V4HImode);
+ h2 = gen_reg_rtx (V4HImode);
+
+ emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l1), operands[1], x1));
+ emit_insn (gen_unpack1_l (gen_lowpart (V8QImode, l2), operands[2], x2));
+ emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h1), operands[1], x1));
+ emit_insn (gen_unpack1_h (gen_lowpart (V8QImode, h2), operands[2], x2));
+
+ p1 = gen_reg_rtx (V2SImode);
+ p2 = gen_reg_rtx (V2SImode);
+ p3 = gen_reg_rtx (V2SImode);
+ p4 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_pmpy2_r (p1, l1, l2));
+ emit_insn (gen_pmpy2_l (p2, l1, l2));
+ emit_insn (gen_pmpy2_r (p3, h1, h2));
+ emit_insn (gen_pmpy2_l (p4, h1, h2));
+
+ s1 = gen_reg_rtx (V2SImode);
+ s2 = gen_reg_rtx (V2SImode);
+ s3 = gen_reg_rtx (V2SImode);
+ emit_insn (gen_addv2si3 (s1, p1, p2));
+ emit_insn (gen_addv2si3 (s2, p3, p4));
+ emit_insn (gen_addv2si3 (s3, s1, operands[3]));
+ emit_insn (gen_addv2si3 (operands[0], s2, s3));
+}
+
/* Emit the appropriate sequence for a call. */
void
@@ -1884,12 +2065,129 @@ ia64_split_call (rtx retval, rtx addr, rtx retaddr, rtx scratch_r,
if ((!TARGET_CONST_GP || is_desc) && !noreturn_p && !sibcall_p)
ia64_reload_gp ();
}
+
+/* Expand an atomic operation. We want to perform MEM <CODE>= VAL atomically.
+
+ This differs from the generic code in that we know about the zero-extending
+ properties of cmpxchg, and the zero-extending requirements of ar.ccv. We
+ also know that ld.acq+cmpxchg.rel equals a full barrier.
+
+ The loop we want to generate looks like
+
+ cmp_reg = mem;
+ label:
+ old_reg = cmp_reg;
+ new_reg = cmp_reg op val;
+ cmp_reg = compare-and-swap(mem, old_reg, new_reg)
+ if (cmp_reg != old_reg)
+ goto label;
+
+ Note that we only do the plain load from memory once. Subsequent
+ iterations use the value loaded by the compare-and-swap pattern. */
+
+void
+ia64_expand_atomic_op (enum rtx_code code, rtx mem, rtx val,
+ rtx old_dst, rtx new_dst)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx old_reg, new_reg, cmp_reg, ar_ccv, label;
+ enum insn_code icode;
+
+ /* Special case for using fetchadd. */
+ if ((mode == SImode || mode == DImode)
+ && (code == PLUS || code == MINUS)
+ && fetchadd_operand (val, mode))
+ {
+ if (code == MINUS)
+ val = GEN_INT (-INTVAL (val));
+
+ if (!old_dst)
+ old_dst = gen_reg_rtx (mode);
+
+ emit_insn (gen_memory_barrier ());
+
+ if (mode == SImode)
+ icode = CODE_FOR_fetchadd_acq_si;
+ else
+ icode = CODE_FOR_fetchadd_acq_di;
+ emit_insn (GEN_FCN (icode) (old_dst, mem, val));
+
+ if (new_dst)
+ {
+ new_reg = expand_simple_binop (mode, PLUS, old_dst, val, new_dst,
+ true, OPTAB_WIDEN);
+ if (new_reg != new_dst)
+ emit_move_insn (new_dst, new_reg);
+ }
+ return;
+ }
+
+ /* Because of the volatile mem read, we get an ld.acq, which is the
+ front half of the full barrier. The end half is the cmpxchg.rel. */
+ gcc_assert (MEM_VOLATILE_P (mem));
+
+ old_reg = gen_reg_rtx (DImode);
+ cmp_reg = gen_reg_rtx (DImode);
+ label = gen_label_rtx ();
+
+ if (mode != DImode)
+ {
+ val = simplify_gen_subreg (DImode, val, mode, 0);
+ emit_insn (gen_extend_insn (cmp_reg, mem, DImode, mode, 1));
+ }
+ else
+ emit_move_insn (cmp_reg, mem);
+
+ emit_label (label);
+
+ ar_ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ emit_move_insn (old_reg, cmp_reg);
+ emit_move_insn (ar_ccv, cmp_reg);
+
+ if (old_dst)
+ emit_move_insn (old_dst, gen_lowpart (mode, cmp_reg));
+
+ new_reg = cmp_reg;
+ if (code == NOT)
+ {
+ new_reg = expand_simple_unop (DImode, NOT, new_reg, NULL_RTX, true);
+ code = AND;
+ }
+ new_reg = expand_simple_binop (DImode, code, new_reg, val, NULL_RTX,
+ true, OPTAB_DIRECT);
+
+ if (mode != DImode)
+ new_reg = gen_lowpart (mode, new_reg);
+ if (new_dst)
+ emit_move_insn (new_dst, new_reg);
+
+ switch (mode)
+ {
+ case QImode: icode = CODE_FOR_cmpxchg_rel_qi; break;
+ case HImode: icode = CODE_FOR_cmpxchg_rel_hi; break;
+ case SImode: icode = CODE_FOR_cmpxchg_rel_si; break;
+ case DImode: icode = CODE_FOR_cmpxchg_rel_di; break;
+ default:
+ gcc_unreachable ();
+ }
+
+ emit_insn (GEN_FCN (icode) (cmp_reg, mem, ar_ccv, new_reg));
+
+ emit_cmp_and_jump_insns (cmp_reg, old_reg, NE, NULL, DImode, true, label);
+}
/* Begin the assembly file. */
static void
ia64_file_start (void)
{
+ /* Variable tracking should be run after all optimizations which change order
+ of insns. It also needs a valid CFG. This can't be done in
+ ia64_override_options, because flag_var_tracking is finalized after
+ that. */
+ ia64_flag_var_tracking = flag_var_tracking;
+ flag_var_tracking = 0;
+
default_file_start ();
emit_safe_across_calls ();
}
@@ -2000,7 +2298,7 @@ next_scratch_gr_reg (void)
}
/* There must be _something_ available. */
- abort ();
+ gcc_unreachable ();
}
/* Helper function for ia64_compute_frame_size, called through
@@ -2012,7 +2310,7 @@ mark_reg_gr_used_mask (rtx reg, void *data ATTRIBUTE_UNUSED)
unsigned int regno = REGNO (reg);
if (regno < 32)
{
- unsigned int i, n = HARD_REGNO_NREGS (regno, GET_MODE (reg));
+ unsigned int i, n = hard_regno_nregs[regno][GET_MODE (reg)];
for (i = 0; i < n; ++i)
current_frame_info.gr_used_mask |= 1 << (regno + i);
}
@@ -2084,12 +2382,14 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
break;
i = regno - OUT_REG (0) + 1;
+#ifndef PROFILE_HOOK
/* When -p profiling, we need one output register for the mcount argument.
Likewise for -a profiling for the bb_init_func argument. For -ax
profiling, we need two output registers for the two bb_init_trace_func
arguments. */
if (current_function_profile)
i = MAX (i, 1);
+#endif
current_frame_info.n_output_regs = i;
/* ??? No rotating register support yet. */
@@ -2152,7 +2452,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
current_frame_info.reg_save_b0 = find_gr_spill (1);
if (current_frame_info.reg_save_b0 == 0)
{
- spill_size += 8;
+ extra_spill_size += 8;
n_spilled += 1;
}
@@ -2181,7 +2481,7 @@ ia64_compute_frame_size (HOST_WIDE_INT size)
if (regs_ever_live[BR_REG (0)] && ! call_used_regs[BR_REG (0)])
{
SET_HARD_REG_BIT (mask, BR_REG (0));
- spill_size += 8;
+ extra_spill_size += 8;
n_spilled += 1;
}
@@ -2297,39 +2597,49 @@ ia64_initial_elimination_offset (int from, int to)
switch (from)
{
case FRAME_POINTER_REGNUM:
- if (to == HARD_FRAME_POINTER_REGNUM)
+ switch (to)
{
+ case HARD_FRAME_POINTER_REGNUM:
if (current_function_is_leaf)
offset = -current_frame_info.total_size;
else
offset = -(current_frame_info.total_size
- current_function_outgoing_args_size - 16);
- }
- else if (to == STACK_POINTER_REGNUM)
- {
+ break;
+
+ case STACK_POINTER_REGNUM:
if (current_function_is_leaf)
offset = 0;
else
offset = 16 + current_function_outgoing_args_size;
+ break;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
break;
case ARG_POINTER_REGNUM:
/* Arguments start above the 16 byte save area, unless stdarg
in which case we store through the 16 byte save area. */
- if (to == HARD_FRAME_POINTER_REGNUM)
- offset = 16 - current_function_pretend_args_size;
- else if (to == STACK_POINTER_REGNUM)
- offset = (current_frame_info.total_size
- + 16 - current_function_pretend_args_size);
- else
- abort ();
+ switch (to)
+ {
+ case HARD_FRAME_POINTER_REGNUM:
+ offset = 16 - current_function_pretend_args_size;
+ break;
+
+ case STACK_POINTER_REGNUM:
+ offset = (current_frame_info.total_size
+ + 16 - current_function_pretend_args_size);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
default:
- abort ();
+ gcc_unreachable ();
}
return offset;
@@ -2619,8 +2929,9 @@ ia64_expand_prologue (void)
if (optimize)
{
edge e;
+ edge_iterator ei;
- for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
if ((e->flags & EDGE_FAKE) == 0
&& (e->flags & EDGE_FALLTHRU) != 0)
break;
@@ -2860,35 +3171,7 @@ ia64_expand_prologue (void)
}
}
- if (current_frame_info.reg_save_gp)
- {
- insn = emit_move_insn (gen_rtx_REG (DImode,
- current_frame_info.reg_save_gp),
- pic_offset_table_rtx);
- /* We don't know for sure yet if this is actually needed, since
- we've not split the PIC call patterns. If all of the calls
- are indirect, and not followed by any uses of the gp, then
- this save is dead. Allow it to go away. */
- REG_NOTES (insn)
- = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
- }
-
- /* We should now be at the base of the gr/br/fr spill area. */
- if (cfa_off != (current_frame_info.spill_cfa_off
- + current_frame_info.spill_size))
- abort ();
-
- /* Spill all general registers. */
- for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
- if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
- {
- reg = gen_rtx_REG (DImode, regno);
- do_spill (gen_gr_spill, reg, cfa_off, reg);
- cfa_off -= 8;
- }
-
- /* Handle BR0 specially -- it may be getting stored permanently in
- some GR register. */
+ /* Save the return pointer. */
if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
{
reg = gen_rtx_REG (DImode, BR_REG (0));
@@ -2913,6 +3196,32 @@ ia64_expand_prologue (void)
}
}
+ if (current_frame_info.reg_save_gp)
+ {
+ insn = emit_move_insn (gen_rtx_REG (DImode,
+ current_frame_info.reg_save_gp),
+ pic_offset_table_rtx);
+ /* We don't know for sure yet if this is actually needed, since
+ we've not split the PIC call patterns. If all of the calls
+ are indirect, and not followed by any uses of the gp, then
+ this save is dead. Allow it to go away. */
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, REG_NOTES (insn));
+ }
+
+ /* We should now be at the base of the gr/br/fr spill area. */
+ gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size));
+
+ /* Spill all general registers. */
+ for (regno = GR_REG (1); regno <= GR_REG (31); ++regno)
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
+ {
+ reg = gen_rtx_REG (DImode, regno);
+ do_spill (gen_gr_spill, reg, cfa_off, reg);
+ cfa_off -= 8;
+ }
+
/* Spill the rest of the BR registers. */
for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
@@ -2929,15 +3238,13 @@ ia64_expand_prologue (void)
for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
- if (cfa_off & 15)
- abort ();
+ gcc_assert (!(cfa_off & 15));
reg = gen_rtx_REG (XFmode, regno);
do_spill (gen_fr_spill_x, reg, cfa_off, reg);
cfa_off -= 16;
}
- if (cfa_off != current_frame_info.spill_cfa_off)
- abort ();
+ gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
finish_spill_pointers ();
}
@@ -3048,10 +3355,25 @@ ia64_expand_epilogue (int sibcall_p)
emit_move_insn (reg, alt_reg);
}
+ /* Restore the return pointer. */
+ if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
+ {
+ if (current_frame_info.reg_save_b0 != 0)
+ alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
+ else
+ {
+ alt_regno = next_scratch_gr_reg ();
+ alt_reg = gen_rtx_REG (DImode, alt_regno);
+ do_restore (gen_movdi_x, alt_reg, cfa_off);
+ cfa_off -= 8;
+ }
+ reg = gen_rtx_REG (DImode, BR_REG (0));
+ emit_move_insn (reg, alt_reg);
+ }
+
/* We should now be at the base of the gr/br/fr spill area. */
- if (cfa_off != (current_frame_info.spill_cfa_off
- + current_frame_info.spill_size))
- abort ();
+ gcc_assert (cfa_off == (current_frame_info.spill_cfa_off
+ + current_frame_info.spill_size));
/* The GP may be stored on the stack in the prologue, but it's
never restored in the epilogue. Skip the stack slot. */
@@ -3067,23 +3389,7 @@ ia64_expand_epilogue (int sibcall_p)
cfa_off -= 8;
}
- /* Restore the branch registers. Handle B0 specially, as it may
- have gotten stored in some GR register. */
- if (TEST_HARD_REG_BIT (current_frame_info.mask, BR_REG (0)))
- {
- if (current_frame_info.reg_save_b0 != 0)
- alt_reg = gen_rtx_REG (DImode, current_frame_info.reg_save_b0);
- else
- {
- alt_regno = next_scratch_gr_reg ();
- alt_reg = gen_rtx_REG (DImode, alt_regno);
- do_restore (gen_movdi_x, alt_reg, cfa_off);
- cfa_off -= 8;
- }
- reg = gen_rtx_REG (DImode, BR_REG (0));
- emit_move_insn (reg, alt_reg);
- }
-
+ /* Restore the branch registers. */
for (regno = BR_REG (1); regno <= BR_REG (7); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
@@ -3099,8 +3405,7 @@ ia64_expand_epilogue (int sibcall_p)
for (regno = FR_REG (2); regno <= FR_REG (127); ++regno)
if (TEST_HARD_REG_BIT (current_frame_info.mask, regno))
{
- if (cfa_off & 15)
- abort ();
+ gcc_assert (!(cfa_off & 15));
reg = gen_rtx_REG (XFmode, regno);
do_restore (gen_fr_restore_x, reg, cfa_off);
cfa_off -= 16;
@@ -3113,8 +3418,7 @@ ia64_expand_epilogue (int sibcall_p)
emit_move_insn (reg, ar_unat_save_reg);
}
- if (cfa_off != current_frame_info.spill_cfa_off)
- abort ();
+ gcc_assert (cfa_off == current_frame_info.spill_cfa_off);
finish_spill_pointers ();
@@ -3488,6 +3792,11 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
}
}
+ /* Make sure addresses are Pmode even if we are in ILP32 mode. */
+ addr = convert_memory_address (Pmode, addr);
+ fnaddr = convert_memory_address (Pmode, fnaddr);
+ static_chain = convert_memory_address (Pmode, static_chain);
+
/* Load up our iterator. */
addr_reg = gen_reg_rtx (Pmode);
emit_move_insn (addr_reg, addr);
@@ -3515,17 +3824,19 @@ ia64_initialize_trampoline (rtx addr, rtx fnaddr, rtx static_chain)
We generate the actual spill instructions during prologue generation. */
-void
-ia64_setup_incoming_varargs (CUMULATIVE_ARGS cum, int int_mode, tree type,
- int * pretend_size,
+static void
+ia64_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int * pretend_size,
int second_time ATTRIBUTE_UNUSED)
{
+ CUMULATIVE_ARGS next_cum = *cum;
+
/* Skip the current argument. */
- ia64_function_arg_advance (&cum, int_mode, type, 1);
+ ia64_function_arg_advance (&next_cum, mode, type, 1);
- if (cum.words < MAX_ARGUMENT_SLOTS)
+ if (next_cum.words < MAX_ARGUMENT_SLOTS)
{
- int n = MAX_ARGUMENT_SLOTS - cum.words;
+ int n = MAX_ARGUMENT_SLOTS - next_cum.words;
*pretend_size = n * UNITS_PER_WORD;
cfun->machine->n_varargs = n;
}
@@ -3537,10 +3848,14 @@ ia64_setup_incoming_varargs (CUMULATIVE_ARGS cum, int int_mode, tree type,
An aggregate is a homogeneous floating point aggregate is if all
fields/elements in it have the same floating point type (e.g,
- SFmode). 128-bit quad-precision floats are excluded. */
+ SFmode). 128-bit quad-precision floats are excluded.
+
+ Variable sized aggregates should never arrive here, since we should
+ have already decided to pass them by reference. Top-level zero-sized
+ aggregates are excluded because our parallels crash the middle-end. */
static enum machine_mode
-hfa_element_mode (tree type, int nested)
+hfa_element_mode (tree type, bool nested)
{
enum machine_mode element_mode = VOIDmode;
enum machine_mode mode;
@@ -3548,13 +3863,15 @@ hfa_element_mode (tree type, int nested)
int know_element_mode = 0;
tree t;
+ if (!nested && (!TYPE_SIZE (type) || integer_zerop (TYPE_SIZE (type))))
+ return VOIDmode;
+
switch (code)
{
case VOID_TYPE: case INTEGER_TYPE: case ENUMERAL_TYPE:
- case BOOLEAN_TYPE: case CHAR_TYPE: case POINTER_TYPE:
+ case BOOLEAN_TYPE: case POINTER_TYPE:
case OFFSET_TYPE: case REFERENCE_TYPE: case METHOD_TYPE:
- case FILE_TYPE: case SET_TYPE: case LANG_TYPE:
- case FUNCTION_TYPE:
+ case LANG_TYPE: case FUNCTION_TYPE:
return VOIDmode;
/* Fortran complex types are supposed to be HFAs, so we need to handle
@@ -3756,13 +4073,7 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
else if (gr_size > UNITS_PER_WORD)
int_regs += gr_size / UNITS_PER_WORD;
}
-
- /* If we ended up using just one location, just return that one loc, but
- change the mode back to the argument mode. */
- if (i == 1)
- return gen_rtx_REG (mode, REGNO (XEXP (loc[0], 0)));
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
/* Integral and aggregates go in general registers. If we have run out of
@@ -3830,13 +4141,13 @@ ia64_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
}
}
-/* Return number of words, at the beginning of the argument, that must be
+/* Return number of bytes, at the beginning of the argument, that must be
put in registers. 0 is the argument is entirely in registers or entirely
in memory. */
-int
-ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named ATTRIBUTE_UNUSED)
+static int
+ia64_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, bool named ATTRIBUTE_UNUSED)
{
int words = ia64_function_arg_words (type, mode);
int offset = ia64_function_arg_offset (cum, type, words);
@@ -3853,7 +4164,7 @@ ia64_function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (words + cum->words + offset <= MAX_ARGUMENT_SLOTS)
return 0;
- return MAX_ARGUMENT_SLOTS - cum->words - offset;
+ return (MAX_ARGUMENT_SLOTS - cum->words - offset) * UNITS_PER_WORD;
}
/* Update CUM to point after this argument. This is patterned after
@@ -3913,10 +4224,11 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->fp_regs = fp_regs;
}
- /* Integral and aggregates go in general registers. If we have run out of
- FR registers, then FP values must also go in general registers. This can
- happen when we have a SFmode HFA. */
- else if (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS)
+ /* Integral and aggregates go in general registers. So do TFmode FP values.
+ If we have run out of FR registers, then other FP values must also go in
+ general registers. This can happen when we have a SFmode HFA. */
+ else if (mode == TFmode || mode == TCmode
+ || (! FLOAT_MODE_P (mode) || cum->fp_regs == MAX_ARGUMENT_SLOTS))
cum->int_regs = cum->words;
/* If there is a prototype, then FP values go in a FR register when
@@ -3939,15 +4251,29 @@ ia64_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
}
-/* Variable sized types are passed by reference. */
-/* ??? At present this is a GCC extension to the IA-64 ABI. */
+/* Arguments with alignment larger than 8 bytes start at the next even
+ boundary. On ILP32 HPUX, TFmode arguments start on next even boundary
+ even though their normal alignment is 8 bytes. See ia64_function_arg. */
int
-ia64_function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int named ATTRIBUTE_UNUSED)
+ia64_function_arg_boundary (enum machine_mode mode, tree type)
{
- return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
+
+ if (mode == TFmode && TARGET_HPUX && TARGET_ILP32)
+ return PARM_BOUNDARY * 2;
+
+ if (type)
+ {
+ if (TYPE_ALIGN (type) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
+ }
+
+ if (GET_MODE_BITSIZE (mode) > PARM_BOUNDARY)
+ return PARM_BOUNDARY * 2;
+ else
+ return PARM_BOUNDARY;
}
/* True if it is OK to do sibling call optimization for the specified
@@ -3970,20 +4296,15 @@ ia64_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
/* Implement va_arg. */
-rtx
-ia64_va_arg (tree valist, tree type)
+static tree
+ia64_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{
- tree t;
-
/* Variable sized types are passed by reference. */
- if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
- rtx addr = force_reg (ptr_mode,
- std_expand_builtin_va_arg (valist, build_pointer_type (type)));
-#ifdef POINTERS_EXTEND_UNSIGNED
- addr = convert_memory_address (Pmode, addr);
-#endif
- return gen_rtx_MEM (ptr_mode, addr);
+ tree ptrtype = build_pointer_type (type);
+ tree addr = std_gimplify_va_arg_expr (valist, ptrtype, pre_p, post_p);
+ return build_va_arg_indirect_ref (addr);
}
/* Aggregate arguments with alignment larger than 8 bytes start at
@@ -3993,23 +4314,22 @@ ia64_va_arg (tree valist, tree type)
if ((TREE_CODE (type) == REAL_TYPE || TREE_CODE (type) == INTEGER_TYPE)
? int_size_in_bytes (type) > 8 : TYPE_ALIGN (type) > 8 * BITS_PER_UNIT)
{
- t = build (PLUS_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (2 * UNITS_PER_WORD - 1, 0));
- t = build (BIT_AND_EXPR, TREE_TYPE (t), t,
- build_int_2 (-2 * UNITS_PER_WORD, -1));
- t = build (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ tree t = build2 (PLUS_EXPR, TREE_TYPE (valist), valist,
+ build_int_cst (NULL_TREE, 2 * UNITS_PER_WORD - 1));
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
+ build_int_cst (NULL_TREE, -2 * UNITS_PER_WORD));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (valist), valist, t);
+ gimplify_and_add (t, pre_p);
}
- return std_expand_builtin_va_arg (valist, type);
+ return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
/* Return 1 if function return value returned in memory. Return 0 if it is
in a register. */
-int
-ia64_return_in_memory (tree valtype)
+static bool
+ia64_return_in_memory (tree valtype, tree fntype ATTRIBUTE_UNUSED)
{
enum machine_mode mode;
enum machine_mode hfa_mode;
@@ -4021,7 +4341,7 @@ ia64_return_in_memory (tree valtype)
{
byte_size = int_size_in_bytes (valtype);
if (byte_size < 0)
- return 1;
+ return true;
}
/* Hfa's with up to 8 elements are returned in the FP argument registers. */
@@ -4032,14 +4352,14 @@ ia64_return_in_memory (tree valtype)
int hfa_size = GET_MODE_SIZE (hfa_mode);
if (byte_size / hfa_size > MAX_ARGUMENT_SLOTS)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
else if (byte_size > UNITS_PER_WORD * MAX_INT_RETURN_SLOTS)
- return 1;
+ return true;
else
- return 0;
+ return false;
}
/* Return rtx for register that holds the function return value. */
@@ -4072,18 +4392,30 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
GEN_INT (offset));
offset += hfa_size;
}
-
- if (i == 1)
- return XEXP (loc[0], 0);
- else
- return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
+ return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
else if (FLOAT_TYPE_P (valtype) && mode != TFmode && mode != TCmode)
return gen_rtx_REG (mode, FR_ARG_FIRST);
else
{
+ bool need_parallel = false;
+
+ /* In big-endian mode, we need to manage the layout of aggregates
+ in the registers so that we get the bits properly aligned in
+ the highpart of the registers. */
if (BYTES_BIG_ENDIAN
&& (mode == BLKmode || (valtype && AGGREGATE_TYPE_P (valtype))))
+ need_parallel = true;
+
+ /* Something like struct S { long double x; char a[0] } is not an
+ HFA structure, and therefore doesn't go in fp registers. But
+ the middle-end will give it XFmode anyway, and XFmode values
+ don't normally fit in integer registers. So we need to smuggle
+ the value inside a parallel. */
+ else if (mode == XFmode || mode == XCmode || mode == RFmode)
+ need_parallel = true;
+
+ if (need_parallel)
{
rtx loc[8];
int offset;
@@ -4092,6 +4424,10 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
offset = 0;
bytesize = int_size_in_bytes (valtype);
+ /* An empty PARALLEL is invalid here, but the return value
+ doesn't matter for empty structs. */
+ if (bytesize == 0)
+ return gen_rtx_REG (mode, GR_RET_FIRST);
for (i = 0; offset < bytesize; i++)
{
loc[i] = gen_rtx_EXPR_LIST (VOIDmode,
@@ -4102,20 +4438,22 @@ ia64_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
}
return gen_rtx_PARALLEL (mode, gen_rtvec_v (i, loc));
}
- else
- return gen_rtx_REG (mode, GR_RET_FIRST);
+
+ return gen_rtx_REG (mode, GR_RET_FIRST);
}
}
-/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
-void
+static void
ia64_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
- if (size != 8)
- abort ();
- fputs ("\tdata8.ua\t@dtprel(", file);
+ gcc_assert (size == 4 || size == 8);
+ if (size == 4)
+ fputs ("\tdata4.ua\t@dtprel(", file);
+ else
+ fputs ("\tdata8.ua\t@dtprel(", file);
output_addr_const (file, x);
fputs (")", file);
}
@@ -4149,8 +4487,11 @@ ia64_print_operand_address (FILE * stream ATTRIBUTE_UNUSED,
for Intel assembler.
U Print an 8-bit sign extended number (K) as a 64-bit unsigned number
for Intel assembler.
+ X A pair of floating point registers.
r Print register name, or constant 0 as r0. HP compatibility for
- Linux kernel. */
+ Linux kernel.
+ v Print vector constant value as an 8-byte integer value. */
+
void
ia64_print_operand (FILE * file, rtx x, int code)
{
@@ -4201,10 +4542,11 @@ ia64_print_operand (FILE * file, rtx x, int code)
str = reg_names [FR_REG (0)];
else if (x == CONST1_RTX (GET_MODE (x)))
str = reg_names [FR_REG (1)];
- else if (GET_CODE (x) == REG)
- str = reg_names [REGNO (x)];
else
- abort ();
+ {
+ gcc_assert (GET_CODE (x) == REG);
+ str = reg_names [REGNO (x)];
+ }
fputs (str, file);
return;
@@ -4242,13 +4584,12 @@ ia64_print_operand (FILE * file, rtx x, int code)
x = XEXP (XEXP (XEXP (x, 0), 1), 1);
if (GET_CODE (x) == CONST_INT)
value = INTVAL (x);
- else if (GET_CODE (x) == REG)
+ else
{
+ gcc_assert (GET_CODE (x) == REG);
fprintf (file, ", %s", reg_names[REGNO (x)]);
return;
}
- else
- abort ();
break;
case POST_INC:
@@ -4295,6 +4636,13 @@ ia64_print_operand (FILE * file, rtx x, int code)
}
break;
+ case 'X':
+ {
+ unsigned int regno = REGNO (x);
+ fprintf (file, "%s, %s", reg_names [regno], reg_names [regno + 1]);
+ }
+ return;
+
case 'r':
/* If this operand is the constant zero, write it as register zero.
Any register, zero, or CONST_INT value is OK here. */
@@ -4308,6 +4656,11 @@ ia64_print_operand (FILE * file, rtx x, int code)
output_operand_lossage ("invalid %%r value");
return;
+ case 'v':
+ gcc_assert (GET_CODE (x) == CONST_VECTOR);
+ x = simplify_subreg (DImode, x, GET_MODE (x), 0);
+ break;
+
case '+':
{
const char *which;
@@ -4320,11 +4673,13 @@ ia64_print_operand (FILE * file, rtx x, int code)
int pred_val = INTVAL (XEXP (x, 0));
/* Guess top and bottom 10% statically predicted. */
- if (pred_val < REG_BR_PROB_BASE / 50)
+ if (pred_val < REG_BR_PROB_BASE / 50
+ && br_prob_note_reliable_p (x))
which = ".spnt";
else if (pred_val < REG_BR_PROB_BASE / 2)
which = ".dpnt";
- else if (pred_val < REG_BR_PROB_BASE / 100 * 98)
+ else if (pred_val < REG_BR_PROB_BASE / 100 * 98
+ || !br_prob_note_reliable_p (x))
which = ".dptk";
else
which = ".sptk";
@@ -4370,7 +4725,7 @@ ia64_print_operand (FILE * file, rtx x, int code)
case MEM:
{
rtx addr = XEXP (x, 0);
- if (GET_RTX_CLASS (GET_CODE (addr)) == 'a')
+ if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
addr = XEXP (addr, 0);
fprintf (file, "[%s]", reg_names [REGNO (addr)]);
break;
@@ -4485,7 +4840,7 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
so that we get secondary memory reloads. Between FR_REGS,
we have to make this at least as expensive as MEMORY_MOVE_COST
to avoid spectacularly poor register class preferencing. */
- if (mode == XFmode)
+ if (mode == XFmode || mode == RFmode)
{
if (to != GR_REGS || from != GR_REGS)
return MEMORY_MOVE_COST (mode, to, 0);
@@ -4519,18 +4874,53 @@ ia64_register_move_cost (enum machine_mode mode, enum reg_class from,
case GR_REGS:
case FR_REGS:
+ case FP_REGS:
case GR_AND_FR_REGS:
case GR_AND_BR_REGS:
case ALL_REGS:
break;
default:
- abort ();
+ gcc_unreachable ();
}
return 2;
}
+/* Implement PREFERRED_RELOAD_CLASS. Place additional restrictions on CLASS
+ to use when copying X into that class. */
+
+enum reg_class
+ia64_preferred_reload_class (rtx x, enum reg_class class)
+{
+ switch (class)
+ {
+ case FR_REGS:
+ case FP_REGS:
+ /* Don't allow volatile mem reloads into floating point registers.
+ This is defined to force reload to choose the r/m case instead
+ of the f/f case when reloading (set (reg fX) (mem/v)). */
+ if (MEM_P (x) && MEM_VOLATILE_P (x))
+ return NO_REGS;
+
+ /* Force all unrecognized constants into the constant pool. */
+ if (CONSTANT_P (x))
+ return NO_REGS;
+ break;
+
+ case AR_M_REGS:
+ case AR_I_REGS:
+ if (!OBJECT_P (x))
+ return NO_REGS;
+ break;
+
+ default:
+ break;
+ }
+
+ return class;
+}
+
/* This function returns the register class required for a secondary
register when copying between one of the registers in CLASS, and X,
using MODE. A return value of NO_REGS means that no secondary register
@@ -4572,6 +4962,7 @@ ia64_secondary_reload_class (enum reg_class class,
break;
case FR_REGS:
+ case FP_REGS:
/* Need to go through general registers to get to other class regs. */
if (regno >= 0 && ! (FR_REGNO_P (regno) || GENERAL_REGNO_P (regno)))
return GR_REGS;
@@ -4690,7 +5081,7 @@ fix_range (const char *const_str)
dash = strchr (str, '-');
if (!dash)
{
- warning ("value of -mfixed-range must have form REG1-REG2");
+ warning (0, "value of -mfixed-range must have form REG1-REG2");
return;
}
*dash = '\0';
@@ -4702,14 +5093,14 @@ fix_range (const char *const_str)
first = decode_reg_name (str);
if (first < 0)
{
- warning ("unknown register name: %s", str);
+ warning (0, "unknown register name: %s", str);
return;
}
last = decode_reg_name (dash + 1);
if (last < 0)
{
- warning ("unknown register name: %s", dash + 1);
+ warning (0, "unknown register name: %s", dash + 1);
return;
}
@@ -4717,7 +5108,7 @@ fix_range (const char *const_str)
if (first > last)
{
- warning ("%s-%s is an empty range", str, dash + 1);
+ warning (0, "%s-%s is an empty range", str, dash + 1);
return;
}
@@ -4732,87 +5123,70 @@ fix_range (const char *const_str)
}
}
-static struct machine_function *
-ia64_init_machine_status (void)
-{
- return ggc_alloc_cleared (sizeof (struct machine_function));
-}
-
-/* Handle TARGET_OPTIONS switches. */
+/* Implement TARGET_HANDLE_OPTION. */
-void
-ia64_override_options (void)
+static bool
+ia64_handle_option (size_t code, const char *arg, int value)
{
- static struct pta
- {
- const char *const name; /* processor name or nickname. */
- const enum processor_type processor;
- }
- const processor_alias_table[] =
+ switch (code)
{
- {"itanium", PROCESSOR_ITANIUM},
- {"itanium1", PROCESSOR_ITANIUM},
- {"merced", PROCESSOR_ITANIUM},
- {"itanium2", PROCESSOR_ITANIUM2},
- {"mckinley", PROCESSOR_ITANIUM2},
- };
-
- int const pta_size = ARRAY_SIZE (processor_alias_table);
- int i;
+ case OPT_mfixed_range_:
+ fix_range (arg);
+ return true;
- if (TARGET_AUTO_PIC)
- target_flags |= MASK_CONST_GP;
+ case OPT_mtls_size_:
+ if (value != 14 && value != 22 && value != 64)
+ error ("bad value %<%s%> for -mtls-size= switch", arg);
+ return true;
- if (TARGET_INLINE_FLOAT_DIV_LAT && TARGET_INLINE_FLOAT_DIV_THR)
- {
- warning ("cannot optimize floating point division for both latency and throughput");
- target_flags &= ~MASK_INLINE_FLOAT_DIV_THR;
- }
+ case OPT_mtune_:
+ {
+ static struct pta
+ {
+ const char *name; /* processor name or nickname. */
+ enum processor_type processor;
+ }
+ const processor_alias_table[] =
+ {
+ {"itanium", PROCESSOR_ITANIUM},
+ {"itanium1", PROCESSOR_ITANIUM},
+ {"merced", PROCESSOR_ITANIUM},
+ {"itanium2", PROCESSOR_ITANIUM2},
+ {"mckinley", PROCESSOR_ITANIUM2},
+ };
+ int const pta_size = ARRAY_SIZE (processor_alias_table);
+ int i;
- if (TARGET_INLINE_INT_DIV_LAT && TARGET_INLINE_INT_DIV_THR)
- {
- warning ("cannot optimize integer division for both latency and throughput");
- target_flags &= ~MASK_INLINE_INT_DIV_THR;
- }
+ for (i = 0; i < pta_size; i++)
+ if (!strcmp (arg, processor_alias_table[i].name))
+ {
+ ia64_tune = processor_alias_table[i].processor;
+ break;
+ }
+ if (i == pta_size)
+ error ("bad value %<%s%> for -mtune= switch", arg);
+ return true;
+ }
- if (TARGET_INLINE_SQRT_LAT && TARGET_INLINE_SQRT_THR)
- {
- warning ("cannot optimize square root for both latency and throughput");
- target_flags &= ~MASK_INLINE_SQRT_THR;
+ default:
+ return true;
}
+}
- if (TARGET_INLINE_SQRT_LAT)
- {
- warning ("not yet implemented: latency-optimized inline square root");
- target_flags &= ~MASK_INLINE_SQRT_LAT;
- }
+/* Implement OVERRIDE_OPTIONS. */
- if (ia64_fixed_range_string)
- fix_range (ia64_fixed_range_string);
+void
+ia64_override_options (void)
+{
+ if (TARGET_AUTO_PIC)
+ target_flags |= MASK_CONST_GP;
- if (ia64_tls_size_string)
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
{
- char *end;
- unsigned long tmp = strtoul (ia64_tls_size_string, &end, 10);
- if (*end || (tmp != 14 && tmp != 22 && tmp != 64))
- error ("bad value (%s) for -mtls-size= switch", ia64_tls_size_string);
- else
- ia64_tls_size = tmp;
+ warning (0, "not yet implemented: latency-optimized inline square root");
+ TARGET_INLINE_SQRT = INL_MAX_THR;
}
- if (!ia64_tune_string)
- ia64_tune_string = "itanium2";
-
- for (i = 0; i < pta_size; i++)
- if (! strcmp (ia64_tune_string, processor_alias_table[i].name))
- {
- ia64_tune = processor_alias_table[i].processor;
- break;
- }
-
- if (i == pta_size)
- error ("bad value (%s) for -tune= switch", ia64_tune_string);
-
ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
flag_schedule_insns_after_reload = 0;
@@ -4820,6 +5194,12 @@ ia64_override_options (void)
init_machine_status = ia64_init_machine_status;
}
+
+static struct machine_function *
+ia64_init_machine_status (void)
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
static enum attr_itanium_class ia64_safe_itanium_class (rtx);
static enum attr_type ia64_safe_type (rtx);
@@ -4851,7 +5231,6 @@ ia64_safe_type (rtx insn)
never explicitly used in gcc generated code, it seems wasteful to
do so (plus it would make the call and return patterns needlessly
complex). */
-#define REG_GP (GR_REG (1))
#define REG_RP (BR_REG (0))
#define REG_AR_CFM (FIRST_PSEUDO_REGISTER + 1)
/* This is used for volatile asms which may require a stop bit immediately
@@ -4896,8 +5275,8 @@ struct reg_write_state rws_sum[NUM_REGS];
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. */
+ in which case we don't need another stop bit. Without this,
+ ia64_variable_issue will die when scheduling an alloc. */
static int first_instruction;
/* Misc flags needed to compute RAW/WAW dependencies while we are traversing
@@ -4915,12 +5294,12 @@ struct reg_flags
static void rws_update (struct reg_write_state *, int, struct reg_flags, int);
static int rws_access_regno (int, struct reg_flags, int);
static int rws_access_reg (rtx, struct reg_flags, int);
-static void update_set_flags (rtx, struct reg_flags *, int *, rtx *);
-static int set_src_needs_barrier (rtx, struct reg_flags, int, rtx);
+static void update_set_flags (rtx, struct reg_flags *);
+static int set_src_needs_barrier (rtx, struct reg_flags, int);
static int rtx_needs_barrier (rtx, struct reg_flags, int);
static void init_insn_group_barriers (void);
-static int group_barrier_needed_p (rtx);
-static int safe_group_barrier_needed_p (rtx);
+static int group_barrier_needed (rtx);
+static int safe_group_barrier_needed (rtx);
/* Update *RWS for REGNO, which is being written by the current instruction,
with predicate PRED, and associated register flags in FLAGS. */
@@ -4948,8 +5327,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
{
int need_barrier = 0;
- if (regno >= NUM_REGS)
- abort ();
+ gcc_assert (regno < NUM_REGS);
if (! PR_REGNO_P (regno))
flags.is_and = flags.is_or = 0;
@@ -4959,8 +5337,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
int write_count;
/* One insn writes same reg multiple times? */
- if (rws_insn[regno].write_count > 0)
- abort ();
+ gcc_assert (!rws_insn[regno].write_count);
/* Update info for current instruction. */
rws_update (rws_insn, regno, flags, pred);
@@ -5001,7 +5378,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
else
@@ -5054,7 +5431,7 @@ rws_access_regno (int regno, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -5082,62 +5459,31 @@ rws_access_reg (rtx reg, struct reg_flags flags, int pred)
the condition, stored in *PFLAGS, *PPRED and *PCOND. */
static void
-update_set_flags (rtx x, struct reg_flags *pflags, int *ppred, rtx *pcond)
+update_set_flags (rtx x, struct reg_flags *pflags)
{
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 ... */
+ /* There are four cases here:
+ (1) The destination is (pc), in which case this is a branch,
+ nothing here applies.
+ (2) The destination is ar.lc, in which case this is a
+ doloop_end_internal,
+ (3) The destination is an fp register, in which case this is
+ an fselect instruction.
+ (4) The condition has (unspec [(reg)] UNSPEC_LDC), in which case
+ this is a check load.
+ In all cases, nothing we do in this function applies. */
+ return;
default:
- if (GET_RTX_CLASS (GET_CODE (src)) == '<'
- && GET_MODE_CLASS (GET_MODE (XEXP (src, 0))) == MODE_FLOAT)
+ if (COMPARISON_P (src)
+ && SCALAR_FLOAT_MODE_P (GET_MODE (XEXP (src, 0))))
/* 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. */
@@ -5161,7 +5507,7 @@ update_set_flags (rtx x, struct reg_flags *pflags, int *ppred, rtx *pcond)
for this insn. */
static int
-set_src_needs_barrier (rtx x, struct reg_flags flags, int pred, rtx cond)
+set_src_needs_barrier (rtx x, struct reg_flags flags, int pred)
{
int need_barrier = 0;
rtx dst;
@@ -5176,22 +5522,29 @@ set_src_needs_barrier (rtx x, struct reg_flags flags, int pred, rtx cond)
/* X is a conditional branch. */
/* ??? This seems redundant, as the caller sets this bit for
all JUMP_INSNs. */
- flags.is_branch = 1;
+ if (!ia64_spec_check_src_p (src))
+ flags.is_branch = 1;
return rtx_needs_barrier (src, flags, pred);
}
- need_barrier = rtx_needs_barrier (src, flags, pred);
+ if (ia64_spec_check_src_p (src))
+ /* Avoid checking one register twice (in condition
+ and in 'then' section) for ldc pattern. */
+ {
+ gcc_assert (REG_P (XEXP (src, 2)));
+ need_barrier = rtx_needs_barrier (XEXP (src, 2), flags, pred);
+
+ /* We process MEM below. */
+ src = XEXP (src, 1);
+ }
- /* This instruction unconditionally uses a predicate register. */
- if (cond)
- need_barrier |= rws_access_reg (cond, flags, 0);
+ need_barrier |= rtx_needs_barrier (src, flags, pred);
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;
}
@@ -5208,7 +5561,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
int need_barrier = 0;
const char *format_ptr;
struct reg_flags new_flags;
- rtx cond = 0;
+ rtx cond;
if (! x)
return 0;
@@ -5218,8 +5571,8 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
switch (GET_CODE (x))
{
case SET:
- update_set_flags (x, &new_flags, &pred, &cond);
- need_barrier = set_src_needs_barrier (x, new_flags, pred, cond);
+ update_set_flags (x, &new_flags);
+ need_barrier = set_src_needs_barrier (x, new_flags, pred);
if (GET_CODE (SET_SRC (x)) != CALL)
{
new_flags.is_write = 1;
@@ -5232,7 +5585,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier |= rws_access_regno (AR_EC_REGNUM, new_flags, pred);
/* Avoid multiple register writes, in case this is a pattern with
- multiple CALL rtx. This avoids an abort in rws_access_reg. */
+ multiple CALL rtx. This avoids a failure in rws_access_reg. */
if (! flags.is_sibcall && ! rws_insn[REG_AR_CFM].write_count)
{
new_flags.is_write = 1;
@@ -5246,16 +5599,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
/* X is a predicated instruction. */
cond = COND_EXEC_TEST (x);
- if (pred)
- abort ();
+ gcc_assert (!pred);
need_barrier = rtx_needs_barrier (cond, flags, 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 ();
+ gcc_assert (GET_CODE (cond) == REG
+ && REGNO_REG_CLASS (REGNO (cond)) == PR_REGS);
pred = REGNO (cond);
if (is_complemented)
++pred;
@@ -5276,7 +5627,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
|| (MEM_VOLATILE_P (x) && TARGET_VOL_ASM_STOP))
{
/* Avoid writing the register multiple times if we have multiple
- asm outputs. This avoids an abort in rws_access_reg. */
+ asm outputs. This avoids a failure in rws_access_reg. */
if (! rws_insn[REG_VOLATILE].write_count)
{
new_flags.is_write = 1;
@@ -5286,7 +5637,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
}
/* For all ASM_OPERANDS, we must traverse the vector of input operands.
- We can not just fall through here since then we would be confused
+ We cannot just fall through here since then we would be confused
by the ASM_INPUT rtx inside ASM_OPERANDS, which do not indicate
traditional asms unlike their normal usage. */
@@ -5299,17 +5650,26 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
for (i = XVECLEN (x, 0) - 1; i >= 0; --i)
{
rtx pat = XVECEXP (x, 0, i);
- if (GET_CODE (pat) == SET)
+ switch (GET_CODE (pat))
{
- update_set_flags (pat, &new_flags, &pred, &cond);
- need_barrier |= set_src_needs_barrier (pat, new_flags, pred, cond);
+ case SET:
+ update_set_flags (pat, &new_flags);
+ need_barrier |= set_src_needs_barrier (pat, new_flags, pred);
+ break;
+
+ case USE:
+ case CALL:
+ case ASM_OPERANDS:
+ need_barrier |= rtx_needs_barrier (pat, flags, pred);
+ break;
+
+ case CLOBBER:
+ case RETURN:
+ break;
+
+ default:
+ gcc_unreachable ();
}
- 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)
{
@@ -5329,8 +5689,8 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
case SUBREG:
- x = SUBREG_REG (x);
- /* FALLTHRU */
+ need_barrier |= rtx_needs_barrier (SUBREG_REG (x), flags, pred);
+ break;
case REG:
if (REGNO (x) == AR_UNAT_REGNUM)
{
@@ -5347,14 +5707,13 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier = rtx_needs_barrier (XEXP (x, 0), new_flags, pred);
break;
- case CONST_INT: case CONST_DOUBLE:
+ case CONST_INT: case CONST_DOUBLE: case CONST_VECTOR:
case SYMBOL_REF: case LABEL_REF: case CONST:
break;
/* Operators with side-effects. */
case POST_INC: case POST_DEC:
- if (GET_CODE (XEXP (x, 0)) != REG)
- abort ();
+ gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
new_flags.is_write = 0;
need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
@@ -5363,8 +5722,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
case POST_MODIFY:
- if (GET_CODE (XEXP (x, 0)) != REG)
- abort ();
+ gcc_assert (GET_CODE (XEXP (x, 0)) == REG);
new_flags.is_write = 0;
need_barrier = rws_access_reg (XEXP (x, 0), new_flags, pred);
@@ -5391,6 +5749,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
break;
+ case VEC_SELECT:
+ /* VEC_SELECT's second argument is a PARALLEL with integers that
+ describe the elements selected. On ia64, those integers are
+ always constants. Avoid walking the PARALLEL so that we don't
+ get confused with "normal" parallels and then die. */
+ need_barrier = rtx_needs_barrier (XEXP (x, 0), flags, pred);
+ break;
+
case UNSPEC:
switch (XINT (x, 1))
{
@@ -5415,7 +5781,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
HOST_WIDE_INT bit = (offset >> 3) & 63;
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
- new_flags.is_write = (XINT (x, 1) == 1);
+ new_flags.is_write = (XINT (x, 1) == UNSPEC_GR_SPILL);
need_barrier |= rws_access_regno (AR_UNAT_BIT_0 + bit,
new_flags, pred);
break;
@@ -5427,10 +5793,17 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
case UNSPEC_SETF_EXP:
case UNSPEC_ADDP4:
case UNSPEC_FR_SQRT_RECIP_APPROX:
+ case UNSPEC_LDA:
+ case UNSPEC_LDS:
+ case UNSPEC_LDSA:
+ case UNSPEC_CHKACLR:
+ case UNSPEC_CHKS:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
break;
case UNSPEC_FR_RECIP_APPROX:
+ case UNSPEC_SHRP:
+ case UNSPEC_COPYSIGN:
need_barrier = rtx_needs_barrier (XVECEXP (x, 0, 0), flags, pred);
need_barrier |= rtx_needs_barrier (XVECEXP (x, 0, 1), flags, pred);
break;
@@ -5441,7 +5814,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -5474,7 +5847,7 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
return 0;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -5513,14 +5886,14 @@ rtx_needs_barrier (rtx x, struct reg_flags flags, int pred)
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
}
return need_barrier;
}
-/* Clear out the state for group_barrier_needed_p at the start of a
+/* Clear out the state for group_barrier_needed at the start of a
sequence of insns. */
static void
@@ -5530,12 +5903,12 @@ init_insn_group_barriers (void)
first_instruction = 1;
}
-/* 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. */
+/* Given the current state, determine whether a group barrier (a stop bit) is
+ necessary before INSN. Return nonzero if so. This modifies the state to
+ include the effects of INSN as a side-effect. */
static int
-group_barrier_needed_p (rtx insn)
+group_barrier_needed (rtx insn)
{
rtx pat;
int need_barrier = 0;
@@ -5572,7 +5945,8 @@ group_barrier_needed_p (rtx insn)
break;
case JUMP_INSN:
- flags.is_branch = 1;
+ if (!ia64_spec_check_p (insn))
+ flags.is_branch = 1;
/* Don't bundle a jump following a call. */
if ((pat = prev_active_insn (insn))
@@ -5628,7 +6002,7 @@ group_barrier_needed_p (rtx insn)
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (first_instruction && INSN_P (insn)
@@ -5643,10 +6017,10 @@ group_barrier_needed_p (rtx insn)
return need_barrier;
}
-/* Like group_barrier_needed_p, but do not clobber the current state. */
+/* Like group_barrier_needed, but do not clobber the current state. */
static int
-safe_group_barrier_needed_p (rtx insn)
+safe_group_barrier_needed (rtx insn)
{
struct reg_write_state rws_saved[NUM_REGS];
int saved_first_instruction;
@@ -5655,7 +6029,7 @@ safe_group_barrier_needed_p (rtx insn)
memcpy (rws_saved, rws_sum, NUM_REGS * sizeof *rws_saved);
saved_first_instruction = first_instruction;
- t = group_barrier_needed_p (insn);
+ t = group_barrier_needed (insn);
memcpy (rws_sum, rws_saved, NUM_REGS * sizeof *rws_saved);
first_instruction = saved_first_instruction;
@@ -5705,7 +6079,7 @@ emit_insn_group_barriers (FILE *dump)
{
insns_since_last_label = 1;
- if (group_barrier_needed_p (insn))
+ if (group_barrier_needed (insn))
{
if (last_label)
{
@@ -5753,158 +6127,17 @@ emit_all_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
{
if (recog_memoized (insn) == CODE_FOR_insn_group_barrier)
init_insn_group_barriers ();
- else if (group_barrier_needed_p (insn))
+ else if (group_barrier_needed (insn))
{
emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
init_insn_group_barriers ();
- group_barrier_needed_p (insn);
+ group_barrier_needed (insn);
}
}
}
}
-static int errata_find_address_regs (rtx *, void *);
-static void errata_emit_nops (rtx);
-static void fixup_errata (void);
-
-/* This structure is used to track some details about the previous insns
- groups so we can determine if it may be necessary to insert NOPs to
- workaround hardware errata. */
-static struct group
-{
- HARD_REG_SET p_reg_set;
- HARD_REG_SET gr_reg_conditionally_set;
-} last_group[2];
-
-/* Index into the last_group array. */
-static int group_idx;
-
-/* Called through for_each_rtx; determines if a hard register that was
- conditionally set in the previous group is used as an address register.
- It ensures that for_each_rtx returns 1 in that case. */
-static int
-errata_find_address_regs (rtx *xp, void *data ATTRIBUTE_UNUSED)
-{
- rtx x = *xp;
- if (GET_CODE (x) != MEM)
- return 0;
- x = XEXP (x, 0);
- if (GET_CODE (x) == POST_MODIFY)
- x = XEXP (x, 0);
- if (GET_CODE (x) == REG)
- {
- struct group *prev_group = last_group + (group_idx ^ 1);
- if (TEST_HARD_REG_BIT (prev_group->gr_reg_conditionally_set,
- REGNO (x)))
- return 1;
- return -1;
- }
- return 0;
-}
-
-/* Called for each insn; this function keeps track of the state in
- last_group and emits additional NOPs if necessary to work around
- an Itanium A/B step erratum. */
-static void
-errata_emit_nops (rtx insn)
-{
- struct group *this_group = last_group + group_idx;
- struct group *prev_group = last_group + (group_idx ^ 1);
- rtx pat = PATTERN (insn);
- rtx cond = GET_CODE (pat) == COND_EXEC ? COND_EXEC_TEST (pat) : 0;
- rtx real_pat = cond ? COND_EXEC_CODE (pat) : pat;
- enum attr_type type;
- rtx set = real_pat;
-
- if (GET_CODE (real_pat) == USE
- || GET_CODE (real_pat) == CLOBBER
- || GET_CODE (real_pat) == ASM_INPUT
- || GET_CODE (real_pat) == ADDR_VEC
- || GET_CODE (real_pat) == ADDR_DIFF_VEC
- || asm_noperands (PATTERN (insn)) >= 0)
- return;
-
- /* single_set doesn't work for COND_EXEC insns, so we have to duplicate
- parts of it. */
-
- if (GET_CODE (set) == PARALLEL)
- {
- int i;
- set = XVECEXP (real_pat, 0, 0);
- for (i = 1; i < XVECLEN (real_pat, 0); i++)
- if (GET_CODE (XVECEXP (real_pat, 0, i)) != USE
- && GET_CODE (XVECEXP (real_pat, 0, i)) != CLOBBER)
- {
- set = 0;
- break;
- }
- }
-
- if (set && GET_CODE (set) != SET)
- set = 0;
-
- type = get_attr_type (insn);
-
- if (type == TYPE_F
- && set && REG_P (SET_DEST (set)) && PR_REGNO_P (REGNO (SET_DEST (set))))
- SET_HARD_REG_BIT (this_group->p_reg_set, REGNO (SET_DEST (set)));
-
- if ((type == TYPE_M || type == TYPE_A) && cond && set
- && REG_P (SET_DEST (set))
- && GET_CODE (SET_SRC (set)) != PLUS
- && GET_CODE (SET_SRC (set)) != MINUS
- && (GET_CODE (SET_SRC (set)) != ASHIFT
- || !shladd_operand (XEXP (SET_SRC (set), 1), VOIDmode))
- && (GET_CODE (SET_SRC (set)) != MEM
- || GET_CODE (XEXP (SET_SRC (set), 0)) != POST_MODIFY)
- && GENERAL_REGNO_P (REGNO (SET_DEST (set))))
- {
- if (GET_RTX_CLASS (GET_CODE (cond)) != '<'
- || ! REG_P (XEXP (cond, 0)))
- abort ();
-
- if (TEST_HARD_REG_BIT (prev_group->p_reg_set, REGNO (XEXP (cond, 0))))
- SET_HARD_REG_BIT (this_group->gr_reg_conditionally_set, REGNO (SET_DEST (set)));
- }
- if (for_each_rtx (&real_pat, errata_find_address_regs, NULL))
- {
- emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
- emit_insn_before (gen_nop (), insn);
- emit_insn_before (gen_insn_group_barrier (GEN_INT (3)), insn);
- group_idx = 0;
- memset (last_group, 0, sizeof last_group);
- }
-}
-
-/* Emit extra nops if they are required to work around hardware errata. */
-
-static void
-fixup_errata (void)
-{
- rtx insn;
-
- if (! TARGET_B_STEP)
- return;
-
- group_idx = 0;
- memset (last_group, 0, sizeof last_group);
-
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
- {
- if (!INSN_P (insn))
- continue;
-
- if (ia64_safe_type (insn) == TYPE_S)
- {
- group_idx ^= 1;
- memset (last_group + group_idx, 0, sizeof last_group[group_idx]);
- }
- else
- errata_emit_nops (insn);
- }
-}
-
/* Instruction scheduling support. */
@@ -5932,7 +6165,7 @@ static const char *bundle_name [NR_BUNDLES] =
int ia64_final_schedule = 0;
-/* Codes of the corresponding quieryied units: */
+/* Codes of the corresponding queried units: */
static int _0mii_, _0mmi_, _0mfi_, _0mmf_;
static int _0bbb_, _0mbb_, _0mib_, _0mmb_, _0mfb_, _0mlx_;
@@ -5967,7 +6200,15 @@ static state_t prev_cycle_state = NULL;
/* The following array element values are TRUE if the corresponding
insn requires to add stop bits before it. */
-static char *stops_p;
+static char *stops_p = NULL;
+
+/* The following array element values are ZERO for non-speculative
+ instructions and hold corresponding speculation check number for
+ speculative instructions. */
+static int *spec_check_no = NULL;
+
+/* Size of spec_check_no array. */
+static int max_uid = 0;
/* The following variable is used to set up the mentioned above array. */
@@ -5989,6 +6230,9 @@ static int *clocks;
static int *add_cycles;
+/* The following variable value is number of data speculations in progress. */
+static int pending_data_specs = 0;
+
static rtx ia64_single_set (rtx);
static void ia64_emit_insn_before (rtx, rtx);
@@ -6038,16 +6282,18 @@ ia64_single_set (rtx insn)
return ret;
}
-/* Adjust the cost of a scheduling dependency. Return the new cost of
- a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
+/* Adjust the cost of a scheduling dependency.
+ Return the new cost of a dependency of type DEP_TYPE or INSN on DEP_INSN.
+ COST is the current cost. */
static int
-ia64_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
+ia64_adjust_cost_2 (rtx insn, int dep_type1, rtx dep_insn, int cost)
{
+ enum reg_note dep_type = (enum reg_note) dep_type1;
enum attr_itanium_class dep_class;
enum attr_itanium_class insn_class;
- if (REG_NOTE_KIND (link) != REG_DEP_OUTPUT)
+ if (dep_type != REG_DEP_OUTPUT)
return cost;
insn_class = ia64_safe_itanium_class (insn);
@@ -6078,6 +6324,12 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{
rtx insn, link, next, next_tail;
+ /* Before reload, which_alternative is not set, which means that
+ ia64_safe_itanium_class will produce wrong results for (at least)
+ move instructions. */
+ if (!reload_completed)
+ return;
+
next_tail = NEXT_INSN (tail);
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
if (INSN_P (insn))
@@ -6088,14 +6340,19 @@ ia64_dependencies_evaluation_hook (rtx head, rtx tail)
{
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
{
+ enum attr_itanium_class c;
+
+ if (REG_NOTE_KIND (link) != REG_DEP_TRUE)
+ continue;
next = XEXP (link, 0);
- if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_ST
- || ia64_safe_itanium_class (next) == ITANIUM_CLASS_STF)
+ c = ia64_safe_itanium_class (next);
+ if ((c == ITANIUM_CLASS_ST
+ || c == ITANIUM_CLASS_STF)
&& ia64_st_address_bypass_p (insn, next))
break;
- else if ((ia64_safe_itanium_class (next) == ITANIUM_CLASS_LD
- || ia64_safe_itanium_class (next)
- == ITANIUM_CLASS_FLD)
+ else if ((c == ITANIUM_CLASS_LD
+ || c == ITANIUM_CLASS_FLD
+ || c == ITANIUM_CLASS_FLDP)
&& ia64_ld_address_bypass_p (insn, next))
break;
}
@@ -6117,13 +6374,32 @@ ia64_sched_init (FILE *dump ATTRIBUTE_UNUSED,
for (insn = NEXT_INSN (current_sched_info->prev_head);
insn != current_sched_info->next_tail;
insn = NEXT_INSN (insn))
- if (SCHED_GROUP_P (insn))
- abort ();
+ gcc_assert (!SCHED_GROUP_P (insn));
#endif
last_scheduled_insn = NULL_RTX;
init_insn_group_barriers ();
}
+/* We're beginning a scheduling pass. Check assertion. */
+
+static void
+ia64_sched_init_global (FILE *dump ATTRIBUTE_UNUSED,
+ int sched_verbose ATTRIBUTE_UNUSED,
+ int max_ready ATTRIBUTE_UNUSED)
+{
+ gcc_assert (!pending_data_specs);
+}
+
+/* Scheduling pass is now finished. Free/reset static variable. */
+static void
+ia64_sched_finish_global (FILE *dump ATTRIBUTE_UNUSED,
+ int sched_verbose ATTRIBUTE_UNUSED)
+{
+ free (spec_check_no);
+ spec_check_no = 0;
+ max_uid = 0;
+}
+
/* We are about to being issuing insns for this clock cycle.
Override the default sort algorithm to better slot instructions. */
@@ -6185,7 +6461,7 @@ ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
int nr_need_stop = 0;
for (insnp = ready; insnp < e_ready; insnp++)
- if (safe_group_barrier_needed_p (*insnp))
+ if (safe_group_barrier_needed (*insnp))
nr_need_stop++;
if (reorder_type == 1 && n_ready == nr_need_stop)
@@ -6199,7 +6475,7 @@ ia64_dfa_sched_reorder (FILE *dump, int sched_verbose, rtx *ready,
while (insnp >= ready + deleted)
{
rtx insn = *insnp;
- if (! safe_group_barrier_needed_p (insn))
+ if (! safe_group_barrier_needed (insn))
break;
memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
*ready = insn;
@@ -6246,12 +6522,23 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
rtx insn ATTRIBUTE_UNUSED,
int can_issue_more ATTRIBUTE_UNUSED)
{
+ if (current_sched_info->flags & DO_SPECULATION)
+ /* Modulo scheduling does not extend h_i_d when emitting
+ new instructions. Deal with it. */
+ {
+ if (DONE_SPEC (insn) & BEGIN_DATA)
+ pending_data_specs++;
+ if (CHECK_SPEC (insn) & BEGIN_DATA)
+ pending_data_specs--;
+ }
+
last_scheduled_insn = insn;
memcpy (prev_cycle_state, curr_state, dfa_state_size);
if (reload_completed)
{
- if (group_barrier_needed_p (insn))
- abort ();
+ int needed = group_barrier_needed (insn);
+
+ gcc_assert (!needed);
if (GET_CODE (insn) == CALL_INSN)
init_insn_group_barriers ();
stops_p [INSN_UID (insn)] = stop_before_p;
@@ -6266,10 +6553,23 @@ ia64_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
static int
ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
{
- if (insn == NULL_RTX || !INSN_P (insn))
- abort ();
- return (!reload_completed
- || !safe_group_barrier_needed_p (insn));
+ gcc_assert (insn && INSN_P (insn));
+ return ((!reload_completed
+ || !safe_group_barrier_needed (insn))
+ && ia64_first_cycle_multipass_dfa_lookahead_guard_spec (insn));
+}
+
+/* We are choosing insn from the ready queue. Return nonzero if INSN
+ can be chosen. */
+
+static bool
+ia64_first_cycle_multipass_dfa_lookahead_guard_spec (rtx insn)
+{
+ gcc_assert (insn && INSN_P (insn));
+ /* Size of ALAT is 32. As far as we perform conservative data speculation,
+ we keep ALAT half-empty. */
+ return (pending_data_specs < 16
+ || !(TODO_SPEC (insn) & BEGIN_DATA));
}
/* The following variable value is pseudo-insn used by the DFA insn
@@ -6278,7 +6578,7 @@ ia64_first_cycle_multipass_dfa_lookahead_guard (rtx insn)
static rtx dfa_pre_cycle_insn;
-/* We are about to being issuing INSN. Return nonzero if we can not
+/* We are about to being issuing INSN. Return nonzero if we cannot
issue it on given cycle CLOCK and return zero if we should not sort
the ready queue on the next clock start. */
@@ -6288,9 +6588,8 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
{
int setup_clocks_p = FALSE;
- if (insn == NULL_RTX || !INSN_P (insn))
- abort ();
- if ((reload_completed && safe_group_barrier_needed_p (insn))
+ gcc_assert (insn && INSN_P (insn));
+ if ((reload_completed && safe_group_barrier_needed (insn))
|| (last_scheduled_insn
&& (GET_CODE (last_scheduled_insn) == CALL_INSN
|| GET_CODE (PATTERN (last_scheduled_insn)) == ASM_INPUT
@@ -6358,6 +6657,590 @@ ia64_dfa_new_cycle (FILE *dump, int verbose, rtx insn, int last_clock,
return 0;
}
+/* Implement targetm.sched.h_i_d_extended hook.
+ Extend internal data structures. */
+static void
+ia64_h_i_d_extended (void)
+{
+ if (current_sched_info->flags & DO_SPECULATION)
+ {
+ int new_max_uid = get_max_uid () + 1;
+
+ spec_check_no = xrecalloc (spec_check_no, new_max_uid,
+ max_uid, sizeof (*spec_check_no));
+ max_uid = new_max_uid;
+ }
+
+ if (stops_p != NULL)
+ {
+ int new_clocks_length = get_max_uid () + 1;
+
+ stops_p = xrecalloc (stops_p, new_clocks_length, clocks_length, 1);
+
+ if (ia64_tune == PROCESSOR_ITANIUM)
+ {
+ clocks = xrecalloc (clocks, new_clocks_length, clocks_length,
+ sizeof (int));
+ add_cycles = xrecalloc (add_cycles, new_clocks_length, clocks_length,
+ sizeof (int));
+ }
+
+ clocks_length = new_clocks_length;
+ }
+}
+
+/* Constants that help mapping 'enum machine_mode' to int. */
+enum SPEC_MODES
+ {
+ SPEC_MODE_INVALID = -1,
+ SPEC_MODE_FIRST = 0,
+ SPEC_MODE_FOR_EXTEND_FIRST = 1,
+ SPEC_MODE_FOR_EXTEND_LAST = 3,
+ SPEC_MODE_LAST = 8
+ };
+
+/* Return index of the MODE. */
+static int
+ia64_mode_to_int (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case BImode: return 0; /* SPEC_MODE_FIRST */
+ case QImode: return 1; /* SPEC_MODE_FOR_EXTEND_FIRST */
+ case HImode: return 2;
+ case SImode: return 3; /* SPEC_MODE_FOR_EXTEND_LAST */
+ case DImode: return 4;
+ case SFmode: return 5;
+ case DFmode: return 6;
+ case XFmode: return 7;
+ case TImode:
+ /* ??? This mode needs testing. Bypasses for ldfp8 instruction are not
+ mentioned in itanium[12].md. Predicate fp_register_operand also
+ needs to be defined. Bottom line: better disable for now. */
+ return SPEC_MODE_INVALID;
+ default: return SPEC_MODE_INVALID;
+ }
+}
+
+/* Provide information about speculation capabilities. */
+static void
+ia64_set_sched_flags (spec_info_t spec_info)
+{
+ unsigned int *flags = &(current_sched_info->flags);
+
+ if (*flags & SCHED_RGN
+ || *flags & SCHED_EBB)
+ {
+ int mask = 0;
+
+ if ((mflag_sched_br_data_spec && !reload_completed && optimize > 0)
+ || (mflag_sched_ar_data_spec && reload_completed))
+ {
+ mask |= BEGIN_DATA;
+
+ if ((mflag_sched_br_in_data_spec && !reload_completed)
+ || (mflag_sched_ar_in_data_spec && reload_completed))
+ mask |= BE_IN_DATA;
+ }
+
+ if (mflag_sched_control_spec)
+ {
+ mask |= BEGIN_CONTROL;
+
+ if (mflag_sched_in_control_spec)
+ mask |= BE_IN_CONTROL;
+ }
+
+ gcc_assert (*flags & USE_GLAT);
+
+ if (mask)
+ {
+ *flags |= USE_DEPS_LIST | DETACH_LIFE_INFO | DO_SPECULATION;
+
+ spec_info->mask = mask;
+ spec_info->flags = 0;
+
+ if ((mask & DATA_SPEC) && mflag_sched_prefer_non_data_spec_insns)
+ spec_info->flags |= PREFER_NON_DATA_SPEC;
+
+ if ((mask & CONTROL_SPEC)
+ && mflag_sched_prefer_non_control_spec_insns)
+ spec_info->flags |= PREFER_NON_CONTROL_SPEC;
+
+ if (mflag_sched_spec_verbose)
+ {
+ if (sched_verbose >= 1)
+ spec_info->dump = sched_dump;
+ else
+ spec_info->dump = stderr;
+ }
+ else
+ spec_info->dump = 0;
+
+ if (mflag_sched_count_spec_in_critical_path)
+ spec_info->flags |= COUNT_SPEC_IN_CRITICAL_PATH;
+ }
+ }
+}
+
+/* Implement targetm.sched.speculate_insn hook.
+ Check if the INSN can be TS speculative.
+ If 'no' - return -1.
+ If 'yes' - generate speculative pattern in the NEW_PAT and return 1.
+ If current pattern of the INSN already provides TS speculation, return 0. */
+static int
+ia64_speculate_insn (rtx insn, ds_t ts, rtx *new_pat)
+{
+ rtx pat, reg, mem, mem_reg;
+ int mode_no, gen_p = 1;
+ bool extend_p;
+
+ gcc_assert (!(ts & ~BEGIN_SPEC) && ts);
+
+ pat = PATTERN (insn);
+
+ if (GET_CODE (pat) == COND_EXEC)
+ pat = COND_EXEC_CODE (pat);
+
+ /* This should be a SET ... */
+ if (GET_CODE (pat) != SET)
+ return -1;
+
+ reg = SET_DEST (pat);
+ /* ... to the general/fp register ... */
+ if (!REG_P (reg) || !(GR_REGNO_P (REGNO (reg)) || FP_REGNO_P (REGNO (reg))))
+ return -1;
+
+ /* ... from the mem ... */
+ mem = SET_SRC (pat);
+
+ /* ... that can, possibly, be a zero_extend ... */
+ if (GET_CODE (mem) == ZERO_EXTEND)
+ {
+ mem = XEXP (mem, 0);
+ extend_p = true;
+ }
+ else
+ extend_p = false;
+
+ /* ... or a speculative load. */
+ if (GET_CODE (mem) == UNSPEC)
+ {
+ int code;
+
+ code = XINT (mem, 1);
+ if (code != UNSPEC_LDA && code != UNSPEC_LDS && code != UNSPEC_LDSA)
+ return -1;
+
+ if ((code == UNSPEC_LDA && !(ts & BEGIN_CONTROL))
+ || (code == UNSPEC_LDS && !(ts & BEGIN_DATA))
+ || code == UNSPEC_LDSA)
+ gen_p = 0;
+
+ mem = XVECEXP (mem, 0, 0);
+ gcc_assert (MEM_P (mem));
+ }
+
+ /* Source should be a mem ... */
+ if (!MEM_P (mem))
+ return -1;
+
+ /* ... addressed by a register. */
+ mem_reg = XEXP (mem, 0);
+ if (!REG_P (mem_reg))
+ return -1;
+
+ /* We should use MEM's mode since REG's mode in presence of ZERO_EXTEND
+ will always be DImode. */
+ mode_no = ia64_mode_to_int (GET_MODE (mem));
+
+ if (mode_no == SPEC_MODE_INVALID
+ || (extend_p
+ && !(SPEC_MODE_FOR_EXTEND_FIRST <= mode_no
+ && mode_no <= SPEC_MODE_FOR_EXTEND_LAST)))
+ return -1;
+
+ extract_insn_cached (insn);
+ gcc_assert (reg == recog_data.operand[0] && mem == recog_data.operand[1]);
+
+ *new_pat = ia64_gen_spec_insn (insn, ts, mode_no, gen_p != 0, extend_p);
+
+ return gen_p;
+}
+
+enum
+ {
+ /* Offset to reach ZERO_EXTEND patterns. */
+ SPEC_GEN_EXTEND_OFFSET = SPEC_MODE_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 1,
+ /* Number of patterns for each speculation mode. */
+ SPEC_N = (SPEC_MODE_LAST
+ + SPEC_MODE_FOR_EXTEND_LAST - SPEC_MODE_FOR_EXTEND_FIRST + 2)
+ };
+
+enum SPEC_GEN_LD_MAP
+ {
+ /* Offset to ld.a patterns. */
+ SPEC_GEN_A = 0 * SPEC_N,
+ /* Offset to ld.s patterns. */
+ SPEC_GEN_S = 1 * SPEC_N,
+ /* Offset to ld.sa patterns. */
+ SPEC_GEN_SA = 2 * SPEC_N,
+ /* Offset to ld.sa patterns. For this patterns corresponding ld.c will
+ mutate to chk.s. */
+ SPEC_GEN_SA_FOR_S = 3 * SPEC_N
+ };
+
+/* These offsets are used to get (4 * SPEC_N). */
+enum SPEC_GEN_CHECK_OFFSET
+ {
+ SPEC_GEN_CHKA_FOR_A_OFFSET = 4 * SPEC_N - SPEC_GEN_A,
+ SPEC_GEN_CHKA_FOR_SA_OFFSET = 4 * SPEC_N - SPEC_GEN_SA
+ };
+
+/* If GEN_P is true, calculate the index of needed speculation check and return
+ speculative pattern for INSN with speculative mode TS, machine mode
+ MODE_NO and with ZERO_EXTEND (if EXTEND_P is true).
+ If GEN_P is false, just calculate the index of needed speculation check. */
+static rtx
+ia64_gen_spec_insn (rtx insn, ds_t ts, int mode_no, bool gen_p, bool extend_p)
+{
+ rtx pat, new_pat;
+ int load_no;
+ int shift = 0;
+
+ static rtx (* const gen_load[]) (rtx, rtx) = {
+ gen_movbi_advanced,
+ gen_movqi_advanced,
+ gen_movhi_advanced,
+ gen_movsi_advanced,
+ gen_movdi_advanced,
+ gen_movsf_advanced,
+ gen_movdf_advanced,
+ gen_movxf_advanced,
+ gen_movti_advanced,
+ gen_zero_extendqidi2_advanced,
+ gen_zero_extendhidi2_advanced,
+ gen_zero_extendsidi2_advanced,
+
+ gen_movbi_speculative,
+ gen_movqi_speculative,
+ gen_movhi_speculative,
+ gen_movsi_speculative,
+ gen_movdi_speculative,
+ gen_movsf_speculative,
+ gen_movdf_speculative,
+ gen_movxf_speculative,
+ gen_movti_speculative,
+ gen_zero_extendqidi2_speculative,
+ gen_zero_extendhidi2_speculative,
+ gen_zero_extendsidi2_speculative,
+
+ gen_movbi_speculative_advanced,
+ gen_movqi_speculative_advanced,
+ gen_movhi_speculative_advanced,
+ gen_movsi_speculative_advanced,
+ gen_movdi_speculative_advanced,
+ gen_movsf_speculative_advanced,
+ gen_movdf_speculative_advanced,
+ gen_movxf_speculative_advanced,
+ gen_movti_speculative_advanced,
+ gen_zero_extendqidi2_speculative_advanced,
+ gen_zero_extendhidi2_speculative_advanced,
+ gen_zero_extendsidi2_speculative_advanced,
+
+ gen_movbi_speculative_advanced,
+ gen_movqi_speculative_advanced,
+ gen_movhi_speculative_advanced,
+ gen_movsi_speculative_advanced,
+ gen_movdi_speculative_advanced,
+ gen_movsf_speculative_advanced,
+ gen_movdf_speculative_advanced,
+ gen_movxf_speculative_advanced,
+ gen_movti_speculative_advanced,
+ gen_zero_extendqidi2_speculative_advanced,
+ gen_zero_extendhidi2_speculative_advanced,
+ gen_zero_extendsidi2_speculative_advanced
+ };
+
+ load_no = extend_p ? mode_no + SPEC_GEN_EXTEND_OFFSET : mode_no;
+
+ if (ts & BEGIN_DATA)
+ {
+ /* We don't need recovery because even if this is ld.sa
+ ALAT entry will be allocated only if NAT bit is set to zero.
+ So it is enough to use ld.c here. */
+
+ if (ts & BEGIN_CONTROL)
+ {
+ load_no += SPEC_GEN_SA;
+
+ if (!mflag_sched_ldc)
+ shift = SPEC_GEN_CHKA_FOR_SA_OFFSET;
+ }
+ else
+ {
+ load_no += SPEC_GEN_A;
+
+ if (!mflag_sched_ldc)
+ shift = SPEC_GEN_CHKA_FOR_A_OFFSET;
+ }
+ }
+ else if (ts & BEGIN_CONTROL)
+ {
+ /* ld.sa can be used instead of ld.s to avoid basic block splitting. */
+ if (!mflag_control_ldc)
+ load_no += SPEC_GEN_S;
+ else
+ {
+ gcc_assert (mflag_sched_ldc);
+ load_no += SPEC_GEN_SA_FOR_S;
+ }
+ }
+ else
+ gcc_unreachable ();
+
+ /* Set the desired check index. We add '1', because zero element in this
+ array means, that instruction with such uid is non-speculative. */
+ spec_check_no[INSN_UID (insn)] = load_no + shift + 1;
+
+ if (!gen_p)
+ return 0;
+
+ new_pat = gen_load[load_no] (copy_rtx (recog_data.operand[0]),
+ copy_rtx (recog_data.operand[1]));
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ new_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx
+ (COND_EXEC_TEST (pat)), new_pat);
+
+ return new_pat;
+}
+
+/* Offset to branchy checks. */
+enum { SPEC_GEN_CHECK_MUTATION_OFFSET = 5 * SPEC_N };
+
+/* Return nonzero, if INSN needs branchy recovery check. */
+static bool
+ia64_needs_block_p (rtx insn)
+{
+ int check_no;
+
+ check_no = spec_check_no[INSN_UID(insn)] - 1;
+ gcc_assert (0 <= check_no && check_no < SPEC_GEN_CHECK_MUTATION_OFFSET);
+
+ return ((SPEC_GEN_S <= check_no && check_no < SPEC_GEN_S + SPEC_N)
+ || (4 * SPEC_N <= check_no && check_no < 4 * SPEC_N + SPEC_N));
+}
+
+/* Generate (or regenerate, if (MUTATE_P)) recovery check for INSN.
+ If (LABEL != 0 || MUTATE_P), generate branchy recovery check.
+ Otherwise, generate a simple check. */
+static rtx
+ia64_gen_check (rtx insn, rtx label, bool mutate_p)
+{
+ rtx op1, pat, check_pat;
+
+ static rtx (* const gen_check[]) (rtx, rtx) = {
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_speculation_check_bi,
+ gen_speculation_check_qi,
+ gen_speculation_check_hi,
+ gen_speculation_check_si,
+ gen_speculation_check_di,
+ gen_speculation_check_sf,
+ gen_speculation_check_df,
+ gen_speculation_check_xf,
+ gen_speculation_check_ti,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_movbi_clr,
+ gen_movqi_clr,
+ gen_movhi_clr,
+ gen_movsi_clr,
+ gen_movdi_clr,
+ gen_movsf_clr,
+ gen_movdf_clr,
+ gen_movxf_clr,
+ gen_movti_clr,
+ gen_zero_extendqidi2_clr,
+ gen_zero_extendhidi2_clr,
+ gen_zero_extendsidi2_clr,
+
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ /* Following checks are generated during mutation. */
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ 0,0,0,0,0,0,0,0,0,0,0,0,
+
+ gen_advanced_load_check_clr_bi,
+ gen_advanced_load_check_clr_qi,
+ gen_advanced_load_check_clr_hi,
+ gen_advanced_load_check_clr_si,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_sf,
+ gen_advanced_load_check_clr_df,
+ gen_advanced_load_check_clr_xf,
+ gen_advanced_load_check_clr_ti,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+ gen_advanced_load_check_clr_di,
+
+ gen_speculation_check_bi,
+ gen_speculation_check_qi,
+ gen_speculation_check_hi,
+ gen_speculation_check_si,
+ gen_speculation_check_di,
+ gen_speculation_check_sf,
+ gen_speculation_check_df,
+ gen_speculation_check_xf,
+ gen_speculation_check_ti,
+ gen_speculation_check_di,
+ gen_speculation_check_di,
+ gen_speculation_check_di
+ };
+
+ extract_insn_cached (insn);
+
+ if (label)
+ {
+ gcc_assert (mutate_p || ia64_needs_block_p (insn));
+ op1 = label;
+ }
+ else
+ {
+ gcc_assert (!mutate_p && !ia64_needs_block_p (insn));
+ op1 = copy_rtx (recog_data.operand[1]);
+ }
+
+ if (mutate_p)
+ /* INSN is ld.c.
+ Find the speculation check number by searching for original
+ speculative load in the RESOLVED_DEPS list of INSN.
+ As long as patterns are unique for each instruction, this can be
+ accomplished by matching ORIG_PAT fields. */
+ {
+ rtx link;
+ int check_no = 0;
+ rtx orig_pat = ORIG_PAT (insn);
+
+ for (link = RESOLVED_DEPS (insn); link; link = XEXP (link, 1))
+ {
+ rtx x = XEXP (link, 0);
+
+ if (ORIG_PAT (x) == orig_pat)
+ check_no = spec_check_no[INSN_UID (x)];
+ }
+ gcc_assert (check_no);
+
+ spec_check_no[INSN_UID (insn)] = (check_no
+ + SPEC_GEN_CHECK_MUTATION_OFFSET);
+ }
+
+ check_pat = (gen_check[spec_check_no[INSN_UID (insn)] - 1]
+ (copy_rtx (recog_data.operand[0]), op1));
+
+ pat = PATTERN (insn);
+ if (GET_CODE (pat) == COND_EXEC)
+ check_pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (pat)),
+ check_pat);
+
+ return check_pat;
+}
+
+/* Return nonzero, if X is branchy recovery check. */
+static int
+ia64_spec_check_p (rtx x)
+{
+ x = PATTERN (x);
+ if (GET_CODE (x) == COND_EXEC)
+ x = COND_EXEC_CODE (x);
+ if (GET_CODE (x) == SET)
+ return ia64_spec_check_src_p (SET_SRC (x));
+ return 0;
+}
+
+/* Return nonzero, if SRC belongs to recovery check. */
+static int
+ia64_spec_check_src_p (rtx src)
+{
+ if (GET_CODE (src) == IF_THEN_ELSE)
+ {
+ rtx t;
+
+ t = XEXP (src, 0);
+ if (GET_CODE (t) == NE)
+ {
+ t = XEXP (t, 0);
+
+ if (GET_CODE (t) == UNSPEC)
+ {
+ int code;
+
+ code = XINT (t, 1);
+
+ if (code == UNSPEC_CHKACLR
+ || code == UNSPEC_CHKS
+ || code == UNSPEC_LDCCLR)
+ {
+ gcc_assert (code != 0);
+ return code;
+ }
+ }
+ }
+ }
+ return 0;
+}
/* The following page contains abstract data `bundle states' which are
@@ -6617,12 +7500,10 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
curr_state->accumulated_insns_num
= originator->accumulated_insns_num + before_nops_num;
curr_state->branch_deviation = originator->branch_deviation;
- if (insn == NULL_RTX)
- abort ();
- else if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
+ gcc_assert (insn);
+ if (INSN_CODE (insn) == CODE_FOR_insn_group_barrier)
{
- if (GET_MODE (insn) == TImode)
- abort ();
+ gcc_assert (GET_MODE (insn) != TImode);
if (!try_issue_nops (curr_state, before_nops_num))
return;
if (!try_issue_insn (curr_state, insn))
@@ -6642,14 +7523,25 @@ issue_nops_and_insn (struct bundle_state *originator, int before_nops_num,
if (!try_issue_insn (curr_state, insn))
return;
curr_state->accumulated_insns_num++;
- if (GET_CODE (PATTERN (insn)) == ASM_INPUT
- || asm_noperands (PATTERN (insn)) >= 0)
- abort ();
+ gcc_assert (GET_CODE (PATTERN (insn)) != ASM_INPUT
+ && asm_noperands (PATTERN (insn)) < 0);
+
if (ia64_safe_type (insn) == TYPE_L)
curr_state->accumulated_insns_num++;
}
else
{
+ /* If this is an insn that must be first in a group, then don't allow
+ nops to be emitted before it. Currently, alloc is the only such
+ supported instruction. */
+ /* ??? The bundling automatons should handle this for us, but they do
+ not yet have support for the first_insn attribute. */
+ if (before_nops_num > 0 && get_attr_first_insn (insn) == FIRST_INSN_YES)
+ {
+ free_bundle_state (curr_state);
+ return;
+ }
+
state_transition (curr_state->dfa_state, dfa_pre_cycle_insn);
state_transition (curr_state->dfa_state, NULL);
curr_state->cost++;
@@ -6728,7 +7620,13 @@ get_max_pos (state_t state)
/* The function returns code of a possible template for given position
and state. The function should be called only with 2 values of
- position equal to 3 or 6. */
+ position equal to 3 or 6. We avoid generating F NOPs by putting
+ templates containing F insns at the end of the template search
+ because undocumented anomaly in McKinley derived cores which can
+ cause stalls if an F-unit insn (including a NOP) is issued within a
+ six-cycle window after reading certain application registers (such
+ as ar.bsp). Furthermore, power-considerations also argue against
+ the use of F-unit instructions unless they're really needed. */
static int
get_template (state_t state, int pos)
@@ -6736,53 +7634,53 @@ get_template (state_t state, int pos)
switch (pos)
{
case 3:
- if (cpu_unit_reservation_p (state, _0mii_))
- return 0;
- else if (cpu_unit_reservation_p (state, _0mmi_))
+ if (cpu_unit_reservation_p (state, _0mmi_))
return 1;
- else if (cpu_unit_reservation_p (state, _0mfi_))
- return 2;
- else if (cpu_unit_reservation_p (state, _0mmf_))
- return 3;
- else if (cpu_unit_reservation_p (state, _0bbb_))
- return 4;
- else if (cpu_unit_reservation_p (state, _0mbb_))
- return 5;
- else if (cpu_unit_reservation_p (state, _0mib_))
- return 6;
+ else if (cpu_unit_reservation_p (state, _0mii_))
+ return 0;
else if (cpu_unit_reservation_p (state, _0mmb_))
return 7;
+ else if (cpu_unit_reservation_p (state, _0mib_))
+ return 6;
+ else if (cpu_unit_reservation_p (state, _0mbb_))
+ return 5;
+ else if (cpu_unit_reservation_p (state, _0bbb_))
+ return 4;
+ else if (cpu_unit_reservation_p (state, _0mmf_))
+ return 3;
+ else if (cpu_unit_reservation_p (state, _0mfi_))
+ return 2;
else if (cpu_unit_reservation_p (state, _0mfb_))
return 8;
else if (cpu_unit_reservation_p (state, _0mlx_))
return 9;
else
- abort ();
+ gcc_unreachable ();
case 6:
- if (cpu_unit_reservation_p (state, _1mii_))
- return 0;
- else if (cpu_unit_reservation_p (state, _1mmi_))
+ if (cpu_unit_reservation_p (state, _1mmi_))
return 1;
- else if (cpu_unit_reservation_p (state, _1mfi_))
- return 2;
- else if (_1mmf_ >= 0 && cpu_unit_reservation_p (state, _1mmf_))
- return 3;
- else if (cpu_unit_reservation_p (state, _1bbb_))
- return 4;
- else if (cpu_unit_reservation_p (state, _1mbb_))
- return 5;
- else if (cpu_unit_reservation_p (state, _1mib_))
- return 6;
+ else if (cpu_unit_reservation_p (state, _1mii_))
+ return 0;
else if (cpu_unit_reservation_p (state, _1mmb_))
return 7;
+ else if (cpu_unit_reservation_p (state, _1mib_))
+ return 6;
+ else if (cpu_unit_reservation_p (state, _1mbb_))
+ return 5;
+ else if (cpu_unit_reservation_p (state, _1bbb_))
+ return 4;
+ else if (_1mmf_ >= 0 && cpu_unit_reservation_p (state, _1mmf_))
+ return 3;
+ else if (cpu_unit_reservation_p (state, _1mfi_))
+ return 2;
else if (cpu_unit_reservation_p (state, _1mfb_))
return 8;
else if (cpu_unit_reservation_p (state, _1mlx_))
return 9;
else
- abort ();
+ gcc_unreachable ();
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -6801,6 +7699,53 @@ get_next_important_insn (rtx insn, rtx tail)
return NULL_RTX;
}
+/* Add a bundle selector TEMPLATE0 before INSN. */
+
+static void
+ia64_add_bundle_selector_before (int template0, rtx insn)
+{
+ rtx b = gen_bundle_selector (GEN_INT (template0));
+
+ ia64_emit_insn_before (b, insn);
+#if NR_BUNDLES == 10
+ if ((template0 == 4 || template0 == 5)
+ && (flag_unwind_tables || (flag_exceptions && !USING_SJLJ_EXCEPTIONS)))
+ {
+ int i;
+ rtx note = NULL_RTX;
+
+ /* In .mbb and .bbb bundles, check if CALL_INSN isn't in the
+ first or second slot. If it is and has REG_EH_NOTE set, copy it
+ to following nops, as br.call sets rp to the address of following
+ bundle and therefore an EH region end must be on a bundle
+ boundary. */
+ insn = PREV_INSN (insn);
+ for (i = 0; i < 3; i++)
+ {
+ do
+ insn = next_active_insn (insn);
+ while (GET_CODE (insn) == INSN
+ && get_attr_empty (insn) == EMPTY_YES);
+ if (GET_CODE (insn) == CALL_INSN)
+ note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
+ else if (note)
+ {
+ int code;
+
+ gcc_assert ((code = recog_memoized (insn)) == CODE_FOR_nop
+ || code == CODE_FOR_nop_b);
+ if (find_reg_note (insn, REG_EH_REGION, NULL_RTX))
+ note = NULL_RTX;
+ else
+ REG_NOTES (insn)
+ = gen_rtx_EXPR_LIST (REG_EH_REGION, XEXP (note, 0),
+ REG_NOTES (insn));
+ }
+ }
+ }
+#endif
+}
+
/* The following function does insn bundling. Bundling means
inserting templates and nop insns to fit insn groups into permitted
templates. Instruction scheduling uses NDFA (non-deterministic
@@ -6813,7 +7758,7 @@ get_next_important_insn (rtx insn, rtx tail)
automata only says that we can issue an insn possibly inserting
some nops before it and using some template. Therefore insn
bundling in this function is implemented by using DFA
- (deterministic finite automata). We follows all possible insn
+ (deterministic finite automata). We follow all possible insn
sequences by inserting 0-2 nops (that is what the NDFA describe for
insn scheduling) before/after each insn being bundled. We know the
start of simulated processor cycle from insn scheduling (insn
@@ -6827,7 +7772,7 @@ get_next_important_insn (rtx insn, rtx tail)
by structure bundle_state (see above). If we generate the same
bundle state (key is automaton state after issuing the insns and
nops for it), we reuse already generated one. As consequence we
- reject some decisions which can not improve the solution and
+ reject some decisions which cannot improve the solution and
reduce memory for the algorithm.
When we reach the end of EBB (extended basic block), we choose the
@@ -6866,7 +7811,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
initiate_bundle_state_table ();
index_to_bundle_states = xmalloc ((insn_num + 2)
* sizeof (struct bundle_state *));
- /* First (forward) pass -- generation of bundle states. */
+ /* First (forward) pass -- generation of bundle states. */
curr_state = get_free_bundle_state ();
curr_state->insn = NULL;
curr_state->before_nops_num = 0;
@@ -6903,16 +7848,15 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
break;
}
}
- /* Froward pass: generation of bundle states. */
+ /* Forward pass: generation of bundle states. */
for (insn = get_next_important_insn (NEXT_INSN (prev_head_insn), tail);
insn != NULL_RTX;
insn = next_insn)
{
- if (!INSN_P (insn)
- || ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IGNORE
- || GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- abort ();
+ gcc_assert (INSN_P (insn)
+ && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER);
type = ia64_safe_type (insn);
next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
insn_num++;
@@ -6952,8 +7896,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
issue_nops_and_insn (curr_state, 0, insn, bundle_end_p,
only_bundle_end_p);
}
- if (index_to_bundle_states [insn_num] == NULL)
- abort ();
+ gcc_assert (index_to_bundle_states [insn_num]);
for (curr_state = index_to_bundle_states [insn_num];
curr_state != NULL;
curr_state = curr_state->next)
@@ -6986,10 +7929,10 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
INSN_UID (insn));
}
}
- if (index_to_bundle_states [insn_num] == NULL)
- /* We should find a solution because the 2nd insn scheduling has
- found one. */
- abort ();
+
+ /* We should find a solution because the 2nd insn scheduling has
+ found one. */
+ gcc_assert (index_to_bundle_states [insn_num]);
/* Find a state corresponding to the best insn sequence. */
best_state = NULL;
for (curr_state = index_to_bundle_states [insn_num];
@@ -7067,8 +8010,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
if (max_pos > 3 && template1 < 0)
/* It may happen when we have the stop inside a bundle. */
{
- if (pos > 3)
- abort ();
+ gcc_assert (pos <= 3);
template1 = get_template (curr_state->dfa_state, 3);
pos += 3;
}
@@ -7079,16 +8021,13 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
nop = gen_nop ();
emit_insn_after (nop, insn);
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0)
{
/* We are at the start of a bundle: emit the template
(it should be defined). */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, nop);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, nop);
/* If we have two bundle window, we make one bundle
rotation. Otherwise template0 will be undefined
(negative value). */
@@ -7105,8 +8044,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
/* Long insn takes 2 slots. */
if (ia64_safe_type (insn) == TYPE_L)
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0
&& INSN_CODE (insn) != CODE_FOR_insn_group_barrier
&& GET_CODE (PATTERN (insn)) != ASM_INPUT
@@ -7114,13 +8052,11 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
{
/* The current insn is at the bundle start: emit the
template. */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, insn);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
- /* See comment above in analogous place for emiting nops
+ /* See comment above in analogous place for emitting nops
after the insn. */
template0 = template1;
template1 = -1;
@@ -7133,16 +8069,13 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
nop = PREV_INSN (insn);
insn = nop;
pos--;
- if (pos < 0)
- abort ();
+ gcc_assert (pos >= 0);
if (pos % 3 == 0)
{
- /* See comment above in analogous place for emiting nops
+ /* See comment above in analogous place for emitting nops
after the insn. */
- if (template0 < 0)
- abort ();
- b = gen_bundle_selector (GEN_INT (template0));
- ia64_emit_insn_before (b, insn);
+ gcc_assert (template0 >= 0);
+ ia64_add_bundle_selector_before (template0, insn);
b = PREV_INSN (insn);
insn = b;
template0 = template1;
@@ -7160,11 +8093,10 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
insn != NULL_RTX;
insn = next_insn)
{
- if (!INSN_P (insn)
- || ia64_safe_itanium_class (insn) == ITANIUM_CLASS_IGNORE
- || GET_CODE (PATTERN (insn)) == USE
- || GET_CODE (PATTERN (insn)) == CLOBBER)
- abort ();
+ gcc_assert (INSN_P (insn)
+ && ia64_safe_itanium_class (insn) != ITANIUM_CLASS_IGNORE
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER);
next_insn = get_next_important_insn (NEXT_INSN (insn), tail);
if (INSN_UID (insn) < clocks_length && add_cycles [INSN_UID (insn)])
/* We found a MM-insn which needs additional cycles. */
@@ -7191,7 +8123,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
onto MFI because we will add nops before the
insn. It simplifies subsequent code a lot. */
PATTERN (last)
- = gen_bundle_selector (GEN_INT (2)); /* -> MFI */
+ = gen_bundle_selector (const2_rtx); /* -> MFI */
break;
}
else if (recog_memoized (last) != CODE_FOR_insn_group_barrier
@@ -7202,9 +8134,9 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
bundle start, there are no more 3 insns in the bundle,
and the MM-insn is not at the start of bundle with
template MLX. */
- if ((pred_stop_p && n == 0) || n > 2
- || (template0 == 9 && n != 0))
- abort ();
+ gcc_assert ((!pred_stop_p || n)
+ && n <= 2
+ && (template0 != 9 || !n));
/* Put nops after the insn in the bundle. */
for (j = 3 - n; j > 0; j --)
ia64_emit_insn_before (gen_nop (), insn);
@@ -7219,7 +8151,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
for (i = add_cycles [INSN_UID (insn)]; i > 0; i--)
{
/* Insert "MII;" template. */
- ia64_emit_insn_before (gen_bundle_selector (GEN_INT (0)),
+ ia64_emit_insn_before (gen_bundle_selector (const0_rtx),
insn);
ia64_emit_insn_before (gen_nop (), insn);
ia64_emit_insn_before (gen_nop (), insn);
@@ -7237,8 +8169,7 @@ bundling (FILE *dump, int verbose, rtx prev_head_insn, rtx tail)
}
/* Put the MM-insn in the same slot of a bundle with the
same template as the original one. */
- ia64_emit_insn_before (gen_bundle_selector (GEN_INT (template0)),
- insn);
+ ia64_add_bundle_selector_before (template0, insn);
/* To put the insn in the same slot, add necessary number
of nops. */
for (j = n; j > 0; j --)
@@ -7318,7 +8249,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
need_barrier_p = 0;
prev_insn = NULL_RTX;
}
- else if (need_barrier_p || group_barrier_needed_p (insn))
+ else if (need_barrier_p || group_barrier_needed (insn))
{
if (TARGET_EARLY_STOP_BITS)
{
@@ -7342,7 +8273,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
last != insn;
last = NEXT_INSN (last))
if (INSN_P (last))
- group_barrier_needed_p (last);
+ group_barrier_needed (last);
}
else
{
@@ -7350,7 +8281,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
insn);
init_insn_group_barriers ();
}
- group_barrier_needed_p (insn);
+ group_barrier_needed (insn);
prev_insn = NULL_RTX;
}
else if (recog_memoized (insn) >= 0)
@@ -7364,16 +8295,7 @@ final_emit_insn_group_barriers (FILE *dump ATTRIBUTE_UNUSED)
-/* If the following function returns TRUE, we will use the the DFA
- insn scheduler. */
-
-static int
-ia64_use_dfa_pipeline_interface (void)
-{
- return 1;
-}
-
-/* If the following function returns TRUE, we will use the the DFA
+/* If the following function returns TRUE, we will use the DFA
insn scheduler. */
static int
@@ -7418,18 +8340,19 @@ ia64_st_address_bypass_p (rtx producer, rtx consumer)
{
rtx dest, reg, mem;
- if (producer == NULL_RTX || consumer == NULL_RTX)
- abort ();
+ gcc_assert (producer && consumer);
dest = ia64_single_set (producer);
- if (dest == NULL_RTX || (reg = SET_DEST (dest)) == NULL_RTX
- || (GET_CODE (reg) != REG && GET_CODE (reg) != SUBREG))
- abort ();
+ gcc_assert (dest);
+ reg = SET_DEST (dest);
+ gcc_assert (reg);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
+ gcc_assert (GET_CODE (reg) == REG);
+
dest = ia64_single_set (consumer);
- if (dest == NULL_RTX || (mem = SET_DEST (dest)) == NULL_RTX
- || GET_CODE (mem) != MEM)
- abort ();
+ gcc_assert (dest);
+ mem = SET_DEST (dest);
+ gcc_assert (mem && GET_CODE (mem) == MEM);
return reg_mentioned_p (reg, mem);
}
@@ -7441,32 +8364,49 @@ ia64_ld_address_bypass_p (rtx producer, rtx consumer)
{
rtx dest, src, reg, mem;
- if (producer == NULL_RTX || consumer == NULL_RTX)
- abort ();
+ gcc_assert (producer && consumer);
dest = ia64_single_set (producer);
- if (dest == NULL_RTX || (reg = SET_DEST (dest)) == NULL_RTX
- || (GET_CODE (reg) != REG && GET_CODE (reg) != SUBREG))
- abort ();
+ gcc_assert (dest);
+ reg = SET_DEST (dest);
+ gcc_assert (reg);
if (GET_CODE (reg) == SUBREG)
reg = SUBREG_REG (reg);
+ gcc_assert (GET_CODE (reg) == REG);
+
src = ia64_single_set (consumer);
- if (src == NULL_RTX || (mem = SET_SRC (src)) == NULL_RTX)
- abort ();
+ gcc_assert (src);
+ mem = SET_SRC (src);
+ gcc_assert (mem);
+
if (GET_CODE (mem) == UNSPEC && XVECLEN (mem, 0) > 0)
mem = XVECEXP (mem, 0, 0);
+ else if (GET_CODE (mem) == IF_THEN_ELSE)
+ /* ??? Is this bypass necessary for ld.c? */
+ {
+ gcc_assert (XINT (XEXP (XEXP (mem, 0), 0), 1) == UNSPEC_LDCCLR);
+ mem = XEXP (mem, 1);
+ }
+
while (GET_CODE (mem) == SUBREG || GET_CODE (mem) == ZERO_EXTEND)
mem = XEXP (mem, 0);
+ if (GET_CODE (mem) == UNSPEC)
+ {
+ int c = XINT (mem, 1);
+
+ gcc_assert (c == UNSPEC_LDA || c == UNSPEC_LDS || c == UNSPEC_LDSA);
+ mem = XVECEXP (mem, 0, 0);
+ }
+
/* Note that LO_SUM is used for GOT loads. */
- if (GET_CODE (mem) != LO_SUM && GET_CODE (mem) != MEM)
- abort ();
+ gcc_assert (GET_CODE (mem) == LO_SUM || GET_CODE (mem) == MEM);
return reg_mentioned_p (reg, mem);
}
/* The following function returns TRUE if INSN produces address for a
load/store insn. We will place such insns into M slot because it
- decreases its latency time. */
+ decreases its latency time. */
int
ia64_produce_address_p (rtx insn)
@@ -7497,8 +8437,10 @@ emit_predicate_relation_info (void)
&& NOTE_LINE_NUMBER (NEXT_INSN (head)) == NOTE_INSN_BASIC_BLOCK)
head = NEXT_INSN (head);
- for (r = PR_REG (0); r < PR_REG (64); r += 2)
- if (REGNO_REG_SET_P (bb->global_live_at_start, r))
+ /* Skip p0, which may be thought to be live due to (reg:DI p0)
+ grabbing the entire block of predicate registers. */
+ for (r = PR_REG (2); r < PR_REG (64); r += 2)
+ if (REGNO_REG_SET_P (bb->il.rtl->global_live_at_start, r))
{
rtx p = gen_rtx_REG (BImode, r);
rtx n = emit_insn_after (gen_pred_rel_mutex (p), head);
@@ -7554,7 +8496,7 @@ ia64_reorg (void)
non-optimizing bootstrap. */
update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
- if (ia64_flag_schedule_insns2)
+ if (optimize && ia64_flag_schedule_insns2)
{
timevar_push (TV_SCHED2);
ia64_final_schedule = 1;
@@ -7628,7 +8570,7 @@ ia64_reorg (void)
_1mfb_ = get_cpu_unit_code ("1b_1mfb.");
_1mlx_ = get_cpu_unit_code ("1b_1mlx.");
}
- schedule_ebbs (rtl_dump_file);
+ schedule_ebbs ();
finish_bundle_states ();
if (ia64_tune == PROCESSOR_ITANIUM)
{
@@ -7636,13 +8578,14 @@ ia64_reorg (void)
free (clocks);
}
free (stops_p);
- emit_insn_group_barriers (rtl_dump_file);
+ stops_p = NULL;
+ emit_insn_group_barriers (dump_file);
ia64_final_schedule = 0;
timevar_pop (TV_SCHED2);
}
else
- emit_all_insn_group_barriers (rtl_dump_file);
+ emit_all_insn_group_barriers (dump_file);
/* 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
@@ -7672,8 +8615,14 @@ ia64_reorg (void)
}
}
- fixup_errata ();
emit_predicate_relation_info ();
+
+ if (ia64_flag_var_tracking)
+ {
+ timevar_push (TV_VAR_TRACKING);
+ variable_tracking_main ();
+ timevar_pop (TV_VAR_TRACKING);
+ }
}
/* Return true if REGNO is used by the epilogue. */
@@ -7766,8 +8715,13 @@ ia64_in_small_data_p (tree exp)
if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
{
const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
+
if (strcmp (section, ".sdata") == 0
- || strcmp (section, ".sbss") == 0)
+ || strncmp (section, ".sdata.", 7) == 0
+ || strncmp (section, ".gnu.linkonce.s.", 16) == 0
+ || strcmp (section, ".sbss") == 0
+ || strncmp (section, ".sbss.", 6) == 0
+ || strncmp (section, ".gnu.linkonce.sb.", 17) == 0)
return true;
}
else
@@ -7793,28 +8747,84 @@ static bool last_block;
static bool need_copy_state;
+#ifndef MAX_ARTIFICIAL_LABEL_BYTES
+# define MAX_ARTIFICIAL_LABEL_BYTES 30
+#endif
+
+/* Emit a debugging label after a call-frame-related insn. We'd
+ rather output the label right away, but we'd have to output it
+ after, not before, the instruction, and the instruction has not
+ been output yet. So we emit the label after the insn, delete it to
+ avoid introducing basic blocks, and mark it as preserved, such that
+ it is still output, given that it is referenced in debug info. */
+
+static const char *
+ia64_emit_deleted_label_after_insn (rtx insn)
+{
+ char label[MAX_ARTIFICIAL_LABEL_BYTES];
+ rtx lb = gen_label_rtx ();
+ rtx label_insn = emit_label_after (lb, insn);
+
+ LABEL_PRESERVE_P (lb) = 1;
+
+ delete_insn (label_insn);
+
+ ASM_GENERATE_INTERNAL_LABEL (label, "L", CODE_LABEL_NUMBER (label_insn));
+
+ return xstrdup (label);
+}
+
+/* Define the CFA after INSN with the steady-state definition. */
+
+static void
+ia64_dwarf2out_def_steady_cfa (rtx insn)
+{
+ rtx fp = frame_pointer_needed
+ ? hard_frame_pointer_rtx
+ : stack_pointer_rtx;
+
+ dwarf2out_def_cfa
+ (ia64_emit_deleted_label_after_insn (insn),
+ REGNO (fp),
+ ia64_initial_elimination_offset
+ (REGNO (arg_pointer_rtx), REGNO (fp))
+ + ARG_POINTER_CFA_OFFSET (current_function_decl));
+}
+
+/* The generic dwarf2 frame debug info generator does not define a
+ separate region for the very end of the epilogue, so refrain from
+ doing so in the IA64-specific code as well. */
+
+#define IA64_CHANGE_CFA_IN_EPILOGUE 0
+
/* The function emits unwind directives for the start of an epilogue. */
static void
-process_epilogue (void)
+process_epilogue (FILE *asm_out_file, rtx insn, bool unwind, bool frame)
{
/* 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 (!last_block)
{
- fprintf (asm_out_file, "\t.label_state 1\n");
+ if (unwind)
+ fprintf (asm_out_file, "\t.label_state %d\n",
+ ++cfun->machine->state_num);
need_copy_state = true;
}
- fprintf (asm_out_file, "\t.restore sp\n");
+ if (unwind)
+ fprintf (asm_out_file, "\t.restore sp\n");
+ if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
+ dwarf2out_def_cfa (ia64_emit_deleted_label_after_insn (insn),
+ STACK_POINTER_REGNUM, INCOMING_FRAME_SP_OFFSET);
}
/* This function processes a SET pattern looking for specific patterns
which result in emitting an assembly directive required for unwinding. */
static int
-process_set (FILE *asm_out_file, rtx pat)
+process_set (FILE *asm_out_file, rtx pat, rtx insn, bool unwind, bool frame)
{
rtx src = SET_SRC (pat);
rtx dest = SET_DEST (pat);
@@ -7830,8 +8840,11 @@ process_set (FILE *asm_out_file, rtx pat)
/* If this is the final destination for ar.pfs, then this must
be the alloc in the prologue. */
if (dest_regno == current_frame_info.reg_save_ar_pfs)
- fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ {
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.pfs, r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ }
else
{
/* This must be an alloc before a sibcall. We must drop the
@@ -7842,8 +8855,9 @@ process_set (FILE *asm_out_file, rtx pat)
sp" now. */
if (current_frame_info.total_size == 0 && !frame_pointer_needed)
/* if haven't done process_epilogue() yet, do it now */
- process_epilogue ();
- fprintf (asm_out_file, "\t.prologue\n");
+ process_epilogue (asm_out_file, insn, unwind, frame);
+ if (unwind)
+ fprintf (asm_out_file, "\t.prologue\n");
}
return 1;
}
@@ -7855,22 +8869,27 @@ process_set (FILE *asm_out_file, rtx pat)
{
rtx op0 = XEXP (src, 0);
rtx op1 = XEXP (src, 1);
- if (op0 == dest && GET_CODE (op1) == CONST_INT)
+
+ gcc_assert (op0 == dest && GET_CODE (op1) == CONST_INT);
+
+ if (INTVAL (op1) < 0)
{
- if (INTVAL (op1) < 0)
+ gcc_assert (!frame_pointer_needed);
+ if (unwind)
fprintf (asm_out_file, "\t.fframe "HOST_WIDE_INT_PRINT_DEC"\n",
-INTVAL (op1));
- else
- process_epilogue ();
+ if (frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
}
else
- abort ();
+ process_epilogue (asm_out_file, insn, unwind, frame);
}
- else if (GET_CODE (src) == REG
- && REGNO (src) == HARD_FRAME_POINTER_REGNUM)
- process_epilogue ();
else
- abort ();
+ {
+ gcc_assert (GET_CODE (src) == REG
+ && REGNO (src) == HARD_FRAME_POINTER_REGNUM);
+ process_epilogue (asm_out_file, insn, unwind, frame);
+ }
return 1;
}
@@ -7885,44 +8904,46 @@ process_set (FILE *asm_out_file, rtx pat)
{
case BR_REG (0):
/* Saving return address pointer. */
- if (dest_regno != current_frame_info.reg_save_b0)
- abort ();
- fprintf (asm_out_file, "\t.save rp, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_b0);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save rp, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case PR_REG (0):
- if (dest_regno != current_frame_info.reg_save_pr)
- abort ();
- fprintf (asm_out_file, "\t.save pr, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_pr);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save pr, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case AR_UNAT_REGNUM:
- if (dest_regno != current_frame_info.reg_save_ar_unat)
- abort ();
- fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_ar_unat);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.unat, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case AR_LC_REGNUM:
- if (dest_regno != current_frame_info.reg_save_ar_lc)
- abort ();
- fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == current_frame_info.reg_save_ar_lc);
+ if (unwind)
+ fprintf (asm_out_file, "\t.save ar.lc, r%d\n",
+ ia64_dbx_register_number (dest_regno));
return 1;
case STACK_POINTER_REGNUM:
- if (dest_regno != HARD_FRAME_POINTER_REGNUM
- || ! frame_pointer_needed)
- abort ();
- fprintf (asm_out_file, "\t.vframe r%d\n",
- ia64_dbx_register_number (dest_regno));
+ gcc_assert (dest_regno == HARD_FRAME_POINTER_REGNUM
+ && frame_pointer_needed);
+ if (unwind)
+ fprintf (asm_out_file, "\t.vframe r%d\n",
+ ia64_dbx_register_number (dest_regno));
+ if (frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
return 1;
default:
/* Everything else should indicate being stored to memory. */
- abort ();
+ gcc_unreachable ();
}
}
@@ -7938,64 +8959,65 @@ process_set (FILE *asm_out_file, rtx pat)
base = XEXP (dest, 0);
off = 0;
}
- else if (GET_CODE (XEXP (dest, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT)
+ else
{
+ gcc_assert (GET_CODE (XEXP (dest, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (dest, 0), 1)) == CONST_INT);
base = XEXP (XEXP (dest, 0), 0);
off = INTVAL (XEXP (XEXP (dest, 0), 1));
}
- else
- abort ();
if (base == hard_frame_pointer_rtx)
{
saveop = ".savepsp";
off = - off;
}
- else if (base == stack_pointer_rtx)
- saveop = ".savesp";
else
- abort ();
+ {
+ gcc_assert (base == stack_pointer_rtx);
+ saveop = ".savesp";
+ }
src_regno = REGNO (src);
switch (src_regno)
{
case BR_REG (0):
- if (current_frame_info.reg_save_b0 != 0)
- abort ();
- fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_b0);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s rp, %ld\n", saveop, off);
return 1;
case PR_REG (0):
- if (current_frame_info.reg_save_pr != 0)
- abort ();
- fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_pr);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s pr, %ld\n", saveop, off);
return 1;
case AR_LC_REGNUM:
- if (current_frame_info.reg_save_ar_lc != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_lc);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.lc, %ld\n", saveop, off);
return 1;
case AR_PFS_REGNUM:
- if (current_frame_info.reg_save_ar_pfs != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_pfs);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.pfs, %ld\n", saveop, off);
return 1;
case AR_UNAT_REGNUM:
- if (current_frame_info.reg_save_ar_unat != 0)
- abort ();
- fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
+ gcc_assert (!current_frame_info.reg_save_ar_unat);
+ if (unwind)
+ fprintf (asm_out_file, "\t%s ar.unat, %ld\n", saveop, off);
return 1;
case GR_REG (4):
case GR_REG (5):
case GR_REG (6):
case GR_REG (7):
- fprintf (asm_out_file, "\t.save.g 0x%x\n",
- 1 << (src_regno - GR_REG (4)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.g 0x%x\n",
+ 1 << (src_regno - GR_REG (4)));
return 1;
case BR_REG (1):
@@ -8003,24 +9025,27 @@ process_set (FILE *asm_out_file, rtx pat)
case BR_REG (3):
case BR_REG (4):
case BR_REG (5):
- fprintf (asm_out_file, "\t.save.b 0x%x\n",
- 1 << (src_regno - BR_REG (1)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.b 0x%x\n",
+ 1 << (src_regno - BR_REG (1)));
return 1;
case FR_REG (2):
case FR_REG (3):
case FR_REG (4):
case FR_REG (5):
- fprintf (asm_out_file, "\t.save.f 0x%x\n",
- 1 << (src_regno - FR_REG (2)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.f 0x%x\n",
+ 1 << (src_regno - FR_REG (2)));
return 1;
case FR_REG (16): case FR_REG (17): case FR_REG (18): case FR_REG (19):
case FR_REG (20): case FR_REG (21): case FR_REG (22): case FR_REG (23):
case FR_REG (24): case FR_REG (25): case FR_REG (26): case FR_REG (27):
case FR_REG (28): case FR_REG (29): case FR_REG (30): case FR_REG (31):
- fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
- 1 << (src_regno - FR_REG (12)));
+ if (unwind)
+ fprintf (asm_out_file, "\t.save.gf 0x0, 0x%x\n",
+ 1 << (src_regno - FR_REG (12)));
return 1;
default:
@@ -8037,8 +9062,11 @@ process_set (FILE *asm_out_file, rtx pat)
void
process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
- if (flag_unwind_tables
- || (flag_exceptions && !USING_SJLJ_EXCEPTIONS))
+ bool unwind = (flag_unwind_tables
+ || (flag_exceptions && !USING_SJLJ_EXCEPTIONS));
+ bool frame = dwarf2out_do_frame ();
+
+ if (unwind || frame)
{
rtx pat;
@@ -8050,8 +9078,14 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
/* 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");
+ if (unwind)
+ {
+ fprintf (asm_out_file, "\t.body\n");
+ fprintf (asm_out_file, "\t.copy_state %d\n",
+ cfun->machine->state_num);
+ }
+ if (IA64_CHANGE_CFA_IN_EPILOGUE && frame)
+ ia64_dwarf2out_def_steady_cfa (insn);
need_copy_state = false;
}
}
@@ -8068,7 +9102,7 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
switch (GET_CODE (pat))
{
case SET:
- process_set (asm_out_file, pat);
+ process_set (asm_out_file, pat, insn, unwind, frame);
break;
case PARALLEL:
@@ -8079,77 +9113,39 @@ process_for_unwind_directive (FILE *asm_out_file, rtx insn)
{
rtx x = XVECEXP (pat, 0, par_index);
if (GET_CODE (x) == SET)
- process_set (asm_out_file, x);
+ process_set (asm_out_file, x, insn, unwind, frame);
}
break;
}
default:
- abort ();
+ gcc_unreachable ();
}
}
}
+enum ia64_builtins
+{
+ IA64_BUILTIN_BSP,
+ IA64_BUILTIN_FLUSHRS
+};
+
void
ia64_init_builtins (void)
{
- tree psi_type_node = build_pointer_type (integer_type_node);
- tree pdi_type_node = build_pointer_type (long_integer_type_node);
-
- /* __sync_val_compare_and_swap_si, __sync_bool_compare_and_swap_si */
- tree si_ftype_psi_si_si
- = build_function_type_list (integer_type_node,
- psi_type_node, integer_type_node,
- integer_type_node, NULL_TREE);
-
- /* __sync_val_compare_and_swap_di */
- tree di_ftype_pdi_di_di
- = build_function_type_list (long_integer_type_node,
- pdi_type_node, long_integer_type_node,
- long_integer_type_node, NULL_TREE);
- /* __sync_bool_compare_and_swap_di */
- tree si_ftype_pdi_di_di
- = build_function_type_list (integer_type_node,
- pdi_type_node, long_integer_type_node,
- long_integer_type_node, NULL_TREE);
- /* __sync_synchronize */
- tree void_ftype_void
- = build_function_type (void_type_node, void_list_node);
-
- /* __sync_lock_test_and_set_si */
- tree si_ftype_psi_si
- = build_function_type_list (integer_type_node,
- psi_type_node, integer_type_node, NULL_TREE);
-
- /* __sync_lock_test_and_set_di */
- tree di_ftype_pdi_di
- = build_function_type_list (long_integer_type_node,
- pdi_type_node, long_integer_type_node,
- NULL_TREE);
-
- /* __sync_lock_release_si */
- tree void_ftype_psi
- = build_function_type_list (void_type_node, psi_type_node, NULL_TREE);
-
- /* __sync_lock_release_di */
- tree void_ftype_pdi
- = build_function_type_list (void_type_node, pdi_type_node, NULL_TREE);
-
tree fpreg_type;
tree float80_type;
/* The __fpreg type. */
fpreg_type = make_node (REAL_TYPE);
- /* ??? The back end should know to load/save __fpreg variables using
- the ldf.fill and stf.spill instructions. */
- TYPE_PRECISION (fpreg_type) = 96;
+ TYPE_PRECISION (fpreg_type) = 82;
layout_type (fpreg_type);
(*lang_hooks.types.register_builtin_type) (fpreg_type, "__fpreg");
/* The __float80 type. */
float80_type = make_node (REAL_TYPE);
- TYPE_PRECISION (float80_type) = 96;
+ TYPE_PRECISION (float80_type) = 80;
layout_type (float80_type);
(*lang_hooks.types.register_builtin_type) (float80_type, "__float80");
@@ -8166,29 +9162,9 @@ ia64_init_builtins (void)
(*lang_hooks.types.register_builtin_type) (long_double_type_node,
"__float128");
-#define def_builtin(name, type, code) \
- builtin_function ((name), (type), (code), BUILT_IN_MD, NULL, NULL_TREE)
-
- def_builtin ("__sync_val_compare_and_swap_si", si_ftype_psi_si_si,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI);
- def_builtin ("__sync_val_compare_and_swap_di", di_ftype_pdi_di_di,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI);
- def_builtin ("__sync_bool_compare_and_swap_si", si_ftype_psi_si_si,
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI);
- def_builtin ("__sync_bool_compare_and_swap_di", si_ftype_pdi_di_di,
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI);
-
- def_builtin ("__sync_synchronize", void_ftype_void,
- IA64_BUILTIN_SYNCHRONIZE);
-
- def_builtin ("__sync_lock_test_and_set_si", si_ftype_psi_si,
- IA64_BUILTIN_LOCK_TEST_AND_SET_SI);
- def_builtin ("__sync_lock_test_and_set_di", di_ftype_pdi_di,
- IA64_BUILTIN_LOCK_TEST_AND_SET_DI);
- def_builtin ("__sync_lock_release_si", void_ftype_psi,
- IA64_BUILTIN_LOCK_RELEASE_SI);
- def_builtin ("__sync_lock_release_di", void_ftype_pdi,
- IA64_BUILTIN_LOCK_RELEASE_DI);
+#define def_builtin(name, type, code) \
+ lang_hooks.builtin_function ((name), (type), (code), BUILT_IN_MD, \
+ NULL, NULL_TREE)
def_builtin ("__builtin_ia64_bsp",
build_function_type (ptr_type_node, void_list_node),
@@ -8198,322 +9174,9 @@ ia64_init_builtins (void)
build_function_type (void_type_node, void_list_node),
IA64_BUILTIN_FLUSHRS);
- def_builtin ("__sync_fetch_and_add_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_ADD_SI);
- def_builtin ("__sync_fetch_and_sub_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_SUB_SI);
- def_builtin ("__sync_fetch_and_or_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_OR_SI);
- def_builtin ("__sync_fetch_and_and_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_AND_SI);
- def_builtin ("__sync_fetch_and_xor_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_XOR_SI);
- def_builtin ("__sync_fetch_and_nand_si", si_ftype_psi_si,
- IA64_BUILTIN_FETCH_AND_NAND_SI);
-
- def_builtin ("__sync_add_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_ADD_AND_FETCH_SI);
- def_builtin ("__sync_sub_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_SUB_AND_FETCH_SI);
- def_builtin ("__sync_or_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_OR_AND_FETCH_SI);
- def_builtin ("__sync_and_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_AND_AND_FETCH_SI);
- def_builtin ("__sync_xor_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_XOR_AND_FETCH_SI);
- def_builtin ("__sync_nand_and_fetch_si", si_ftype_psi_si,
- IA64_BUILTIN_NAND_AND_FETCH_SI);
-
- def_builtin ("__sync_fetch_and_add_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_ADD_DI);
- def_builtin ("__sync_fetch_and_sub_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_SUB_DI);
- def_builtin ("__sync_fetch_and_or_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_OR_DI);
- def_builtin ("__sync_fetch_and_and_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_AND_DI);
- def_builtin ("__sync_fetch_and_xor_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_XOR_DI);
- def_builtin ("__sync_fetch_and_nand_di", di_ftype_pdi_di,
- IA64_BUILTIN_FETCH_AND_NAND_DI);
-
- def_builtin ("__sync_add_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_ADD_AND_FETCH_DI);
- def_builtin ("__sync_sub_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_SUB_AND_FETCH_DI);
- def_builtin ("__sync_or_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_OR_AND_FETCH_DI);
- def_builtin ("__sync_and_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_AND_AND_FETCH_DI);
- def_builtin ("__sync_xor_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_XOR_AND_FETCH_DI);
- def_builtin ("__sync_nand_and_fetch_di", di_ftype_pdi_di,
- IA64_BUILTIN_NAND_AND_FETCH_DI);
-
#undef def_builtin
}
-/* Expand fetch_and_op intrinsics. The basic code sequence is:
-
- mf
- tmp = [ptr];
- do {
- ret = tmp;
- ar.ccv = tmp;
- tmp <op>= value;
- cmpxchgsz.acq tmp = [ptr], tmp
- } while (tmp != ret)
-*/
-
-static rtx
-ia64_expand_fetch_and_op (optab binoptab, enum machine_mode mode,
- tree arglist, rtx target)
-{
- rtx ret, label, tmp, ccv, insn, mem, value;
- tree arg0, arg1;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE(mem) != Pmode)
- mem = convert_memory_address (Pmode, mem);
-#endif
- value = expand_expr (arg1, NULL_RTX, mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- if (target && register_operand (target, mode))
- ret = target;
- else
- ret = gen_reg_rtx (mode);
-
- emit_insn (gen_mf ());
-
- /* Special case for fetchadd instructions. */
- if (binoptab == add_optab && fetchadd_operand (value, VOIDmode))
- {
- if (mode == SImode)
- insn = gen_fetchadd_acq_si (ret, mem, value);
- else
- insn = gen_fetchadd_acq_di (ret, mem, value);
- emit_insn (insn);
- return ret;
- }
-
- tmp = gen_reg_rtx (mode);
- /* ar.ccv must always be loaded with a zero-extended DImode value. */
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
- emit_move_insn (tmp, mem);
-
- label = gen_label_rtx ();
- emit_label (label);
- emit_move_insn (ret, tmp);
- convert_move (ccv, tmp, /*unsignedp=*/1);
-
- /* Perform the specific operation. Special case NAND by noticing
- one_cmpl_optab instead. */
- if (binoptab == one_cmpl_optab)
- {
- tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
- binoptab = and_optab;
- }
- tmp = expand_binop (mode, binoptab, tmp, value, tmp, 1, OPTAB_WIDEN);
-
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, tmp, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, tmp, ccv);
- emit_insn (insn);
-
- emit_cmp_and_jump_insns (tmp, ret, NE, 0, mode, 1, label);
-
- return ret;
-}
-
-/* Expand op_and_fetch intrinsics. The basic code sequence is:
-
- mf
- tmp = [ptr];
- do {
- old = tmp;
- ar.ccv = tmp;
- ret = tmp <op> value;
- cmpxchgsz.acq tmp = [ptr], ret
- } while (tmp != old)
-*/
-
-static rtx
-ia64_expand_op_and_fetch (optab binoptab, enum machine_mode mode,
- tree arglist, rtx target)
-{
- rtx old, label, tmp, ret, ccv, insn, mem, value;
- tree arg0, arg1;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, Pmode, 0);
-#ifdef POINTERS_EXTEND_UNSIGNED
- if (GET_MODE(mem) != Pmode)
- mem = convert_memory_address (Pmode, mem);
-#endif
-
- value = expand_expr (arg1, NULL_RTX, mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (Pmode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- if (target && ! register_operand (target, mode))
- target = NULL_RTX;
-
- emit_insn (gen_mf ());
- tmp = gen_reg_rtx (mode);
- old = gen_reg_rtx (mode);
- /* ar.ccv must always be loaded with a zero-extended DImode value. */
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
-
- emit_move_insn (tmp, mem);
-
- label = gen_label_rtx ();
- emit_label (label);
- emit_move_insn (old, tmp);
- convert_move (ccv, tmp, /*unsignedp=*/1);
-
- /* Perform the specific operation. Special case NAND by noticing
- one_cmpl_optab instead. */
- if (binoptab == one_cmpl_optab)
- {
- tmp = expand_unop (mode, binoptab, tmp, NULL, OPTAB_WIDEN);
- binoptab = and_optab;
- }
- ret = expand_binop (mode, binoptab, tmp, value, target, 1, OPTAB_WIDEN);
-
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, ret, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, ret, ccv);
- emit_insn (insn);
-
- emit_cmp_and_jump_insns (tmp, old, NE, 0, mode, 1, label);
-
- return ret;
-}
-
-/* Expand val_ and bool_compare_and_swap. For val_ we want:
-
- ar.ccv = oldval
- mf
- cmpxchgsz.acq ret = [ptr], newval, ar.ccv
- return ret
-
- For bool_ it's the same except return ret == oldval.
-*/
-
-static rtx
-ia64_expand_compare_and_swap (enum machine_mode rmode, enum machine_mode mode,
- int boolp, tree arglist, rtx target)
-{
- tree arg0, arg1, arg2;
- rtx mem, old, new, ccv, tmp, insn;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
- old = expand_expr (arg1, NULL_RTX, mode, 0);
- new = expand_expr (arg2, NULL_RTX, mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- if (GET_MODE (old) != mode)
- old = convert_to_mode (mode, old, /*unsignedp=*/1);
- if (GET_MODE (new) != mode)
- new = convert_to_mode (mode, new, /*unsignedp=*/1);
-
- if (! register_operand (old, mode))
- old = copy_to_mode_reg (mode, old);
- if (! register_operand (new, mode))
- new = copy_to_mode_reg (mode, new);
-
- if (! boolp && target && register_operand (target, mode))
- tmp = target;
- else
- tmp = gen_reg_rtx (mode);
-
- ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
- convert_move (ccv, old, /*unsignedp=*/1);
- emit_insn (gen_mf ());
- if (mode == SImode)
- insn = gen_cmpxchg_acq_si (tmp, mem, new, ccv);
- else
- insn = gen_cmpxchg_acq_di (tmp, mem, new, ccv);
- emit_insn (insn);
-
- if (boolp)
- {
- if (! target)
- target = gen_reg_rtx (rmode);
- return emit_store_flag_force (target, EQ, tmp, old, mode, 1, 1);
- }
- else
- return tmp;
-}
-
-/* Expand lock_test_and_set. I.e. `xchgsz ret = [ptr], new'. */
-
-static rtx
-ia64_expand_lock_test_and_set (enum machine_mode mode, tree arglist,
- rtx target)
-{
- tree arg0, arg1;
- rtx mem, new, ret, insn;
-
- arg0 = TREE_VALUE (arglist);
- arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
- new = expand_expr (arg1, NULL_RTX, mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
- MEM_VOLATILE_P (mem) = 1;
- if (! register_operand (new, mode))
- new = copy_to_mode_reg (mode, new);
-
- if (target && register_operand (target, mode))
- ret = target;
- else
- ret = gen_reg_rtx (mode);
-
- if (mode == SImode)
- insn = gen_xchgsi (ret, mem, new);
- else
- insn = gen_xchgdi (ret, mem, new);
- emit_insn (insn);
-
- return ret;
-}
-
-/* Expand lock_release. I.e. `stsz.rel [ptr] = r0'. */
-
-static rtx
-ia64_expand_lock_release (enum machine_mode mode, tree arglist,
- rtx target ATTRIBUTE_UNUSED)
-{
- tree arg0;
- rtx mem;
-
- arg0 = TREE_VALUE (arglist);
- mem = expand_expr (arg0, NULL_RTX, ptr_mode, 0);
-
- mem = gen_rtx_MEM (mode, force_reg (ptr_mode, mem));
- MEM_VOLATILE_P (mem) = 1;
-
- emit_move_insn (mem, const0_rtx);
-
- return const0_rtx;
-}
-
rtx
ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
@@ -8521,89 +9184,9 @@ ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- tree arglist = TREE_OPERAND (exp, 1);
- enum machine_mode rmode = VOIDmode;
switch (fcode)
{
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
- mode = SImode;
- rmode = SImode;
- break;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
- case IA64_BUILTIN_LOCK_RELEASE_SI:
- case IA64_BUILTIN_FETCH_AND_ADD_SI:
- case IA64_BUILTIN_FETCH_AND_SUB_SI:
- case IA64_BUILTIN_FETCH_AND_OR_SI:
- case IA64_BUILTIN_FETCH_AND_AND_SI:
- case IA64_BUILTIN_FETCH_AND_XOR_SI:
- case IA64_BUILTIN_FETCH_AND_NAND_SI:
- case IA64_BUILTIN_ADD_AND_FETCH_SI:
- case IA64_BUILTIN_SUB_AND_FETCH_SI:
- case IA64_BUILTIN_OR_AND_FETCH_SI:
- case IA64_BUILTIN_AND_AND_FETCH_SI:
- case IA64_BUILTIN_XOR_AND_FETCH_SI:
- case IA64_BUILTIN_NAND_AND_FETCH_SI:
- mode = SImode;
- break;
-
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
- mode = DImode;
- rmode = SImode;
- break;
-
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
- mode = DImode;
- rmode = DImode;
- break;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
- case IA64_BUILTIN_LOCK_RELEASE_DI:
- case IA64_BUILTIN_FETCH_AND_ADD_DI:
- case IA64_BUILTIN_FETCH_AND_SUB_DI:
- case IA64_BUILTIN_FETCH_AND_OR_DI:
- case IA64_BUILTIN_FETCH_AND_AND_DI:
- case IA64_BUILTIN_FETCH_AND_XOR_DI:
- case IA64_BUILTIN_FETCH_AND_NAND_DI:
- case IA64_BUILTIN_ADD_AND_FETCH_DI:
- case IA64_BUILTIN_SUB_AND_FETCH_DI:
- case IA64_BUILTIN_OR_AND_FETCH_DI:
- case IA64_BUILTIN_AND_AND_FETCH_DI:
- case IA64_BUILTIN_XOR_AND_FETCH_DI:
- case IA64_BUILTIN_NAND_AND_FETCH_DI:
- mode = DImode;
- break;
-
- default:
- break;
- }
-
- switch (fcode)
- {
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI:
- return ia64_expand_compare_and_swap (rmode, mode, 1, arglist,
- target);
-
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI:
- case IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI:
- return ia64_expand_compare_and_swap (rmode, mode, 0, arglist,
- target);
-
- case IA64_BUILTIN_SYNCHRONIZE:
- emit_insn (gen_mf ());
- return const0_rtx;
-
- case IA64_BUILTIN_LOCK_TEST_AND_SET_SI:
- case IA64_BUILTIN_LOCK_TEST_AND_SET_DI:
- return ia64_expand_lock_test_and_set (mode, arglist, target);
-
- case IA64_BUILTIN_LOCK_RELEASE_SI:
- case IA64_BUILTIN_LOCK_RELEASE_DI:
- return ia64_expand_lock_release (mode, arglist, target);
-
case IA64_BUILTIN_BSP:
if (! target || ! register_operand (target, DImode))
target = gen_reg_rtx (DImode);
@@ -8617,54 +9200,6 @@ ia64_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
emit_insn (gen_flushrs ());
return const0_rtx;
- case IA64_BUILTIN_FETCH_AND_ADD_SI:
- case IA64_BUILTIN_FETCH_AND_ADD_DI:
- return ia64_expand_fetch_and_op (add_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_SUB_SI:
- case IA64_BUILTIN_FETCH_AND_SUB_DI:
- return ia64_expand_fetch_and_op (sub_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_OR_SI:
- case IA64_BUILTIN_FETCH_AND_OR_DI:
- return ia64_expand_fetch_and_op (ior_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_AND_SI:
- case IA64_BUILTIN_FETCH_AND_AND_DI:
- return ia64_expand_fetch_and_op (and_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_XOR_SI:
- case IA64_BUILTIN_FETCH_AND_XOR_DI:
- return ia64_expand_fetch_and_op (xor_optab, mode, arglist, target);
-
- case IA64_BUILTIN_FETCH_AND_NAND_SI:
- case IA64_BUILTIN_FETCH_AND_NAND_DI:
- return ia64_expand_fetch_and_op (one_cmpl_optab, mode, arglist, target);
-
- case IA64_BUILTIN_ADD_AND_FETCH_SI:
- case IA64_BUILTIN_ADD_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (add_optab, mode, arglist, target);
-
- case IA64_BUILTIN_SUB_AND_FETCH_SI:
- case IA64_BUILTIN_SUB_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (sub_optab, mode, arglist, target);
-
- case IA64_BUILTIN_OR_AND_FETCH_SI:
- case IA64_BUILTIN_OR_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (ior_optab, mode, arglist, target);
-
- case IA64_BUILTIN_AND_AND_FETCH_SI:
- case IA64_BUILTIN_AND_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (and_optab, mode, arglist, target);
-
- case IA64_BUILTIN_XOR_AND_FETCH_SI:
- case IA64_BUILTIN_XOR_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (xor_optab, mode, arglist, target);
-
- case IA64_BUILTIN_NAND_AND_FETCH_SI:
- case IA64_BUILTIN_NAND_AND_FETCH_DI:
- return ia64_expand_op_and_fetch (one_cmpl_optab, mode, arglist, target);
-
default:
break;
}
@@ -8722,8 +9257,7 @@ ia64_hpux_file_end (void)
tree decl = p->decl;
tree id = DECL_ASSEMBLER_NAME (decl);
- if (!id)
- abort ();
+ gcc_assert (id);
if (!TREE_ASM_WRITTEN (decl) && TREE_SYMBOL_REFERENCED (id))
{
@@ -8740,19 +9274,72 @@ ia64_hpux_file_end (void)
extern_func_head = 0;
}
-/* Rename all the TFmode libfuncs using the HPUX conventions. */
+/* Set SImode div/mod functions, init_integral_libfuncs only initializes
+ modes of word_mode and larger. Rename the TFmode libfuncs using the
+ HPUX conventions. __divtf3 is used for XFmode. We need to keep it for
+ backward compatibility. */
static void
-ia64_hpux_init_libfuncs (void)
+ia64_init_libfuncs (void)
{
+ set_optab_libfunc (sdiv_optab, SImode, "__divsi3");
+ set_optab_libfunc (udiv_optab, SImode, "__udivsi3");
+ set_optab_libfunc (smod_optab, SImode, "__modsi3");
+ set_optab_libfunc (umod_optab, SImode, "__umodsi3");
+
set_optab_libfunc (add_optab, TFmode, "_U_Qfadd");
set_optab_libfunc (sub_optab, TFmode, "_U_Qfsub");
set_optab_libfunc (smul_optab, TFmode, "_U_Qfmpy");
set_optab_libfunc (sdiv_optab, TFmode, "_U_Qfdiv");
+ set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
+
+ set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
+ set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
+ set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
+
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
+ set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
+ set_conv_libfunc (sfix_optab, TImode, TFmode, "_U_Qfcnvfxt_quad_to_quad");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
+ set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
+
+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
+ set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
+ set_conv_libfunc (sfloat_optab, TFmode, TImode, "_U_Qfcnvxf_quad_to_quad");
+ /* HP-UX 11.23 libc does not have a function for unsigned
+ SImode-to-TFmode conversion. */
+ set_conv_libfunc (ufloat_optab, TFmode, DImode, "_U_Qfcnvxuf_dbl_to_quad");
+}
+
+/* Rename all the TFmode libfuncs using the HPUX conventions. */
+
+static void
+ia64_hpux_init_libfuncs (void)
+{
+ ia64_init_libfuncs ();
+
+ /* The HP SI millicode division and mod functions expect DI arguments.
+ By turning them off completely we avoid using both libgcc and the
+ non-standard millicode routines and use the HP DI millicode routines
+ instead. */
+
+ set_optab_libfunc (sdiv_optab, SImode, 0);
+ set_optab_libfunc (udiv_optab, SImode, 0);
+ set_optab_libfunc (smod_optab, SImode, 0);
+ set_optab_libfunc (umod_optab, SImode, 0);
+
+ set_optab_libfunc (sdiv_optab, DImode, "__milli_divI");
+ set_optab_libfunc (udiv_optab, DImode, "__milli_divU");
+ set_optab_libfunc (smod_optab, DImode, "__milli_remI");
+ set_optab_libfunc (umod_optab, DImode, "__milli_remU");
+
+ /* HP-UX libc has TF min/max/abs routines in it. */
set_optab_libfunc (smin_optab, TFmode, "_U_Qfmin");
set_optab_libfunc (smax_optab, TFmode, "_U_Qfmax");
set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
- set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
/* ia64_expand_compare uses this. */
cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
@@ -8764,21 +9351,6 @@ ia64_hpux_init_libfuncs (void)
set_optab_libfunc (ge_optab, TFmode, 0);
set_optab_libfunc (lt_optab, TFmode, 0);
set_optab_libfunc (le_optab, TFmode, 0);
-
- set_conv_libfunc (sext_optab, TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
- set_conv_libfunc (sext_optab, TFmode, XFmode, "_U_Qfcnvff_f80_to_quad");
- set_conv_libfunc (trunc_optab, SFmode, TFmode, "_U_Qfcnvff_quad_to_sgl");
- set_conv_libfunc (trunc_optab, DFmode, TFmode, "_U_Qfcnvff_quad_to_dbl");
- set_conv_libfunc (trunc_optab, XFmode, TFmode, "_U_Qfcnvff_quad_to_f80");
-
- set_conv_libfunc (sfix_optab, SImode, TFmode, "_U_Qfcnvfxt_quad_to_sgl");
- set_conv_libfunc (sfix_optab, DImode, TFmode, "_U_Qfcnvfxt_quad_to_dbl");
- set_conv_libfunc (ufix_optab, SImode, TFmode, "_U_Qfcnvfxut_quad_to_sgl");
- set_conv_libfunc (ufix_optab, DImode, TFmode, "_U_Qfcnvfxut_quad_to_dbl");
-
- set_conv_libfunc (sfloat_optab, TFmode, SImode, "_U_Qfcnvxf_sgl_to_quad");
- set_conv_libfunc (sfloat_optab, TFmode, DImode, "_U_Qfcnvxf_dbl_to_quad");
}
/* Rename the division and modulus functions in VMS. */
@@ -8795,50 +9367,79 @@ ia64_vms_init_libfuncs (void)
set_optab_libfunc (umod_optab, SImode, "OTS$REM_UI");
set_optab_libfunc (umod_optab, DImode, "OTS$REM_UL");
}
-
-/* Switch to the section to which we should output X. The only thing
- special we do here is to honor small data. */
+
+/* Rename the TFmode libfuncs available from soft-fp in glibc using
+ the HPUX conventions. */
static void
-ia64_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
+ia64_sysv4_init_libfuncs (void)
{
- if (GET_MODE_SIZE (mode) > 0
- && GET_MODE_SIZE (mode) <= ia64_section_threshold)
- sdata_section ();
- else
- default_elf_select_rtx_section (mode, x, align);
-}
+ ia64_init_libfuncs ();
-/* It is illegal to have relocations in shared segments on AIX and HPUX.
- Pretend flag_pic is always set. */
+ /* These functions are not part of the HPUX TFmode interface. We
+ use them instead of _U_Qfcmp, which doesn't work the way we
+ expect. */
+ set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
+ set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
+ set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
+ set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
+ set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
+ set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
-static void
-ia64_rwreloc_select_section (tree exp, int reloc, unsigned HOST_WIDE_INT align)
+ /* We leave out _U_Qfmin, _U_Qfmax and _U_Qfabs since soft-fp in
+ glibc doesn't have them. */
+}
+
+/* For HPUX, it is illegal to have relocations in shared segments. */
+
+static int
+ia64_hpux_reloc_rw_mask (void)
{
- default_elf_select_section_1 (exp, reloc, align, true);
+ return 3;
}
-static void
-ia64_rwreloc_unique_section (tree decl, int reloc)
+/* For others, relax this so that relocations to local data goes in
+ read-only segments, but we still cannot allow global relocations
+ in read-only segments. */
+
+static int
+ia64_reloc_rw_mask (void)
{
- default_unique_section_1 (decl, reloc, true);
+ return flag_pic ? 3 : 2;
}
-static void
-ia64_rwreloc_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
+/* Return the section to use for X. The only special thing we do here
+ is to honor small data. */
+
+static section *
+ia64_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
{
- int save_pic = flag_pic;
- flag_pic = 1;
- ia64_select_rtx_section (mode, x, align);
- flag_pic = save_pic;
+ if (GET_MODE_SIZE (mode) > 0
+ && GET_MODE_SIZE (mode) <= ia64_section_threshold
+ && !TARGET_NO_SDATA)
+ return sdata_section;
+ else
+ return default_elf_select_rtx_section (mode, x, align);
}
static unsigned int
-ia64_rwreloc_section_type_flags (tree decl, const char *name, int reloc)
+ia64_section_type_flags (tree decl, const char *name, int reloc)
{
- return default_section_type_flags_1 (decl, name, reloc, true);
+ unsigned int flags = 0;
+
+ if (strcmp (name, ".sdata") == 0
+ || strncmp (name, ".sdata.", 7) == 0
+ || strncmp (name, ".gnu.linkonce.s.", 16) == 0
+ || strncmp (name, ".sdata2.", 8) == 0
+ || strncmp (name, ".gnu.linkonce.s2.", 17) == 0
+ || strcmp (name, ".sbss") == 0
+ || strncmp (name, ".sbss.", 6) == 0
+ || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
+ flags = SECTION_SMALL;
+
+ flags |= default_section_type_flags (decl, name, reloc);
+ return flags;
}
/* Returns true if FNTYPE (a FUNCTION_TYPE or a METHOD_TYPE) returns a
@@ -8881,6 +9482,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
reload_completed = 1;
epilogue_completed = 1;
no_new_pseudos = 1;
+ reset_block_changes ();
/* Set things up as ia64_expand_prologue might. */
last_scratch_gr_reg = 15;
@@ -9003,7 +9605,7 @@ ia64_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
insn = get_insns ();
shorten_branches (insn);
final_start_function (insn, file, 1);
- final (insn, file, 1, 0);
+ final (insn, file, 1);
final_end_function ();
reload_completed = 0;
@@ -9022,4 +9624,216 @@ ia64_struct_value_rtx (tree fntype,
return gen_rtx_REG (Pmode, GR_REG (8));
}
+static bool
+ia64_scalar_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case QImode:
+ case HImode:
+ case SImode:
+ case DImode:
+ case TImode:
+ return true;
+
+ case SFmode:
+ case DFmode:
+ case XFmode:
+ case RFmode:
+ return true;
+
+ case TFmode:
+ return TARGET_HPUX;
+
+ default:
+ return false;
+ }
+}
+
+static bool
+ia64_vector_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V8QImode:
+ case V4HImode:
+ case V2SImode:
+ return true;
+
+ case V2SFmode:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Implement the FUNCTION_PROFILER macro. */
+
+void
+ia64_output_function_profiler (FILE *file, int labelno)
+{
+ bool indirect_call;
+
+ /* If the function needs a static chain and the static chain
+ register is r15, we use an indirect call so as to bypass
+ the PLT stub in case the executable is dynamically linked,
+ because the stub clobbers r15 as per 5.3.6 of the psABI.
+ We don't need to do that in non canonical PIC mode. */
+
+ if (cfun->static_chain_decl && !TARGET_NO_PIC && !TARGET_AUTO_PIC)
+ {
+ gcc_assert (STATIC_CHAIN_REGNUM == 15);
+ indirect_call = true;
+ }
+ else
+ indirect_call = false;
+
+ if (TARGET_GNU_AS)
+ fputs ("\t.prologue 4, r40\n", file);
+ else
+ fputs ("\t.prologue\n\t.save ar.pfs, r40\n", file);
+ fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", file);
+
+ if (NO_PROFILE_COUNTERS)
+ fputs ("\tmov out3 = r0\n", file);
+ else
+ {
+ char buf[20];
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+
+ if (TARGET_AUTO_PIC)
+ fputs ("\tmovl out3 = @gprel(", file);
+ else
+ fputs ("\taddl out3 = @ltoff(", file);
+ assemble_name (file, buf);
+ if (TARGET_AUTO_PIC)
+ fputs (")\n", file);
+ else
+ fputs ("), r1\n", file);
+ }
+
+ if (indirect_call)
+ fputs ("\taddl r14 = @ltoff(@fptr(_mcount)), r1\n", file);
+ fputs ("\t;;\n", file);
+
+ fputs ("\t.save rp, r42\n", file);
+ fputs ("\tmov out2 = b0\n", file);
+ if (indirect_call)
+ fputs ("\tld8 r14 = [r14]\n\t;;\n", file);
+ fputs ("\t.body\n", file);
+ fputs ("\tmov out1 = r1\n", file);
+ if (indirect_call)
+ {
+ fputs ("\tld8 r16 = [r14], 8\n\t;;\n", file);
+ fputs ("\tmov b6 = r16\n", file);
+ fputs ("\tld8 r1 = [r14]\n", file);
+ fputs ("\tbr.call.sptk.many b0 = b6\n\t;;\n", file);
+ }
+ else
+ fputs ("\tbr.call.sptk.many b0 = _mcount\n\t;;\n", file);
+}
+
+static GTY(()) rtx mcount_func_rtx;
+static rtx
+gen_mcount_func_rtx (void)
+{
+ if (!mcount_func_rtx)
+ mcount_func_rtx = init_one_libfunc ("_mcount");
+ return mcount_func_rtx;
+}
+
+void
+ia64_profile_hook (int labelno)
+{
+ rtx label, ip;
+
+ if (NO_PROFILE_COUNTERS)
+ label = const0_rtx;
+ else
+ {
+ char buf[30];
+ const char *label_name;
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
+ label_name = (*targetm.strip_name_encoding) (ggc_strdup (buf));
+ label = gen_rtx_SYMBOL_REF (Pmode, label_name);
+ SYMBOL_REF_FLAGS (label) = SYMBOL_FLAG_LOCAL;
+ }
+ ip = gen_reg_rtx (Pmode);
+ emit_insn (gen_ip_value (ip));
+ emit_library_call (gen_mcount_func_rtx (), LCT_NORMAL,
+ VOIDmode, 3,
+ gen_rtx_REG (Pmode, BR_REG (0)), Pmode,
+ ip, Pmode,
+ label, Pmode);
+}
+
+/* Return the mangling of TYPE if it is an extended fundamental type. */
+
+static const char *
+ia64_mangle_fundamental_type (tree type)
+{
+ /* On HP-UX, "long double" is mangled as "e" so __float128 is
+ mangled as "e". */
+ if (!TARGET_HPUX && TYPE_MODE (type) == TFmode)
+ return "g";
+ /* On HP-UX, "e" is not available as a mangling of __float80 so use
+ an extended mangling. Elsewhere, "e" is available since long
+ double is 80 bits. */
+ if (TYPE_MODE (type) == XFmode)
+ return TARGET_HPUX ? "u9__float80" : "e";
+ if (TYPE_MODE (type) == RFmode)
+ return "u7__fpreg";
+ return NULL;
+}
+
+/* Return the diagnostic message string if conversion from FROMTYPE to
+ TOTYPE is not allowed, NULL otherwise. */
+static const char *
+ia64_invalid_conversion (tree fromtype, tree totype)
+{
+ /* Reject nontrivial conversion to or from __fpreg. */
+ if (TYPE_MODE (fromtype) == RFmode
+ && TYPE_MODE (totype) != RFmode
+ && TYPE_MODE (totype) != VOIDmode)
+ return N_("invalid conversion from %<__fpreg%>");
+ if (TYPE_MODE (totype) == RFmode
+ && TYPE_MODE (fromtype) != RFmode)
+ return N_("invalid conversion to %<__fpreg%>");
+ return NULL;
+}
+
+/* Return the diagnostic message string if the unary operation OP is
+ not permitted on TYPE, NULL otherwise. */
+static const char *
+ia64_invalid_unary_op (int op, tree type)
+{
+ /* Reject operations on __fpreg other than unary + or &. */
+ if (TYPE_MODE (type) == RFmode
+ && op != CONVERT_EXPR
+ && op != ADDR_EXPR)
+ return N_("invalid operation on %<__fpreg%>");
+ return NULL;
+}
+
+/* Return the diagnostic message string if the binary operation OP is
+ not permitted on TYPE1 and TYPE2, NULL otherwise. */
+static const char *
+ia64_invalid_binary_op (int op ATTRIBUTE_UNUSED, tree type1, tree type2)
+{
+ /* Reject operations on __fpreg. */
+ if (TYPE_MODE (type1) == RFmode || TYPE_MODE (type2) == RFmode)
+ return N_("invalid operation on %<__fpreg%>");
+ return NULL;
+}
+
+/* Implement overriding of the optimization options. */
+void
+ia64_optimization_options (int level ATTRIBUTE_UNUSED,
+ int size ATTRIBUTE_UNUSED)
+{
+ /* Let the scheduler form additional regions. */
+ set_param_value ("max-sched-extend-regions-iters", 2);
+}
+
#include "gt-ia64.h"
diff --git a/contrib/gcc/config/ia64/ia64.h b/contrib/gcc/config/ia64/ia64.h
index 9f7dd05..c9bb417 100644
--- a/contrib/gcc/config/ia64/ia64.h
+++ b/contrib/gcc/config/ia64/ia64.h
@@ -1,5 +1,6 @@
/* Definitions of target machine GNU compiler. IA-64 version.
- Copyright (C) 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by James E. Wilson <wilson@cygnus.com> and
David Mosberger <davidm@hpl.hp.com>.
@@ -17,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* ??? Look at ABI group documents for list of preprocessor macros and
other features required for ABI compliance. */
@@ -26,8 +27,6 @@ Boston, MA 02111-1307, USA. */
/* ??? Functions containing a non-local goto target save many registers. Why?
See for instance execute/920428-2.c. */
-/* ??? Add support for short data/bss sections. */
-
/* Run-time target specifications */
@@ -55,95 +54,9 @@ do { \
#define ASM_EXTRA_SPEC ""
-
-/* This declaration should be present. */
-extern int target_flags;
-
-/* This series of macros is to allow compiler command arguments to enable or
- disable the use of optional features of the target machine. */
-
-#define MASK_BIG_ENDIAN 0x00000001 /* Generate big endian code. */
-
-#define MASK_GNU_AS 0x00000002 /* Generate code for GNU as. */
-
-#define MASK_GNU_LD 0x00000004 /* Generate code for GNU ld. */
-
-#define MASK_NO_PIC 0x00000008 /* Generate code without GP reg. */
-
-#define MASK_VOL_ASM_STOP 0x00000010 /* Emit stop bits for vol ext asm. */
-
-#define MASK_ILP32 0x00000020 /* Generate ILP32 code. */
-
-#define MASK_B_STEP 0x00000040 /* Emit code for Itanium B step. */
-
-#define MASK_REG_NAMES 0x00000080 /* Use in/loc/out register names. */
-
-#define MASK_NO_SDATA 0x00000100 /* Disable sdata/scommon/sbss. */
-
-#define MASK_CONST_GP 0x00000200 /* treat gp as program-wide constant */
-
-#define MASK_AUTO_PIC 0x00000400 /* generate automatically PIC */
-
-#define MASK_INLINE_FLOAT_DIV_LAT 0x00000800 /* inline div, min latency. */
-
-#define MASK_INLINE_FLOAT_DIV_THR 0x00001000 /* inline div, max throughput. */
-
-#define MASK_INLINE_INT_DIV_LAT 0x00000800 /* inline div, min latency. */
-
-#define MASK_INLINE_INT_DIV_THR 0x00001000 /* inline div, max throughput. */
-
-#define MASK_INLINE_SQRT_LAT 0x00002000 /* inline sqrt, min latency. */
-
-#define MASK_INLINE_SQRT_THR 0x00004000 /* inline sqrt, max throughput. */
-
-#define MASK_DWARF2_ASM 0x40000000 /* test dwarf2 line info via gas. */
-
-#define MASK_EARLY_STOP_BITS 0x00002000 /* tune stop bits for the model. */
-
-#define TARGET_BIG_ENDIAN (target_flags & MASK_BIG_ENDIAN)
-
-#define TARGET_GNU_AS (target_flags & MASK_GNU_AS)
-
-#define TARGET_GNU_LD (target_flags & MASK_GNU_LD)
-
-#define TARGET_NO_PIC (target_flags & MASK_NO_PIC)
-
-#define TARGET_VOL_ASM_STOP (target_flags & MASK_VOL_ASM_STOP)
-
-#define TARGET_ILP32 (target_flags & MASK_ILP32)
-
-#define TARGET_B_STEP (target_flags & MASK_B_STEP)
-
-#define TARGET_REG_NAMES (target_flags & MASK_REG_NAMES)
-
-#define TARGET_NO_SDATA (target_flags & MASK_NO_SDATA)
-
-#define TARGET_CONST_GP (target_flags & MASK_CONST_GP)
-
-#define TARGET_AUTO_PIC (target_flags & MASK_AUTO_PIC)
-
-#define TARGET_INLINE_FLOAT_DIV_LAT (target_flags & MASK_INLINE_FLOAT_DIV_LAT)
-
-#define TARGET_INLINE_FLOAT_DIV_THR (target_flags & MASK_INLINE_FLOAT_DIV_THR)
-
-#define TARGET_INLINE_INT_DIV_LAT (target_flags & MASK_INLINE_INT_DIV_LAT)
-
-#define TARGET_INLINE_INT_DIV_THR (target_flags & MASK_INLINE_INT_DIV_THR)
-
-#define TARGET_INLINE_FLOAT_DIV \
- (target_flags & (MASK_INLINE_FLOAT_DIV_LAT | MASK_INLINE_FLOAT_DIV_THR))
-
-#define TARGET_INLINE_INT_DIV \
- (target_flags & (MASK_INLINE_INT_DIV_LAT | MASK_INLINE_INT_DIV_THR))
-
-#define TARGET_INLINE_SQRT_LAT (target_flags & MASK_INLINE_SQRT_LAT)
-
-#define TARGET_INLINE_SQRT_THR (target_flags & MASK_INLINE_SQRT_THR)
-
-#define TARGET_INLINE_SQRT \
- (target_flags & (MASK_INLINE_SQRT_LAT | MASK_INLINE_SQRT_THR))
-
-#define TARGET_DWARF2_ASM (target_flags & MASK_DWARF2_ASM)
+/* Variables which are this size or smaller are put in the sdata/sbss
+ sections. */
+extern unsigned int ia64_section_threshold;
/* If the assembler supports thread-local storage, assume that the
system does as well. If a particular target system has an
@@ -154,126 +67,54 @@ extern int target_flags;
#define TARGET_HAVE_TLS true
#endif
-extern int ia64_tls_size;
#define TARGET_TLS14 (ia64_tls_size == 14)
#define TARGET_TLS22 (ia64_tls_size == 22)
#define TARGET_TLS64 (ia64_tls_size == 64)
-#define TARGET_EARLY_STOP_BITS (target_flags & MASK_EARLY_STOP_BITS)
#define TARGET_HPUX 0
#define TARGET_HPUX_LD 0
+#ifndef TARGET_ILP32
+#define TARGET_ILP32 0
+#endif
+
#ifndef HAVE_AS_LTOFFX_LDXMOV_RELOCS
#define HAVE_AS_LTOFFX_LDXMOV_RELOCS 0
#endif
-/* This macro defines names of command options to set and clear bits in
- `target_flags'. Its definition is an initializer with a subgrouping for
- each command option. */
+/* Values for TARGET_INLINE_FLOAT_DIV, TARGET_INLINE_INT_DIV, and
+ TARGET_INLINE_SQRT. */
-#define TARGET_SWITCHES \
-{ \
- { "big-endian", MASK_BIG_ENDIAN, \
- N_("Generate big endian code") }, \
- { "little-endian", -MASK_BIG_ENDIAN, \
- N_("Generate little endian code") }, \
- { "gnu-as", MASK_GNU_AS, \
- N_("Generate code for GNU as") }, \
- { "no-gnu-as", -MASK_GNU_AS, \
- N_("Generate code for Intel as") }, \
- { "gnu-ld", MASK_GNU_LD, \
- N_("Generate code for GNU ld") }, \
- { "no-gnu-ld", -MASK_GNU_LD, \
- N_("Generate code for Intel ld") }, \
- { "no-pic", MASK_NO_PIC, \
- N_("Generate code without GP reg") }, \
- { "volatile-asm-stop", MASK_VOL_ASM_STOP, \
- N_("Emit stop bits before and after volatile extended asms") }, \
- { "no-volatile-asm-stop", -MASK_VOL_ASM_STOP, \
- N_("Don't emit stop bits before and after volatile extended asms") }, \
- { "b-step", MASK_B_STEP, \
- N_("Emit code for Itanium (TM) processor B step")}, \
- { "register-names", MASK_REG_NAMES, \
- N_("Use in/loc/out register names")}, \
- { "no-sdata", MASK_NO_SDATA, \
- N_("Disable use of sdata/scommon/sbss")}, \
- { "sdata", -MASK_NO_SDATA, \
- N_("Enable use of sdata/scommon/sbss")}, \
- { "constant-gp", MASK_CONST_GP, \
- N_("gp is constant (but save/restore gp on indirect calls)") }, \
- { "auto-pic", MASK_AUTO_PIC, \
- N_("Generate self-relocatable code") }, \
- { "inline-float-divide-min-latency", MASK_INLINE_FLOAT_DIV_LAT, \
- N_("Generate inline floating point division, optimize for latency") },\
- { "inline-float-divide-max-throughput", MASK_INLINE_FLOAT_DIV_THR, \
- N_("Generate inline floating point division, optimize for throughput") },\
- { "inline-int-divide-min-latency", MASK_INLINE_INT_DIV_LAT, \
- N_("Generate inline integer division, optimize for latency") }, \
- { "inline-int-divide-max-throughput", MASK_INLINE_INT_DIV_THR, \
- N_("Generate inline integer division, optimize for throughput") },\
- { "inline-sqrt-min-latency", MASK_INLINE_SQRT_LAT, \
- N_("Generate inline square root, optimize for latency") }, \
- { "inline-sqrt-max-throughput", MASK_INLINE_SQRT_THR, \
- N_("Generate inline square root, optimize for throughput") }, \
- { "dwarf2-asm", MASK_DWARF2_ASM, \
- N_("Enable Dwarf 2 line debug info via GNU as")}, \
- { "no-dwarf2-asm", -MASK_DWARF2_ASM, \
- N_("Disable Dwarf 2 line debug info via GNU as")}, \
- { "early-stop-bits", MASK_EARLY_STOP_BITS, \
- N_("Enable earlier placing stop bits for better scheduling")}, \
- { "no-early-stop-bits", -MASK_EARLY_STOP_BITS, \
- N_("Disable earlier placing stop bits")}, \
- SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT | TARGET_CPU_DEFAULT, \
- NULL } \
-}
+enum ia64_inline_type
+{
+ INL_NO = 0,
+ INL_MIN_LAT = 1,
+ INL_MAX_THR = 2
+};
/* Default target_flags if no switches are specified */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT MASK_DWARF2_ASM
+#define TARGET_DEFAULT (MASK_DWARF2_ASM)
#endif
#ifndef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT 0
#endif
-#ifndef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES
-#endif
-
-/* This macro is similar to `TARGET_SWITCHES' but defines names of command
- options that have values. Its definition is an initializer with a
- subgrouping for each command option. */
-
-extern const char *ia64_fixed_range_string;
-extern const char *ia64_tls_size_string;
-
/* Which processor to schedule for. The cpu attribute defines a list
- that mirrors this list, so changes to i64.md must be made at the
+ that mirrors this list, so changes to ia64.md must be made at the
same time. */
enum processor_type
{
- PROCESSOR_ITANIUM, /* Original Itanium. */
+ PROCESSOR_ITANIUM, /* Original Itanium. */
PROCESSOR_ITANIUM2,
PROCESSOR_max
};
extern enum processor_type ia64_tune;
-extern const char *ia64_tune_string;
-
-#define TARGET_OPTIONS \
-{ \
- { "fixed-range=", &ia64_fixed_range_string, \
- N_("Specify range of registers to make fixed"), 0}, \
- { "tls-size=", &ia64_tls_size_string, \
- N_("Specify bit size of immediate TLS offsets"), 0}, \
- { "tune=", &ia64_tune_string, \
- N_("Schedule code for given CPU"), 0}, \
-}
-
/* Sometimes certain combinations of command options do not make sense on a
particular target machine. You can define a macro `OVERRIDE_OPTIONS' to
take account of this. This macro, if defined, is executed once just after
@@ -349,12 +190,6 @@ do \
} \
while (0)
-/* ??? ABI doesn't allow us to define this. */
-/* #define PROMOTE_FUNCTION_ARGS */
-
-/* ??? ABI doesn't allow us to define this. */
-/* #define PROMOTE_FUNCTION_RETURN */
-
#define PARM_BOUNDARY 64
/* Define this macro if you wish to preserve a certain alignment for the stack
@@ -439,8 +274,6 @@ while (0)
#define LONG_TYPE_SIZE (TARGET_ILP32 ? 32 : 64)
-#define MAX_LONG_TYPE_SIZE 64
-
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
@@ -448,10 +281,10 @@ while (0)
#define DOUBLE_TYPE_SIZE 64
/* long double is XFmode normally, TFmode for HPUX. */
-#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 96)
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_HPUX ? 128 : 80)
/* We always want the XFmode operations from libgcc2.c. */
-#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 96
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 80
#define DEFAULT_SIGNED_CHAR 1
@@ -491,6 +324,7 @@ while (0)
#define ADDL_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 3)
#define GR_REGNO_P(REGNO) ((unsigned HOST_WIDE_INT) (REGNO) <= 127)
#define FR_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 255)
+#define FP_REGNO_P(REGNO) ((REGNO) >= 128 && (REGNO) <= 254 && (REGNO) != 159)
#define PR_REGNO_P(REGNO) ((REGNO) >= 256 && (REGNO) <= 319)
#define BR_REGNO_P(REGNO) ((REGNO) >= 320 && (REGNO) <= 327)
#define GENERAL_REGNO_P(REGNO) \
@@ -620,7 +454,7 @@ while (0)
#define CALL_REALLY_USED_REGISTERS \
{ /* General registers. */ \
- 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, \
+ 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -629,7 +463,7 @@ while (0)
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Floating-point registers. */ \
- 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
@@ -638,7 +472,7 @@ while (0)
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
/* Predicate registers. */ \
- 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -672,9 +506,7 @@ while (0)
#define LOCAL_REGNO(REGNO) \
(IN_REGNO_P (REGNO) || LOC_REGNO_P (REGNO))
-/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- return the mode to be used for the comparison. Must be defined if
- EXTRA_CC_MODES is defined. */
+/* We define CCImode in ia64-modes.def so we need a selector. */
#define SELECT_CC_MODE(OP,X,Y) CCmode
@@ -810,6 +642,7 @@ while (0)
: PR_REGNO_P (REGNO) && (MODE) == BImode ? 2 \
: PR_REGNO_P (REGNO) && (MODE) == CCImode ? 1 \
: FR_REGNO_P (REGNO) && (MODE) == XFmode ? 1 \
+ : FR_REGNO_P (REGNO) && (MODE) == XCmode ? 2 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
/* A C expression that is nonzero if it is permissible to store a value of mode
@@ -819,12 +652,12 @@ while (0)
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
(FR_REGNO_P (REGNO) ? \
GET_MODE_CLASS (MODE) != MODE_CC && \
- (MODE) != TImode && \
(MODE) != BImode && \
(MODE) != TFmode \
: PR_REGNO_P (REGNO) ? \
(MODE) == BImode || GET_MODE_CLASS (MODE) == MODE_CC \
- : GR_REGNO_P (REGNO) ? (MODE) != CCImode && (MODE) != XFmode \
+ : GR_REGNO_P (REGNO) ? \
+ (MODE) != CCImode && (MODE) != XFmode && (MODE) != XCmode \
: AR_REGNO_P (REGNO) ? (MODE) == DImode \
: BR_REGNO_P (REGNO) ? (MODE) == DImode \
: 0)
@@ -841,7 +674,8 @@ while (0)
we can't tie it with any other modes. */
#define MODES_TIEABLE_P(MODE1, MODE2) \
(GET_MODE_CLASS (MODE1) == GET_MODE_CLASS (MODE2) \
- && (((MODE1) == XFmode) == ((MODE2) == XFmode)) \
+ && ((((MODE1) == XFmode) || ((MODE1) == XCmode)) \
+ == (((MODE2) == XFmode) || ((MODE2) == XCmode))) \
&& (((MODE1) == BImode) == ((MODE2) == BImode)))
/* Specify the modes required to caller save a given hard regno.
@@ -887,6 +721,7 @@ enum reg_class
AR_I_REGS,
ADDL_REGS,
GR_REGS,
+ FP_REGS,
FR_REGS,
GR_AND_BR_REGS,
GR_AND_FR_REGS,
@@ -903,7 +738,7 @@ enum reg_class
constants. These names are used in writing some of the debugging dumps. */
#define REG_CLASS_NAMES \
{ "NO_REGS", "PR_REGS", "BR_REGS", "AR_M_REGS", "AR_I_REGS", \
- "ADDL_REGS", "GR_REGS", "FR_REGS", \
+ "ADDL_REGS", "GR_REGS", "FP_REGS", "FR_REGS", \
"GR_AND_BR_REGS", "GR_AND_FR_REGS", "ALL_REGS" }
/* An initializer containing the contents of the register classes, as integers
@@ -940,6 +775,10 @@ enum reg_class
{ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0x00000000, 0x00000000, 0x0100 }, \
+ /* FP_REGS. */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ 0x7FFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x7FFFFFFF, \
+ 0x00000000, 0x00000000, 0x0000 }, \
/* FR_REGS. */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, \
@@ -967,7 +806,8 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) \
(ADDL_REGNO_P (REGNO) ? ADDL_REGS \
: GENERAL_REGNO_P (REGNO) ? GR_REGS \
- : FR_REGNO_P (REGNO) ? FR_REGS \
+ : FR_REGNO_P (REGNO) ? (REGNO) != R_FR (31) \
+ && (REGNO) != R_FR(127) ? FP_REGS : FR_REGS \
: PR_REGNO_P (REGNO) ? PR_REGS \
: BR_REGNO_P (REGNO) ? BR_REGS \
: AR_M_REGNO_P (REGNO) ? AR_M_REGS \
@@ -998,6 +838,7 @@ enum reg_class
: (CHAR) == 'c' ? PR_REGS \
: (CHAR) == 'd' ? AR_M_REGS \
: (CHAR) == 'e' ? AR_I_REGS \
+ : (CHAR) == 'x' ? FP_REGS \
: NO_REGS)
/* A C expression which is nonzero if register number NUM is suitable for use
@@ -1017,18 +858,8 @@ enum reg_class
The value is a register class; perhaps CLASS, or perhaps another, smaller
class. */
-/* Don't allow volatile mem reloads into floating point registers. This
- is defined to force reload to choose the r/m case instead of the f/f case
- when reloading (set (reg fX) (mem/v)).
-
- Do not reload expressions into AR regs. */
-
#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- (CLASS == FR_REGS && GET_CODE (X) == MEM && MEM_VOLATILE_P (X) ? NO_REGS \
- : CLASS == FR_REGS && GET_CODE (X) == CONST_DOUBLE ? NO_REGS \
- : GET_RTX_CLASS (GET_CODE (X)) != 'o' \
- && (CLASS == AR_M_REGS || CLASS == AR_I_REGS) ? NO_REGS \
- : CLASS)
+ ia64_preferred_reload_class (X, CLASS)
/* You should define this macro to indicate to the reload phase that it may
need to allocate at least one register for a reload in addition to the
@@ -1053,8 +884,9 @@ enum reg_class
with unions should be solved with the addressof fiddling done by
movxf and friends. */
#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
- ((MODE) == XFmode && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
- || ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
+ (((MODE) == XFmode || (MODE) == XCmode) \
+ && (((CLASS1) == GR_REGS && (CLASS2) == FR_REGS) \
+ || ((CLASS1) == FR_REGS && (CLASS2) == GR_REGS)))
#endif
/* A C expression for the maximum number of consecutive registers of
@@ -1063,14 +895,15 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
((MODE) == BImode && (CLASS) == PR_REGS ? 2 \
- : ((CLASS) == FR_REGS && (MODE) == XFmode) ? 1 \
+ : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XFmode) ? 1 \
+ : (((CLASS) == FR_REGS || (CLASS) == FP_REGS) && (MODE) == XCmode) ? 2 \
: (GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
-/* In FP regs, we can't change FP values to integer values and vice
- versa, but we can change e.g. DImode to SImode. */
+/* In FP regs, we can't change FP values to integer values and vice versa,
+ but we can change e.g. DImode to SImode, and V2SFmode into DImode. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_CLASS (FROM) != GET_MODE_CLASS (TO) \
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (SCALAR_FLOAT_MODE_P (FROM) != SCALAR_FLOAT_MODE_P (TO) \
? reg_classes_intersect_p (CLASS, FR_REGS) : 0)
/* A C expression that defines the machine-dependent operand constraint
@@ -1097,15 +930,7 @@ enum reg_class
#define CONST_OK_FOR_P(VALUE) ((VALUE) == 0 || (VALUE) == -1)
#define CONST_OK_FOR_LETTER_P(VALUE, C) \
-((C) == 'I' ? CONST_OK_FOR_I (VALUE) \
- : (C) == 'J' ? CONST_OK_FOR_J (VALUE) \
- : (C) == 'K' ? CONST_OK_FOR_K (VALUE) \
- : (C) == 'L' ? CONST_OK_FOR_L (VALUE) \
- : (C) == 'M' ? CONST_OK_FOR_M (VALUE) \
- : (C) == 'N' ? CONST_OK_FOR_N (VALUE) \
- : (C) == 'O' ? CONST_OK_FOR_O (VALUE) \
- : (C) == 'P' ? CONST_OK_FOR_P (VALUE) \
- : 0)
+ ia64_const_ok_for_letter_p (VALUE, C)
/* A C expression that defines the machine-dependent operand constraint letters
(`G', `H') that specify particular ranges of `const_double' values. */
@@ -1116,33 +941,21 @@ enum reg_class
|| (VALUE) == CONST1_RTX (GET_MODE (VALUE)))
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? CONST_DOUBLE_OK_FOR_G (VALUE) : 0)
+ ia64_const_double_ok_for_letter_p (VALUE, C)
/* A C expression that defines the optional machine-dependent constraint
letters (`Q', `R', `S', `T', `U') that can be used to segregate specific
types of operands, usually memory references, for the target machine. */
-/* Non-volatile memory for FP_REG loads/stores. */
-#define CONSTRAINT_OK_FOR_Q(VALUE) \
- (memory_operand((VALUE), VOIDmode) && ! MEM_VOLATILE_P (VALUE))
-/* 1..4 for shladd arguments. */
-#define CONSTRAINT_OK_FOR_R(VALUE) \
- (GET_CODE (VALUE) == CONST_INT && INTVAL (VALUE) >= 1 && INTVAL (VALUE) <= 4)
-/* Non-post-inc memory for asms and other unsavory creatures. */
-#define CONSTRAINT_OK_FOR_S(VALUE) \
- (GET_CODE (VALUE) == MEM \
- && GET_RTX_CLASS (GET_CODE (XEXP ((VALUE), 0))) != 'a' \
- && (reload_in_progress || memory_operand ((VALUE), VOIDmode)))
-/* Symbol ref to small-address-area: */
-#define CONSTRAINT_OK_FOR_T(VALUE) \
- (GET_CODE (VALUE) == SYMBOL_REF && SYMBOL_REF_SMALL_ADDR_P (VALUE))
-
#define EXTRA_CONSTRAINT(VALUE, C) \
- ((C) == 'Q' ? CONSTRAINT_OK_FOR_Q (VALUE) \
- : (C) == 'R' ? CONSTRAINT_OK_FOR_R (VALUE) \
- : (C) == 'S' ? CONSTRAINT_OK_FOR_S (VALUE) \
- : (C) == 'T' ? CONSTRAINT_OK_FOR_T (VALUE) \
- : 0)
+ ia64_extra_constraint (VALUE, C)
+
+/* Document the constraints that can accept reloaded memory operands. This is
+ needed by the extended asm support, and by reload. 'Q' accepts mem, but
+ only non-volatile mem. Since we can't reload a volatile mem into a
+ non-volatile mem, it can not be listed here. */
+
+#define EXTRA_MEMORY_CONSTRAINT(C, STR) ((C) == 'S')
/* Basic Stack Layout */
@@ -1150,9 +963,9 @@ enum reg_class
to a smaller address. */
#define STACK_GROWS_DOWNWARD 1
-/* Define this macro if the addresses of local variable slots are at negative
- offsets from the frame pointer. */
-/* #define FRAME_GROWS_DOWNWARD */
+/* Define this macro to nonzero if the addresses of local variable slots
+ are at negative offsets from the frame pointer. */
+#define FRAME_GROWS_DOWNWARD 0
/* Offset from the frame pointer to the first local variable slot to
be allocated. */
@@ -1203,7 +1016,12 @@ enum reg_class
beginning of any function, before the prologue. The top of the frame is
defined to be the value of the stack pointer in the previous frame, just
before the call instruction. */
-#define INCOMING_FRAME_SP_OFFSET 0
+/* The CFA is past the red zone, not at the entry-point stack
+ pointer. */
+#define INCOMING_FRAME_SP_OFFSET STACK_POINTER_OFFSET
+
+/* We shorten debug info by using CFA-16 as DW_AT_frame_base. */
+#define CFA_FRAME_BASE_OFFSET(FUNDECL) (-INCOMING_FRAME_SP_OFFSET)
/* Register That Address the Stack Frame. */
@@ -1279,13 +1097,6 @@ enum reg_class
/* Passing Function Arguments on the Stack */
-/* Define this macro if an argument declared in a prototype as an integral type
- smaller than `int' should actually be passed as an `int'. In addition to
- avoiding errors in certain cases of mismatch, it also makes for better code
- on certain machines. */
-/* ??? Investigate. */
-/* #define PROMOTE_PROTOTYPES */
-
/* If defined, the maximum amount of space required for outgoing arguments will
be computed and placed into the variable
`current_function_outgoing_args_size'. */
@@ -1324,29 +1135,6 @@ enum reg_class
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
ia64_function_arg (&CUM, MODE, TYPE, NAMED, 1)
-/* A C expression for the number of words, at the beginning of an argument,
- must be put in registers. The value must be zero for arguments that are
- passed entirely in registers or that are entirely pushed on the stack. */
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
-
-/* A C expression that indicates when an argument must be passed by reference.
- If nonzero for an argument, a copy of that argument is made in memory and a
- pointer to the argument is passed instead of the argument itself. The
- pointer is passed in whatever way is appropriate for passing a pointer to
- that type. */
-
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- ia64_function_arg_pass_by_reference (&CUM, MODE, TYPE, NAMED)
-
-/* Nonzero if we do not know how to pass TYPE solely in registers. */
-
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE)))
-
/* A C type for declaring a variable that is used as the first argument of
`FUNCTION_ARG' and other related values. For some target machines, the type
`int' suffices and can hold the number of bytes of argument so far. */
@@ -1395,15 +1183,11 @@ do { \
/* If defined, a C expression that gives the alignment boundary, in bits, of an
argument with the specified mode and type. */
-/* Arguments with alignment larger than 8 bytes start at the next even
- boundary. See ia64_function_arg. */
+/* Return the alignment boundary in bits for an argument with a specified
+ mode and type. */
#define FUNCTION_ARG_BOUNDARY(MODE, TYPE) \
- (((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)
+ ia64_function_arg_boundary (MODE, TYPE)
/* A C expression that is nonzero if REGNO is the number of a hard register in
which function arguments are sometimes passed. This does *not* include
@@ -1414,10 +1198,6 @@ do { \
(((REGNO) >= AR_ARG_FIRST && (REGNO) < (AR_ARG_FIRST + MAX_ARGUMENT_SLOTS)) \
|| ((REGNO) >= FR_ARG_FIRST && (REGNO) < (FR_ARG_FIRST + MAX_ARGUMENT_SLOTS)))
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- ia64_va_arg (valist, type)
-
/* How Scalar Function Values are Returned */
/* A C expression to create an RTX representing the place where a function
@@ -1446,15 +1226,6 @@ do { \
/* How Large Values are Returned */
-/* A nonzero value says to return the function value in memory, just as large
- structures are always returned. */
-
-#define RETURN_IN_MEMORY(TYPE) \
- ia64_return_in_memory (TYPE)
-
-/* If you define this macro to be 0, then the conventions used for structure
- and union return values are decided by the `RETURN_IN_MEMORY' macro. */
-
#define DEFAULT_PCC_STRUCT_RETURN 0
@@ -1499,6 +1270,7 @@ do { \
fputs ("\tdata8.ua @iplt(", FILE); \
else \
fputs ("\tdata16.ua @iplt(", FILE); \
+ mark_decl_referenced (DECL); \
assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0)); \
fputs (")\n", FILE); \
if (TARGET_ILP32) \
@@ -1512,39 +1284,11 @@ do { \
call the profiling subroutine `mcount'. */
#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(FILE, LABELNO) \
-do { \
- char buf[20]; \
- ASM_GENERATE_INTERNAL_LABEL (buf, "LP", LABELNO); \
- fputs ("\talloc out0 = ar.pfs, 8, 0, 4, 0\n", FILE); \
- if (TARGET_AUTO_PIC) \
- fputs ("\tmovl out3 = @gprel(", FILE); \
- else \
- fputs ("\taddl out3 = @ltoff(", FILE); \
- assemble_name (FILE, buf); \
- if (TARGET_AUTO_PIC) \
- fputs (");;\n", FILE); \
- else \
- fputs ("), r1;;\n", FILE); \
- fputs ("\tmov out1 = r1\n", FILE); \
- fputs ("\tmov out2 = b0\n", FILE); \
- fputs ("\tbr.call.sptk.many b0 = _mcount;;\n", FILE); \
-} while (0)
-
-/* Implementing the Varargs Macros. */
-
-/* Define this macro to store the anonymous register arguments into the stack
- so that all the arguments appear to have been passed consecutively on the
- stack. */
-
-#define SETUP_INCOMING_VARARGS(ARGS_SO_FAR, MODE, TYPE, PRETEND_ARGS_SIZE, SECOND_TIME) \
- ia64_setup_incoming_varargs (ARGS_SO_FAR, MODE, TYPE, & PRETEND_ARGS_SIZE, SECOND_TIME)
-
-/* Define this macro if the location where a function argument is passed
- depends on whether or not it is a named argument. */
-
-#define STRICT_ARGUMENT_NAMING 1
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+ ia64_output_function_profiler(FILE, LABELNO)
+/* Neither hpux nor linux use profile counters. */
+#define NO_PROFILE_COUNTERS 1
/* Trampolines for Nested Functions. */
@@ -1592,15 +1336,6 @@ do { \
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, STATIC_CHAIN) \
ia64_initialize_trampoline((ADDR), (FNADDR), (STATIC_CHAIN))
-/* Implicit Calls to Library Routines */
-
-/* Define this macro if GCC should generate calls to the System V (and ANSI
- C) library functions `memcpy' and `memset' rather than the BSD functions
- `bcopy' and `bzero'. */
-
-#define TARGET_MEM_FUNCTIONS
-
-
/* Addressing Modes */
/* Define this macro if the machine supports post-increment addressing. */
@@ -1666,13 +1401,6 @@ do { \
#define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
-/* A C compound statement that attempts to replace X with a valid memory
- address for an operand of mode MODE.
-
- This must be present, but there is nothing useful to be done here. */
-
-#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
-
/* A C statement or compound statement with a conditional `goto LABEL;'
executed if memory address X (an RTX) can have different meanings depending
on the machine mode of the memory reference it is used for or if the address
@@ -1685,10 +1413,7 @@ do { \
/* A C expression that is nonzero if X is a legitimate constant for an
immediate operand on the target machine. */
-#define LEGITIMATE_CONSTANT_P(X) \
- (GET_CODE (X) != CONST_DOUBLE || GET_MODE (X) == VOIDmode \
- || GET_MODE (X) == DImode || CONST_DOUBLE_OK_FOR_G (X)) \
-
+#define LEGITIMATE_CONSTANT_P(X) ia64_legitimate_constant_p (X)
/* Condition Code Status */
@@ -1708,7 +1433,7 @@ do { \
/* A C expression for the cost of moving data of mode M between a
register and memory. */
#define MEMORY_MOVE_COST(MODE,CLASS,IN) \
- ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS \
+ ((CLASS) == GENERAL_REGS || (CLASS) == FR_REGS || (CLASS) == FP_REGS \
|| (CLASS) == GR_AND_FR_REGS ? 4 : 10)
/* A C expression for the cost of a branch instruction. A value of 1 is the
@@ -2014,13 +1739,6 @@ do { \
{ "loc79", LOC_REG (79) }, \
}
-/* Emit a dtp-relative reference to a TLS variable. */
-
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- ia64_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
-
/* A C compound statement to output to stdio stream STREAM the assembler syntax
for an instruction operand X. X is an RTL expression. */
@@ -2066,11 +1784,6 @@ do { \
fprintf (STREAM, "\tdata8 @pcrel(.L%d)\n", VALUE); \
} while (0)
-/* This is how to output an element of a case-vector that is absolute.
- (Ia64 does not use such vectors, but we must define this macro anyway.) */
-
-#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) abort ()
-
/* Jump tables only need 8 byte alignment. */
#define ADDR_VEC_ALIGN(ADDR_VEC) 3
@@ -2159,6 +1872,12 @@ do { \
#define DWARF2_DEBUGGING_INFO 1
+/* We do not want call-frame info to be output, since debuggers are
+ supposed to use the target unwind info. Leave this undefined it
+ TARGET_UNWIND_INFO might ever be false. */
+
+#define DWARF2_FRAME_INFO 0
+
#define DWARF2_ASM_LINE_DEBUG_INFO (TARGET_DWARF2_ASM)
/* Use tags for debug info labels, so that they don't break instruction
@@ -2172,12 +1891,12 @@ do { \
/* Use section-relative relocations for debugging offsets. Unlike other
targets that fake this by putting the section VMA at 0, IA-64 has
proper relocations for them. */
-#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL) \
- do { \
- fputs (integer_asm_op (SIZE, FALSE), FILE); \
- fputs ("@secrel(", FILE); \
- assemble_name (FILE, LABEL); \
- fputc (')', FILE); \
+#define ASM_OUTPUT_DWARF_OFFSET(FILE, SIZE, LABEL, SECTION) \
+ do { \
+ fputs (integer_asm_op (SIZE, FALSE), FILE); \
+ fputs ("@secrel(", FILE); \
+ assemble_name (FILE, LABEL); \
+ fputc (')', FILE); \
} while (0)
/* Emit a PC-relative relocation. */
@@ -2206,58 +1925,6 @@ do { \
#define SYMBOL_REF_SMALL_ADDR_P(X) \
((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_SMALL_ADDR) != 0)
-/* Define this if you have defined special-purpose predicates in the file
- `MACHINE.c'. For each predicate, list all rtl codes that can be in
- expressions matched by the predicate. */
-
-#define PREDICATE_CODES \
-{ "call_operand", {SUBREG, REG, SYMBOL_REF}}, \
-{ "got_symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "sdata_symbolic_operand", {SYMBOL_REF, CONST}}, \
-{ "small_addr_symbolic_operand", {SYMBOL_REF}}, \
-{ "symbolic_operand", {SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "function_operand", {SYMBOL_REF}}, \
-{ "setjmp_operand", {SYMBOL_REF}}, \
-{ "destination_operand", {SUBREG, REG, MEM}}, \
-{ "not_postinc_memory_operand", {MEM}}, \
-{ "move_operand", {SUBREG, REG, MEM, CONST_INT, CONST_DOUBLE, \
- CONSTANT_P_RTX, SYMBOL_REF, CONST, LABEL_REF}}, \
-{ "gr_register_operand", {SUBREG, REG}}, \
-{ "fr_register_operand", {SUBREG, REG}}, \
-{ "grfr_register_operand", {SUBREG, REG}}, \
-{ "gr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "fr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "grfr_nonimmediate_operand", {SUBREG, REG, MEM}}, \
-{ "gr_reg_or_0_operand", {SUBREG, REG, CONST_INT}}, \
-{ "gr_reg_or_5bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_6bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "grfr_reg_or_8bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_adjusted_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "gr_reg_or_8bit_and_adjusted_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "gr_reg_or_14bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "gr_reg_or_22bit_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "shift_count_operand", {SUBREG, REG, CONST_INT, CONSTANT_P_RTX}}, \
-{ "shift_32bit_count_operand", {SUBREG, REG, CONST_INT, \
- CONSTANT_P_RTX}}, \
-{ "shladd_operand", {CONST_INT}}, \
-{ "fetchadd_operand", {CONST_INT}}, \
-{ "fr_reg_or_fp01_operand", {SUBREG, REG, CONST_DOUBLE}}, \
-{ "normal_comparison_operator", {EQ, NE, GT, LE, GTU, LEU}}, \
-{ "adjusted_comparison_operator", {LT, GE, LTU, GEU}}, \
-{ "signed_inequality_operator", {GE, GT, LE, LT}}, \
-{ "predicate_operator", {NE, EQ}}, \
-{ "condop_operator", {PLUS, MINUS, IOR, XOR, AND}}, \
-{ "ar_lc_reg_operand", {REG}}, \
-{ "ar_ccv_reg_operand", {REG}}, \
-{ "ar_pfs_reg_operand", {REG}}, \
-{ "general_xfmode_operand", {SUBREG, REG, CONST_DOUBLE, MEM}}, \
-{ "destination_xfmode_operand", {SUBREG, REG, MEM}}, \
-{ "xfreg_or_fp01_operand", {REG, CONST_DOUBLE}}, \
-{ "basereg_operand", {SUBREG, REG}},
-
/* An alias for a machine mode name. This is the machine mode that elements of
a jump-table should have. */
@@ -2336,8 +2003,9 @@ do { \
extern int ia64_final_schedule;
-#define IA64_UNWIND_INFO 1
-#define IA64_UNWIND_EMIT(f,i) process_for_unwind_directive (f,i)
+#define TARGET_UNWIND_INFO 1
+
+#define TARGET_UNWIND_TABLES_DEFAULT true
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 15 : INVALID_REGNUM)
@@ -2355,66 +2023,9 @@ struct machine_function GTY(())
/* The number of varargs registers to save. */
int n_varargs;
-};
-
-
-enum ia64_builtins
-{
- IA64_BUILTIN_SYNCHRONIZE,
-
- IA64_BUILTIN_FETCH_AND_ADD_SI,
- IA64_BUILTIN_FETCH_AND_SUB_SI,
- IA64_BUILTIN_FETCH_AND_OR_SI,
- IA64_BUILTIN_FETCH_AND_AND_SI,
- IA64_BUILTIN_FETCH_AND_XOR_SI,
- IA64_BUILTIN_FETCH_AND_NAND_SI,
-
- IA64_BUILTIN_ADD_AND_FETCH_SI,
- IA64_BUILTIN_SUB_AND_FETCH_SI,
- IA64_BUILTIN_OR_AND_FETCH_SI,
- IA64_BUILTIN_AND_AND_FETCH_SI,
- IA64_BUILTIN_XOR_AND_FETCH_SI,
- IA64_BUILTIN_NAND_AND_FETCH_SI,
-
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_SI,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_SI,
-
- IA64_BUILTIN_SYNCHRONIZE_SI,
-
- IA64_BUILTIN_LOCK_TEST_AND_SET_SI,
-
- IA64_BUILTIN_LOCK_RELEASE_SI,
-
- IA64_BUILTIN_FETCH_AND_ADD_DI,
- IA64_BUILTIN_FETCH_AND_SUB_DI,
- IA64_BUILTIN_FETCH_AND_OR_DI,
- IA64_BUILTIN_FETCH_AND_AND_DI,
- IA64_BUILTIN_FETCH_AND_XOR_DI,
- IA64_BUILTIN_FETCH_AND_NAND_DI,
- IA64_BUILTIN_ADD_AND_FETCH_DI,
- IA64_BUILTIN_SUB_AND_FETCH_DI,
- IA64_BUILTIN_OR_AND_FETCH_DI,
- IA64_BUILTIN_AND_AND_FETCH_DI,
- IA64_BUILTIN_XOR_AND_FETCH_DI,
- IA64_BUILTIN_NAND_AND_FETCH_DI,
-
- IA64_BUILTIN_BOOL_COMPARE_AND_SWAP_DI,
- IA64_BUILTIN_VAL_COMPARE_AND_SWAP_DI,
-
- IA64_BUILTIN_SYNCHRONIZE_DI,
-
- IA64_BUILTIN_LOCK_TEST_AND_SET_DI,
-
- IA64_BUILTIN_LOCK_RELEASE_DI,
-
- IA64_BUILTIN_BSP,
- IA64_BUILTIN_FLUSHRS
-};
-
-/* Codes for expand_compare_and_swap and expand_swap_and_compare. */
-enum fetchop_code {
- IA64_ADD_OP, IA64_SUB_OP, IA64_OR_OP, IA64_AND_OP, IA64_XOR_OP, IA64_NAND_OP
+ /* The number of the next unwind state to copy. */
+ int state_num;
};
#define DONT_USE_BUILTIN_SETJMP
@@ -2424,9 +2035,16 @@ enum fetchop_code {
#undef PROFILE_BEFORE_PROLOGUE
#define PROFILE_BEFORE_PROLOGUE 1
+/* Initialize library function table. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ia64_init_libfuncs
/* Switch on code for querying unit reservations. */
#define CPU_UNITS_QUERY 1
+/* Define this to change the optimizations performed by default. */
+#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
+ ia64_optimization_options ((LEVEL), (SIZE))
+
/* End of ia64.h */
diff --git a/contrib/gcc/config/ia64/ia64.md b/contrib/gcc/config/ia64/ia64.md
index 4bda8f4..e573c55 100644
--- a/contrib/gcc/config/ia64/ia64.md
+++ b/contrib/gcc/config/ia64/ia64.md
@@ -1,5 +1,5 @@
;; IA-64 Machine description template
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
;; Free Software Foundation, Inc.
;; Contributed by James E. Wilson <wilson@cygnus.com> and
;; David Mosberger <davidm@hpl.hp.com>.
@@ -18,8 +18,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
@@ -56,6 +56,7 @@
(UNSPEC_DTPREL 2)
(UNSPEC_LTOFF_TPREL 3)
(UNSPEC_TPREL 4)
+ (UNSPEC_DTPMOD 5)
(UNSPEC_LD_BASE 9)
(UNSPEC_GR_SPILL 10)
@@ -77,6 +78,15 @@
(UNSPEC_RET_ADDR 26)
(UNSPEC_SETF_EXP 27)
(UNSPEC_FR_SQRT_RECIP_APPROX 28)
+ (UNSPEC_SHRP 29)
+ (UNSPEC_COPYSIGN 30)
+ (UNSPEC_VECT_EXTR 31)
+ (UNSPEC_LDA 40)
+ (UNSPEC_LDS 41)
+ (UNSPEC_LDSA 42)
+ (UNSPEC_LDCCLR 43)
+ (UNSPEC_CHKACLR 45)
+ (UNSPEC_CHKS 47)
])
(define_constants
@@ -89,6 +99,8 @@
(UNSPECV_PSAC_NORMAL 6)
(UNSPECV_SETJMP_RECEIVER 7)
])
+
+(include "predicates.md")
;; ::::::::::::::::::::
;; ::
@@ -117,19 +129,21 @@
;; which emit instruction that can go in any slot (e.g. nop).
(define_attr "itanium_class" "unknown,ignore,stop_bit,br,fcmp,fcvtfx,fld,
- fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,ld,
- chk_s,long_i,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,st,syst_m0,
- syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop,nop_b,nop_f,
- nop_i,nop_m,nop_x,lfetch,pre_cycle"
+ fldp,fmac,fmisc,frar_i,frar_m,frbr,frfr,frpr,ialu,icmp,ilog,ishf,
+ ld,chk_s_i,chk_s_f,chk_a,long_i,mmalua,mmmul,mmshf,mmshfi,rse_m,scall,sem,stf,
+ st,syst_m0, syst_m,tbit,toar_i,toar_m,tobr,tofr,topr,xmpy,xtd,nop,
+ nop_b,nop_f,nop_i,nop_m,nop_x,lfetch,pre_cycle"
(const_string "unknown"))
-;; chk_s has an I and an M form; use type A for convenience.
+;; chk_s_i has an I and an M form; use type A for convenience.
(define_attr "type" "unknown,A,I,M,F,B,L,X,S"
- (cond [(eq_attr "itanium_class" "ld,st,fld,stf,sem,nop_m") (const_string "M")
+ (cond [(eq_attr "itanium_class" "ld,st,fld,fldp,stf,sem,nop_m") (const_string "M")
(eq_attr "itanium_class" "rse_m,syst_m,syst_m0") (const_string "M")
(eq_attr "itanium_class" "frar_m,toar_m,frfr,tofr") (const_string "M")
(eq_attr "itanium_class" "lfetch") (const_string "M")
- (eq_attr "itanium_class" "chk_s,ialu,icmp,ilog") (const_string "A")
+ (eq_attr "itanium_class" "chk_s_f,chk_a") (const_string "M")
+ (eq_attr "itanium_class" "chk_s_i,ialu,icmp,ilog,mmalua")
+ (const_string "A")
(eq_attr "itanium_class" "fmisc,fmac,fcmp,xmpy") (const_string "F")
(eq_attr "itanium_class" "fcvtfx,nop_f") (const_string "F")
(eq_attr "itanium_class" "frar_i,toar_i,frbr,tobr") (const_string "I")
@@ -158,8 +172,18 @@
(define_attr "empty" "no,yes" (const_string "no"))
-
+;; True iff this insn must be the first insn of an instruction group.
+;; This is true for the alloc instruction, and will also be true of others
+;; when we have full intrinsics support.
+
+(define_attr "first_insn" "no,yes" (const_string "no"))
+
+(define_attr "data_speculative" "no,yes" (const_string "no"))
+(define_attr "control_speculative" "no,yes" (const_string "no"))
+
+(define_attr "check_load" "no,yes" (const_string "no"))
+
;; DFA descriptions of ia64 processors used for insn scheduling and
;; bundling.
@@ -170,9 +194,6 @@
(automata_option "w")
-;;(automata_option "no-minimization")
-
-
(include "itanium1.md")
(include "itanium2.md")
@@ -198,8 +219,8 @@
(set_attr "predicable" "no")])
(define_insn "movbi"
- [(set (match_operand:BI 0 "nonimmediate_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
- (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))]
+ [(set (match_operand:BI 0 "destination_operand" "=c,c,?c,?*r, c,*r,*r,*m,*r")
+ (match_operand:BI 1 "move_operand" " O,n, c, c,*r, n,*m,*r,*r"))]
""
"@
cmp.ne %0, %I0 = r0, r0
@@ -357,65 +378,252 @@
"mov pr = %1, -1"
};
- if (which_alternative == 2 && ! TARGET_NO_PIC
- && symbolic_operand (operands[1], VOIDmode))
- abort ();
+ gcc_assert (which_alternative != 2 || TARGET_NO_PIC
+ || !symbolic_operand (operands[1], VOIDmode));
return alt[which_alternative];
}
[(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,frfr,tofr,fmisc,fld,stf,frbr,tobr,frar_i,toar_i,frar_m,toar_m,frpr,topr")])
+(define_mode_macro MODE [BI QI HI SI DI SF DF XF TI])
+(define_mode_macro MODE_FOR_EXTEND [QI HI SI])
+
+(define_mode_attr output_a [
+ (BI "ld1.a %0 = %1%P1")
+ (QI "ld1.a %0 = %1%P1")
+ (HI "ld2.a %0 = %1%P1")
+ (SI "ld4.a %0 = %1%P1")
+ (DI
+ "@
+ ld8.a %0 = %1%P1
+ ldf8.a %0 = %1%P1")
+ (SF
+ "@
+ ldfs.a %0 = %1%P1
+ ld4.a %0 = %1%P1")
+ (DF
+ "@
+ ldfd.a %0 = %1%P1
+ ld8.a %0 = %1%P1")
+ (XF "ldfe.a %0 = %1%P1")
+ (TI "ldfp8.a %X0 = %1%P1")])
+
+(define_mode_attr output_s [
+ (BI "ld1.s %0 = %1%P1")
+ (QI "ld1.s %0 = %1%P1")
+ (HI "ld2.s %0 = %1%P1")
+ (SI "ld4.s %0 = %1%P1")
+ (DI
+ "@
+ ld8.s %0 = %1%P1
+ ldf8.s %0 = %1%P1")
+ (SF
+ "@
+ ldfs.s %0 = %1%P1
+ ld4.s %0 = %1%P1")
+ (DF
+ "@
+ ldfd.s %0 = %1%P1
+ ld8.s %0 = %1%P1")
+ (XF "ldfe.s %0 = %1%P1")
+ (TI "ldfp8.s %X0 = %1%P1")])
+
+(define_mode_attr output_sa [
+ (BI "ld1.sa %0 = %1%P1")
+ (QI "ld1.sa %0 = %1%P1")
+ (HI "ld2.sa %0 = %1%P1")
+ (SI "ld4.sa %0 = %1%P1")
+ (DI
+ "@
+ ld8.sa %0 = %1%P1
+ ldf8.sa %0 = %1%P1")
+ (SF
+ "@
+ ldfs.sa %0 = %1%P1
+ ld4.sa %0 = %1%P1")
+ (DF
+ "@
+ ldfd.sa %0 = %1%P1
+ ld8.sa %0 = %1%P1")
+ (XF "ldfe.sa %0 = %1%P1")
+ (TI "ldfp8.sa %X0 = %1%P1")])
+
+(define_mode_attr output_c_clr [
+ (BI "ld1.c.clr%O1 %0 = %1%P1")
+ (QI "ld1.c.clr%O1 %0 = %1%P1")
+ (HI "ld2.c.clr%O1 %0 = %1%P1")
+ (SI "ld4.c.clr%O1 %0 = %1%P1")
+ (DI
+ "@
+ ld8.c.clr%O1 %0 = %1%P1
+ ldf8.c.clr %0 = %1%P1")
+ (SF
+ "@
+ ldfs.c.clr %0 = %1%P1
+ ld4.c.clr%O1 %0 = %1%P1")
+ (DF
+ "@
+ ldfd.c.clr %0 = %1%P1
+ ld8.c.clr%O1 %0 = %1%P1")
+ (XF "ldfe.c.clr %0 = %1%P1")
+ (TI "ldfp8.c.clr %X0 = %1%P1")])
+
+(define_mode_attr ld_reg_constr [(BI "=*r") (QI "=r") (HI "=r") (SI "=r") (DI "=r,*f") (SF "=f,*r") (DF "=f,*r") (XF "=f") (TI "=*x")])
+(define_mode_attr ldc_reg_constr [(BI "+*r") (QI "+r") (HI "+r") (SI "+r") (DI "+r,*f") (SF "+f,*r") (DF "+f,*r") (XF "+f") (TI "+*x")])
+(define_mode_attr chk_reg_constr [(BI "*r") (QI "r") (HI "r") (SI "r") (DI "r,*f") (SF "f,*r") (DF "f,*r") (XF "f") (TI "*x")])
+
+(define_mode_attr mem_constr [(BI "*m") (QI "m") (HI "m") (SI "m") (DI "m,Q") (SF "Q,m") (DF "Q,m") (XF "m") (TI "Q")])
+
+;; Define register predicate prefix.
+;; We can generate speculative loads only for general and fp registers - this
+;; is constrainted in ia64.c: ia64_speculate_insn ().
+(define_mode_attr reg_pred_prefix [(BI "gr") (QI "gr") (HI "gr") (SI "gr") (DI "grfr") (SF "grfr") (DF "grfr") (XF "fr") (TI "fr")])
+
+(define_mode_attr ld_class [(BI "ld") (QI "ld") (HI "ld") (SI "ld") (DI "ld,fld") (SF "fld,ld") (DF "fld,ld") (XF "fld") (TI "fldp")])
+(define_mode_attr chka_class [(BI "chk_a") (QI "chk_a") (HI "chk_a") (SI "chk_a") (DI "chk_a,chk_a") (SF "chk_a,chk_a") (DF "chk_a,chk_a") (XF "chk_a") (TI "chk_a")])
+(define_mode_attr chks_class [(BI "chk_s_i") (QI "chk_s_i") (HI "chk_s_i") (SI "chk_s_i") (DI "chk_s_i,chk_s_f") (SF "chk_s_f,chk_s_i") (DF "chk_s_f,chk_s_i") (XF "chk_s_f") (TI "chk_s_i")])
+
+(define_mode_attr attr_yes [(BI "yes") (QI "yes") (HI "yes") (SI "yes") (DI "yes,yes") (SF "yes,yes") (DF "yes,yes") (XF "yes") (TI "yes")])
+
+(define_insn "mov<mode>_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDA)))]
+ ""
+ "<output_a>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDS)))]
+ ""
+ "<output_s>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_speculative_advanced"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ld_reg_constr>")
+ (unspec:MODE [(match_operand:MODE 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_speculative_advanced"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI (unspec:MODE_FOR_EXTEND [(match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>")] UNSPEC_LDSA)))]
+ ""
+ "<output_sa>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "data_speculative" "<attr_yes>")
+ (set_attr "control_speculative" "<attr_yes>")])
+
+(define_insn "mov<mode>_clr"
+ [(set (match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<ldc_reg_constr>")
+ (if_then_else:MODE (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (match_operand:MODE 1 "memory_operand" "<mem_constr>")
+ (match_dup 0)))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "zero_extend<mode>di2_clr"
+ [(set (match_operand:DI 0 "gr_register_operand" "+r")
+ (if_then_else:DI (ne (unspec [(match_dup 0)] UNSPEC_LDCCLR) (const_int 0))
+ (zero_extend:DI (match_operand:MODE_FOR_EXTEND 1 "memory_operand" "<mem_constr>"))
+ (match_dup 0)))]
+ ""
+ "<output_c_clr>"
+ [(set_attr "itanium_class" "<ld_class>")
+ (set_attr "check_load" "<attr_yes>")])
+
+(define_insn "advanced_load_check_clr_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKACLR) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.a.clr %0, %l1"
+ [(set_attr "itanium_class" "<chka_class>")])
+
+(define_insn "speculation_check_<mode>"
+ [(set (pc)
+ (if_then_else (ne (unspec [(match_operand:MODE 0 "<reg_pred_prefix>_register_operand" "<chk_reg_constr>")] UNSPEC_CHKS) (const_int 0))
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ ""
+ "chk.s %0, %l1"
+ [(set_attr "itanium_class" "<chks_class>")])
+
(define_split
[(set (match_operand 0 "register_operand" "")
(match_operand 1 "symbolic_operand" ""))]
- "reload_completed && ! TARGET_NO_PIC"
+ "reload_completed"
[(const_int 0)]
{
- ia64_expand_load_address (operands[0], operands[1]);
- DONE;
+ if (ia64_expand_load_address (operands[0], operands[1]))
+ DONE;
+ else
+ FAIL;
})
(define_expand "load_fptr"
- [(set (match_dup 2)
- (plus:DI (reg:DI 1) (match_operand 1 "function_operand" "")))
- (set (match_operand:DI 0 "register_operand" "") (match_dup 3))]
- ""
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_dup 2) (match_operand 1 "function_operand" "")))
+ (set (match_dup 0) (match_dup 3))]
+ "reload_completed"
{
- operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
- operands[3] = gen_rtx_MEM (DImode, operands[2]);
- RTX_UNCHANGING_P (operands[3]) = 1;
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
})
(define_insn "*load_fptr_internal1"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1) (match_operand 1 "function_operand" "s")))]
- ""
+ "reload_completed"
"addl %0 = @ltoff(@fptr(%1)), gp"
[(set_attr "itanium_class" "ialu")])
(define_insn "load_gprel"
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (reg:DI 1) (match_operand 1 "sdata_symbolic_operand" "s")))]
- ""
+ "reload_completed"
"addl %0 = @gprel(%1), gp"
[(set_attr "itanium_class" "ialu")])
-(define_insn "gprel64_offset"
+(define_insn "*gprel64_offset"
[(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_operand:DI 1 "symbolic_operand" "") (reg:DI 1)))]
- ""
+ "reload_completed"
"movl %0 = @gprel(%1)"
[(set_attr "itanium_class" "long_i")])
(define_expand "load_gprel64"
- [(set (match_dup 2)
- (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 3)))
- (set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_dup 3) (match_dup 2)))]
- ""
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "symbolic_operand" "") (match_dup 2)))
+ (set (match_dup 0)
+ (plus:DI (match_dup 2) (match_dup 0)))]
+ "reload_completed"
{
- operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (DImode);
- operands[3] = pic_offset_table_rtx;
+ operands[2] = pic_offset_table_rtx;
})
;; This is used as a placeholder for the return address during early
@@ -441,7 +649,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (high:DI (match_operand 1 "got_symbolic_operand" "s"))
(match_operand:DI 2 "register_operand" "a")))]
- ""
+ "reload_completed"
{
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
return "%,addl %0 = @ltoffx(%1), %2";
@@ -454,7 +662,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(lo_sum:DI (match_operand:DI 1 "register_operand" "r")
(match_operand 2 "got_symbolic_operand" "s")))]
- ""
+ "reload_completed"
{
if (HAVE_AS_LTOFFX_LDXMOV_RELOCS)
return "%,ld8.mov %0 = [%1], %2";
@@ -463,34 +671,41 @@
}
[(set_attr "itanium_class" "ld")])
-(define_insn "load_ltoff_dtpmod"
+(define_insn_and_split "load_dtpmod"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1)
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
- UNSPEC_LTOFF_DTPMOD)))]
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPMOD))]
""
- "addl %0 = @ltoff(@dtpmod(%1)), gp"
- [(set_attr "itanium_class" "ialu")])
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPMOD)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
-(define_insn "load_ltoff_dtprel"
+(define_insn "*load_ltoff_dtpmod"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1)
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
- UNSPEC_LTOFF_DTPREL)))]
- ""
- "addl %0 = @ltoff(@dtprel(%1)), gp"
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPMOD)
+ (match_operand:DI 2 "register_operand" "a")))]
+ "reload_completed"
+ "addl %0 = @ltoff(@dtpmod(%1)), %2"
[(set_attr "itanium_class" "ialu")])
(define_expand "load_dtprel"
[(set (match_operand:DI 0 "register_operand" "")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
""
"")
(define_insn "*load_dtprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
"TARGET_TLS64"
"movl %0 = @dtprel(%1)"
@@ -498,57 +713,73 @@
(define_insn "*load_dtprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
UNSPEC_DTPREL))]
""
"addl %0 = @dtprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
+(define_insn_and_split "*load_dtprel_gd"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_DTPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_DTPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_dtprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@dtprel(%1)), %2"
+ [(set_attr "itanium_class" "ialu")])
+
(define_expand "add_dtprel"
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "register_operand" "")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_DTPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "")))]
"!TARGET_TLS64"
"")
(define_insn "*add_dtprel14"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_DTPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_TLS14"
- "adds %0 = @dtprel(%2), %1"
+ "adds %0 = @dtprel(%1), %2"
[(set_attr "itanium_class" "ialu")])
(define_insn "*add_dtprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "a")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_DTPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "ld_tls_symbolic_operand" "")]
+ UNSPEC_DTPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
"TARGET_TLS22"
- "addl %0 = @dtprel(%2), %1"
- [(set_attr "itanium_class" "ialu")])
-
-(define_insn "load_ltoff_tprel"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (reg:DI 1)
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
- UNSPEC_LTOFF_TPREL)))]
- ""
- "addl %0 = @ltoff(@tprel(%1)), gp"
+ "addl %0 = @dtprel(%1), %2"
[(set_attr "itanium_class" "ialu")])
(define_expand "load_tprel"
[(set (match_operand:DI 0 "register_operand" "")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "tls_symbolic_operand" "")]
UNSPEC_TPREL))]
""
"")
(define_insn "*load_tprel64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
UNSPEC_TPREL))]
"TARGET_TLS64"
"movl %0 = @tprel(%1)"
@@ -556,36 +787,61 @@
(define_insn "*load_tprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "symbolic_operand" "")]
+ (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
UNSPEC_TPREL))]
""
"addl %0 = @tprel(%1), r0"
[(set_attr "itanium_class" "ialu")])
+(define_insn_and_split "*load_tprel_ie"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_TPREL))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:DI (unspec:DI [(match_dup 1)] UNSPEC_LTOFF_TPREL)
+ (match_dup 2)))
+ (set (match_dup 0) (match_dup 3))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_const_mem (DImode, operands[0]);
+})
+
+(define_insn "*load_ltoff_tprel"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (unspec:DI [(match_operand 1 "ie_tls_symbolic_operand" "")]
+ UNSPEC_LTOFF_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
+ ""
+ "addl %0 = @ltoff(@tprel(%1)), %2"
+ [(set_attr "itanium_class" "ialu")])
+
(define_expand "add_tprel"
[(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "register_operand" "")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_TPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "")))]
"!TARGET_TLS64"
"")
(define_insn "*add_tprel14"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "r")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_TPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "r")))]
"TARGET_TLS14"
- "adds %0 = @tprel(%2), %1"
+ "adds %0 = @tprel(%1), %2"
[(set_attr "itanium_class" "ialu")])
(define_insn "*add_tprel22"
[(set (match_operand:DI 0 "register_operand" "=r")
- (plus:DI (match_operand:DI 1 "register_operand" "a")
- (unspec:DI [(match_operand:DI 2 "symbolic_operand" "")]
- UNSPEC_TPREL)))]
+ (plus:DI (unspec:DI [(match_operand 1 "le_tls_symbolic_operand" "")]
+ UNSPEC_TPREL)
+ (match_operand:DI 2 "register_operand" "a")))]
"TARGET_TLS22"
- "addl %0 = @tprel(%2), %1"
+ "addl %0 = @tprel(%1), %2"
[(set_attr "itanium_class" "ialu")])
;; With no offsettable memory references, we've got to have a scratch
@@ -604,18 +860,22 @@
})
(define_insn_and_split "*movti_internal"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,r,m")
- (match_operand:TI 1 "general_operand" "ri,m,r"))]
+ [(set (match_operand:TI 0 "destination_operand" "=r, *fm,*x,*f, Q")
+ (match_operand:TI 1 "general_operand" "r*fim,r, Q, *fOQ,*f"))]
"ia64_move_ok (operands[0], operands[1])"
- "#"
- "reload_completed"
+ "@
+ #
+ #
+ ldfp8 %X0 = %1%P1
+ #
+ #"
+ "reload_completed && !ia64_load_pair_ok(operands[0], operands[1])"
[(const_int 0)]
{
ia64_split_tmode_move (operands);
DONE;
}
- [(set_attr "itanium_class" "unknown")
- (set_attr "predicable" "no")])
+ [(set_attr "itanium_class" "unknown,unknown,fldp,unknown,unknown")])
;; Floating Point Moves
;;
@@ -681,72 +941,15 @@
(match_operand:XF 1 "general_operand" ""))]
""
{
- /* We must support XFmode loads into general registers for stdarg/vararg
- and unprototyped calls. We split them into DImode loads for convenience.
- We don't need XFmode stores from general regs, because a stdarg/vararg
- routine does a block store to memory of unnamed arguments. */
- if (GET_CODE (operands[0]) == REG
- && GR_REGNO_P (REGNO (operands[0])))
- {
- /* We're hoping to transform everything that deals with XFmode
- quantities and GR registers early in the compiler. */
- if (no_new_pseudos)
- abort ();
-
- /* Struct to register can just use TImode instead. */
- if ((GET_CODE (operands[1]) == SUBREG
- && GET_MODE (SUBREG_REG (operands[1])) == TImode)
- || (GET_CODE (operands[1]) == REG
- && GR_REGNO_P (REGNO (operands[1]))))
- {
- emit_move_insn (gen_rtx_REG (TImode, REGNO (operands[0])),
- SUBREG_REG (operands[1]));
- DONE;
- }
-
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0])),
- operand_subword (operands[1], 0, 0, XFmode));
- emit_move_insn (gen_rtx_REG (DImode, REGNO (operands[0]) + 1),
- operand_subword (operands[1], 1, 0, XFmode));
- DONE;
- }
-
- /* If the quantity is in a register not known to be GR, spill it. */
- if (register_operand (operands[1], XFmode))
- operands[1] = spill_xfmode_operand (operands[1], 1);
-
- if (GET_CODE (operands[1]) == MEM)
- {
- rtx out[2];
-
- out[WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0]));
- out[!WORDS_BIG_ENDIAN] = gen_rtx_REG (DImode, REGNO (operands[0])+1);
-
- emit_move_insn (out[0], adjust_address (operands[1], DImode, 0));
- emit_move_insn (out[1], adjust_address (operands[1], DImode, 8));
- DONE;
- }
-
- abort ();
- }
-
- if (! reload_in_progress && ! reload_completed)
- {
- operands[0] = spill_xfmode_operand (operands[0], 0);
- operands[1] = spill_xfmode_operand (operands[1], 0);
-
- if (! ia64_move_ok (operands[0], operands[1]))
- operands[1] = force_reg (XFmode, operands[1]);
- }
+ if (ia64_expand_movxf_movrf (XFmode, operands))
+ DONE;
})
;; ??? There's no easy way to mind volatile acquire/release semantics.
(define_insn "*movxf_internal"
- [(set (match_operand:XF 0 "destination_xfmode_operand" "=f,f, m")
- (match_operand:XF 1 "general_xfmode_operand" "fG,m,fG"))]
+ [(set (match_operand:XF 0 "destination_operand" "=f,f, m")
+ (match_operand:XF 1 "general_operand" "fG,m,fG"))]
"ia64_move_ok (operands[0], operands[1])"
"@
mov %0 = %F1
@@ -754,6 +957,26 @@
stfe %0 = %F1%P0"
[(set_attr "itanium_class" "fmisc,fld,stf")])
+;; Same as for movxf, but for RFmode.
+(define_expand "movrf"
+ [(set (match_operand:RF 0 "general_operand" "")
+ (match_operand:RF 1 "general_operand" ""))]
+ ""
+{
+ if (ia64_expand_movxf_movrf (RFmode, operands))
+ DONE;
+})
+
+(define_insn "*movrf_internal"
+ [(set (match_operand:RF 0 "destination_operand" "=f,f, m")
+ (match_operand:RF 1 "general_operand" "fG,m,fG"))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %F1
+ ldf.fill %0 = %1%P1
+ stf.spill %0 = %F1%P0"
+ [(set_attr "itanium_class" "fmisc,fld,stf")])
+
;; Better code generation via insns that deal with TFmode register pairs
;; directly. Same concerns apply as for TImode.
(define_expand "movtf"
@@ -768,7 +991,7 @@
})
(define_insn_and_split "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=r,r,m")
+ [(set (match_operand:TF 0 "destination_operand" "=r,r,m")
(match_operand:TF 1 "general_operand" "ri,m,r"))]
"ia64_move_ok (operands[0], operands[1])"
"#"
@@ -839,10 +1062,10 @@
(match_operand:SI 1 "grfr_nonimmediate_operand" "r,m,f")))]
""
"@
- zxt4 %0 = %1
+ addp4 %0 = %1, r0
ld4%O1 %0 = %1%P1
fmix.r %0 = f0, %1"
- [(set_attr "itanium_class" "xtd,ld,fmisc")])
+ [(set_attr "itanium_class" "ialu,ld,fmisc")])
;; Convert between floating point types of different sizes.
@@ -1001,8 +1224,8 @@
(define_insn "extv"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(sign_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "n")
- (match_operand:DI 3 "const_int_operand" "n")))]
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
""
"extr %0 = %1, %3, %2"
[(set_attr "itanium_class" "ishf")])
@@ -1010,8 +1233,8 @@
(define_insn "extzv"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
- (match_operand:DI 2 "const_int_operand" "n")
- (match_operand:DI 3 "const_int_operand" "n")))]
+ (match_operand:DI 2 "extr_len_operand" "n")
+ (match_operand:DI 3 "shift_count_operand" "M")))]
""
"extr.u %0 = %1, %3, %2"
[(set_attr "itanium_class" "ishf")])
@@ -1111,6 +1334,15 @@
[(set_attr "itanium_class" "ishf")])
;; Combine doesn't like to create bit-field insertions into zero.
+(define_insn "*shladdp4_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shladd_log2_operand" "n"))
+ (match_operand:DI 3 "const_int_operand" "n")))]
+ "ia64_depz_field_mask (operands[3], operands[2]) + INTVAL (operands[2]) == 32"
+ "shladdp4 %0 = %1, %2, r0"
+ [(set_attr "itanium_class" "ialu")])
+
(define_insn "*depz_internal"
[(set (match_operand:DI 0 "gr_register_operand" "=r")
(and:DI (ashift:DI (match_operand:DI 1 "gr_register_operand" "r")
@@ -1138,18 +1370,7 @@
(const_int 32) (const_int 0))
(match_operand:DI 1 "register_operand" ""))
(clobber (match_operand:DI 2 "register_operand" ""))]
- "reload_completed"
- [(set (match_dup 3) (ashift:DI (match_dup 1) (const_int 32)))
- (set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 0))
- (lshiftrt:DI (match_dup 3) (const_int 32)))]
- "operands[3] = operands[2];")
-
-(define_split
- [(set (zero_extract:DI (match_operand:DI 0 "register_operand" "")
- (const_int 32) (const_int 0))
- (match_operand:DI 1 "register_operand" ""))
- (clobber (match_operand:DI 2 "register_operand" ""))]
- "! reload_completed"
+ ""
[(set (match_dup 3) (ashift:DI (match_dup 1) (const_int 32)))
(set (zero_extract:DI (match_dup 0) (const_int 32) (const_int 0))
(lshiftrt:DI (match_dup 3) (const_int 32)))]
@@ -1409,7 +1630,7 @@
(and:BI (ne:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1421,7 +1642,7 @@
(and:BI (eq:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1533,7 +1754,7 @@
(ior:BI (ne:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1545,7 +1766,7 @@
(ior:BI (eq:BI (zero_extract:DI
(match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "const_int_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0))
(match_operand:BI 3 "register_operand" "0")))]
""
@@ -1855,8 +2076,7 @@
(match_operand:SI 2 "general_operand" "")))]
"TARGET_INLINE_INT_DIV"
{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
- REAL_VALUE_TYPE twon34_r;
+ rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1872,10 +2092,14 @@
expand_float (op2_xf, operands[2], 0);
/* 2^-34 */
- real_2expN (&twon34_r, -34);
- twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
- twon34 = force_reg (XFmode, twon34);
-
+ twon34_exp = gen_reg_rtx (DImode);
+ emit_move_insn (twon34_exp, GEN_INT (65501));
+ twon34 = gen_reg_rtx (XFmode);
+ emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
@@ -1912,8 +2136,7 @@
(match_operand:SI 2 "general_operand" "")))]
"TARGET_INLINE_INT_DIV"
{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34;
- REAL_VALUE_TYPE twon34_r;
+ rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
op0_xf = gen_reg_rtx (XFmode);
op0_di = gen_reg_rtx (DImode);
@@ -1929,10 +2152,14 @@
expand_float (op2_xf, operands[2], 1);
/* 2^-34 */
- real_2expN (&twon34_r, -34);
- twon34 = CONST_DOUBLE_FROM_REAL_VALUE (twon34_r, XFmode);
- twon34 = force_reg (XFmode, twon34);
-
+ twon34_exp = gen_reg_rtx (DImode);
+ emit_move_insn (twon34_exp, GEN_INT (65501));
+ twon34 = gen_reg_rtx (XFmode);
+ emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
@@ -1983,8 +2210,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
@@ -2124,9 +2351,6 @@
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
"")
-;; ??? There are highpart multiply and add instructions, but we have no way
-;; to generate them.
-
(define_insn "smuldi3_highpart"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
(truncate:DI
@@ -2294,7 +2518,10 @@
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 0);
- if (TARGET_INLINE_INT_DIV_LAT)
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
@@ -2340,7 +2567,10 @@
op2_xf = gen_reg_rtx (XFmode);
expand_float (op2_xf, operands[2], 1);
- if (TARGET_INLINE_INT_DIV_LAT)
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
else
emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
@@ -2374,7 +2604,7 @@
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_INT_DIV_LAT"
+ "TARGET_INLINE_INT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
@@ -2383,8 +2613,8 @@
(use (const_int 1))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
@@ -2414,8 +2644,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2433,7 +2663,7 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_INT_DIV_THR"
+ "TARGET_INLINE_INT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
@@ -2442,8 +2672,8 @@
(use (const_int 1))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2463,8 +2693,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -2477,6 +2707,200 @@
;; ::::::::::::::::::::
;; ::
+;; :: 128 bit Integer arithmetic
+;; ::
+;; ::::::::::::::::::::
+
+(define_insn "addti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (plus:TI (match_operand:TI 1 "gr_register_operand" "%r")
+ (match_operand:TI 2 "gr_reg_or_14bit_operand" "rI")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (plus:DI (match_dup 5) (match_dup 6))
+ (const_int 1))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (plus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "immediate_operand" "")))
+ (clobber (match_scratch:BI 3 ""))]
+ "reload_completed"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5) (match_dup 7))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = INTVAL (operands[2]) < 0 ? constm1_rtx : const0_rtx;
+ operands[7] = INTVAL (operands[2]) < 0 ? const0_rtx : const1_rtx;
+})
+
+(define_insn "subti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (minus:TI (match_operand:TI 1 "gr_reg_or_8bit_operand" "rK")
+ (match_operand:TI 2 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ ""
+ "#"
+ [(set_attr "itanium_class" "unknown")])
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "register_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (ltu:BI (match_dup 1) (match_dup 0)))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 5) (match_dup 6))))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4)
+ (plus:DI (not:DI (match_dup 6)) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+ operands[6] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+})
+
+(define_split
+ [(set (match_operand:TI 0 "register_operand" "")
+ (minus:TI (match_operand:TI 1 "immediate_operand" "")
+ (match_operand:TI 2 "register_operand" "")))
+ (clobber (match_scratch:BI 3 "=&c"))]
+ "reload_completed && CONST_OK_FOR_K (INTVAL (operands[1]))"
+ [(set (match_dup 0) (minus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (gtu:BI (match_dup 0) (match_dup 1)))
+ (cond_exec (ne (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 6) (match_dup 5))))
+ (cond_exec (eq (match_dup 3) (const_int 0))
+ (set (match_dup 4) (minus:DI (match_dup 7) (match_dup 5))))]
+{
+ operands[4] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[5] = gen_highpart (DImode, operands[2]);
+ operands[2] = gen_lowpart (DImode, operands[2]);
+ operands[6] = INTVAL (operands[1]) < 0 ? GEN_INT (-2) : constm1_rtx;
+ operands[7] = INTVAL (operands[1]) < 0 ? constm1_rtx : const0_rtx;
+})
+
+(define_expand "mulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_register_operand" ""))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_register_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*mulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (sign_extend:TI
+ (match_operand:DI 1 "fr_register_operand" "%f"))
+ (sign_extend:TI
+ (match_operand:DI 2 "fr_register_operand" "f"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (sign_extend:TI (match_dup 1))
+ (sign_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_expand "umulditi3"
+ [(set (match_operand:TI 0 "fr_register_operand" "")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_register_operand" ""))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_register_operand" ""))))]
+ ""
+ "")
+
+(define_insn_and_split "*umulditi3_internal"
+ [(set (match_operand:TI 0 "fr_register_operand" "=&f")
+ (mult:TI (zero_extend:TI
+ (match_operand:DI 1 "fr_register_operand" "%f"))
+ (zero_extend:TI
+ (match_operand:DI 2 "fr_register_operand" "f"))))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (mult:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 3) (truncate:DI
+ (lshiftrt:TI
+ (mult:TI (zero_extend:TI (match_dup 1))
+ (zero_extend:TI (match_dup 2)))
+ (const_int 64))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn_and_split "negti2"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (neg:TI (match_operand:TI 1 "gr_register_operand" "r")))
+ (clobber (match_scratch:BI 2 "=&c"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 2) (eq:BI (match_dup 1) (const_int 0)))
+ (set (match_dup 0) (minus:DI (const_int 0) (match_dup 1)))
+ (cond_exec (eq (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int -1) (match_dup 4))))
+ (cond_exec (ne (match_dup 2) (const_int 0))
+ (set (match_dup 3) (minus:DI (const_int 0) (match_dup 4))))]
+{
+ operands[3] = gen_highpart (DImode, operands[0]);
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[4] = gen_highpart (DImode, operands[1]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+}
+ [(set_attr "itanium_class" "unknown")])
+
+;; ::::::::::::::::::::
+;; ::
;; :: 32 bit floating point arithmetic
;; ::
;; ::::::::::::::::::::
@@ -2526,7 +2950,25 @@
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "minsf3"
+(define_insn "copysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignsf3"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (neg:SF (unspec:SF [(match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smin:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2534,7 +2976,7 @@
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxsf3"
+(define_insn "smaxsf3"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(smax:SF (match_operand:SF 1 "fr_register_operand" "f")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2568,18 +3010,25 @@
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmaddsf4"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
- (plus:SF (neg:SF (mult:SF
- (match_operand:SF 1 "fr_register_operand" "f")
- (match_operand:SF 2 "fr_register_operand" "f")))
- (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f"))))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmaddsf4_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:SF (match_operand:SF 1 "fr_register_operand" "f")
+ (match_operand:SF 2 "fr_register_operand" "f"))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %1, %2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_expand "divsf3"
[(set (match_operand:SF 0 "fr_register_operand" "")
(div:SF (match_operand:SF 1 "fr_register_operand" "")
@@ -2587,7 +3036,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -2602,20 +3051,20 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3) (mult:XF (match_dup 7) (match_dup 6)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2659,17 +3108,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -2688,8 +3137,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 3)))
- (match_dup 7)))
+ (minus:XF (match_dup 7)
+ (mult:XF (match_dup 8) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -2720,7 +3169,7 @@
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
-(define_insn "*setf_exp_xf"
+(define_insn "setf_exp_xf"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(unspec:XF [(match_operand:DI 1 "register_operand" "r")]
UNSPEC_SETF_EXP))]
@@ -2734,14 +3183,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -2764,7 +3213,7 @@
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -2799,8 +3248,8 @@
;; d = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 7) (match_dup 4))))
(use (const_int 1))]))
;; Step 5
;; d' = d + 1/2 * d in f8
@@ -2835,8 +3284,8 @@
;; d1 = a - S1 * S1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 10
;; S = S1 + d1 * H1 in f7
@@ -2933,7 +3382,25 @@
"fnegabs %0 = %1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "mindf3"
+(define_insn "copysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysigndf3"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (neg:DF (unspec:DF [(match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "smindf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smin:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -2941,7 +3408,7 @@
"fmin %0 = %1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxdf3"
+(define_insn "smaxdf3"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(smax:DF (match_operand:DF 1 "fr_register_operand" "f")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))]
@@ -3004,40 +3471,46 @@
"fnmpy.s %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmadddf4"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))))]
""
"fnma.d %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmadddf4_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f"))))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.d.s%4 %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*nmadddf4_trunc"
+(define_insn "*nmadddf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
- (plus:DF (neg:DF (mult:DF
- (match_operand:DF 1 "fr_register_operand" "f")
- (match_operand:DF 2 "fr_register_operand" "f")))
- (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))))]
""
"fnma.s %0 = %1, %2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmadddf4_truncsf_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
+ (mult:DF (match_operand:DF 1 "fr_register_operand" "f")
+ (match_operand:DF 2 "fr_register_operand" "f")))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %1, %2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_expand "divdf3"
[(set (match_operand:DF 0 "fr_register_operand" "")
(div:DF (match_operand:DF 1 "fr_register_operand" "")
@@ -3045,7 +3518,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -3061,20 +3534,20 @@
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 7) (div:XF (const_int 1) (match_dup 9)))
(set (match_dup 6) (unspec:BI [(match_dup 8) (match_dup 9)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3) (mult:XF (match_dup 8) (match_dup 7)))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 7)))
- (match_dup 12)))
+ (minus:XF (match_dup 12)
+ (mult:XF (match_dup 9) (match_dup 7))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3116,8 +3589,8 @@
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 11)
(float_truncate:DF
- (plus:XF (neg:XF (mult:XF (match_dup 9) (match_dup 3)))
- (match_dup 8))))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 9) (match_dup 3)))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 6) (const_int 0))
(set (match_dup 0)
@@ -3141,17 +3614,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:DF 4 "=f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 6) (div:XF (const_int 1) (match_dup 8)))
(set (match_dup 5) (unspec:BI [(match_dup 7) (match_dup 8)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 6)))
- (match_dup 10)))
+ (minus:XF (match_dup 10)
+ (mult:XF (match_dup 8) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 6)
@@ -3179,12 +3652,12 @@
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 9)
(float_truncate:DF
- (mult:XF (match_dup 7) (match_dup 3))))
+ (mult:XF (match_dup 7) (match_dup 6))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:DF (neg:DF (mult:DF (match_dup 2) (match_dup 9)))
- (match_dup 1)))
+ (minus:DF (match_dup 1)
+ (mult:DF (match_dup 2) (match_dup 9))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -3208,14 +3681,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -3238,7 +3711,7 @@
(clobber (match_scratch:XF 5 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -3273,8 +3746,8 @@
;; r0 = 1/2 - G0 * H0 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
- (match_dup 5)))
+ (minus:XF (match_dup 5)
+ (mult:XF (match_dup 7) (match_dup 3))))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + r0 * H0 in f8
@@ -3294,8 +3767,8 @@
;; r1 = 1/2 - G1 * H1 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 3)))
- (match_dup 5)))
+ (minus:XF (match_dup 5)
+ (mult:XF (match_dup 7) (match_dup 3))))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + r1 * H1 in f8
@@ -3315,8 +3788,8 @@
;; d2 = a - G2 * G2 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 11
;; G3 = G2 + d2 * H2 in f7
@@ -3329,8 +3802,8 @@
;; d3 = a - G3 * G3 in f9
(cond_exec (ne (match_dup 6) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 7) (match_dup 7)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 7) (match_dup 7))))
(use (const_int 1))]))
;; Step 13
;; S = G3 + d3 * H2 in f7
@@ -3483,7 +3956,25 @@
"fnegabs %0 = %F1"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "minxf3"
+(define_insn "copysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN))]
+ ""
+ "fmerge.s %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*ncopysignxf3"
+ [(set (match_operand:XF 0 "register_operand" "=f")
+ (neg:XF (unspec:XF [(match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_COPYSIGN)))]
+ ""
+ "fmerge.ns %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(smin:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
@@ -3491,7 +3982,7 @@
"fmin %0 = %F1, %F2"
[(set_attr "itanium_class" "fmisc")])
-(define_insn "maxxf3"
+(define_insn "smaxxf3"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(smax:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))]
@@ -3617,14 +4108,12 @@
"fnmpy.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
-;; ??? Is it possible to canonicalize this as (minus (reg) (mult))?
-
(define_insn "*nmaddxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ )))]
""
"fnma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3632,10 +4121,10 @@
(define_insn "*nmaddxf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))]
""
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3643,33 +4132,44 @@
(define_insn "*nmaddxf4_truncdf"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))]
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))]
""
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
(define_insn "*nmaddxf4_alts"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
- (plus:XF (neg:XF (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ )))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.s%4 %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
+(define_insn "*nmaddxf4_truncsf_alts"
+ [(set (match_operand:SF 0 "fr_register_operand" "=f")
+ (float_truncate:SF
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))
+ (use (match_operand:SI 4 "const_int_operand" ""))]
+ ""
+ "fnma.s.s%4 %0 = %F1, %F2, %F3"
+ [(set_attr "itanium_class" "fmac")])
+
(define_insn "*nmaddxf4_truncdf_alts"
[(set (match_operand:DF 0 "fr_register_operand" "=f")
(float_truncate:DF
- (plus:XF (neg:XF
- (mult:XF
- (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
+ (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
+ (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
+ (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
+ ))))
(use (match_operand:SI 4 "const_int_operand" ""))]
""
"fnma.d.s%4 %0 = %F1, %F2, %F3"
@@ -3682,7 +4182,7 @@
"TARGET_INLINE_FLOAT_DIV"
{
rtx insn;
- if (TARGET_INLINE_FLOAT_DIV_LAT)
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
insn = gen_divxf3_internal_lat (operands[0], operands[1], operands[2]);
else
insn = gen_divxf3_internal_thr (operands[0], operands[1], operands[2]);
@@ -3699,17 +4199,17 @@
(clobber (match_scratch:XF 5 "=&f"))
(clobber (match_scratch:XF 6 "=&f"))
(clobber (match_scratch:BI 7 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_LAT"
+ "TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
(set (match_dup 7) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
@@ -3739,8 +4239,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 4))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3749,8 +4249,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 8)))
+ (minus:XF (match_dup 8)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3759,8 +4259,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 7) (const_int 0))
(set (match_dup 0)
@@ -3777,17 +4277,17 @@
(clobber (match_scratch:XF 3 "=&f"))
(clobber (match_scratch:XF 4 "=&f"))
(clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_FLOAT_DIV_THR"
+ "TARGET_INLINE_FLOAT_DIV == INL_MAX_THR"
"#"
"&& reload_completed"
[(parallel [(set (match_dup 0) (div:XF (const_int 1) (match_dup 2)))
(set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
+ (use (const_int 0))])
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
@@ -3807,8 +4307,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3817,8 +4317,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 4)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 4))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 3)
@@ -3827,8 +4327,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 0)))
- (match_dup 6)))
+ (minus:XF (match_dup 6)
+ (mult:XF (match_dup 2) (match_dup 0))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 0)
@@ -3837,8 +4337,8 @@
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(parallel [(set (match_dup 4)
- (plus:XF (neg:XF (mult:XF (match_dup 2) (match_dup 3)))
- (match_dup 1)))
+ (minus:XF (match_dup 1)
+ (mult:XF (match_dup 2) (match_dup 3))))
(use (const_int 1))]))
(cond_exec (ne (match_dup 5) (const_int 0))
(set (match_dup 0)
@@ -3856,14 +4356,14 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
- if (TARGET_INLINE_SQRT_LAT)
#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]);
+ else
#else
- abort ();
+ gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
- else
- insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
@@ -3888,7 +4388,7 @@
(clobber (match_scratch:XF 6 "=&f"))
;; Register p6 in optimization guide.
(clobber (match_scratch:BI 7 "=c"))]
- "TARGET_INLINE_SQRT_THR"
+ "TARGET_INLINE_SQRT == INL_MAX_THR"
"#"
"&& reload_completed"
[ ;; exponent of +1/2 in r2
@@ -3923,8 +4423,8 @@
;; d0 = 1/2 - S0 * H0 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 5
;; H1 = H0 + d0 * H0 in f9
@@ -3944,8 +4444,8 @@
;; d1 = 1/2 - S1 * H1 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 8
;; H2 = H1 + d1 * H1 in f9
@@ -3965,15 +4465,15 @@
;; d2 = 1/2 - S2 * H2 in f10
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 5)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 4)))
- (match_dup 3)))
+ (minus:XF (match_dup 3)
+ (mult:XF (match_dup 8) (match_dup 4))))
(use (const_int 1))]))
;; Step 11
;; e2 = a - S2 * S2 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
- (match_dup 9)))
+ (minus:XF (match_dup 9)
+ (mult:XF (match_dup 8) (match_dup 8))))
(use (const_int 1))]))
;; Step 12
;; S3 = S2 + e2 * H2 in f7
@@ -3993,8 +4493,8 @@
;; e3 = a - S3 * S3 in f8
(cond_exec (ne (match_dup 7) (const_int 0))
(parallel [(set (match_dup 3)
- (plus:XF (neg:XF (mult:XF (match_dup 8) (match_dup 8)))
- (match_dup 9)))
+ (minus:XF (match_dup 9)
+ (mult:XF (match_dup 8) (match_dup 8))))
(use (const_int 1))]))
;; Step 15
;; S = S3 + e3 * H3 in f7
@@ -4154,8 +4654,8 @@
(rotate:SI (match_operand:SI 1 "gr_register_operand" "r")
(match_operand:SI 2 "shift_32bit_count_operand" "n")))]
""
- "#"
- "reload_completed"
+ "mux2 %0 = %1, 0xe1"
+ "reload_completed && INTVAL (operands[2]) != 16"
[(set (match_dup 3)
(ior:DI (zero_extend:DI (match_dup 1))
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
@@ -4164,7 +4664,8 @@
{
operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-})
+}
+ [(set_attr "itanium_class" "mmshf")])
;; ::::::::::::::::::::
;; ::
@@ -4209,7 +4710,7 @@
(match_operand:DI 3 "nonmemory_operand" "r"))
(match_operand:DI 4 "nonmemory_operand" "rI")))]
"reload_in_progress"
- "* abort ();"
+ "* gcc_unreachable ();"
"reload_completed"
[(set (match_dup 0) (plus:DI (mult:DI (match_dup 1) (match_dup 2))
(match_dup 3)))
@@ -4280,6 +4781,199 @@
;; ::::::::::::::::::::
;; ::
+;; :: 128 bit Integer Shifts and Rotates
+;; ::
+;; ::::::::::::::::::::
+
+(define_expand "ashlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashift:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ emit_move_insn (rl, const0_rtx);
+ if (shift & 63)
+ emit_insn (gen_ashldi3 (rh, lo, shiftlo));
+ else
+ emit_move_insn (rh, lo);
+ }
+ else
+ {
+ rtx hi = gen_highpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rh, hi, lo, GEN_INT (-shift & 63)));
+ emit_insn (gen_ashldi3 (rl, lo, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "ashrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*ashrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (ashiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_ashrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_insn (gen_ashrdi3 (rh, hi, GEN_INT (63)));
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_ashrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "lshrti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (!dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*lshrti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (lshiftrt:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT shift = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx shiftlo = GEN_INT (shift & 63);
+
+ if (shift & 64)
+ {
+ if (shift & 63)
+ emit_insn (gen_lshrdi3 (rl, hi, shiftlo));
+ else
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, const0_rtx);
+ }
+ else
+ {
+ rtx lo = gen_lowpart (DImode, operands[1]);
+
+ emit_insn (gen_shrp (rl, hi, lo, shiftlo));
+ emit_insn (gen_lshrdi3 (rh, hi, shiftlo));
+ }
+ DONE;
+})
+
+(define_expand "rotlti3"
+ [(set (match_operand:TI 0 "gr_register_operand" "")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+{
+ if (! dshift_count_operand (operands[2], DImode))
+ FAIL;
+})
+
+(define_insn_and_split "*rotlti3_internal"
+ [(set (match_operand:TI 0 "gr_register_operand" "=&r")
+ (rotate:TI (match_operand:TI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "dshift_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ HOST_WIDE_INT count = INTVAL (operands[2]);
+ rtx rl = gen_lowpart (DImode, operands[0]);
+ rtx rh = gen_highpart (DImode, operands[0]);
+ rtx lo = gen_lowpart (DImode, operands[1]);
+ rtx hi = gen_highpart (DImode, operands[1]);
+ rtx countlo = GEN_INT (-count & 63);
+
+ if (count & 64)
+ {
+ if (count & 63)
+ {
+ emit_insn (gen_shrp (rl, hi, lo, countlo));
+ emit_insn (gen_shrp (rh, lo, hi, countlo));
+ }
+ else
+ {
+ emit_move_insn (rl, hi);
+ emit_move_insn (rh, lo);
+ }
+ }
+ else
+ {
+ emit_insn (gen_shrp (rl, lo, hi, countlo));
+ emit_insn (gen_shrp (rh, hi, lo, countlo));
+ }
+ DONE;
+}
+ [(set_attr "itanium_class" "unknown")])
+
+(define_insn "shrp"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_register_operand" "r")
+ (match_operand:DI 3 "shift_count_operand" "M")]
+ UNSPEC_SHRP))]
+ ""
+ "shrp %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "ishf")])
+
+;; ::::::::::::::::::::
+;; ::
;; :: 32 bit Integer Logical operations
;; ::
;; ::::::::::::::::::::
@@ -4516,7 +5210,7 @@
[(set (match_operand:BI 0 "register_operand" "=c")
(eq:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "immediate_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0)))]
""
"tbit.z %0, %I0 = %1, %2"
@@ -4526,7 +5220,7 @@
[(set (match_operand:BI 0 "register_operand" "=c")
(ne:BI (zero_extract:DI (match_operand:DI 1 "gr_register_operand" "r")
(const_int 1)
- (match_operand:DI 2 "immediate_operand" "n"))
+ (match_operand:DI 2 "shift_count_operand" "M"))
(const_int 0)))]
""
"tbit.nz %0, %I0 = %1, %2"
@@ -4816,7 +5510,7 @@
"rim,rim,rim, rim, *f, *b,*d*e,*f,*b,*d*e,rO,*f,rOQ,rO, rK")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- { abort (); }
+ { gcc_unreachable (); }
[(set_attr "predicable" "no")])
(define_split
@@ -4919,7 +5613,7 @@
"rim*f,rO,rO,0,0,0,rim*f,rO,rO")))]
"ia64_move_ok (operands[0], operands[2])
&& ia64_move_ok (operands[0], operands[3])"
- { abort (); }
+ { gcc_unreachable (); }
[(set_attr "predicable" "no")])
(define_insn "*abssi2_internal"
@@ -5318,12 +6012,10 @@
start_sequence ();
set = single_set (last);
- if (! rtx_equal_p (SET_DEST (set), op0)
- || GET_CODE (SET_SRC (set)) != MEM)
- abort ();
+ gcc_assert (rtx_equal_p (SET_DEST (set), op0)
+ && GET_CODE (SET_SRC (set)) == MEM);
addr = XEXP (SET_SRC (set), 0);
- if (rtx_equal_p (addr, op0))
- abort ();
+ gcc_assert (!rtx_equal_p (addr, op0));
}
/* Jump table elements are stored pc-relative. That is, a displacement
@@ -5421,7 +6113,8 @@
""
"alloc %0 = ar.pfs, %1, %2, %3, %4"
[(set_attr "itanium_class" "syst_m0")
- (set_attr "predicable" "no")])
+ (set_attr "predicable" "no")
+ (set_attr "first_insn" "yes")])
;; Modifies ar.unat
(define_expand "gr_spill"
@@ -5434,7 +6127,7 @@
"operands[3] = gen_rtx_REG (DImode, AR_UNAT_REGNUM);")
(define_insn "gr_spill_internal"
- [(set (match_operand:DI 0 "memory_operand" "=m")
+ [(set (match_operand:DI 0 "destination_operand" "=m")
(unspec:DI [(match_operand:DI 1 "register_operand" "r")
(match_operand:DI 2 "const_int_operand" "")]
UNSPEC_GR_SPILL))
@@ -5468,7 +6161,7 @@
[(set_attr "itanium_class" "ld")])
(define_insn "fr_spill"
- [(set (match_operand:XF 0 "memory_operand" "=m")
+ [(set (match_operand:XF 0 "destination_operand" "=m")
(unspec:XF [(match_operand:XF 1 "register_operand" "f")]
UNSPEC_FR_SPILL))]
""
@@ -5622,7 +6315,7 @@
[(trap_if (const_int 1) (match_operand 0 "const_int_operand" ""))]
""
"break %0"
- [(set_attr "itanium_class" "chk_s")])
+ [(set_attr "itanium_class" "chk_s_i")])
(define_expand "conditional_trap"
[(trap_if (match_operand 0 "" "") (match_operand 1 "" ""))]
@@ -5638,7 +6331,7 @@
(match_operand 2 "const_int_operand" ""))]
""
"(%J0) break %2"
- [(set_attr "itanium_class" "chk_s")
+ [(set_attr "itanium_class" "chk_s_i")
(set_attr "predicable" "no")])
(define_insn "break_f"
@@ -5670,10 +6363,8 @@
int i = (INTVAL (operands[1]));
int j = (INTVAL (operands[2]));
- if (i != 0 && i != 1)
- abort ();
- if (j < 0 || j > 3)
- abort ();
+ gcc_assert (i == 0 || i == 1);
+ gcc_assert (j >= 0 && j <= 3);
return alt[i][j];
}
[(set_attr "itanium_class" "lfetch")])
@@ -5760,88 +6451,6 @@
})
-;;; Intrinsics support.
-
-(define_expand "mf"
- [(set (mem:BLK (match_dup 0))
- (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_MF))]
- ""
-{
- operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
- MEM_VOLATILE_P (operands[0]) = 1;
-})
-
-(define_insn "*mf_internal"
- [(set (match_operand:BLK 0 "" "")
- (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_MF))]
- ""
- "mf"
- [(set_attr "itanium_class" "syst_m")])
-
-(define_insn "fetchadd_acq_si"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:SI [(match_dup 1)
- (match_operand:SI 2 "fetchadd_operand" "n")]
- UNSPEC_FETCHADD_ACQ))]
- ""
- "fetchadd4.acq %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "fetchadd_acq_di"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:DI [(match_dup 1)
- (match_operand:DI 2 "fetchadd_operand" "n")]
- UNSPEC_FETCHADD_ACQ))]
- ""
- "fetchadd8.acq %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "cmpxchg_acq_si"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:SI [(match_dup 1)
- (match_operand:SI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")]
- UNSPEC_CMPXCHG_ACQ))]
- ""
- "cmpxchg4.acq %0 = %1, %2, %3"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "cmpxchg_acq_di"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (unspec:DI [(match_dup 1)
- (match_operand:DI 2 "gr_register_operand" "r")
- (match_operand:DI 3 "ar_ccv_reg_operand" "")]
- UNSPEC_CMPXCHG_ACQ))]
- ""
- "cmpxchg8.acq %0 = %1, %2, %3"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "xchgsi"
- [(set (match_operand:SI 0 "gr_register_operand" "=r")
- (match_operand:SI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (match_operand:SI 2 "gr_register_operand" "r"))]
- ""
- "xchg4 %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
-(define_insn "xchgdi"
- [(set (match_operand:DI 0 "gr_register_operand" "=r")
- (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
- (set (match_dup 1)
- (match_operand:DI 2 "gr_register_operand" "r"))]
- ""
- "xchg8 %0 = %1, %2"
- [(set_attr "itanium_class" "sem")])
-
;; Predication.
(define_cond_exec
@@ -5909,3 +6518,18 @@
"addp4_optimize_ok (operands[1], operands[2])"
"addp4 %0 = %1, %2"
[(set_attr "itanium_class" "ialu")])
+
+;;
+;; Get instruction pointer
+
+(define_insn "ip_value"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (pc))]
+ ""
+ "mov %0 = ip"
+ [(set_attr "itanium_class" "ialu")])
+
+;; Vector operations
+(include "vect.md")
+;; Atomic operations
+(include "sync.md")
diff --git a/contrib/gcc/config/ia64/ia64.opt b/contrib/gcc/config/ia64/ia64.opt
new file mode 100644
index 0000000..2ff3d59
--- /dev/null
+++ b/contrib/gcc/config/ia64/ia64.opt
@@ -0,0 +1,147 @@
+mbig-endian
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Generate big endian code
+
+mlittle-endian
+Target Report RejectNegative InverseMask(BIG_ENDIAN)
+Generate little endian code
+
+mgnu-as
+Target Report Mask(GNU_AS)
+Generate code for GNU as
+
+mgnu-ld
+Target Report Mask(GNU_LD)
+Generate code for GNU ld
+
+mvolatile-asm-stop
+Target Report Mask(VOL_ASM_STOP)
+Emit stop bits before and after volatile extended asms
+
+mregister-names
+Target Mask(REG_NAMES)
+Use in/loc/out register names
+
+mno-sdata
+Target Report RejectNegative Mask(NO_SDATA)
+
+msdata
+Target Report RejectNegative InverseMask(NO_SDATA)
+Enable use of sdata/scommon/sbss
+
+mno-pic
+Target Report RejectNegative Mask(NO_PIC)
+Generate code without GP reg
+
+mconstant-gp
+Target Report RejectNegative Mask(CONST_GP)
+gp is constant (but save/restore gp on indirect calls)
+
+mauto-pic
+Target Report RejectNegative Mask(AUTO_PIC)
+Generate self-relocatable code
+
+minline-float-divide-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 1)
+Generate inline floating point division, optimize for latency
+
+minline-float-divide-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 2) Init(2)
+Generate inline floating point division, optimize for throughput
+
+mno-inline-float-divide
+Target Report RejectNegative Var(TARGET_INLINE_FLOAT_DIV, 0)
+
+minline-int-divide-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 1)
+Generate inline integer division, optimize for latency
+
+minline-int-divide-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 2)
+Generate inline integer division, optimize for throughput
+
+mno-inline-int-divide
+Target Report RejectNegative Var(TARGET_INLINE_INT_DIV, 0)
+Do not inline integer division
+
+minline-sqrt-min-latency
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 1)
+Generate inline square root, optimize for latency
+
+minline-sqrt-max-throughput
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 2)
+Generate inline square root, optimize for throughput
+
+mno-inline-sqrt
+Target Report RejectNegative Var(TARGET_INLINE_SQRT, 0)
+Do not inline square root
+
+mdwarf2-asm
+Target Report Mask(DWARF2_ASM)
+Enable Dwarf 2 line debug info via GNU as
+
+mearly-stop-bits
+Target Report Mask(EARLY_STOP_BITS)
+Enable earlier placing stop bits for better scheduling
+
+mfixed-range=
+Target RejectNegative Joined
+Specify range of registers to make fixed
+
+mtls-size=
+Target RejectNegative Joined UInteger Var(ia64_tls_size) Init(22)
+Specify bit size of immediate TLS offsets
+
+mtune=
+Target RejectNegative Joined
+Schedule code for given CPU
+
+msched-br-data-spec
+Target Report Var(mflag_sched_br_data_spec) Init(0)
+Use data speculation before reload
+
+msched-ar-data-spec
+Target Report Var(mflag_sched_ar_data_spec) Init(1)
+Use data speculation after reload
+
+msched-control-spec
+Target Report Var(mflag_sched_control_spec) Init(0)
+Use control speculation
+
+msched-br-in-data-spec
+Target Report Var(mflag_sched_br_in_data_spec) Init(1)
+Use in block data speculation before reload
+
+msched-ar-in-data-spec
+Target Report Var(mflag_sched_ar_in_data_spec) Init(1)
+Use in block data speculation after reload
+
+msched-in-control-spec
+Target Report Var(mflag_sched_in_control_spec) Init(1)
+Use in block control speculation
+
+msched-ldc
+Target Report Var(mflag_sched_ldc) Init(1)
+Use simple data speculation check
+
+msched-control-ldc
+Target Report Var(mflag_control_ldc) Init(0)
+Use simple data speculation check for control speculation
+
+msched-spec-verbose
+Common Report Var(mflag_sched_spec_verbose) Init(0)
+Print information about speculative motions.
+
+msched-prefer-non-data-spec-insns
+Common Report Var(mflag_sched_prefer_non_data_spec_insns) Init(0)
+If set, data speculative instructions will be chosen for schedule only if there are no other choices at the moment
+
+msched-prefer-non-control-spec-insns
+Common Report Var(mflag_sched_prefer_non_control_spec_insns) Init(0)
+If set, control speculative instructions will be chosen for schedule only if there are no other choices at the moment
+
+msched-count-spec-in-critical-path
+Common Report Var(mflag_sched_count_spec_in_critical_path) Init(0)
+Count speculative dependencies while calculating priority of instructions
+
+; This comment is to ensure we retain the blank line above.
diff --git a/contrib/gcc/config/ia64/ia64intrin.h b/contrib/gcc/config/ia64/ia64intrin.h
index 262dc20..fba7296 100644
--- a/contrib/gcc/config/ia64/ia64intrin.h
+++ b/contrib/gcc/config/ia64/ia64intrin.h
@@ -1,130 +1,2 @@
-#ifndef _IA64INTRIN_H_INCLUDED
-#define _IA64INTRIN_H_INCLUDED
-
-/* Actually, everything is a compiler builtin, but just so
- there's no confusion... */
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void __sync_synchronize (void);
-
-extern int __sync_val_compare_and_swap_si (int *, int, int);
-extern long __sync_val_compare_and_swap_di (long *, long, long);
-#define __sync_val_compare_and_swap(PTR, OLD, NEW) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) \
- __sync_val_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \
- : (__typeof__(*(PTR))) \
- __sync_val_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW)))
-
-extern int __sync_bool_compare_and_swap_si (int *, int, int);
-extern int __sync_bool_compare_and_swap_di (long *, long, long);
-#define __sync_bool_compare_and_swap(PTR, OLD, NEW) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? __sync_bool_compare_and_swap_si((int *)(PTR),(int)(OLD),(int)(NEW)) \
- : __sync_bool_compare_and_swap_di((long *)(PTR),(long)(OLD),(long)(NEW)))
-
-extern void __sync_lock_release_si (int *);
-extern void __sync_lock_release_di (long *);
-#define __sync_lock_release(PTR) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? __sync_lock_release_si((int *)(PTR)) \
- : __sync_lock_release_di((long *)(PTR)))
-
-extern int __sync_lock_test_and_set_si (int *, int);
-extern long __sync_lock_test_and_set_di (long *, long);
-#define __sync_lock_test_and_set(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_lock_test_and_set_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_lock_test_and_set_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_add_si (int *, int);
-extern long __sync_fetch_and_add_di (long *, long);
-#define __sync_fetch_and_add(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_add_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_add_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_sub_si (int *, int);
-extern long __sync_fetch_and_sub_di (long *, long);
-#define __sync_fetch_and_sub(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_sub_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_sub_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_and_si (int *, int);
-extern long __sync_fetch_and_and_di (long *, long);
-#define __sync_fetch_and_and(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_and_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_and_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_or_si (int *, int);
-extern long __sync_fetch_and_or_di (long *, long);
-#define __sync_fetch_and_or(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_or_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_or_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_xor_si (int *, int);
-extern long __sync_fetch_and_xor_di (long *, long);
-#define __sync_fetch_and_xor(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_xor_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_xor_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_fetch_and_nand_si (int *, int);
-extern long __sync_fetch_and_nand_di (long *, long);
-#define __sync_fetch_and_nand(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_fetch_and_nand_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_fetch_and_nand_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_add_and_fetch_si (int *, int);
-extern long __sync_add_and_fetch_di (long *, long);
-#define __sync_add_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_add_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_add_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_sub_and_fetch_si (int *, int);
-extern long __sync_sub_and_fetch_di (long *, long);
-#define __sync_sub_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_sub_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_sub_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_and_and_fetch_si (int *, int);
-extern long __sync_and_and_fetch_di (long *, long);
-#define __sync_and_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_and_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_and_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_or_and_fetch_si (int *, int);
-extern long __sync_or_and_fetch_di (long *, long);
-#define __sync_or_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_or_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_or_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_xor_and_fetch_si (int *, int);
-extern long __sync_xor_and_fetch_di (long *, long);
-#define __sync_xor_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_xor_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_xor_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-extern int __sync_nand_and_fetch_si (int *, int);
-extern long __sync_nand_and_fetch_di (long *, long);
-#define __sync_nand_and_fetch(PTR,VAL) \
- ((sizeof (*(PTR)) == sizeof(int)) \
- ? (__typeof__(*(PTR))) __sync_nand_and_fetch_si((int *)(PTR),(int)(VAL)) \
- : (__typeof__(*(PTR))) __sync_nand_and_fetch_di((long *)(PTR),(long)(VAL)))
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* Overloaded builtins have been ported to C++: nothing is needed
+ in the header anymore. This file intentionally left void. */
diff --git a/contrib/gcc/config/ia64/ilp32.opt b/contrib/gcc/config/ia64/ilp32.opt
new file mode 100644
index 0000000..bcb6473
--- /dev/null
+++ b/contrib/gcc/config/ia64/ilp32.opt
@@ -0,0 +1,7 @@
+milp32
+Target Report RejectNegative Mask(ILP32)
+Generate ILP32 code
+
+mlp64
+Target Report RejectNegative InverseMask(ILP32)
+Generate LP64 code
diff --git a/contrib/gcc/config/ia64/itanium1.md b/contrib/gcc/config/ia64/itanium1.md
index 2b84411..f9b7f91 100644
--- a/contrib/gcc/config/ia64/itanium1.md
+++ b/contrib/gcc/config/ia64/itanium1.md
@@ -1,6 +1,6 @@
;; Itanium1 (original Itanium) DFA descriptions for insn scheduling
;; and bundling.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Vladimir Makarov <vmakarov@redhat.com>.
;;
;; This file is part of GCC.
@@ -17,8 +17,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
@@ -33,10 +33,10 @@
DEFINE_AUTOMATON).
All define_reservations and define_cpu_units should have unique
- names which can not be "nothing".
+ names which cannot be "nothing".
o (exclusion_set string string) means that each CPU function unit
- in the first string can not be reserved simultaneously with each
+ in the first string cannot be reserved simultaneously with each
unit whose name is in the second string and vise versa. CPU
units in the string are separated by commas. For example, it is
useful for description CPU with fully pipelined floating point
@@ -44,7 +44,7 @@
floating point insns or only double floating point insns.
o (presence_set string string) means that each CPU function unit in
- the first string can not be reserved unless at least one of
+ the first string cannot be reserved unless at least one of
pattern of units whose names are in the second string is
reserved. This is an asymmetric relation. CPU units or unit
patterns in the strings are separated by commas. Pattern is one
@@ -92,13 +92,13 @@
string are separated by commas. Pattern is one unit name or unit
names separated by white-spaces.
- For example, it is useful for description that slot0 can not be
+ For example, it is useful for description that slot0 cannot be
reserved after slot1 or slot2 reservation for a VLIW processor.
We could describe it by the following construction
(absence_set "slot2" "slot0, slot1")
- Or slot2 can not be reserved if slot0 and unit b0 are reserved or
+ Or slot2 cannot be reserved if slot0 and unit b0 are reserved or
slot1 and unit b1 are reserved . In this case we could write
(absence_set "slot2" "slot0 b0, slot1 b1")
@@ -140,7 +140,7 @@
case, you describe common part and use one its name (the 1st
parameter) in regular expression in define_insn_reservation. All
define_reservations, define results and define_cpu_units should
- have unique names which can not be "nothing".
+ have unique names which cannot be "nothing".
o (define_insn_reservation name default_latency condition regexpr)
describes reservation of cpu functional units (the 3nd operand)
@@ -525,10 +525,29 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fcvtfx"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_F")
+
(define_insn_reservation "1_fld" 9
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "fld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
+(define_insn_reservation "1_fldp" 9
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
(define_insn_reservation "1_fmac" 5
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fmac"))
@@ -589,14 +608,25 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ilog"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_A")
+(define_insn_reservation "1_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "mmalua"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "1_A")
(define_insn_reservation "1_ishf" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ishf"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"1_I+1_not_ui1")
(define_insn_reservation "1_ld" 2
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
(define_insn_reservation "1_long_i" 1
(and (and (eq_attr "cpu" "itanium")
@@ -687,10 +717,19 @@
(eq_attr "itanium_class" "xtd"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_I")
-(define_insn_reservation "1_chk_s" 0
+(define_insn_reservation "1_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(eq (symbol_ref "bundling_p") (const_int 0))) "1_A")
+(define_insn_reservation "1_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+(define_insn_reservation "1_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_a"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "1_M")
+
(define_insn_reservation "1_lfetch" 0
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "lfetch"))
@@ -920,7 +959,7 @@
;; There is only one insn `mov ar.pfs =' for toar_i.
(define_bypass 0 "1_tobr,1_topr,1_toar_i" "1_br,1_scall")
-(define_bypass 3 "1_ialu,1_ialu_addr" "1_mmmul,1_mmshf")
+(define_bypass 3 "1_ialu,1_ialu_addr" "1_mmmul,1_mmshf,1_mmalua")
;; ??? howto describe ialu for I slot only. We use ialu_addr for that
;;(define_bypass 2 "1_ialu" "1_ld" "ia64_ld_address_bypass_p")
;; ??? howto describe ialu st/address for I slot only. We use ialu_addr
@@ -934,15 +973,15 @@
(define_bypass 2 "1_ilog,1_xtd" "1_ld" "ia64_ld_address_bypass_p")
(define_bypass 2 "1_ilog,1_xtd" "1_st" "ia64_st_address_bypass_p")
-(define_bypass 3 "1_ld" "1_mmmul,1_mmshf")
+(define_bypass 3 "1_ld,1_ldc" "1_mmmul,1_mmshf")
(define_bypass 3 "1_ld" "1_ld" "ia64_ld_address_bypass_p")
(define_bypass 3 "1_ld" "1_st" "ia64_st_address_bypass_p")
;; Intel docs say only LD, ST, IALU, ILOG, ISHF consumers have latency 4,
;; but HP engineers say any non-MM operation.
-(define_bypass 4 "1_mmmul,1_mmshf"
- "1_br,1_fcmp,1_fcvtfx,1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
- 1_frbr,1_frfr,1_frpr,1_ialu,1_icmp,1_ilog,1_ishf,1_ld,1_chk_s,\
+(define_bypass 4 "1_mmmul,1_mmshf,1_mmalua"
+ "1_br,1_fcmp,1_fcvtfx,1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
+ 1_frbr,1_frfr,1_frpr,1_ialu,1_icmp,1_ilog,1_ishf,1_ld,1_ldc,1_chk_s_i,1_chk_s_f,1_chk_a,\
1_long_i,1_rse_m,1_sem,1_stf,1_st,1_syst_m0,1_syst_m,\
1_tbit,1_toar_i,1_toar_m,1_tobr,1_tofr,1_topr,1_xmpy,1_xtd")
@@ -956,15 +995,15 @@
(define_bypass 8 "1_fmisc,1_fcvtfx,1_fmac,1_xmpy" "1_stf")
;; We don't use here fcmp because scall may be predicated.
-(define_bypass 0 "1_fcvtfx,1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
+(define_bypass 0 "1_fcvtfx,1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,\
1_frbr,1_frfr,1_frpr,1_ialu,1_ialu_addr,1_ilog,1_ishf,\
- 1_ld,1_long_i,1_mmmul,1_mmshf,1_mmshfi,1_toar_m,1_tofr,\
- 1_xmpy,1_xtd" "1_scall")
+ 1_ld,1_ldc,1_long_i,1_mmalua,1_mmmul,1_mmshf,1_mmshfi,\
+ 1_toar_m,1_tofr,1_xmpy,1_xtd" "1_scall")
(define_bypass 0 "1_unknown,1_ignore,1_stop_bit,1_br,1_fcmp,1_fcvtfx,\
- 1_fld,1_fmac,1_fmisc,1_frar_i,1_frar_m,1_frbr,1_frfr,\
- 1_frpr,1_ialu,1_ialu_addr,1_icmp,1_ilog,1_ishf,1_ld,\
- 1_chk_s,1_long_i,1_mmmul,1_mmshf,1_mmshfi,1_nop,\
+ 1_fld,1_fldc,1_fmac,1_fmisc,1_frar_i,1_frar_m,1_frbr,1_frfr,\
+ 1_frpr,1_ialu,1_ialu_addr,1_icmp,1_ilog,1_ishf,1_ld,1_ldc,\
+ 1_chk_s_i,1_chk_s_f,1_chk_a,1_long_i,1_mmalua,1_mmmul,1_mmshf,1_mmshfi,1_nop,\
1_nop_b,1_nop_f,1_nop_i,1_nop_m,1_nop_x,1_rse_m,1_scall,\
1_sem,1_stf,1_st,1_syst_m0,1_syst_m,1_tbit,1_toar_i,\
1_toar_m,1_tobr,1_tofr,1_topr,1_xmpy,1_xtd,1_lfetch"
@@ -1398,10 +1437,29 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fcvtfx"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_F")
+
(define_insn_reservation "1b_fld" 9
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "fld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "no"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
+(define_insn_reservation "1b_fldp" 9
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_fmac" 5
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "fmac"))
@@ -1458,15 +1516,27 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ilog"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
+(define_insn_reservation "1b_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "mmalua"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
(define_insn_reservation "1b_ishf" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "ishf"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"1b_I+1b_not_ui1")
+
(define_insn_reservation "1b_ld" 2
- (and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_long_i" 1
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "long_i"))
@@ -1549,10 +1619,20 @@
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "xtd"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_I")
-(define_insn_reservation "1b_chk_s" 0
+
+(define_insn_reservation "1b_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(ne (symbol_ref "bundling_p") (const_int 0))) "1b_A")
+(define_insn_reservation "1b_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+(define_insn_reservation "1b_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium")
+ (eq_attr "itanium_class" "chk_a"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "1b_M")
+
(define_insn_reservation "1b_lfetch" 0
(and (and (eq_attr "cpu" "itanium")
(eq_attr "itanium_class" "lfetch"))
diff --git a/contrib/gcc/config/ia64/itanium2.md b/contrib/gcc/config/ia64/itanium2.md
index 0cdb070..a10971d 100644
--- a/contrib/gcc/config/ia64/itanium2.md
+++ b/contrib/gcc/config/ia64/itanium2.md
@@ -1,5 +1,5 @@
;; Itanium2 DFA descriptions for insn scheduling and bundling.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Vladimir Makarov <vmakarov@redhat.com>.
;;
;; This file is part of GCC.
@@ -16,8 +16,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA. */
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA. */
;;
/* This is description of pipeline hazards based on DFA. The
@@ -31,10 +31,10 @@
DEFINE_AUTOMATON).
All define_reservations and define_cpu_units should have unique
- names which can not be "nothing".
+ names which cannot be "nothing".
o (exclusion_set string string) means that each CPU function unit
- in the first string can not be reserved simultaneously with each
+ in the first string cannot be reserved simultaneously with each
unit whose name is in the second string and vise versa. CPU
units in the string are separated by commas. For example, it is
useful for description CPU with fully pipelined floating point
@@ -42,7 +42,7 @@
floating point insns or only double floating point insns.
o (presence_set string string) means that each CPU function unit in
- the first string can not be reserved unless at least one of
+ the first string cannot be reserved unless at least one of
pattern of units whose names are in the second string is
reserved. This is an asymmetric relation. CPU units or unit
patterns in the strings are separated by commas. Pattern is one
@@ -90,13 +90,13 @@
string are separated by commas. Pattern is one unit name or unit
names separated by white-spaces.
- For example, it is useful for description that slot0 can not be
+ For example, it is useful for description that slot0 cannot be
reserved after slot1 or slot2 reservation for a VLIW processor.
We could describe it by the following construction
(absence_set "slot2" "slot0, slot1")
- Or slot2 can not be reserved if slot0 and unit b0 are reserved or
+ Or slot2 cannot be reserved if slot0 and unit b0 are reserved or
slot1 and unit b1 are reserved . In this case we could write
(absence_set "slot2" "slot0 b0, slot1 b1")
@@ -138,7 +138,7 @@
case, you describe common part and use one its name (the 1st
parameter) in regular expression in define_insn_reservation. All
define_reservations, define results and define_cpu_units should
- have unique names which can not be "nothing".
+ have unique names which cannot be "nothing".
o (define_insn_reservation name default_latency condition regexpr)
describes reservation of cpu functional units (the 3nd operand)
@@ -398,7 +398,7 @@
"2_stop")
;; The issue logic can reorder M slot insns between different subtypes
-;; but can not reorder insn within the same subtypes. The following
+;; but cannot reorder insn within the same subtypes. The following
;; constraint is enough to describe this.
(final_presence_set "2_um1" "2_um0")
(final_presence_set "2_um3" "2_um2")
@@ -484,7 +484,7 @@
(define_reservation "2_M_only_um01" "2_M0_only_um01|2_M1_only_um01")
;; I instruction is dispersed to the lowest numbered I unit
-;; not already in use. Remeber about possible splitting.
+;; not already in use. Remember about possible splitting.
(define_reservation "2_I0"
"2_0mi.i+2_ui0|2_0mii.+(2_ui0|2_ui1)|2_0mmi.+2_ui0\
|2_0mfi.+2_ui0|2_0mi.b+2_ui0|(2_1mi.i|2_1mi.b)+(2_ui0|2_ui1)\
@@ -731,9 +731,38 @@
(eq_attr "itanium_class" "fcvtfx"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_F")
(define_insn_reservation "2_fld" 6
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "fld"))
- (eq (symbol_ref "bundling_p") (const_int 0))) "2_M")
+ (and (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "no"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M")
+(define_insn_reservation "2_flda" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
+(define_insn_reservation "2_fldp" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
(define_insn_reservation "2_fmac" 4
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "fmac"))
@@ -786,17 +815,29 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ilog"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_A")
+(define_insn_reservation "2_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "mmalua"))
+ (eq (symbol_ref "bundling_p") (const_int 0))) "2_A")
;; Latency time ???
(define_insn_reservation "2_ishf" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ishf"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_I+2_only_ui0")
+
(define_insn_reservation "2_ld" 1
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+(define_insn_reservation "2_ldc" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_M_only_um01")
+
(define_insn_reservation "2_long_i" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "long_i"))
@@ -900,11 +941,22 @@
(eq_attr "itanium_class" "xtd"))
(eq (symbol_ref "bundling_p") (const_int 0))) "2_I")
-(define_insn_reservation "2_chk_s" 0
+(define_insn_reservation "2_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(eq (symbol_ref "bundling_p") (const_int 0)))
"2_I|2_M_only_um23")
+(define_insn_reservation "2_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um23")
+(define_insn_reservation "2_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_a"))
+ (eq (symbol_ref "bundling_p") (const_int 0)))
+ "2_M_only_um01")
+
(define_insn_reservation "2_lfetch" 0
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "lfetch"))
@@ -1016,23 +1068,24 @@
(define_bypass 0 "2_tbit" "2_br,2_scall")
(define_bypass 2 "2_ld" "2_ld" "ia64_ld_address_bypass_p")
(define_bypass 2 "2_ld" "2_st" "ia64_st_address_bypass_p")
-(define_bypass 2 "2_ld" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_ilog" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_ialu" "2_mmmul,2_mmshf")
-(define_bypass 3 "2_mmmul,2_mmshf" "2_ialu,2_ilog,2_ishf,2_st,2_ld")
+(define_bypass 2 "2_ld,2_ldc" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_ilog" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_ialu" "2_mmalua,2_mmmul,2_mmshf")
+(define_bypass 3 "2_mmalua,2_mmmul,2_mmshf" "2_ialu,2_ilog,2_ishf,2_st,2_ld,2_ldc")
(define_bypass 6 "2_tofr" "2_frfr,2_stf")
(define_bypass 7 "2_fmac" "2_frfr,2_stf")
;; We don't use here fcmp because scall may be predicated.
-(define_bypass 0 "2_fcvtfx,2_fld,2_fmac,2_fmisc,2_frar_i,2_frar_m,\
- 2_frbr,2_frfr,2_frpr,2_ialu,2_ilog,2_ishf,2_ld,2_long_i,\
- 2_mmmul,2_mmshf,2_mmshfi,2_toar_m,2_tofr,2_xmpy,2_xtd"
+(define_bypass 0 "2_fcvtfx,2_fld,2_flda,2_fldc,2_fmac,2_fmisc,2_frar_i,2_frar_m,\
+ 2_frbr,2_frfr,2_frpr,2_ialu,2_ilog,2_ishf,2_ld,2_ldc,2_long_i,\
+ 2_mmalua,2_mmmul,2_mmshf,2_mmshfi,2_toar_m,2_tofr,\
+ 2_xmpy,2_xtd"
"2_scall")
-(define_bypass 0 "2_unknown,2_ignore,2_stop_bit,2_br,2_fcmp,2_fcvtfx,2_fld,\
+(define_bypass 0 "2_unknown,2_ignore,2_stop_bit,2_br,2_fcmp,2_fcvtfx,2_fld,2_flda,2_fldc,\
2_fmac,2_fmisc,2_frar_i,2_frar_m,2_frbr,2_frfr,2_frpr,\
- 2_ialu,2_icmp,2_ilog,2_ishf,2_ld,2_chk_s,\
- 2_long_i,2_mmmul,2_mmshf,2_mmshfi,2_nop,2_nop_b,2_nop_f,\
+ 2_ialu,2_icmp,2_ilog,2_ishf,2_ld,2_ldc,2_chk_s_i,2_chk_s_f,2_chk_a,2_long_i,\
+ 2_mmalua,2_mmmul,2_mmshf,2_mmshfi,2_nop,2_nop_b,2_nop_f,\
2_nop_i,2_nop_m,2_nop_x,2_rse_m,2_scall,2_sem,2_stf,2_st,\
2_syst_m0,2_syst_m,2_tbit,2_toar_i,2_toar_m,2_tobr,2_tofr,\
2_topr,2_xmpy,2_xtd,2_lfetch" "2_ignore")
@@ -1274,7 +1327,7 @@
"2b_stop")
;; The issue logic can reorder M slot insns between different subtypes
-;; but can not reorder insn within the same subtypes. The following
+;; but cannot reorder insn within the same subtypes. The following
;; constraint is enough to describe this.
(final_presence_set "2b_um1" "2b_um0")
(final_presence_set "2b_um3" "2b_um2")
@@ -1335,7 +1388,7 @@
+(2b_um2|2b_um3)")
;; I instruction is dispersed to the lowest numbered I unit
-;; not already in use. Remeber about possible splitting.
+;; not already in use. Remember about possible splitting.
(define_reservation "2b_I"
"2b_0mi.i+2_2+2b_ui0|2b_0mii.+2_3+(2b_ui0|2b_ui1)|2b_0mmi.+2_3+2b_ui0\
|2b_0mfi.+2_3+2b_ui0|2b_0mi.b+2_2+2b_ui0\
@@ -1533,9 +1586,38 @@
(eq_attr "itanium_class" "fcvtfx"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_F")
(define_insn_reservation "2b_fld" 6
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "fld"))
- (ne (symbol_ref "bundling_p") (const_int 0))) "2b_M")
+ (and (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "no"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M")
+(define_insn_reservation "2b_flda" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "data_speculative" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_fldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fld"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
+(define_insn_reservation "2b_fldp" 6
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_fldpc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "fldp"))
+ (eq_attr "check_load" "yes"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
(define_insn_reservation "2b_fmac" 4
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "fmac"))
@@ -1586,17 +1668,30 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ilog"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_A")
+(define_insn_reservation "2b_mmalua" 2
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "mmalua"))
+ (ne (symbol_ref "bundling_p") (const_int 0))) "2b_A")
;; Latency time ???
(define_insn_reservation "2b_ishf" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "ishf"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_I+2b_only_ui0")
+
(define_insn_reservation "2b_ld" 1
- (and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "ld"))
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "no"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+(define_insn_reservation "2b_ldc" 0
+ (and (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "ld"))
+ (eq_attr "check_load" "yes"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_M_only_um01")
+
(define_insn_reservation "2b_long_i" 1
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "long_i"))
@@ -1695,11 +1790,23 @@
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "xtd"))
(ne (symbol_ref "bundling_p") (const_int 0))) "2b_I")
-(define_insn_reservation "2b_chk_s" 0
+
+(define_insn_reservation "2b_chk_s_i" 0
(and (and (eq_attr "cpu" "itanium2")
- (eq_attr "itanium_class" "chk_s"))
+ (eq_attr "itanium_class" "chk_s_i"))
(ne (symbol_ref "bundling_p") (const_int 0)))
"2b_I|2b_M_only_um23")
+(define_insn_reservation "2b_chk_s_f" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_s_f"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um23")
+(define_insn_reservation "2b_chk_a" 0
+ (and (and (eq_attr "cpu" "itanium2")
+ (eq_attr "itanium_class" "chk_a"))
+ (ne (symbol_ref "bundling_p") (const_int 0)))
+ "2b_M_only_um01")
+
(define_insn_reservation "2b_lfetch" 0
(and (and (eq_attr "cpu" "itanium2")
(eq_attr "itanium_class" "lfetch"))
diff --git a/contrib/gcc/config/ia64/lib1funcs.asm b/contrib/gcc/config/ia64/lib1funcs.asm
index e3d348b..245a8bb 100644
--- a/contrib/gcc/config/ia64/lib1funcs.asm
+++ b/contrib/gcc/config/ia64/lib1funcs.asm
@@ -1,3 +1,30 @@
+/* Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
+ Contributed by James E. Wilson <wilson@cygnus.com>.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, 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. */
+
#ifdef L__divxf3
// Compute a 80-bit IEEE double-extended quotient.
//
@@ -139,10 +166,13 @@ __divdi3:
// Transfer inputs to FP registers.
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, so that they won't be treated as unsigned.
fcvt.xf f8 = f8
fcvt.xf f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -189,10 +219,13 @@ __moddi3:
// Transfer inputs to FP registers.
setf.sig f14 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, so that they won't be treated as unsigned.
fcvt.xf f8 = f14
fcvt.xf f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -243,10 +276,13 @@ __udivdi3:
// Transfer inputs to FP registers.
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, to avoid FP software-assist faults.
fcvt.xuf.s1 f8 = f8
fcvt.xuf.s1 f9 = f9
+(p7) break 1
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -293,10 +329,13 @@ __umoddi3:
// Transfer inputs to FP registers.
setf.sig f14 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
// Convert the inputs to FP, to avoid FP software assist faults.
fcvt.xuf.s1 f8 = f14
fcvt.xuf.s1 f9 = f9
+(p7) break 1;
;;
// Compute the reciprocal approximation.
frcpa.s1 f10, p6 = f8, f9
@@ -345,11 +384,14 @@ __umoddi3:
.proc __divsi3
__divsi3:
.regstk 2,0,0,0
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
sxt4 in0 = in0
sxt4 in1 = in1
;;
setf.sig f8 = in0
setf.sig f9 = in1
+(p7) break 1
;;
mov r2 = 0x0ffdd
fcvt.xf f8 = f8
@@ -394,6 +436,8 @@ __modsi3:
;;
setf.sig f13 = r32
setf.sig f9 = r33
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
sub in1 = r0, in1
fcvt.xf f8 = f13
@@ -401,6 +445,7 @@ __modsi3:
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
+(p7) break 1
;;
(p6) fmpy.s1 f12 = f8, f10
(p6) fnma.s1 f10 = f9, f10, f1
@@ -441,9 +486,12 @@ __udivsi3:
;;
setf.sig f8 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
fcvt.xf f8 = f8
fcvt.xf f9 = f9
+(p7) break 1
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
@@ -484,6 +532,8 @@ __umodsi3:
;;
setf.sig f13 = in0
setf.sig f9 = in1
+ // Check divide by zero.
+ cmp.ne.unc p0,p7=0,in1
;;
sub in1 = r0, in1
fcvt.xf f8 = f13
@@ -491,6 +541,7 @@ __umodsi3:
;;
setf.exp f11 = r2
frcpa.s1 f10, p6 = f8, f9
+(p7) break 1;
;;
(p6) fmpy.s1 f12 = f8, f10
(p6) fnma.s1 f10 = f9, f10, f1
@@ -706,9 +757,8 @@ __ia64_trampoline:
.endp __ia64_trampoline
#endif
-#ifdef L__compat
// Thunks for backward compatibility.
-
+#ifdef L_fixtfdi
.text
.align 16
.global __fixtfti
@@ -719,7 +769,8 @@ __fixtfti:
;;
}
.endp __fixtfti
-
+#endif
+#ifdef L_fixunstfdi
.align 16
.global __fixunstfti
.proc __fixunstfti
@@ -729,7 +780,8 @@ __fixunstfti:
;;
}
.endp __fixunstfti
-
+#endif
+#if L_floatditf
.align 16
.global __floattitf
.proc __floattitf
@@ -739,5 +791,4 @@ __floattitf:
;;
}
.endp __floattitf
-
#endif
diff --git a/contrib/gcc/config/ia64/linux-unwind.h b/contrib/gcc/config/ia64/linux-unwind.h
new file mode 100644
index 0000000..8b2878e
--- /dev/null
+++ b/contrib/gcc/config/ia64/linux-unwind.h
@@ -0,0 +1,193 @@
+/* DWARF2 EH unwinding support for IA64 Linux.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 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 with other programs, and to
+ distribute those programs 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 another program.)
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+/* This works only for glibc-2.3 and later, because sigcontext is different
+ in glibc-2.2.4. */
+
+#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
+#include <signal.h>
+#include <sys/ucontext.h>
+
+#define IA64_GATE_AREA_START 0xa000000000000100LL
+#define IA64_GATE_AREA_END 0xa000000000030000LL
+
+#define MD_FALLBACK_FRAME_STATE_FOR ia64_fallback_frame_state
+
+static _Unwind_Reason_Code
+ia64_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ if (context->rp >= IA64_GATE_AREA_START
+ && context->rp < IA64_GATE_AREA_END)
+ {
+ struct sigframe {
+ char scratch[16];
+ unsigned long sig_number;
+ struct siginfo *info;
+ struct sigcontext *sc;
+ } *frame_ = (struct sigframe *)context->psp;
+ struct sigcontext *sc = frame_->sc;
+
+ /* Restore scratch registers in case the unwinder needs to
+ refer to a value stored in one of them. */
+ {
+ int i;
+
+ for (i = 2; i < 4; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 8; i < 12; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 14; i < 32; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ }
+
+ context->fpsr_loc = &(sc->sc_ar_fpsr);
+ context->pfs_loc = &(sc->sc_ar_pfs);
+ context->lc_loc = &(sc->sc_ar_lc);
+ context->unat_loc = &(sc->sc_ar_unat);
+ context->br_loc[0] = &(sc->sc_br[0]);
+ context->br_loc[6] = &(sc->sc_br[6]);
+ context->br_loc[7] = &(sc->sc_br[7]);
+ context->pr = sc->sc_pr;
+ context->psp = sc->sc_gr[12];
+ context->gp = sc->sc_gr[1];
+ /* Signal frame doesn't have an associated reg. stack frame
+ other than what we adjust for below. */
+ fs -> no_reg_stack_frame = 1;
+
+ if (sc->sc_rbs_base)
+ {
+ /* Need to switch from alternate register backing store. */
+ long ndirty, loadrs = sc->sc_loadrs >> 16;
+ unsigned long alt_bspstore = context->bsp - loadrs;
+ unsigned long bspstore;
+ unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
+
+ ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
+ (unsigned long *) context->bsp);
+ bspstore = (unsigned long)
+ ia64_rse_skip_regs (ar_bsp, -ndirty);
+ ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
+ sc->sc_ar_rnat);
+ }
+
+ /* Don't touch the branch registers o.t. b0, b6 and b7.
+ The kernel doesn't pass the preserved branch registers
+ in the sigcontext but leaves them intact, so there's no
+ need to do anything with them here. */
+ {
+ unsigned long sof = sc->sc_cfm & 0x7f;
+ context->bsp = (unsigned long)
+ ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
+ }
+
+ fs->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL;
+ fs->curr.reg[UNW_REG_RP].val
+ = (unsigned long)&(sc->sc_ip) - context->psp;
+ fs->curr.reg[UNW_REG_RP].when = -1;
+
+ return _URC_NO_REASON;
+ }
+ return _URC_END_OF_STACK;
+}
+
+#define MD_HANDLE_UNWABI ia64_handle_unwabi
+
+static void
+ia64_handle_unwabi (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ if (fs->unwabi == ((3 << 8) | 's')
+ || fs->unwabi == ((0 << 8) | 's'))
+ {
+ struct sigframe {
+ char scratch[16];
+ unsigned long sig_number;
+ struct siginfo *info;
+ struct sigcontext *sc;
+ } *frame = (struct sigframe *)context->psp;
+ struct sigcontext *sc = frame->sc;
+
+ /* Restore scratch registers in case the unwinder needs to
+ refer to a value stored in one of them. */
+ {
+ int i;
+
+ for (i = 2; i < 4; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 8; i < 12; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ for (i = 14; i < 32; i++)
+ context->ireg[i - 2].loc = &sc->sc_gr[i];
+ }
+
+ context->pfs_loc = &(sc->sc_ar_pfs);
+ context->lc_loc = &(sc->sc_ar_lc);
+ context->unat_loc = &(sc->sc_ar_unat);
+ context->br_loc[0] = &(sc->sc_br[0]);
+ context->br_loc[6] = &(sc->sc_br[6]);
+ context->br_loc[7] = &(sc->sc_br[7]);
+ context->pr = sc->sc_pr;
+ context->gp = sc->sc_gr[1];
+ /* Signal frame doesn't have an associated reg. stack frame
+ other than what we adjust for below. */
+ fs -> no_reg_stack_frame = 1;
+
+ if (sc->sc_rbs_base)
+ {
+ /* Need to switch from alternate register backing store. */
+ long ndirty, loadrs = sc->sc_loadrs >> 16;
+ unsigned long alt_bspstore = context->bsp - loadrs;
+ unsigned long bspstore;
+ unsigned long *ar_bsp = (unsigned long *)(sc->sc_ar_bsp);
+
+ ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore,
+ (unsigned long *) context->bsp);
+ bspstore = (unsigned long) ia64_rse_skip_regs (ar_bsp, -ndirty);
+ ia64_copy_rbs (context, bspstore, alt_bspstore, loadrs,
+ sc->sc_ar_rnat);
+ }
+
+ /* Don't touch the branch registers o.t. b0, b6 and b7.
+ The kernel doesn't pass the preserved branch registers
+ in the sigcontext but leaves them intact, so there's no
+ need to do anything with them here. */
+ {
+ unsigned long sof = sc->sc_cfm & 0x7f;
+ context->bsp = (unsigned long)
+ ia64_rse_skip_regs ((unsigned long *)(sc->sc_ar_bsp), -sof);
+ }
+
+ /* pfs_loc already set above. Without this pfs_loc would point
+ incorrectly to sc_cfm instead of sc_ar_pfs. */
+ fs->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE;
+ }
+}
+#endif /* glibc-2.3 or better */
diff --git a/contrib/gcc/config/ia64/linux.h b/contrib/gcc/config/ia64/linux.h
index 5c73b0c..cecae0d 100644
--- a/contrib/gcc/config/ia64/linux.h
+++ b/contrib/gcc/config/ia64/linux.h
@@ -37,15 +37,18 @@ do { \
/* Define this for shared library support because it isn't in the main
linux.h file. */
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux-ia64.so.2"
+
#undef LINK_SPEC
#define LINK_SPEC "\
%{shared:-shared} \
%{!shared: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux-ia64.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "}} \
%{static:-static}}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#define JMP_BUF_SIZE 76
@@ -55,161 +58,4 @@ do { \
#undef LINK_EH_SPEC
#define LINK_EH_SPEC ""
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-/* This works only for glibc-2.3 and later, because sigcontext is different
- in glibc-2.2.4. */
-
-#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)
-
-#ifdef IN_LIBGCC2
-#include <signal.h>
-#include <sys/ucontext.h>
-
-#define IA64_GATE_AREA_START 0xa000000000000100LL
-#define IA64_GATE_AREA_END 0xa000000000030000LL
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- if ((CONTEXT)->rp >= IA64_GATE_AREA_START \
- && (CONTEXT)->rp < IA64_GATE_AREA_END) \
- { \
- struct sigframe { \
- char scratch[16]; \
- unsigned long sig_number; \
- struct siginfo *info; \
- struct sigcontext *sc; \
- } *frame_ = (struct sigframe *)(CONTEXT)->psp; \
- struct sigcontext *sc_ = frame_->sc; \
- \
- /* Restore scratch registers in case the unwinder needs to \
- refer to a value stored in one of them. */ \
- { \
- int i_; \
- \
- for (i_ = 2; i_ < 4; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 8; i_ < 12; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 14; i_ < 32; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- } \
- \
- (CONTEXT)->fpsr_loc = &(sc_->sc_ar_fpsr); \
- (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
- (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
- (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
- (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
- (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
- (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
- (CONTEXT)->pr = sc_->sc_pr; \
- (CONTEXT)->psp = sc_->sc_gr[12]; \
- (CONTEXT)->gp = sc_->sc_gr[1]; \
- /* Signal frame doesn't have an associated reg. stack frame \
- other than what we adjust for below. */ \
- (FS) -> no_reg_stack_frame = 1; \
- \
- if (sc_->sc_rbs_base) \
- { \
- /* Need to switch from alternate register backing store. */ \
- long ndirty, loadrs = sc_->sc_loadrs >> 16; \
- unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
- unsigned long bspstore; \
- unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
- \
- ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
- (unsigned long *) (CONTEXT)->bsp);\
- bspstore = (unsigned long) \
- ia64_rse_skip_regs (ar_bsp, -ndirty); \
- ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
- sc_->sc_ar_rnat); \
- } \
- \
- /* Don't touch the branch registers o.t. b0, b6 and b7. \
- The kernel doesn't pass the preserved branch registers \
- in the sigcontext but leaves them intact, so there's no \
- need to do anything with them here. */ \
- { \
- unsigned long sof = sc_->sc_cfm & 0x7f; \
- (CONTEXT)->bsp = (unsigned long) \
- ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
- } \
- \
- (FS)->curr.reg[UNW_REG_RP].where = UNW_WHERE_SPREL; \
- (FS)->curr.reg[UNW_REG_RP].val \
- = (unsigned long)&(sc_->sc_ip) - (CONTEXT)->psp; \
- (FS)->curr.reg[UNW_REG_RP].when = -1; \
- \
- goto SUCCESS; \
- }
-
-#define MD_HANDLE_UNWABI(CONTEXT, FS) \
- if ((FS)->unwabi == ((3 << 8) | 's') \
- || (FS)->unwabi == ((0 << 8) | 's')) \
- { \
- struct sigframe { \
- char scratch[16]; \
- unsigned long sig_number; \
- struct siginfo *info; \
- struct sigcontext *sc; \
- } *frame_ = (struct sigframe *)(CONTEXT)->psp; \
- struct sigcontext *sc_ = frame_->sc; \
- \
- /* Restore scratch registers in case the unwinder needs to \
- refer to a value stored in one of them. */ \
- { \
- int i_; \
- \
- for (i_ = 2; i_ < 4; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 8; i_ < 12; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- for (i_ = 14; i_ < 32; i_++) \
- (CONTEXT)->ireg[i_ - 2].loc = &sc_->sc_gr[i_]; \
- } \
- \
- (CONTEXT)->pfs_loc = &(sc_->sc_ar_pfs); \
- (CONTEXT)->lc_loc = &(sc_->sc_ar_lc); \
- (CONTEXT)->unat_loc = &(sc_->sc_ar_unat); \
- (CONTEXT)->br_loc[0] = &(sc_->sc_br[0]); \
- (CONTEXT)->br_loc[6] = &(sc_->sc_br[6]); \
- (CONTEXT)->br_loc[7] = &(sc_->sc_br[7]); \
- (CONTEXT)->pr = sc_->sc_pr; \
- (CONTEXT)->gp = sc_->sc_gr[1]; \
- /* Signal frame doesn't have an associated reg. stack frame \
- other than what we adjust for below. */ \
- (FS) -> no_reg_stack_frame = 1; \
- \
- if (sc_->sc_rbs_base) \
- { \
- /* Need to switch from alternate register backing store. */ \
- long ndirty, loadrs = sc_->sc_loadrs >> 16; \
- unsigned long alt_bspstore = (CONTEXT)->bsp - loadrs; \
- unsigned long bspstore; \
- unsigned long *ar_bsp = (unsigned long *)(sc_->sc_ar_bsp); \
- \
- ndirty = ia64_rse_num_regs ((unsigned long *) alt_bspstore, \
- (unsigned long *) (CONTEXT)->bsp);\
- bspstore = (unsigned long) \
- ia64_rse_skip_regs (ar_bsp, -ndirty); \
- ia64_copy_rbs ((CONTEXT), bspstore, alt_bspstore, loadrs, \
- sc_->sc_ar_rnat); \
- } \
- \
- /* Don't touch the branch registers o.t. b0, b6 and b7. \
- The kernel doesn't pass the preserved branch registers \
- in the sigcontext but leaves them intact, so there's no \
- need to do anything with them here. */ \
- { \
- unsigned long sof = sc_->sc_cfm & 0x7f; \
- (CONTEXT)->bsp = (unsigned long) \
- ia64_rse_skip_regs ((unsigned long *)(sc_->sc_ar_bsp), -sof); \
- } \
- \
- /* pfs_loc already set above. Without this pfs_loc would point \
- incorrectly to sc_cfm instead of sc_ar_pfs. */ \
- (FS)->curr.reg[UNW_REG_PFS].where = UNW_WHERE_NONE; \
- }
-
-#endif /* IN_LIBGCC2 */
-#endif /* glibc-2.3 or better */
+#define MD_UNWIND_SUPPORT "config/ia64/linux-unwind.h"
diff --git a/contrib/gcc/config/ia64/predicates.md b/contrib/gcc/config/ia64/predicates.md
new file mode 100644
index 0000000..657c150
--- /dev/null
+++ b/contrib/gcc/config/ia64/predicates.md
@@ -0,0 +1,591 @@
+;; Predicate definitions for IA-64.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; True if OP is a valid operand for the MEM of a CALL insn.
+(define_predicate "call_operand"
+ (ior (match_code "symbol_ref")
+ (match_operand 0 "register_operand")))
+
+;; True if OP refers to any kind of symbol.
+;; For roughly the same reasons that pmode_register_operand exists, this
+;; predicate ignores its mode argument.
+(define_special_predicate "symbolic_operand"
+ (match_code "symbol_ref,const,label_ref"))
+
+;; True if OP is a SYMBOL_REF which refers to a function.
+(define_predicate "function_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_FUNCTION_P (op)")))
+
+;; True if OP refers to a symbol in the sdata section.
+(define_predicate "sdata_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ HOST_WIDE_INT offset = 0, size = 0;
+
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ offset = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ if (CONSTANT_POOL_ADDRESS_P (op))
+ {
+ size = GET_MODE_SIZE (get_pool_mode (op));
+ if (size > ia64_section_threshold)
+ return false;
+ }
+ else
+ {
+ tree t;
+
+ if (!SYMBOL_REF_LOCAL_P (op) || !SYMBOL_REF_SMALL_P (op))
+ return false;
+
+ /* Note that in addition to DECLs, we can get various forms
+ of constants here. */
+ t = SYMBOL_REF_DECL (op);
+ if (DECL_P (t))
+ t = DECL_SIZE_UNIT (t);
+ else
+ t = TYPE_SIZE_UNIT (TREE_TYPE (t));
+ if (t && host_integerp (t, 0))
+ {
+ size = tree_low_cst (t, 0);
+ if (size < 0)
+ size = 0;
+ }
+ }
+
+ /* Deny the stupid user trick of addressing outside the object. Such
+ things quickly result in GPREL22 relocation overflows. Of course,
+ they're also highly undefined. From a pure pedant's point of view
+ they deserve a slap on the wrist (such as provided by a relocation
+ overflow), but that just leads to bugzilla noise. */
+ return (offset >= 0 && offset <= size);
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; True if OP refers to a symbol in the small address area.
+(define_predicate "small_addr_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_SMALL_ADDR_P (op);
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; True if OP refers to a symbol with which we may use any offset.
+(define_predicate "any_offset_symbol_operand"
+ (match_code "symbol_ref")
+{
+ if (TARGET_NO_PIC || TARGET_AUTO_PIC)
+ return true;
+ if (SYMBOL_REF_SMALL_ADDR_P (op))
+ return true;
+ if (SYMBOL_REF_FUNCTION_P (op))
+ return false;
+ if (sdata_symbolic_operand (op, mode))
+ return true;
+ return false;
+})
+
+;; True if OP refers to a symbol with which we may use 14-bit aligned offsets.
+;; False if OP refers to a symbol with which we may not use any offset at any
+;; time.
+(define_predicate "aligned_offset_symbol_operand"
+ (and (match_code "symbol_ref")
+ (match_test "! SYMBOL_REF_FUNCTION_P (op)")))
+
+;; True if OP refers to a symbol, and is appropriate for a GOT load.
+(define_predicate "got_symbolic_operand"
+ (match_operand 0 "symbolic_operand" "")
+{
+ HOST_WIDE_INT addend = 0;
+
+ switch (GET_CODE (op))
+ {
+ case LABEL_REF:
+ return true;
+
+ case CONST:
+ /* Accept only (plus (symbol_ref) (const_int)). */
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ addend = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ /* These symbols shouldn't be used with got loads. */
+ if (SYMBOL_REF_SMALL_ADDR_P (op))
+ return false;
+ if (SYMBOL_REF_TLS_MODEL (op) != 0)
+ return false;
+
+ if (any_offset_symbol_operand (op, mode))
+ return true;
+
+ /* The low 14 bits of the constant have been forced to zero
+ so that we do not use up so many GOT entries. Prevent cse
+ from undoing this. */
+ if (aligned_offset_symbol_operand (op, mode))
+ return (addend & 0x3fff) == 0;
+
+ return addend == 0;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a valid thread local storage symbolic operand.
+(define_predicate "tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) != 0;
+
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ /* We only allow certain offsets for certain tls models. */
+ switch (SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ return false;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ return (INTVAL (XEXP (op, 1)) & 0x3fff) == 0;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ return true;
+
+ default:
+ return false;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a local-dynamic thread local storage symbolic operand.
+(define_predicate "ld_tls_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+
+;; Return true if OP is an initial-exec thread local storage symbolic operand.
+(define_predicate "ie_tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT
+ || (INTVAL (XEXP (op, 1)) & 0x3fff) != 0)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a local-exec thread local storage symbolic operand.
+(define_predicate "le_tls_symbolic_operand"
+ (match_code "symbol_ref,const")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+ op = XEXP (op, 0);
+ /* FALLTHRU */
+
+ case SYMBOL_REF:
+ return SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Like nonimmediate_operand, but don't allow MEMs that try to use a
+;; POST_MODIFY with a REG as displacement.
+(define_predicate "destination_operand"
+ (and (match_operand 0 "nonimmediate_operand")
+ (match_test "GET_CODE (op) != MEM
+ || GET_CODE (XEXP (op, 0)) != POST_MODIFY
+ || GET_CODE (XEXP (XEXP (XEXP (op, 0), 1), 1)) != REG")))
+
+;; Like memory_operand, but don't allow post-increments.
+(define_predicate "not_postinc_memory_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "GET_RTX_CLASS (GET_CODE (XEXP (op, 0))) != RTX_AUTOINC")))
+
+;; True if OP is a general operand, with some restrictions on symbols.
+(define_predicate "move_operand"
+ (match_operand 0 "general_operand")
+{
+ switch (GET_CODE (op))
+ {
+ case CONST:
+ {
+ HOST_WIDE_INT addend;
+
+ /* Accept only (plus (symbol_ref) (const_int)). */
+ op = XEXP (op, 0);
+ if (GET_CODE (op) != PLUS
+ || GET_CODE (XEXP (op, 0)) != SYMBOL_REF
+ || GET_CODE (XEXP (op, 1)) != CONST_INT)
+ return false;
+
+ addend = INTVAL (XEXP (op, 1));
+ op = XEXP (op, 0);
+
+ /* After reload, we want to allow any offset whatsoever. This
+ allows reload the opportunity to avoid spilling addresses to
+ the stack, and instead simply substitute in the value from a
+ REG_EQUIV. We'll split this up again when splitting the insn. */
+ if (reload_in_progress || reload_completed)
+ return true;
+
+ /* Some symbol types we allow to use with any offset. */
+ if (any_offset_symbol_operand (op, mode))
+ return true;
+
+ /* Some symbol types we allow offsets with the low 14 bits of the
+ constant forced to zero so that we do not use up so many GOT
+ entries. We want to prevent cse from undoing this. */
+ if (aligned_offset_symbol_operand (op, mode))
+ return (addend & 0x3fff) == 0;
+
+ /* The remaining symbol types may never be used with an offset. */
+ return false;
+ }
+
+ default:
+ return true;
+ }
+})
+
+;; True if OP is a register operand that is (or could be) a GR reg.
+(define_predicate "gr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
+})
+
+;; True if OP is a register operand that is (or could be) an FR reg.
+(define_predicate "fr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno));
+})
+
+;; True if OP is a register operand that is (or could be) a GR/FR reg.
+(define_predicate "grfr_register_operand"
+ (match_operand 0 "register_operand")
+{
+ unsigned int regno;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER
+ || GENERAL_REGNO_P (regno)
+ || FR_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a GR reg.
+(define_predicate "gr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || GENERAL_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a FR reg.
+(define_predicate "fr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER || FR_REGNO_P (regno));
+})
+
+;; True if OP is a nonimmediate operand that is (or could be) a GR/FR reg.
+(define_predicate "grfr_nonimmediate_operand"
+ (match_operand 0 "nonimmediate_operand")
+{
+ unsigned int regno;
+
+ if (GET_CODE (op) == MEM)
+ return true;
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ regno = REGNO (op);
+ return (regno >= FIRST_PSEUDO_REGISTER
+ || GENERAL_REGNO_P (regno)
+ || FR_REGNO_P (regno));
+})
+
+;; True if OP is a GR register operand, or zero.
+(define_predicate "gr_reg_or_0_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))"))))
+
+;; True if OP is a GR register operand, or a 5 bit immediate operand.
+(define_predicate "gr_reg_or_5bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32"))))
+
+;; True if OP is a GR register operand, or a 6 bit immediate operand.
+(define_predicate "gr_reg_or_6bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op))"))))
+
+;; True if OP is a GR register operand, or an 8 bit immediate operand.
+(define_predicate "gr_reg_or_8bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))"))))
+
+;; True if OP is a GR/FR register operand, or an 8 bit immediate operand.
+(define_predicate "grfr_reg_or_8bit_operand"
+ (ior (match_operand 0 "grfr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))"))))
+
+;; True if OP is a register operand, or an 8 bit adjusted immediate operand.
+(define_predicate "gr_reg_or_8bit_adjusted_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_L (INTVAL (op))"))))
+
+;; True if OP is a register operand, or is valid for both an 8 bit
+;; immediate and an 8 bit adjusted immediate operand. This is necessary
+;; because when we emit a compare, we don't know what the condition will be,
+;; so we need the union of the immediates accepted by GT and LT.
+(define_predicate "gr_reg_or_8bit_and_adjusted_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_K (INTVAL (op))
+ && CONST_OK_FOR_L (INTVAL (op))"))))
+
+;; True if OP is a register operand, or a 14 bit immediate operand.
+(define_predicate "gr_reg_or_14bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_I (INTVAL (op))"))))
+
+;; True if OP is a register operand, or a 22 bit immediate operand.
+(define_predicate "gr_reg_or_22bit_operand"
+ (ior (match_operand 0 "gr_register_operand")
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_J (INTVAL (op))"))))
+
+;; True if OP is a 7 bit immediate operand.
+(define_predicate "dshift_count_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 128")))
+
+;; True if OP is a 6 bit immediate operand.
+(define_predicate "shift_count_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op))")))
+
+;; True if OP-1 is a 6 bit immediate operand, used in extr instruction.
+(define_predicate "extr_len_operand"
+ (and (match_code "const_int")
+ (match_test "CONST_OK_FOR_M (INTVAL (op) - 1)")))
+
+;; True if OP is a 5 bit immediate operand.
+(define_predicate "shift_32bit_count_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) < 32")))
+
+;; True if OP is one of the immediate values 2, 4, 8, or 16.
+(define_predicate "shladd_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 2 || INTVAL (op) == 4 ||
+ INTVAL (op) == 8 || INTVAL (op) == 16")))
+
+;; True if OP is one of the immediate values 1, 2, 3, or 4.
+(define_predicate "shladd_log2_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 1 && INTVAL (op) <= 4")))
+
+;; True if OP is one of the immediate values -16, -8, -4, -1, 1, 4, 8, 16.
+(define_predicate "fetchadd_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == -16 || INTVAL (op) == -8 ||
+ INTVAL (op) == -4 || INTVAL (op) == -1 ||
+ INTVAL (op) == 1 || INTVAL (op) == 4 ||
+ INTVAL (op) == 8 || INTVAL (op) == 16")))
+
+;; True if OP is 0..3.
+(define_predicate "const_int_2bit_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 3")))
+
+;; True if OP is a floating-point constant zero, one, or a register.
+(define_predicate "fr_reg_or_fp01_operand"
+ (ior (match_operand 0 "fr_register_operand")
+ (and (match_code "const_double")
+ (match_test "CONST_DOUBLE_OK_FOR_G (op)"))))
+
+;; Like fr_reg_or_fp01_operand, but don't allow any SUBREGs.
+(define_predicate "xfreg_or_fp01_operand"
+ (and (match_operand 0 "fr_reg_or_fp01_operand")
+ (not (match_code "subreg"))))
+
+;; True if OP is a constant zero, or a register.
+(define_predicate "fr_reg_or_0_operand"
+ (ior (match_operand 0 "fr_register_operand")
+ (and (match_code "const_double,const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))"))))
+
+;; True if this is a comparison operator, which accepts a normal 8-bit
+;; signed immediate operand.
+(define_predicate "normal_comparison_operator"
+ (match_code "eq,ne,gt,le,gtu,leu"))
+
+;; True if this is a comparison operator, which accepts an adjusted 8-bit
+;; signed immediate operand.
+(define_predicate "adjusted_comparison_operator"
+ (match_code "lt,ge,ltu,geu"))
+
+;; True if this is a signed inequality operator.
+(define_predicate "signed_inequality_operator"
+ (match_code "ge,gt,le,lt"))
+
+;; True if this operator is valid for predication.
+(define_predicate "predicate_operator"
+ (match_code "eq,ne"))
+
+;; True if this operator can be used in a conditional operation.
+(define_predicate "condop_operator"
+ (match_code "plus,minus,ior,xor,and"))
+
+;; These three are hardware registers that can only be addressed in
+;; DImode. It's not strictly necessary to test mode == DImode here,
+;; but it makes decent insurance against someone writing a
+;; match_operand wrong.
+
+;; True if this is the ar.lc register.
+(define_predicate "ar_lc_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_LC_REGNUM")))
+
+;; True if this is the ar.ccv register.
+(define_predicate "ar_ccv_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_CCV_REGNUM")))
+
+;; True if this is the ar.pfs register.
+(define_predicate "ar_pfs_reg_operand"
+ (and (match_code "reg")
+ (match_test "mode == DImode && REGNO (op) == AR_PFS_REGNUM")))
+
+;; True if OP is valid as a base register in a reg + offset address.
+;; ??? Should I copy the flag_omit_frame_pointer and cse_not_expected
+;; checks from pa.c basereg_operand as well? Seems to be OK without them
+;; in test runs.
+(define_predicate "basereg_operand"
+ (match_operand 0 "register_operand")
+{
+ return REG_P (op) && REG_POINTER (op);
+})
+
diff --git a/contrib/gcc/config/ia64/quadlib.c b/contrib/gcc/config/ia64/quadlib.c
index cc367ea..e4bff78 100644
--- a/contrib/gcc/config/ia64/quadlib.c
+++ b/contrib/gcc/config/ia64/quadlib.c
@@ -24,8 +24,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
extern int _U_Qfcmp (long double a, long double b, int);
diff --git a/contrib/gcc/config/ia64/sync.md b/contrib/gcc/config/ia64/sync.md
new file mode 100644
index 0000000..43ad28b
--- /dev/null
+++ b/contrib/gcc/config/ia64/sync.md
@@ -0,0 +1,178 @@
+;; GCC machine description for IA-64 synchronization instructions.
+;; Copyright (C) 2005
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_mode_macro IMODE [QI HI SI DI])
+(define_mode_macro I124MODE [QI HI SI])
+(define_mode_macro I48MODE [SI DI])
+(define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")])
+
+(define_code_macro FETCHOP [plus minus ior xor and])
+(define_code_attr fetchop_name
+ [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
+
+(define_insn "memory_barrier"
+ [(set (mem:BLK (match_scratch:DI 0 "X"))
+ (unspec:BLK [(mem:BLK (match_scratch:DI 1 "X"))] UNSPEC_MF))]
+ ""
+ "mf"
+ [(set_attr "itanium_class" "syst_m")])
+
+(define_insn "fetchadd_acq_<mode>"
+ [(set (match_operand:I48MODE 0 "gr_register_operand" "=r")
+ (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:I48MODE [(match_dup 1)
+ (match_operand:I48MODE 2 "fetchadd_operand" "n")]
+ UNSPEC_FETCHADD_ACQ))]
+ ""
+ "fetchadd<modesuffix>.acq %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_expand "sync_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (FETCHOP:IMODE (match_dup 0)
+ (match_operand:IMODE 1 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL);
+ DONE;
+})
+
+(define_expand "sync_nand<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (and:IMODE (not:IMODE (match_dup 0))
+ (match_operand:IMODE 1 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL);
+ DONE;
+})
+
+(define_expand "sync_old_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL);
+ DONE;
+})
+
+(define_expand "sync_old_nand<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (and:IMODE
+ (not:IMODE (match_operand:IMODE 1 "memory_operand" ""))
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL);
+ DONE;
+})
+
+(define_expand "sync_new_<fetchop_name><mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (FETCHOP:IMODE
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0]);
+ DONE;
+})
+
+(define_expand "sync_new_nand<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "")
+ (and:IMODE
+ (not:IMODE (match_operand:IMODE 1 "memory_operand" ""))
+ (match_operand:IMODE 2 "general_operand" "")))]
+ ""
+{
+ ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0]);
+ DONE;
+})
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(match_operand:IMODE 0 "gr_register_operand" "")
+ (match_operand:IMODE 1 "memory_operand" "")
+ (match_operand:IMODE 2 "gr_register_operand" "")
+ (match_operand:IMODE 3 "gr_register_operand" "")]
+ ""
+{
+ rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM);
+ rtx dst;
+
+ convert_move (ccv, operands[2], 1);
+
+ dst = operands[0];
+ if (GET_MODE (dst) != DImode)
+ dst = gen_reg_rtx (DImode);
+
+ emit_insn (gen_memory_barrier ());
+ emit_insn (gen_cmpxchg_rel_<mode> (dst, operands[1], ccv, operands[3]));
+
+ if (dst != operands[0])
+ emit_move_insn (operands[0], gen_lowpart (<MODE>mode, dst));
+ DONE;
+})
+
+(define_insn "cmpxchg_rel_<mode>"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (zero_extend:DI
+ (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S")))
+ (set (match_dup 1)
+ (unspec:I124MODE
+ [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:I124MODE 3 "gr_register_operand" "r")]
+ UNSPEC_CMPXCHG_ACQ))]
+ ""
+ "cmpxchg<modesuffix>.rel %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "cmpxchg_rel_di"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (match_operand:DI 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (unspec:DI [(match_dup 1)
+ (match_operand:DI 2 "ar_ccv_reg_operand" "")
+ (match_operand:DI 3 "gr_register_operand" "r")]
+ UNSPEC_CMPXCHG_ACQ))]
+ ""
+ "cmpxchg8.rel %0 = %1, %3, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_insn "sync_lock_test_and_set<mode>"
+ [(set (match_operand:IMODE 0 "gr_register_operand" "=r")
+ (match_operand:IMODE 1 "not_postinc_memory_operand" "+S"))
+ (set (match_dup 1)
+ (match_operand:IMODE 2 "gr_register_operand" "r"))]
+ ""
+ "xchg<modesuffix> %0 = %1, %2"
+ [(set_attr "itanium_class" "sem")])
+
+(define_expand "sync_lock_release<mode>"
+ [(set (match_operand:IMODE 0 "memory_operand" "")
+ (match_operand:IMODE 1 "gr_reg_or_0_operand" ""))]
+ ""
+{
+ gcc_assert (MEM_VOLATILE_P (operands[0]));
+})
diff --git a/contrib/gcc/config/ia64/sysv4.h b/contrib/gcc/config/ia64/sysv4.h
index 15a57d9..795b6ea 100644
--- a/contrib/gcc/config/ia64/sysv4.h
+++ b/contrib/gcc/config/ia64/sysv4.h
@@ -1,5 +1,8 @@
/* Override definitions in elfos.h/svr4.h to be correct for IA64. */
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ia64_sysv4_init_libfuncs
+
/* We want DWARF2 as specified by the IA64 ABI. */
#undef PREFERRED_DEBUGGING_TYPE
#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
@@ -43,9 +46,9 @@ extern int size_directive_output;
#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
if ((DECL) && sdata_symbolic_operand (XEXP (DECL_RTL (DECL), 0), Pmode)) \
- sbss_section (); \
+ switch_to_section (sbss_section); \
else \
- bss_section (); \
+ switch_to_section (bss_section); \
ASM_OUTPUT_ALIGN (FILE, floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
ASM_DECLARE_OBJECT_NAME (FILE, NAME, DECL); \
ASM_OUTPUT_SKIP (FILE, SIZE ? SIZE : 1); \
@@ -118,39 +121,10 @@ do { \
} while (0)
/* Override default elf definition. */
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK ia64_reloc_rw_mask
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION ia64_select_rtx_section
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_sdata, in_sbss
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- SDATA_SECTION_FUNCTION \
- SBSS_SECTION_FUNCTION
-
#define SDATA_SECTION_ASM_OP "\t.sdata"
-
-#define SDATA_SECTION_FUNCTION \
-void \
-sdata_section (void) \
-{ \
- if (in_section != in_sdata) \
- { \
- fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
- in_section = in_sdata; \
- } \
-}
-
#define SBSS_SECTION_ASM_OP "\t.sbss"
-
-#define SBSS_SECTION_FUNCTION \
-void \
-sbss_section (void) \
-{ \
- if (in_section != in_sbss) \
- { \
- fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
- in_section = in_sbss; \
- } \
-}
diff --git a/contrib/gcc/config/ia64/t-hpux b/contrib/gcc/config/ia64/t-hpux
index d89f174..b925c73 100644
--- a/contrib/gcc/config/ia64/t-hpux
+++ b/contrib/gcc/config/ia64/t-hpux
@@ -7,9 +7,15 @@ MULTILIB_OPTIONS = milp32/mlp64
MULTILIB_DIRNAMES = hpux32 hpux64
MULTILIB_MATCHES =
+# On HP-UX we do not want _fixtfdi, _fixunstfdi, or _floatditf from
+# LIB1ASMSRC. These functions map the 128 bit conversion function names
+# to 80 bit conversions and were done for Linux backwards compatibility.
+
+LIB1ASMFUNCS := $(filter-out _fixtfdi _fixunstfdi _floatditf,$(LIB1ASMFUNCS))
+
# Support routines for HP-UX 128 bit floats.
-LIB2FUNCS_EXTRA=quadlib.c
+LIB2FUNCS_EXTRA=quadlib.c $(srcdir)/config/floatunsitf.c
quadlib.c: $(srcdir)/config/ia64/quadlib.c
cat $(srcdir)/config/ia64/quadlib.c > quadlib.c
@@ -32,14 +38,19 @@ SHLIB_EXT = .so
# DT_NEEDED entry for libunwind.
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,+h,@shlib_base_name@.so.0 \
- -o @shlib_base_name@.so @multilib_flags@ @shlib_objs@ -lunwind -lc && \
- rm -f @shlib_base_name@.so.0 && \
- $(LN_S) @shlib_base_name@.so @shlib_base_name@.so.0
+ -o @multilib_dir@/@shlib_base_name@.so @multilib_flags@ \
+ @shlib_objs@ -lunwind -lc && \
+ rm -f @multilib_dir@/@shlib_base_name@.so.0 && \
+ $(LN_S) @shlib_base_name@.so @multilib_dir@/@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 $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so.0; \
- rm -f $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
- $(LN_S) @shlib_base_name@.so.0 $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so; \
- chmod +x $$(DESTDIR)$$(slibdir)/@shlib_base_name@.so
+SHLIB_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
+ $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.so \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so.0; \
+ rm -f $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
+ $(LN_S) @shlib_base_name@.so.0 \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so; \
+ chmod +x $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/@shlib_base_name@.so
SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
diff --git a/contrib/gcc/config/ia64/t-ia64 b/contrib/gcc/config/ia64/t-ia64
index 21d37a7..6053588 100644
--- a/contrib/gcc/config/ia64/t-ia64
+++ b/contrib/gcc/config/ia64/t-ia64
@@ -8,7 +8,8 @@ LIB1ASMSRC = ia64/lib1funcs.asm
LIB1ASMFUNCS = __divxf3 __divdf3 __divsf3 \
__divdi3 __moddi3 __udivdi3 __umoddi3 \
__divsi3 __modsi3 __udivsi3 __umodsi3 __save_stack_nonlocal \
- __nonlocal_goto __restore_stack_nonlocal __trampoline __compat
+ __nonlocal_goto __restore_stack_nonlocal __trampoline \
+ _fixtfdi _fixunstfdi _floatditf
# ??? Hack to get -P option used when compiling lib1funcs.asm, because Intel
# assembler does not accept # line number as a comment.
@@ -41,7 +42,7 @@ crtfastmath.o: $(srcdir)/config/ia64/crtfastmath.c $(GCC_PASSES)
$(srcdir)/config/ia64/crtfastmath.c
LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
- $(srcdir)/unwind-c.c $(srcdir)/gthr-gnat.c
+ $(srcdir)/unwind-c.c
ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
@@ -49,3 +50,5 @@ ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
# genattrtab generates very long string literals.
insn-attrtab.o-warn = -Wno-error
+
+ia64.o: debug.h $(PARAMS_H)
diff --git a/contrib/gcc/config/ia64/unwind-ia64.c b/contrib/gcc/config/ia64/unwind-ia64.c
index a49652e..fc7b207 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.c
+++ b/contrib/gcc/config/ia64/unwind-ia64.c
@@ -1,6 +1,6 @@
/* Subroutines needed for unwinding IA-64 standard format stack frame
info for exception handling.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Andrew MacLeod <amacleod@cygnus.com>
Andrew Haley <aph@cygnus.com>
@@ -20,8 +20,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
@@ -44,6 +44,7 @@
#undef ENABLE_MALLOC_CHECKING
#ifndef __USING_SJLJ_EXCEPTIONS__
+
#define UNW_VER(x) ((x) >> 48)
#define UNW_FLAG_MASK 0x0000ffff00000000
#define UNW_FLAG_OSMASK 0x0000f00000000000
@@ -284,10 +285,10 @@ atomic_free (unsigned int *mask, int bit)
#define PTR_IN(X, P) ((P) >= (X) && (P) < (X) + SIZE (X))
static struct unw_reg_state emergency_reg_state[32];
-static int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
+static unsigned int emergency_reg_state_free = MASK_FOR (emergency_reg_state);
static struct unw_labeled_state emergency_labeled_state[8];
-static int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
+static unsigned int emergency_labeled_state_free = MASK_FOR (emergency_labeled_state);
#ifdef ENABLE_MALLOC_CHECKING
static int reg_state_alloced;
@@ -1703,6 +1704,13 @@ _Unwind_GetIP (struct _Unwind_Context *context)
return context->rp;
}
+inline _Unwind_Ptr
+_Unwind_GetIPInfo (struct _Unwind_Context *context, int *ip_before_insn)
+{
+ *ip_before_insn = 0;
+ return context->rp;
+}
+
/* Overwrite the return address for CONTEXT with VAL. */
inline void
@@ -1754,6 +1762,9 @@ _Unwind_GetBSP (struct _Unwind_Context *context)
return (_Unwind_Ptr) context->bsp;
}
+#ifdef MD_UNWIND_SUPPORT
+#include MD_UNWIND_SUPPORT
+#endif
static _Unwind_Reason_Code
uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
@@ -1777,7 +1788,8 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
os-specific fallback mechanism. This will necessarily
not provide a personality routine or LSDA. */
#ifdef MD_FALLBACK_FRAME_STATE_FOR
- MD_FALLBACK_FRAME_STATE_FOR (context, fs, success);
+ if (MD_FALLBACK_FRAME_STATE_FOR (context, fs) == _URC_NO_REASON)
+ return _URC_NO_REASON;
/* [SCRA 11.4.1] A leaf function with no memory stack, no exception
handlers, and which keeps the return value in B0 does not need
@@ -1792,15 +1804,10 @@ uw_frame_state_for (struct _Unwind_Context *context, _Unwind_FrameState *fs)
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 = 0;
- goto success;
+ return _URC_NO_REASON;
}
-
- return _URC_END_OF_STACK;
- success:
- return _URC_NO_REASON;
-#else
- return _URC_END_OF_STACK;
#endif
+ return _URC_END_OF_STACK;
}
context->region_start = ent->start_offset + segment_base;
@@ -2060,6 +2067,12 @@ uw_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
}
}
+static void
+uw_advance_context (struct _Unwind_Context *context, _Unwind_FrameState *fs)
+{
+ uw_update_context (context, fs);
+}
+
/* Fill in CONTEXT for top-of-stack. The only valid registers at this
level will be the return address and the CFA. Note that CFA = SP+16. */
@@ -2111,7 +2124,7 @@ uw_init_context_1 (struct _Unwind_Context *context, void *bsp)
uw_update_context (context, &fs);
}
-/* Install (ie longjmp to) the contents of TARGET. */
+/* Install (i.e. longjmp to) the contents of TARGET. */
static void __attribute__((noreturn))
uw_install_context (struct _Unwind_Context *current __attribute__((unused)),
@@ -2389,7 +2402,6 @@ uw_identify_context (struct _Unwind_Context *context)
alias (_Unwind_Backtrace);
alias (_Unwind_DeleteException);
alias (_Unwind_FindEnclosingFunction);
-alias (_Unwind_FindTableEntry);
alias (_Unwind_ForcedUnwind);
alias (_Unwind_GetBSP);
alias (_Unwind_GetCFA);
diff --git a/contrib/gcc/config/ia64/unwind-ia64.h b/contrib/gcc/config/ia64/unwind-ia64.h
index 053829f..09b4a98 100644
--- a/contrib/gcc/config/ia64/unwind-ia64.h
+++ b/contrib/gcc/config/ia64/unwind-ia64.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
struct unw_table_entry
{
diff --git a/contrib/gcc/config/ia64/vect.md b/contrib/gcc/config/ia64/vect.md
new file mode 100644
index 0000000..94380bf
--- /dev/null
+++ b/contrib/gcc/config/ia64/vect.md
@@ -0,0 +1,1304 @@
+;; IA-64 machine description for vector operations.
+;; Copyright (C) 2004, 2005
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;; Integer vector operations
+
+(define_mode_macro VECINT [V8QI V4HI V2SI])
+(define_mode_macro VECINT12 [V8QI V4HI])
+(define_mode_macro VECINT24 [V4HI V2SI])
+(define_mode_attr vecsize [(V8QI "1") (V4HI "2") (V2SI "4")])
+
+(define_expand "mov<mode>"
+ [(set (match_operand:VECINT 0 "general_operand" "")
+ (match_operand:VECINT 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:VECINT 0 "destination_operand"
+ "=r,r,r,r,m ,*f ,*f,Q ,r ,*f")
+ (match_operand:VECINT 1 "move_operand"
+ "rU,W,i,m,rU,U*f,Q ,*f,*f,r "))]
+ "ia64_move_ok (operands[0], operands[1])"
+ "@
+ mov %0 = %r1
+ addl %0 = %v1, r0
+ movl %0 = %v1
+ ld8%O1 %0 = %1%P1
+ st8%Q0 %0 = %r1%P0
+ mov %0 = %F1
+ ldf8 %0 = %1%P1
+ stf8 %0 = %1%P0
+ getf.sig %0 = %1
+ setf.sig %0 = %1"
+ [(set_attr "itanium_class" "ialu,ialu,long_i,ld,st,fmisc,fld,stf,frfr,tofr")])
+
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (not:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")))]
+ ""
+ "andcm %0 = -1, %1"
+ [(set_attr "itanium_class" "ilog")])
+
+(define_insn "and<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (and:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ and %0 = %2, %1
+ fand %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "*andnot<mode>"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (and:VECINT
+ (not:VECINT (match_operand:VECINT 1 "grfr_register_operand" "r,*f"))
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ andcm %0 = %2, %1
+ fandcm %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "ior<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (ior:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ or %0 = %2, %1
+ for %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "xor<mode>3"
+ [(set (match_operand:VECINT 0 "grfr_register_operand" "=r,*f")
+ (xor:VECINT
+ (match_operand:VECINT 1 "grfr_register_operand" "r,*f")
+ (match_operand:VECINT 2 "grfr_reg_or_8bit_operand" "r,*f")))]
+ ""
+ "@
+ xor %0 = %2, %1
+ fxor %0 = %2, %1"
+ [(set_attr "itanium_class" "ilog,fmisc")])
+
+(define_insn "neg<mode>2"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (neg:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize> %0 = r0, %1"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "add<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (plus:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")
+ (match_operand:VECINT 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*ssadd<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (ss_plus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize>.sss %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*usadd<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (us_plus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "padd<vecsize>.uuu %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (minus:VECINT (match_operand:VECINT 1 "gr_register_operand" "r")
+ (match_operand:VECINT 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*sssub<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (ss_minus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize>.sss %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*ussub<mode>3"
+ [(set (match_operand:VECINT12 0 "gr_register_operand" "=r")
+ (us_minus:VECINT12
+ (match_operand:VECINT12 1 "gr_register_operand" "r")
+ (match_operand:VECINT12 2 "gr_register_operand" "r")))]
+ ""
+ "psub<vecsize>.uuu %0 = %1, %2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_expand "mulv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "")
+ (mult:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+{
+ rtx r1, l1, r2, l2, rm, lm;
+
+ r1 = gen_reg_rtx (V4HImode);
+ l1 = gen_reg_rtx (V4HImode);
+ r2 = gen_reg_rtx (V4HImode);
+ l2 = gen_reg_rtx (V4HImode);
+
+ /* Zero-extend the QImode elements into two words of HImode elements
+ by interleaving them with zero bytes. */
+ emit_insn (gen_mix1_r (gen_lowpart (V8QImode, r1),
+ operands[1], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_r (gen_lowpart (V8QImode, r2),
+ operands[2], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_l (gen_lowpart (V8QImode, l1),
+ operands[1], CONST0_RTX (V8QImode)));
+ emit_insn (gen_mix1_l (gen_lowpart (V8QImode, l2),
+ operands[2], CONST0_RTX (V8QImode)));
+
+ /* Multiply. */
+ rm = gen_reg_rtx (V4HImode);
+ lm = gen_reg_rtx (V4HImode);
+ emit_insn (gen_mulv4hi3 (rm, r1, r2));
+ emit_insn (gen_mulv4hi3 (lm, l1, l2));
+
+ /* Zap the high order bytes of the HImode elements by overwriting those
+ in one part with the low order bytes of the other. */
+ emit_insn (gen_mix1_r (operands[0],
+ gen_lowpart (V8QImode, rm),
+ gen_lowpart (V8QImode, lm)));
+ DONE;
+})
+
+(define_insn "mulv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (mult:V4HI (match_operand:V4HI 1 "gr_register_operand" "r")
+ (match_operand:V4HI 2 "gr_register_operand" "r")))]
+ ""
+ "pmpyshr2 %0 = %1, %2, 0"
+ [(set_attr "itanium_class" "mmmul")])
+
+(define_insn "pmpy2_r"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (mult:V2SI
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 1 "gr_register_operand" "r"))
+ (parallel [(const_int 0) (const_int 2)]))
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "gr_register_operand" "r"))
+ (parallel [(const_int 0) (const_int 2)]))))]
+ ""
+ "pmpy2.r %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "pmpy2_l"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (mult:V2SI
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 1 "gr_register_operand" "r"))
+ (parallel [(const_int 1) (const_int 3)]))
+ (vec_select:V2SI
+ (sign_extend:V4SI
+ (match_operand:V4HI 2 "gr_register_operand" "r"))
+ (parallel [(const_int 1) (const_int 3)]))))]
+ ""
+ "pmpy2.l %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "umax<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (umax:VECINT (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:VECINT 2 "gr_register_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (UMAX, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "smax<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (smax:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (SMAX, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "umin<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (umin:VECINT (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:VECINT 2 "gr_register_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (UMIN, <MODE>mode, operands))
+ DONE;
+})
+
+(define_expand "smin<mode>3"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (smin:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ if (ia64_expand_vecint_minmax (SMIN, <MODE>mode, operands))
+ DONE;
+})
+
+(define_insn "*umaxv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (umax:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+ "pmax1.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*smaxv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (smax:V4HI (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pmax2 %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*uminv8qi3"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (umin:V8QI (match_operand:V8QI 1 "gr_register_operand" "r")
+ (match_operand:V8QI 2 "gr_register_operand" "r")))]
+ ""
+ "pmin1.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*sminv4hi3"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (smin:V4HI (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pmin2 %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "ashl<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (ashift:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshl<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "ashr<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (ashiftrt:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshr<vecsize> %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "lshr<mode>3"
+ [(set (match_operand:VECINT24 0 "gr_register_operand" "=r")
+ (lshiftrt:VECINT24
+ (match_operand:VECINT24 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rn")))]
+ ""
+ "pshr<vecsize>.u %0 = %1, %2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "vec_shl_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (ashift:DI (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "")))]
+ ""
+{
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+})
+
+(define_expand "vec_shr_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (lshiftrt:DI (match_operand:VECINT 1 "gr_register_operand" "")
+ (match_operand:DI 2 "gr_reg_or_6bit_operand" "")))]
+ ""
+{
+ operands[0] = gen_lowpart (DImode, operands[0]);
+ operands[1] = gen_lowpart (DImode, operands[1]);
+})
+
+(define_expand "widen_usumv8qi3"
+ [(match_operand:V4HI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, true);
+ DONE;
+})
+
+(define_expand "widen_usumv4hi3"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V2SI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, true);
+ DONE;
+})
+
+(define_expand "widen_ssumv8qi3"
+ [(match_operand:V4HI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, false);
+ DONE;
+})
+
+(define_expand "widen_ssumv4hi3"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V2SI 2 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_widen_sum (operands, false);
+ DONE;
+})
+
+(define_expand "udot_prodv8qi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V8QI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_dot_prod_v8qi (operands, true);
+ DONE;
+})
+
+(define_expand "sdot_prodv8qi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V8QI 1 "gr_register_operand" "")
+ (match_operand:V8QI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ ia64_expand_dot_prod_v8qi (operands, false);
+ DONE;
+})
+
+(define_expand "sdot_prodv4hi"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand:V4HI 1 "gr_register_operand" "")
+ (match_operand:V4HI 2 "gr_register_operand" "")
+ (match_operand:V2SI 3 "gr_register_operand" "")]
+ ""
+{
+ rtx l, r, t;
+
+ r = gen_reg_rtx (V2SImode);
+ l = gen_reg_rtx (V2SImode);
+ t = gen_reg_rtx (V2SImode);
+
+ emit_insn (gen_pmpy2_r (r, operands[1], operands[2]));
+ emit_insn (gen_pmpy2_l (l, operands[1], operands[2]));
+ emit_insn (gen_addv2si3 (t, r, operands[3]));
+ emit_insn (gen_addv2si3 (operands[0], t, l));
+ DONE;
+})
+
+(define_expand "vcond<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (if_then_else:VECINT
+ (match_operator 3 ""
+ [(match_operand:VECINT 4 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 5 "gr_reg_or_0_operand" "")])
+ (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ ia64_expand_vecint_cmov (operands);
+ DONE;
+})
+
+(define_expand "vcondu<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "")
+ (if_then_else:VECINT
+ (match_operator 3 ""
+ [(match_operand:VECINT 4 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 5 "gr_reg_or_0_operand" "")])
+ (match_operand:VECINT 1 "gr_reg_or_0_operand" "")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "")))]
+ ""
+{
+ ia64_expand_vecint_cmov (operands);
+ DONE;
+})
+
+(define_insn "*cmpeq_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (eq:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pcmp<vecsize>.eq %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "*cmpgt_<mode>"
+ [(set (match_operand:VECINT 0 "gr_register_operand" "=r")
+ (gt:VECINT (match_operand:VECINT 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:VECINT 2 "gr_reg_or_0_operand" "rU")))]
+ ""
+ "pcmp<vecsize>.gt %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmalua")])
+
+(define_insn "pack2_sss"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_concat:V8QI
+ (ss_truncate:V4QI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU"))
+ (ss_truncate:V4QI
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack2.sss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*pack2_uss"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_concat:V8QI
+ (us_truncate:V4QI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU"))
+ (us_truncate:V4QI
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack2.uss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "pack4_sss"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_concat:V4HI
+ (ss_truncate:V2HI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU"))
+ (ss_truncate:V2HI
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))))]
+ ""
+ "pack4.sss %0 = %r1, %r2"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack1_l"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 1)
+ (const_int 2)
+ (const_int 3)
+ (const_int 8)
+ (const_int 9)
+ (const_int 10)
+ (const_int 11)])))]
+ ""
+ "unpack1.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack1_h"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 4)
+ (const_int 5)
+ (const_int 6)
+ (const_int 7)
+ (const_int 12)
+ (const_int 13)
+ (const_int 14)
+ (const_int 15)])))]
+ ""
+ "unpack1.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "mix1_r"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 8)
+ (const_int 2)
+ (const_int 10)
+ (const_int 4)
+ (const_int 12)
+ (const_int 6)
+ (const_int 14)])))]
+ ""
+ "mix1.r %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "mix1_l"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (vec_concat:V16QI
+ (match_operand:V8QI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V8QI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 9)
+ (const_int 3)
+ (const_int 11)
+ (const_int 5)
+ (const_int 13)
+ (const_int 7)
+ (const_int 15)])))]
+ ""
+ "mix1.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_rev"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 7)
+ (const_int 6)
+ (const_int 5)
+ (const_int 4)
+ (const_int 3)
+ (const_int 2)
+ (const_int 1)
+ (const_int 0)])))]
+ ""
+ "mux1 %0 = %1, @rev"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_mix"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 2)
+ (const_int 6)
+ (const_int 1)
+ (const_int 5)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @mix"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_shuf"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 1)
+ (const_int 5)
+ (const_int 2)
+ (const_int 6)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @shuf"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_alt"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 4)
+ (const_int 6)
+ (const_int 1)
+ (const_int 3)
+ (const_int 5)
+ (const_int 7)])))]
+ ""
+ "mux1 %0 = %1, @alt"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_brcst_v8qi"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_select:V8QI
+ (match_operand:V8QI 1 "gr_register_operand" "r")
+ (parallel [(const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)
+ (const_int 0)])))]
+ ""
+ "mux1 %0 = %1, @brcst"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux1_brcst_qi"
+ [(set (match_operand:V8QI 0 "gr_register_operand" "=r")
+ (vec_duplicate:V8QI
+ (match_operand:QI 1 "gr_register_operand" "r")))]
+ ""
+ "mux1 %0 = %1, @brcst"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack2_l"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 1)
+ (const_int 5)])))]
+ ""
+ "unpack2.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "unpack2_h"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 2)
+ (const_int 6)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "unpack2.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mix2_r"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 2)
+ (const_int 6)])))]
+ ""
+ "mix2.r %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mix2_l"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (vec_concat:V8HI
+ (match_operand:V4HI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V4HI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 5)
+ (const_int 3)
+ (const_int 7)])))]
+ ""
+ "mix2.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux2"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_select:V4HI
+ (match_operand:V4HI 1 "gr_register_operand" "r")
+ (parallel [(match_operand 2 "const_int_2bit_operand" "")
+ (match_operand 3 "const_int_2bit_operand" "")
+ (match_operand 4 "const_int_2bit_operand" "")
+ (match_operand 5 "const_int_2bit_operand" "")])))]
+ ""
+{
+ int mask;
+ mask = INTVAL (operands[2]);
+ mask |= INTVAL (operands[3]) << 2;
+ mask |= INTVAL (operands[4]) << 4;
+ mask |= INTVAL (operands[5]) << 6;
+ operands[2] = GEN_INT (mask);
+ return "%,mux2 %0 = %1, %2";
+}
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_insn "*mux2_brcst_hi"
+ [(set (match_operand:V4HI 0 "gr_register_operand" "=r")
+ (vec_duplicate:V4HI
+ (match_operand:HI 1 "gr_register_operand" "r")))]
+ ""
+ "mux2 %0 = %1, 0"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Note that mix4.r performs the exact same operation.
+(define_insn "*unpack4_l"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 0)
+ (const_int 2)])))]
+ ""
+ "unpack4.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Note that mix4.l performs the exact same operation.
+(define_insn "*unpack4_h"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_select:V2SI
+ (vec_concat:V4SI
+ (match_operand:V2SI 1 "gr_reg_or_0_operand" "rU")
+ (match_operand:V2SI 2 "gr_reg_or_0_operand" "rU"))
+ (parallel [(const_int 1)
+ (const_int 3)])))]
+ ""
+ "unpack4.h %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+(define_expand "vec_initv2si"
+ [(match_operand:V2SI 0 "gr_register_operand" "")
+ (match_operand 1 "" "")]
+ ""
+{
+ rtx op1 = XVECEXP (operands[1], 0, 0);
+ rtx op2 = XVECEXP (operands[1], 0, 1);
+ rtx x;
+
+ if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
+ {
+ rtvec v = rtvec_alloc (2);
+ RTVEC_ELT (v, 0) = TARGET_BIG_ENDIAN ? op2 : op1;
+ RTVEC_ELT (v, 1) = TARGET_BIG_ENDIAN ? op1 : op2;;
+ x = gen_rtx_CONST_VECTOR (V2SImode, v);
+ emit_move_insn (operands[0], x);
+ DONE;
+ }
+
+ if (!gr_reg_or_0_operand (op1, SImode))
+ op1 = force_reg (SImode, op1);
+ if (!gr_reg_or_0_operand (op2, SImode))
+ op2 = force_reg (SImode, op2);
+
+ if (TARGET_BIG_ENDIAN)
+ x = gen_rtx_VEC_CONCAT (V2SImode, op2, op1);
+ else
+ x = gen_rtx_VEC_CONCAT (V2SImode, op1, op2);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*vecinit_v2si"
+ [(set (match_operand:V2SI 0 "gr_register_operand" "=r")
+ (vec_concat:V2SI
+ (match_operand:SI 1 "gr_reg_or_0_operand" "rO")
+ (match_operand:SI 2 "gr_reg_or_0_operand" "rO")))]
+ ""
+ "unpack4.l %0 = %r2, %r1"
+ [(set_attr "itanium_class" "mmshf")])
+
+;; Missing operations
+;; padd.uus
+;; pavg
+;; pavgsub
+;; pmpyshr, general form
+;; psad
+;; pshladd
+;; pshradd
+;; psub.uus
+
+;; Floating point vector operations
+
+(define_expand "movv2sf"
+ [(set (match_operand:V2SF 0 "general_operand" "")
+ (match_operand:V2SF 1 "general_operand" ""))]
+ ""
+{
+ rtx op1 = ia64_expand_move (operands[0], operands[1]);
+ if (!op1)
+ DONE;
+ operands[1] = op1;
+})
+
+(define_insn "*movv2sf_internal"
+ [(set (match_operand:V2SF 0 "destination_operand"
+ "=f,f,f,Q,*r ,*r,*r,*r,m ,f ,*r")
+ (match_operand:V2SF 1 "move_operand"
+ "fU,Y,Q,f,U*r,W ,i ,m ,*r,*r,f "))]
+ "ia64_move_ok (operands[0], operands[1])"
+{
+ static const char * const alt[] = {
+ "%,mov %0 = %F1",
+ "%,fpack %0 = %F2, %F1",
+ "%,ldf8 %0 = %1%P1",
+ "%,stf8 %0 = %1%P0",
+ "%,mov %0 = %r1",
+ "%,addl %0 = %v1, r0",
+ "%,movl %0 = %v1",
+ "%,ld8%O1 %0 = %1%P1",
+ "%,st8%Q0 %0 = %r1%P0",
+ "%,setf.sig %0 = %1",
+ "%,getf.sig %0 = %1"
+ };
+
+ if (which_alternative == 1)
+ {
+ operands[2] = XVECEXP (operands[1], 0, 1);
+ operands[1] = XVECEXP (operands[1], 0, 0);
+ }
+
+ return alt[which_alternative];
+}
+ [(set_attr "itanium_class" "fmisc,fmisc,fld,stf,ialu,ialu,long_i,ld,st,tofr,frfr")])
+
+(define_insn "absv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (abs:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")))]
+ ""
+ "fpabs %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "negv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")))]
+ ""
+ "fpneg %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*negabsv2sf2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF
+ (abs:V2SF (match_operand:V2SF 1 "fr_register_operand" "f"))))]
+ ""
+ "fpnegabs %0 = %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+;; In order to convince combine to merge plus and mult to a useful fpma,
+;; we need a couple of extra patterns.
+(define_expand "addv2sf3"
+ [(parallel
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (plus:V2SF (match_operand:V2SF 1 "fr_register_operand" "")
+ (match_operand:V2SF 2 "fr_register_operand" "")))
+ (use (match_dup 3))])]
+ ""
+{
+ rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
+ operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+})
+
+;; The split condition here could be combine_completed, if we had such.
+(define_insn_and_split "*addv2sf3_1"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 3 "fr_register_operand" "f"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (plus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 3))
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "*addv2sf3_2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 4 "" "X"))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0)
+ (plus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 2))
+ (match_dup 3)))]
+ "")
+
+;; In order to convince combine to merge minus and mult to a useful fpms,
+;; we need a couple of extra patterns.
+(define_expand "subv2sf3"
+ [(parallel
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (minus:V2SF (match_operand:V2SF 1 "fr_register_operand" "")
+ (match_operand:V2SF 2 "fr_register_operand" "")))
+ (use (match_dup 3))])]
+ ""
+{
+ rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
+ operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+})
+
+;; The split condition here could be combine_completed, if we had such.
+(define_insn_and_split "*subv2sf3_1"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 3 "fr_register_operand" "f"))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0)
+ (minus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 3))
+ (match_dup 2)))]
+ "")
+
+(define_insn_and_split "*subv2sf3_2"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))
+ (use (match_operand:V2SF 4 "" "X"))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0)
+ (minus:V2SF
+ (mult:V2SF (match_dup 1) (match_dup 2))
+ (match_dup 3)))]
+ "")
+
+(define_insn "mulv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmpy %0 = %1, %2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpma"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpma %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpms"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (minus:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpms %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpnmpy"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (neg:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f"))))]
+ ""
+ "fpnmpy %0 = %1, %2"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "*fpnma"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (plus:V2SF
+ (neg:V2SF
+ (mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))
+ (match_operand:V2SF 3 "fr_register_operand" "f")))]
+ ""
+ "fpnma %0 = %1, %2, %3"
+ [(set_attr "itanium_class" "fmac")])
+
+(define_insn "smaxv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (smax:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmax %0 = %1, %2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "sminv2sf3"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (smin:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_register_operand" "f")))]
+ ""
+ "fpmin %0 = %1, %2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "reduc_splus_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_addv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "reduc_smax_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_smaxv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "reduc_smin_v2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:V2SF 1 "fr_register_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fswap (tmp, operands[1], CONST0_RTX (V2SFmode)));
+ emit_insn (gen_sminv2sf3 (operands[0], operands[1], tmp));
+ DONE;
+})
+
+(define_expand "vcondv2sf"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "")
+ (if_then_else:V2SF
+ (match_operator 3 ""
+ [(match_operand:V2SF 4 "fr_reg_or_0_operand" "")
+ (match_operand:V2SF 5 "fr_reg_or_0_operand" "")])
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "")))]
+ ""
+{
+ rtx x, cmp;
+
+ cmp = gen_reg_rtx (V2SFmode);
+ PUT_MODE (operands[3], V2SFmode);
+ emit_insn (gen_rtx_SET (VOIDmode, cmp, operands[3]));
+
+ x = gen_rtx_IF_THEN_ELSE (V2SFmode, cmp, operands[1], operands[2]);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0], x));
+ DONE;
+})
+
+(define_insn "*fpcmp"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (match_operator:V2SF 3 "comparison_operator"
+ [(match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU")]))]
+ ""
+ "fpcmp.%D3 %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*fselect"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (if_then_else:V2SF
+ (match_operand:V2SF 1 "fr_register_operand" "f")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 3 "fr_reg_or_0_operand" "fU")))]
+ ""
+ "fselect %0 = %F2, %F3, %1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "vec_initv2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand 1 "" "")]
+ ""
+{
+ rtx op1 = XVECEXP (operands[1], 0, 0);
+ rtx op2 = XVECEXP (operands[1], 0, 1);
+ rtx x;
+
+ if (GET_CODE (op1) == CONST_DOUBLE && GET_CODE (op2) == CONST_DOUBLE)
+ {
+ x = gen_rtx_CONST_VECTOR (V2SFmode, XVEC (operands[1], 0));
+ emit_move_insn (operands[0], x);
+ DONE;
+ }
+
+ if (!fr_reg_or_fp01_operand (op1, SFmode))
+ op1 = force_reg (SFmode, op1);
+ if (!fr_reg_or_fp01_operand (op2, SFmode))
+ op2 = force_reg (SFmode, op2);
+
+ if (TARGET_BIG_ENDIAN)
+ emit_insn (gen_fpack (operands[0], op2, op1));
+ else
+ emit_insn (gen_fpack (operands[0], op1, op2));
+ DONE;
+})
+
+(define_insn "fpack"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_concat:V2SF
+ (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fpack %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fswap"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 1) (const_int 2)])))]
+ ""
+ "fswap %0 = %F1, %F2"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "*fmix_l"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 1) (const_int 3)])))]
+ ""
+ "fmix.l %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fmix_r"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 0) (const_int 2)])))]
+ ""
+ "fmix.r %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_insn "fmix_lr"
+ [(set (match_operand:V2SF 0 "fr_register_operand" "=f")
+ (vec_select:V2SF
+ (vec_concat:V4SF
+ (match_operand:V2SF 1 "fr_reg_or_0_operand" "fU")
+ (match_operand:V2SF 2 "fr_reg_or_0_operand" "fU"))
+ (parallel [(const_int 0) (const_int 3)])))]
+ ""
+ "fmix.lr %0 = %F2, %F1"
+ [(set_attr "itanium_class" "fmisc")])
+
+(define_expand "vec_setv2sf"
+ [(match_operand:V2SF 0 "fr_register_operand" "")
+ (match_operand:SF 1 "fr_register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ ""
+{
+ rtx tmp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_fpack (tmp, operands[1], CONST0_RTX (SFmode)));
+
+ switch (INTVAL (operands[2]))
+ {
+ case 0:
+ emit_insn (gen_fmix_lr (operands[0], tmp, operands[0]));
+ break;
+ case 1:
+ emit_insn (gen_fmix_r (operands[0], operands[0], tmp));
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ DONE;
+})
+
+(define_insn_and_split "*vec_extractv2sf_0_le"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,f,m")
+ (unspec:SF [(match_operand:V2SF 1 "nonimmediate_operand" "rfm,rm,r")
+ (const_int 0)]
+ UNSPEC_VECT_EXTR))]
+ "!TARGET_BIG_ENDIAN"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]) && FR_REGNO_P (REGNO (operands[1])))
+ operands[0] = gen_rtx_REG (V2SFmode, REGNO (operands[0]));
+ else if (MEM_P (operands[1]))
+ operands[1] = adjust_address (operands[1], SFmode, 0);
+ else
+ operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1]));
+})
+
+(define_insn_and_split "*vec_extractv2sf_0_be"
+ [(set (match_operand:SF 0 "register_operand" "=r,f")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "rf,r")
+ (const_int 0)]
+ UNSPEC_VECT_EXTR))]
+ "TARGET_BIG_ENDIAN"
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ if (REG_P (operands[1]) && FR_REGNO_P (REGNO (operands[1])))
+ operands[0] = gen_rtx_REG (V2SFmode, REGNO (operands[0]));
+ else
+ operands[1] = gen_rtx_REG (SFmode, REGNO (operands[1]));
+})
+
+(define_insn_and_split "*vec_extractv2sf_1"
+ [(set (match_operand:SF 0 "register_operand" "=r")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "r")
+ (const_int 1)]
+ UNSPEC_VECT_EXTR))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+{
+ operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[1] = gen_rtx_REG (DImode, REGNO (operands[1]));
+ if (TARGET_BIG_ENDIAN)
+ emit_move_insn (operands[0], operands[1]);
+ else
+ emit_insn (gen_lshrdi3 (operands[0], operands[1], GEN_INT (32)));
+ DONE;
+})
+
+(define_expand "vec_extractv2sf"
+ [(set (match_operand:SF 0 "register_operand" "")
+ (unspec:SF [(match_operand:V2SF 1 "register_operand" "")
+ (match_operand:DI 2 "const_int_operand" "")]
+ UNSPEC_VECT_EXTR))]
+ ""
+ "")
+
+;; Missing operations
+;; fprcpa
+;; fpsqrta
diff --git a/contrib/gcc/config/interix.h b/contrib/gcc/config/interix.h
index 9d05f1b..0fa5dee 100644
--- a/contrib/gcc/config/interix.h
+++ b/contrib/gcc/config/interix.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
Interix
- Copyright (C) 1994, 1995, 1999, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1994, 1995, 1999, 2002, 2004 Free Software Foundation, Inc.
Donn Terry, Softway Systems, Inc. (donn@softway.com)
Modified from code
Contributed by Douglas B. Rupp (drupp@cs.washington.edu).
@@ -19,12 +19,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#ifndef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-#endif
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* POSIX/Uni-thread only for now. Look at the winnt version
for windows/multi thread */
diff --git a/contrib/gcc/config/interix3.h b/contrib/gcc/config/interix3.h
index 9e2cc35..f7c3aa6 100644
--- a/contrib/gcc/config/interix3.h
+++ b/contrib/gcc/config/interix3.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Interix 3.x has a single rooted file system and properly named
libraries, so LIB_SPEC can be simplified */
diff --git a/contrib/gcc/config/kaos.h b/contrib/gcc/config/kaos.h
index 45938da..2425fd4 100644
--- a/contrib/gcc/config/kaos.h
+++ b/contrib/gcc/config/kaos.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Specify predefined symbols in preprocessor. */
#define TARGET_OS_CPP_BUILTINS() \
diff --git a/contrib/gcc/config/kfreebsd-gnu.h b/contrib/gcc/config/kfreebsd-gnu.h
new file mode 100644
index 0000000..8c11ca5
--- /dev/null
+++ b/contrib/gcc/config/kfreebsd-gnu.h
@@ -0,0 +1,38 @@
+/* Definitions for kFreeBSD-based GNU systems with ELF format
+ Copyright (C) 2004, 2006
+ Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef LINUX_TARGET_OS_CPP_BUILTINS
+#define LINUX_TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__FreeBSD_kernel__"); \
+ builtin_define ("__GLIBC__"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
+
+#ifdef GLIBC_DYNAMIC_LINKER
+#undef GLIBC_DYNAMIC_LINKER
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#endif
diff --git a/contrib/gcc/config/knetbsd-gnu.h b/contrib/gcc/config/knetbsd-gnu.h
new file mode 100644
index 0000000..e1ff325
--- /dev/null
+++ b/contrib/gcc/config/knetbsd-gnu.h
@@ -0,0 +1,39 @@
+/* Definitions for kNetBSD-based GNU systems with ELF format
+ Copyright (C) 2004, 2006
+ Free Software Foundation, Inc.
+ Contributed by Robert Millan.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef LINUX_TARGET_OS_CPP_BUILTINS
+#define LINUX_TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__NetBSD_kernel__"); \
+ builtin_define ("__GLIBC__"); \
+ builtin_define_std ("unix"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ } \
+ while (0)
+
+
+#ifdef GLIBC_DYNAMIC_LINKER
+#undef GLIBC_DYNAMIC_LINKER
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#endif
diff --git a/contrib/gcc/config/libgloss.h b/contrib/gcc/config/libgloss.h
index 3f9bf6c..82de626c 100644
--- a/contrib/gcc/config/libgloss.h
+++ b/contrib/gcc/config/libgloss.h
@@ -1,6 +1,6 @@
/* libgloss.h -- operating system specific defines to be used when
targeting GCC for Libgloss supported targets.
- Copyright (C) 1996 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file should not be used for ELF targets, as this definition of
STARTFILE_SPEC is all wrong. */
@@ -29,7 +29,7 @@ Boston, MA 02111-1307, USA. */
/* This file used to force LINK_SPEC to be the null string, but that is not
correct. LINK_SPEC is used to pass machine specific arguments to the
- linker and hence can not be redefined here. LINK_SPEC is never used to
+ linker and hence cannot be redefined here. LINK_SPEC is never used to
specify startup files or libraries, so it should never conflict with
libgloss. */
diff --git a/contrib/gcc/config/linux.h b/contrib/gcc/config/linux.h
index 0f7ba17..59e3e85 100644
--- a/contrib/gcc/config/linux.h
+++ b/contrib/gcc/config/linux.h
@@ -1,5 +1,5 @@
/* Definitions for Linux-based GNU systems with ELF format
- Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003
+ Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu (hjl@lucon.org).
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Don't assume anything about the header files. */
#define NO_IMPLICIT_EXTERN_C
@@ -39,14 +39,7 @@ Boston, MA 02111-1307, USA. */
object constructed before entering `main'. */
#undef STARTFILE_SPEC
-#ifdef USE_GNULIBC_1
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
- %{!p:%{profile:gcrt1.o%s} \
- %{!profile:crt1.o%s}}}} \
- crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-#elif defined HAVE_LD_PIE
+#if defined HAVE_LD_PIE
#define STARTFILE_SPEC \
"%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
@@ -76,26 +69,10 @@ Boston, MA 02111-1307, USA. */
#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
#undef LIB_SPEC
-/* We no longer link with libc_p.a or libg.a by default. If you
- want to profile or debug the GNU/Linux C library, please add
- -profile or -ggdb to LDFLAGS at the link time, respectively. */
-#if 1
-#ifdef USE_GNULIBC_1
-#define LIB_SPEC \
- "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \
- %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}"
-#else
#define LIB_SPEC \
"%{pthread:-lpthread} \
%{shared:-lc} \
%{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}"
-#endif
-#else
-#define LIB_SPEC \
- "%{!shared: \
- %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \
- %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}"
-#endif
#define LINUX_TARGET_OS_CPP_BUILTINS() \
do { \
@@ -107,7 +84,7 @@ Boston, MA 02111-1307, USA. */
builtin_assert ("system=posix"); \
} while (0)
-#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR)
+#if defined(HAVE_LD_EH_FRAME_HDR)
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
@@ -117,10 +94,36 @@ Boston, MA 02111-1307, USA. */
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
-/* Determine whether the the entire c99 runtime
- is present in the runtime library. */
-#ifndef USE_GNULIBC_1
-#define TARGET_C99_FUNCTIONS 1
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+/* Determine which dynamic linker to use depending on whether GLIBC or
+ uClibc is the default C library and whether -muclibc or -mglibc has
+ been passed to change the default. */
+#if UCLIBC_DEFAULT
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+#else
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}" U ";:" G "}"
#endif
-#define TARGET_HAS_F_SETLKW
+/* For most targets the following definitions suffice;
+ GLIBC_DYNAMIC_LINKER must be defined for each target using them, or
+ GLIBC_DYNAMIC_LINKER32 and GLIBC_DYNAMIC_LINKER64 for targets
+ supporting both 32-bit and 64-bit compilation. */
+#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#define LINUX_DYNAMIC_LINKER \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER)
+#define LINUX_DYNAMIC_LINKER32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32)
+#define LINUX_DYNAMIC_LINKER64 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64)
+
+/* Determine whether the entire c99 runtime
+ is present in the runtime library. */
+#define TARGET_C99_FUNCTIONS (OPTION_GLIBC)
+
+#define TARGET_POSIX_IO
diff --git a/contrib/gcc/config/linux.opt b/contrib/gcc/config/linux.opt
new file mode 100644
index 0000000..3f615bb
--- /dev/null
+++ b/contrib/gcc/config/linux.opt
@@ -0,0 +1,29 @@
+; Processor-independent options for GNU/Linux.
+;
+; Copyright (C) 2006 Free Software Foundation, Inc.
+; Contributed by CodeSourcery.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+muclibc
+Target RejectNegative Report Mask(UCLIBC) Var(linux_uclibc) Init(UCLIBC_DEFAULT ? OPTION_MASK_UCLIBC : 0)
+Use uClibc instead of GNU libc
+
+mglibc
+Target RejectNegative Report InverseMask(UCLIBC, GLIBC) Var(linux_uclibc) VarExists
+Use GNU libc instead of uClibc
diff --git a/contrib/gcc/config/lynx.h b/contrib/gcc/config/lynx.h
index a2366d1..271fb62 100644
--- a/contrib/gcc/config/lynx.h
+++ b/contrib/gcc/config/lynx.h
@@ -1,5 +1,5 @@
-/* Target independent definitions for LynxOS using gas and gnu ld.
- Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000, 2002, 2003
+/* Target independent definitions for LynxOS.
+ Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,128 +16,163 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* LynxOS is a multi-platform Unix, similar to SVR3, but not identical. */
-
-/* Define various macros, depending on the combination of flags. */
-
-#undef CPP_SPEC
-#define CPP_SPEC "%{mthreads:-D_MULTITHREADED} \
- %{mposix:-D_POSIX_SOURCE} \
- %{msystem-v:-I/usr/include_v}"
-
-/* No asm spec needed, since using GNU assembler always. */
-
-/* No linker spec needed, since using GNU linker always. */
-
-#undef LIB_SPEC
-#define LIB_SPEC "%{mthreads:-L/lib/thread/} \
- %{msystem-v:-lc_v} \
- %{!msystem-v:%{mposix:-lc_p} -lc -lm}"
-
-/* Set the appropriate names for the Lynx startfiles. */
-
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{p:%{mthreads:thread/pinit1.o%s}%{!mthreads:pinit1.o%s}}%{!p:%{msystem-v:vinit1.o%s -e_start}%{!msystem-v:%{mthreads:thread/init1.o%s}%{!mthreads:init1.o%s}}}"
-
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC "%{p:_etext.o%s}%{!p:initn.o%s}"
-
-/* Override the svr3 versions. */
-
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-
-#undef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-
-/* We want to output DBX (stabs) debugging information normally. */
-
-#define DBX_DEBUGGING_INFO 1
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
-
-/* It is convenient to be able to generate standard coff debugging
- if requested via -gcoff. */
-
-#define SDB_DEBUGGING_INFO 1
-
-/* Be function-relative for block and source line stab directives. */
-
-#define DBX_BLOCKS_FUNCTION_RELATIVE 1
-
-/* but, to make this work, functions must appear prior to line info */
-
-#define DBX_FUNCTION_FIRST
-
-/* Generate a blank trailing N_SO to mark the end of the .o file, since
- we can't depend upon the linker to mark .o file boundaries with
- embedded stabs. */
-
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
- fprintf (FILE, \
- "\t.text\n\t.stabs \"\",%d,0,0,Letext\nLetext:\n", N_SO)
-
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(file, line, counter) \
- { fprintf (file, ".stabn 68,0,%d,.LM%d-", \
- line, counter); \
- assemble_name (file, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
- fprintf (file, "\n.LM%d:\n", counter); }
-
-/* Handle #pragma pack and sometimes #pragma weak. */
-
-#define HANDLE_SYSV_PRAGMA 1
-
-/* Some additional command-line options. */
-
-#define TARGET_THREADS (target_flags & MASK_THREADS)
-#define MASK_THREADS 0x40000000
-
-#define TARGET_POSIX (target_flags & MASK_POSIX)
-#define MASK_POSIX 0x20000000
-
-#define TARGET_SYSTEM_V (target_flags & MASK_SYSTEM_V)
-#define MASK_SYSTEM_V 0x10000000
-
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- {"threads", MASK_THREADS}, \
- {"posix", MASK_POSIX}, \
- {"system-v", MASK_SYSTEM_V},
-
-#undef SUBTARGET_OVERRIDE_OPTIONS
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_SYSTEM_V && profile_flag) \
- warning ("-msystem-v and -p are incompatible"); \
- if (TARGET_SYSTEM_V && TARGET_THREADS) \
- warning ("-msystem-v and -mthreads are incompatible"); \
-} while (0)
-
-/* Since init.o et al put all sorts of stuff into the init section,
- we can't use the standard init section support in crtbegin.o. */
-
-#undef INIT_SECTION_ASM_OP
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_fini
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- FINI_SECTION_FUNCTION
-
-#undef CTORS_SECTION_ASM_OP
-#define CTORS_SECTION_ASM_OP "\t.section\t.ctors"
-#undef DTORS_SECTION_ASM_OP
-#define DTORS_SECTION_ASM_OP "\t.section\t.dtors"
-
-#undef DO_GLOBAL_CTORS_BODY
-#undef DO_GLOBAL_DTORS_BODY
-
-/* LynxOS doesn't have mcount. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(file, profile_label_no)
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* In this file we set up defaults that can be chosen by
+ <target>/lynx.h files. A target-specific lynx.h file can decide
+ either to define and override these definitions or to use them by
+ ensuring they are undefined at this point. If we were to #undef
+ them here we might accidentally disable some target-specific
+ defines. */
+
+#ifndef EXTRA_OS_LYNX_TARGET_SPECS
+# define EXTRA_OS_LYNX_TARGET_SPECS
+#endif
+
+#ifndef EXTRA_OS_LYNX_SPECS
+# define EXTRA_OS_LYNX_SPECS \
+ { "cpp_os_lynx", CPP_OS_LYNX_SPEC }, \
+ { "lib_os_lynx", LIB_OS_LYNX_SPEC }, \
+ { "link_os_lynx", LINK_OS_LYNX_SPEC }, \
+ { "startfile_os_lynx", STARTFILE_OS_LYNX_SPEC }, \
+ { "endfile_os_lynx", ENDFILE_OS_LYNX_SPEC }, \
+ EXTRA_OS_LYNX_TARGET_SPECS
+#endif
+
+#ifndef SUBTARGET_EXTRA_SPECS
+# define SUBTARGET_EXTRA_SPECS EXTRA_OS_LYNX_SPECS
+#endif
+
+#ifndef CPP_SPEC
+# define CPP_SPEC "%(cpp_cpu) %(cpp_os_lynx)"
+#endif
+
+#ifndef LIB_SPEC
+# define LIB_SPEC "%(lib_os_lynx)"
+#endif
+
+#ifndef LINK_SPEC
+# define LINK_SPEC "%(link_os_lynx)"
+#endif
+
+#ifndef STARTFILE_SPEC
+# define STARTFILE_SPEC "%(startfile_os_lynx)"
+#endif
+
+#ifndef ENDFILE_SPEC
+# define ENDFILE_SPEC "%(endfile_os_lynx)"
+#endif
+
+#ifndef CPP_OS_LYNX_SPEC
+# define CPP_OS_LYNX_SPEC \
+"%{mthreads: \
+ %{mlegacy-threads: \
+ %ecannot use mthreads and mlegacy-threads together}} \
+ %{mthreads: -D_MULTITHREADED} \
+ %{mlegacy-threads: -D_THREADS_POSIX4ad4} \
+ -Asystem=lynx -Asystem=unix -D__Lynx__ -D__unix__"
+#endif
+
+#ifndef LIB_OS_LYNX_SPEC
+# define LIB_OS_LYNX_SPEC \
+"%{mlegacy-threads:-lposix-pre1c} -lm -lc"
+#endif
+
+/* We link static executables for LynxOS by default unless -mshared is
+ used when linking an executable. Along the same line, we link to
+ shared libraries when linking a shared object by default unless
+ -static is used.
+
+ We have to pass in our -L options here otherwise the translated
+ startfile directories (%D) will take priority over this.
+ Furthermore since we have to pass in -L options here we have to
+ make sure that -L options provided by the user take priority over
+ everything we specify. */
+
+#ifndef LINK_OS_LYNX_SPEC
+# define LINK_OS_LYNX_SPEC \
+"%{shared} %{static} \
+ %{mshared: %{static: %ecannot use mshared and static together}} \
+ %{!mshared: %{!shared: %{!static: -static}}} \
+ %{L*} \
+ %{mthreads: \
+ %{mshared: -L/lib/thread/shlib -rpath /lib/thread/shlib} \
+ %{shared: \
+ %{!static: -L/lib/thread/shlib -rpath /lib/thread/shlib} \
+ %{!mshared: -L/lib/thread}} \
+ %{shared: %{static: -L/lib/thread}}} \
+ %{!mthreads: \
+ %{mshared: -L/lib/shlib -rpath /lib/shlib} \
+ %{shared: -L/lib/shlib -rpath /lib/shlib}} \
+ %{mlegacy-threads:-lposix-pre1c} -lm -lc"
+#endif
+
+#ifndef STARTFILE_OS_LYNX_SPEC
+# define STARTFILE_OS_LYNX_SPEC \
+"%{!shared: \
+ %{!mthreads: \
+ %{p:gcrt1.o%s} %{pg:gcrt1.o%s} \
+ %{!p:%{!pg:crt1.o%s}}} \
+ %{mthreads: \
+ %{p:thread/gcrt1.o%s} %{pg:thread/gcrt1.o%s} \
+ %{!p:%{!pg:thread/crt1.o%s }}}}\
+ %{mthreads: thread/crti.o%s} %{!mthreads: crti.o%s} \
+ %{!shared: crtbegin.o%s} \
+ %{shared: crtbeginS.o%s}"
+#endif
+
+#ifndef ENDFILE_OS_LYNX_SPEC
+# define ENDFILE_OS_LYNX_SPEC \
+"%{!shared: crtend.o%s} \
+ %{shared: crtendS.o%s} \
+ %{mthreads: thread/crtn.o%s} %{!mthreads: crtn.o%s}"
+#endif
+
+/* Define the actual types of some ANSI-mandated types. */
+
+#ifndef SIZE_TYPE
+# define SIZE_TYPE "unsigned int"
+#endif
+
+#ifndef PTRDIFF_TYPE
+# define PTRDIFF_TYPE "int"
+#endif
+
+#ifndef WCHAR_TYPE
+# define WCHAR_TYPE "long int"
+#endif
+
+#ifndef WCHAR_TYPE_SIZE
+# define WCHAR_TYPE_SIZE BITS_PER_WORD
+#endif
+
+/* Define ASM_OUTPUT_ALIGN to use the .balign directive rather that
+ the .align directive with GAS. */
+
+#ifndef ASM_OUTPUT_ALIGN
+# define ASM_OUTPUT_ALIGN(FILE, LOG) \
+ do \
+ { \
+ if ((LOG) != 0) \
+ fprintf ((FILE), "\t.balign %d\n", 1 << (LOG)); \
+ } \
+ while (0)
+#endif
+
+/* Keep the *_DEBUGGING_INFO defines from elfos.h except that stabs is
+ the default on LynxOS. */
+
+#ifndef PREFERRED_DEBUGGING_TYPE
+# define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#endif
+
+/* We have C++ support in our system headers. */
+
+#ifndef NO_IMPLICIT_EXTERN_C
+# define NO_IMPLICIT_EXTERN_C
+#endif
+
+#ifndef TARGET_POSIX_IO
+# define TARGET_POSIX_IO
+#endif
diff --git a/contrib/gcc/config/lynx.opt b/contrib/gcc/config/lynx.opt
new file mode 100644
index 0000000..d576ef8
--- /dev/null
+++ b/contrib/gcc/config/lynx.opt
@@ -0,0 +1,32 @@
+; Processor-independent options for LynxOS.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mlegacy-threads
+Target RejectNegative
+Support legacy multi-threading
+
+mshared
+Target RejectNegative
+Use shared libraries
+
+mthreads
+Target RejectNegative
+Support multi-threading
diff --git a/contrib/gcc/config/memcmp.c b/contrib/gcc/config/memcmp.c
new file mode 100644
index 0000000..2348afe
--- /dev/null
+++ b/contrib/gcc/config/memcmp.c
@@ -0,0 +1,16 @@
+/* Public domain. */
+#include <stddef.h>
+
+int
+memcmp (const void *str1, const void *str2, size_t count)
+{
+ const unsigned char *s1 = str1;
+ const unsigned char *s2 = str2;
+
+ while (count-- > 0)
+ {
+ if (*s1++ != *s2++)
+ return s1[-1] < s2[-1] ? -1 : 1;
+ }
+ return 0;
+}
diff --git a/contrib/gcc/config/memcpy.c b/contrib/gcc/config/memcpy.c
new file mode 100644
index 0000000..58b1e40
--- /dev/null
+++ b/contrib/gcc/config/memcpy.c
@@ -0,0 +1,12 @@
+/* Public domain. */
+#include <stddef.h>
+
+void *
+memcpy (void *dest, const void *src, size_t len)
+{
+ char *d = dest;
+ const char *s = src;
+ while (len--)
+ *d++ = *s++;
+ return dest;
+}
diff --git a/contrib/gcc/config/memmove.c b/contrib/gcc/config/memmove.c
new file mode 100644
index 0000000..13b340a
--- /dev/null
+++ b/contrib/gcc/config/memmove.c
@@ -0,0 +1,20 @@
+/* Public domain. */
+#include <stddef.h>
+
+void *
+memmove (void *dest, const void *src, size_t len)
+{
+ char *d = dest;
+ const char *s = src;
+ if (d < s)
+ while (len--)
+ *d++ = *s++;
+ else
+ {
+ char *lasts = s + (len-1);
+ char *lastd = d + (len-1);
+ while (len--)
+ *lastd-- = *lasts--;
+ }
+ return dest;
+}
diff --git a/contrib/gcc/config/memset.c b/contrib/gcc/config/memset.c
new file mode 100644
index 0000000..3e7025e
--- /dev/null
+++ b/contrib/gcc/config/memset.c
@@ -0,0 +1,11 @@
+/* Public domain. */
+#include <stddef.h>
+
+void *
+memset (void *dest, int val, size_t len)
+{
+ unsigned char *ptr = dest;
+ while (len-- > 0)
+ *ptr++ = val;
+ return dest;
+}
diff --git a/contrib/gcc/config/mips/24k.md b/contrib/gcc/config/mips/24k.md
new file mode 100644
index 0000000..0dbb9f0
--- /dev/null
+++ b/contrib/gcc/config/mips/24k.md
@@ -0,0 +1,455 @@
+;; DFA-based pipeline descriptions for MIPS Technologies 24K core.
+;; Contributed by Chao-ying Fu (fu@mips.com), Nigel Stephens (nigel@mips.com)
+;; and David Ung (davidu@mips.com)
+;;
+;; The 24K is a single-issue processor with a half-clocked fpu.
+;; The 24Kx is 24k with 1:1 clocked fpu.
+;;
+;; References:
+;; "MIPS32 24K Processor Core Family Software User's Manual, Rev 3.04."
+;;
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+(define_automaton "r24k_cpu, r24k_mdu, r24k_fpu")
+
+;; Integer execution unit.
+(define_cpu_unit "r24k_iss" "r24k_cpu")
+(define_cpu_unit "r24k_ixu_arith" "r24k_cpu")
+(define_cpu_unit "r24k_mul3a" "r24k_mdu")
+(define_cpu_unit "r24k_mul3b" "r24k_mdu")
+(define_cpu_unit "r24k_mul3c" "r24k_mdu")
+
+;; --------------------------------------------------------------
+;; Producers
+;; --------------------------------------------------------------
+
+;; 1. Loads: lb, lbu, lh, lhu, ll, lw, lwl, lwr, lwpc, lwxs
+(define_insn_reservation "r24k_int_load" 2
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "load"))
+ "r24k_iss+r24k_ixu_arith")
+
+
+;; 2. Arithmetic: add, addi, addiu, addiupc, addu, and, andi, clo, clz,
+;; ext, ins, lui, movn, movz, nor, or, ori, rotr, rotrv, seb, seh, sll,
+;; sllv, slt, slti, sltiu, sltu, sra, srav, srl, srlv, sub, subu, wsbh,
+;; xor, xori
+;; (movn/movz is not matched, we'll need to split condmov to
+;; differentiate between integer/float moves)
+(define_insn_reservation "r24k_int_arith" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "arith,const,nop,shift,slt"))
+ "r24k_iss+r24k_ixu_arith")
+
+
+;; 3. Links: bgezal, bgezall, bltzal, bltzall, jal, jalr, jalx
+;; 3a. jr/jalr consumer
+(define_insn_reservation "r24k_int_jump" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "call,jump"))
+ "r24k_iss+r24k_ixu_arith")
+
+;; 3b. branch consumer
+(define_insn_reservation "r24k_int_branch" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "branch"))
+ "r24k_iss+r24k_ixu_arith")
+
+
+;; 4. MDU: fully pipelined multiplier
+;; mult - delivers result to hi/lo in 1 cycle (pipelined)
+(define_insn_reservation "r24k_int_mult" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "imul"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; madd, msub - delivers result to hi/lo in 1 cycle (pipelined)
+(define_insn_reservation "r24k_int_madd" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "imadd"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; mul - delivers result to gpr in 5 cycles
+(define_insn_reservation "r24k_int_mul3" 5
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "imul3"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)*5")
+
+;; mfhi, mflo, mflhxu - deliver result to gpr in 5 cycles
+(define_insn_reservation "r24k_int_mfhilo" 5
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "mfhilo"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; mthi, mtlo, mtlhx - deliver result to hi/lo, thence madd, handled as bypass
+(define_insn_reservation "r24k_int_mthilo" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "mthilo"))
+ "r24k_iss+(r24k_mul3a|r24k_mul3b|r24k_mul3c)")
+
+;; div - default to 36 cycles for 32bit operands. Faster for 24bit, 16bit and
+;; 8bit, but is tricky to identify.
+(define_insn_reservation "r24k_int_div" 36
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "idiv"))
+ "r24k_iss+(r24k_mul3a+r24k_mul3b+r24k_mul3c)*36")
+
+
+;; 5. Cop: cfc1, di, ei, mfc0, mtc0
+;; (Disabled until we add proper cop0 support)
+;;(define_insn_reservation "r24k_int_cop" 3
+;; (and (eq_attr "cpu" "24k,24kx")
+;; (eq_attr "type" "cop0"))
+;; "r24k_iss+r24k_ixu_arith")
+
+
+;; 6. Store
+(define_insn_reservation "r24k_int_store" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (and (eq_attr "type" "store")
+ (eq_attr "mode" "!unknown")))
+ "r24k_iss+r24k_ixu_arith")
+
+;; 6.1 Special case - matches the cprestore pattern which don't set the mode
+;; attrib. This avoids being set as r24k_int_store and have it checked
+;; against store_data_bypass_p, which would then fail because cprestore
+;; does not have a normal SET pattern.
+(define_insn_reservation "r24k_unknown_store" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (and (eq_attr "type" "store")
+ (eq_attr "mode" "unknown")))
+ "r24k_iss+r24k_ixu_arith")
+
+
+;; 7. Multiple instructions
+(define_insn_reservation "r24k_int_multi" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "multi"))
+ "r24k_iss+r24k_ixu_arith+r24k_fpu_arith+(r24k_mul3a+r24k_mul3b+r24k_mul3c)")
+
+
+;; 8. Unknowns - Currently these include blockage, consttable and alignment
+;; rtls. They do not really affect scheduling latency, (blockage affects
+;; scheduling via log links, but not used here).
+(define_insn_reservation "r24k_int_unknown" 0
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "unknown"))
+ "r24k_iss")
+
+
+;; 9. Prefetch
+(define_insn_reservation "r24k_int_prefetch" 1
+ (and (eq_attr "cpu" "24k,24kx")
+ (eq_attr "type" "prefetch,prefetchx"))
+ "r24k_iss+r24k_ixu_arith")
+
+
+;; --------------------------------------------------------------
+;; Bypass to Consumer
+;; --------------------------------------------------------------
+
+;; load->next use : 2 cycles (Default)
+;; load->load base: 3 cycles
+;; load->store base: 3 cycles
+;; load->prefetch: 3 cycles
+(define_bypass 3 "r24k_int_load" "r24k_int_load")
+(define_bypass 3 "r24k_int_load" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 3 "r24k_int_load" "r24k_int_prefetch")
+
+;; arith->next use : 1 cycles (Default)
+;; arith->load base: 2 cycles
+;; arith->store base: 2 cycles
+;; arith->prefetch: 2 cycles
+(define_bypass 2 "r24k_int_arith" "r24k_int_load")
+(define_bypass 2 "r24k_int_arith" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 2 "r24k_int_arith" "r24k_int_prefetch")
+
+;; mul3->next use : 5 cycles (default)
+;; mul3->l/s base : 6 cycles
+;; mul3->prefetch : 6 cycles
+(define_bypass 6 "r24k_int_mul3" "r24k_int_load")
+(define_bypass 6 "r24k_int_mul3" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24k_int_mul3" "r24k_int_prefetch")
+
+;; mfhilo->next use : 5 cycles (default)
+;; mfhilo->l/s base : 6 cycles
+;; mfhilo->prefetch : 6 cycles
+;; mthilo->madd/msub : 2 cycle (only for mthi/lo not mfhi/lo)
+(define_bypass 6 "r24k_int_mfhilo" "r24k_int_load")
+(define_bypass 6 "r24k_int_mfhilo" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24k_int_mfhilo" "r24k_int_prefetch")
+(define_bypass 2 "r24k_int_mthilo" "r24k_int_madd")
+
+;; cop->next use : 3 cycles (Default)
+;; cop->l/s base : 4 cycles
+;; (define_bypass 4 "r24k_int_cop" "r24k_int_load")
+;; (define_bypass 4 "r24k_int_cop" "r24k_int_store" "!store_data_bypass_p")
+
+;; multi->next use : 1 cycles (Default)
+;; multi->l/s base : 2 cycles
+;; multi->prefetch : 2 cycles
+(define_bypass 2 "r24k_int_multi" "r24k_int_load")
+(define_bypass 2 "r24k_int_multi" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 2 "r24k_int_multi" "r24k_int_prefetch")
+
+
+;; --------------------------------------------------------------
+;; Floating Point Instructions
+;; --------------------------------------------------------------
+
+(define_cpu_unit "r24k_fpu_arith" "r24k_fpu")
+
+;; The 24k is a single issue cpu, and the fpu runs at half clock speed,
+;; so each fpu instruction ties up the shared instruction scheduler for
+;; 1 cycle, and the fpu scheduler for 2 cycles.
+;;
+;; These timings are therefore twice the values in the 24K manual,
+;; which are quoted in fpu clocks.
+;;
+;; The 24kx is a 24k configured with 1:1 cpu and fpu, so use
+;; the unscaled timings
+
+(define_reservation "r24k_fpu_iss" "r24k_iss+(r24k_fpu_arith*2)")
+
+;; fadd, fabs, fneg
+(define_insn_reservation "r24k_fadd" 8
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "fadd,fabs,fneg"))
+ "r24k_fpu_iss")
+
+;; fmove, fcmove
+(define_insn_reservation "r24k_fmove" 8
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "fmove,condmove"))
+ "r24k_fpu_iss")
+
+;; fload
+(define_insn_reservation "r24k_fload" 6
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "fpload,fpidxload"))
+ "r24k_fpu_iss")
+
+;; fstore
+(define_insn_reservation "r24k_fstore" 2
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "fpstore"))
+ "r24k_fpu_iss")
+
+;; fmul, fmadd
+(define_insn_reservation "r24k_fmul_sf" 8
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "r24k_fpu_iss")
+
+(define_insn_reservation "r24k_fmul_df" 10
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "r24k_fpu_iss,(r24k_fpu_arith*2)")
+
+
+;; fdiv, fsqrt, frsqrt
+(define_insn_reservation "r24k_fdiv_sf" 34
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "r24k_fpu_iss,(r24k_fpu_arith*26)")
+
+(define_insn_reservation "r24k_fdiv_df" 64
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "r24k_fpu_iss,(r24k_fpu_arith*56)")
+
+;; frsqrt
+(define_insn_reservation "r24k_frsqrt_df" 70
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "r24k_fpu_iss,(r24k_fpu_arith*60)")
+
+;; fcmp
+(define_insn_reservation "r24k_fcmp" 4
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "fcmp"))
+ "r24k_fpu_iss")
+
+;; fcmp -> movf.fmt & movt.fmt bypass (dependency must be on the condition)
+(define_bypass 2 "r24k_fcmp" "r24k_fmove")
+
+;; fcvt (cvt.d.s, cvt.[sd].[wl])
+(define_insn_reservation "r24k_fcvt_i2f_s2d" 8
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "I2S,I2D,S2D")))
+ "r24k_fpu_iss")
+
+;; fcvt (cvt.s.d)
+(define_insn_reservation "r24k_fcvt_s2d" 12
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "D2S")))
+ "r24k_fpu_iss")
+
+;; fcvt (cvt.[wl].[sd], etc)
+(define_insn_reservation "r24k_fcvt_f2i" 10
+ (and (eq_attr "cpu" "24k")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "S2I,D2I")))
+ "r24k_fpu_iss")
+
+;; fxfer (mfc1, mfhc1, mtc1, mthc1)
+(define_insn_reservation "r24k_fxfer" 4
+ (and (eq_attr "cpu" "24k")
+ (eq_attr "type" "xfer"))
+ "r24k_fpu_iss")
+
+;; --------------------------------------------------------------
+;; Bypass to Consumer
+;; --------------------------------------------------------------
+;; r24k_fcvt_f2i->l/s base : 11 cycles
+;; r24k_fcvt_f2i->prefetch : 11 cycles
+(define_bypass 11 "r24k_fcvt_f2i" "r24k_int_load")
+(define_bypass 11 "r24k_fcvt_f2i" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 11 "r24k_fcvt_f2i" "r24k_int_prefetch")
+
+;; r24k_fxfer->l/s base : 5 cycles
+;; r24k_fxfer->prefetch : 5 cycles
+(define_bypass 5 "r24k_fxfer" "r24k_int_load")
+(define_bypass 5 "r24k_fxfer" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 5 "r24k_fxfer" "r24k_int_prefetch")
+
+;; --------------------------------------------------------------
+;; The 24kx is a 24k configured with 1:1 cpu and fpu, so use
+;; the unscaled timings
+;; --------------------------------------------------------------
+
+(define_reservation "r24kx_fpu_iss" "r24k_iss+r24k_fpu_arith")
+
+;; fadd, fabs, fneg
+(define_insn_reservation "r24kx_fadd" 4
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "fadd,fabs,fneg"))
+ "r24kx_fpu_iss")
+
+;; fmove, fcmove
+(define_insn_reservation "r24kx_fmove" 4
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "fmove,condmove"))
+ "r24kx_fpu_iss")
+
+;; fload
+(define_insn_reservation "r24kx_fload" 3
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "fpload,fpidxload"))
+ "r24kx_fpu_iss")
+
+;; fstore
+(define_insn_reservation "r24kx_fstore" 1
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "fpstore"))
+ "r24kx_fpu_iss")
+
+;; fmul, fmadd
+(define_insn_reservation "r24kx_fmul_sf" 4
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "r24kx_fpu_iss")
+
+(define_insn_reservation "r24kx_fmul_df" 5
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "r24kx_fpu_iss,r24k_fpu_arith")
+
+
+;; fdiv, fsqrt, frsqrt
+(define_insn_reservation "r24kx_fdiv_sf" 17
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "r24kx_fpu_iss,(r24k_fpu_arith*13)")
+
+(define_insn_reservation "r24kx_fdiv_df" 32
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "r24kx_fpu_iss,(r24k_fpu_arith*28)")
+
+;; frsqrt
+(define_insn_reservation "r24kx_frsqrt_df" 35
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "r24kx_fpu_iss,(r24k_fpu_arith*30)")
+
+;; fcmp
+(define_insn_reservation "r24kx_fcmp" 2
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "fcmp"))
+ "r24kx_fpu_iss")
+
+;; fcmp -> movf.fmt & movt.fmt bypass (dependency must be on the condition)
+(define_bypass 1 "r24kx_fcmp" "r24kx_fmove")
+
+;; fcvt (cvt.d.s, cvt.[sd].[wl])
+(define_insn_reservation "r24kx_fcvt_i2f_s2d" 4
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "I2S,I2D,S2D")))
+ "r24kx_fpu_iss")
+
+;; fcvt (cvt.s.d)
+(define_insn_reservation "r24kx_fcvt_s2d" 6
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "D2S")))
+ "r24kx_fpu_iss")
+
+;; fcvt (cvt.[wl].[sd], etc)
+(define_insn_reservation "r24kx_fcvt_f2i" 5
+ (and (eq_attr "cpu" "24kx")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "S2I,D2I")))
+ "r24kx_fpu_iss")
+
+;; fxfer (mfc1, mfhc1, mtc1, mthc1)
+(define_insn_reservation "r24kx_fxfer" 2
+ (and (eq_attr "cpu" "24kx")
+ (eq_attr "type" "xfer"))
+ "r24kx_fpu_iss")
+
+;; --------------------------------------------------------------
+;; Bypass to Consumer
+;; --------------------------------------------------------------
+;; r24kx_fcvt_f2i->l/s base : 6 cycles
+;; r24kx_fcvt_f2i->prefetch : 6 cycles
+(define_bypass 6 "r24kx_fcvt_f2i" "r24k_int_load")
+(define_bypass 6 "r24kx_fcvt_f2i" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 6 "r24kx_fcvt_f2i" "r24k_int_prefetch")
+
+;; r24kx_fxfer->l/s base : 3 cycles
+;; r24kx_fxfer->prefetch : 3 cycles
+(define_bypass 3 "r24kx_fxfer" "r24k_int_load")
+(define_bypass 3 "r24kx_fxfer" "r24k_int_store" "!store_data_bypass_p")
+(define_bypass 3 "r24kx_fxfer" "r24k_int_prefetch")
+
diff --git a/contrib/gcc/config/mips/3000.md b/contrib/gcc/config/mips/3000.md
new file mode 100644
index 0000000..67c7ac0
--- /dev/null
+++ b/contrib/gcc/config/mips/3000.md
@@ -0,0 +1,72 @@
+;; R3000 and TX39 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r3k_load" 2
+ (and (eq_attr "cpu" "r3000,r3900")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "alu")
+
+(define_insn_reservation "r3k_imul" 12
+ (and (eq_attr "cpu" "r3000,r3900")
+ (eq_attr "type" "imul,imul3,imadd"))
+ "imuldiv*12")
+
+(define_insn_reservation "r3k_idiv" 35
+ (and (eq_attr "cpu" "r3000,r3900")
+ (eq_attr "type" "idiv"))
+ "imuldiv*35")
+
+(define_insn_reservation "r3k_fmove" 1
+ (and (eq_attr "cpu" "r3000,r3900")
+ (eq_attr "type" "fabs,fneg,fmove"))
+ "alu")
+
+(define_insn_reservation "r3k_fadd" 2
+ (and (eq_attr "cpu" "r3000,r3900")
+ (eq_attr "type" "fcmp,fadd"))
+ "alu")
+
+(define_insn_reservation "r3k_fmul_single" 4
+ (and (eq_attr "cpu" "r3000,r3900")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r3k_fmul_double" 5
+ (and (eq_attr "cpu" "r3000,r3900")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "alu")
+
+(define_insn_reservation "r3k_fdiv_single" 12
+ (and (eq_attr "cpu" "r3000,r3900")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r3k_fdiv_double" 19
+ (and (eq_attr "cpu" "r3000,r3900")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "DF")))
+ "alu")
diff --git a/contrib/gcc/config/mips/4000.md b/contrib/gcc/config/mips/4000.md
new file mode 100644
index 0000000..1e2875f
--- /dev/null
+++ b/contrib/gcc/config/mips/4000.md
@@ -0,0 +1,33 @@
+;; R4000 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r4k_imul" 10
+ (and (eq_attr "cpu" "r4000")
+ (eq_attr "type" "imul,imul3,imadd"))
+ "imuldiv*10")
+
+(define_insn_reservation "r4k_idiv" 69
+ (and (eq_attr "cpu" "r4000")
+ (eq_attr "type" "idiv"))
+ "imuldiv*69")
diff --git a/contrib/gcc/config/mips/4100.md b/contrib/gcc/config/mips/4100.md
new file mode 100644
index 0000000..c7314d8
--- /dev/null
+++ b/contrib/gcc/config/mips/4100.md
@@ -0,0 +1,52 @@
+;; VR4100 and VR4120 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r4100_load" 2
+ (and (eq_attr "cpu" "r4100,r4120")
+ (eq_attr "type" "load,fpload,fpidxload,xfer"))
+ "alu")
+
+(define_insn_reservation "r4100_imul_si" 1
+ (and (eq_attr "cpu" "r4100,r4120")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI")))
+ "imuldiv")
+
+(define_insn_reservation "r4100_imul_di" 4
+ (and (eq_attr "cpu" "r4100,r4120")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI")))
+ "imuldiv*4")
+
+(define_insn_reservation "r4100_idiv_si" 35
+ (and (eq_attr "cpu" "r4100,r4120")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "imuldiv*35")
+
+(define_insn_reservation "r4100_idiv_di" 67
+ (and (eq_attr "cpu" "r4100,r4120")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "imuldiv*67")
diff --git a/contrib/gcc/config/mips/4130.md b/contrib/gcc/config/mips/4130.md
new file mode 100644
index 0000000..6feeab3
--- /dev/null
+++ b/contrib/gcc/config/mips/4130.md
@@ -0,0 +1,136 @@
+;;
+;; Pipeline description for the VR4130 family.
+;;
+;; The processor issues each 8-byte aligned pair of instructions together,
+;; stalling the second instruction if it depends on the first. Thus, if we
+;; want two instructions to issue in parallel, we need to make sure that the
+;; first one is 8-byte aligned.
+;;
+;; For the purposes of this pipeline description, we treat the processor
+;; like a standard two-way superscalar architecture. If scheduling were
+;; the last pass to run, we could use the scheduler hooks to vary the
+;; issue rate depending on whether an instruction is at an aligned or
+;; unaligned address. Unfortunately, delayed branch scheduling and
+;; hazard avoidance are done after the final scheduling pass, and they
+;; can change the addresses of many instructions.
+;;
+;; We get around this in two ways:
+;;
+;; (1) By running an extra pass at the end of compilation. This pass goes
+;; through the function looking for pairs of instructions that could
+;; execute in parallel. It makes sure that the first instruction in
+;; each pair is suitably aligned, inserting nops if necessary. Doing
+;; this gives the same kind of pipeline behavior we would see on a
+;; normal superscalar target.
+;;
+;; This pass is generally a speed improvement, but the extra nops will
+;; obviously make the program bigger. It is therefore unsuitable for
+;; -Os (at the very least).
+;;
+;; (2) By modifying the scheduler hooks so that, where possible:
+;;
+;; (a) dependent instructions are separated by a non-dependent
+;; instruction;
+;;
+;; (b) instructions that use the multiplication unit are separated
+;; by non-multiplication instructions; and
+;;
+;; (c) memory access instructions are separated by non-memory
+;; instructions.
+;;
+;; The idea is to keep conflicting instructions apart wherever possible
+;; and thus make the schedule less dependent on alignment.
+
+(define_automaton "vr4130_main, vr4130_muldiv, vr4130_mulpre")
+
+(define_cpu_unit "vr4130_alu1, vr4130_alu2, vr4130_dcache" "vr4130_main")
+(define_cpu_unit "vr4130_muldiv" "vr4130_muldiv")
+
+;; This is a fake unit for pre-reload scheduling of multiplications.
+;; It enforces the true post-reload repeat rate.
+(define_cpu_unit "vr4130_mulpre" "vr4130_mulpre")
+
+;; The scheduling hooks use this attribute for (b) above.
+(define_attr "vr4130_class" "mul,mem,alu"
+ (cond [(eq_attr "type" "load,store")
+ (const_string "mem")
+
+ (eq_attr "type" "mfhilo,mthilo,imul,imul3,imadd,idiv")
+ (const_string "mul")]
+ (const_string "alu")))
+
+(define_insn_reservation "vr4130_multi" 1
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "multi,unknown"))
+ "vr4130_alu1 + vr4130_alu2 + vr4130_dcache + vr4130_muldiv")
+
+(define_insn_reservation "vr4130_int" 1
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "const,arith,shift,slt,nop"))
+ "vr4130_alu1 | vr4130_alu2")
+
+(define_insn_reservation "vr4130_load" 3
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "load"))
+ "vr4130_dcache")
+
+(define_insn_reservation "vr4130_store" 1
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "store"))
+ "vr4130_dcache")
+
+(define_insn_reservation "vr4130_mfhilo" 3
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "mfhilo"))
+ "vr4130_muldiv")
+
+(define_insn_reservation "vr4130_mthilo" 1
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "mthilo"))
+ "vr4130_muldiv")
+
+;; The product is available in LO & HI after one cycle. Moving the result
+;; into an integer register will take an additional three cycles, see mflo
+;; & mfhi above. Note that the same latencies and repeat rates apply if we
+;; use "mtlo; macc" instead of "mult; mflo".
+(define_insn_reservation "vr4130_mulsi" 4
+ (and (eq_attr "cpu" "r4130")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "SI")))
+ "vr4130_muldiv + (vr4130_mulpre * 2)")
+
+;; As for vr4130_mulsi, but the product is available in LO and HI
+;; after 3 cycles.
+(define_insn_reservation "vr4130_muldi" 6
+ (and (eq_attr "cpu" "r4130")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "DI")))
+ "(vr4130_muldiv * 3) + (vr4130_mulpre * 4)")
+
+;; maccs can execute in consecutive cycles without stalling, but it
+;; is 3 cycles before the integer destination can be read.
+(define_insn_reservation "vr4130_macc" 3
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "imadd"))
+ "vr4130_muldiv")
+
+(define_bypass 1 "vr4130_mulsi,vr4130_macc" "vr4130_macc" "mips_linked_madd_p")
+(define_bypass 1 "vr4130_mulsi,vr4130_macc" "vr4130_mfhilo")
+(define_bypass 3 "vr4130_muldi" "vr4130_mfhilo")
+
+(define_insn_reservation "vr4130_divsi" 36
+ (and (eq_attr "cpu" "r4130")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "vr4130_muldiv * 36")
+
+(define_insn_reservation "vr4130_divdi" 72
+ (and (eq_attr "cpu" "r4130")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "vr4130_muldiv * 72")
+
+(define_insn_reservation "vr4130_branch" 0
+ (and (eq_attr "cpu" "r4130")
+ (eq_attr "type" "branch,jump,call"))
+ "vr4130_alu1 | vr4130_alu2")
diff --git a/contrib/gcc/config/mips/4300.md b/contrib/gcc/config/mips/4300.md
new file mode 100644
index 0000000..7453f4c
--- /dev/null
+++ b/contrib/gcc/config/mips/4300.md
@@ -0,0 +1,86 @@
+;; VR4300 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r4300_load" 2
+ (and (eq_attr "cpu" "r4300")
+ (eq_attr "type" "load,fpload,fpidxload,xfer"))
+ "alu")
+
+(define_insn_reservation "r4300_imul_si" 5
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI")))
+ "imuldiv*5")
+
+(define_insn_reservation "r4300_imul_di" 8
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI")))
+ "imuldiv*8")
+
+(define_insn_reservation "r4300_idiv_si" 37
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "imuldiv*37")
+
+(define_insn_reservation "r4300_idiv_di" 69
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "imuldiv*69")
+
+(define_insn_reservation "r4300_fmove" 1
+ (and (eq_attr "cpu" "r4300")
+ (eq_attr "type" "fcmp,fabs,fneg,fmove"))
+ "imuldiv")
+
+(define_insn_reservation "r4300_fadd" 3
+ (and (eq_attr "cpu" "r4300")
+ (eq_attr "type" "fadd"))
+ "imuldiv*3")
+
+(define_insn_reservation "r4300_fmul_single" 5
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "imuldiv*5")
+
+(define_insn_reservation "r4300_fmul_double" 8
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "imuldiv*8")
+
+(define_insn_reservation "r4300_fdiv_single" 29
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "imuldiv*29")
+
+(define_insn_reservation "r4300_fdiv_double" 58
+ (and (eq_attr "cpu" "r4300")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "DF")))
+ "imuldiv*58")
diff --git a/contrib/gcc/config/mips/4600.md b/contrib/gcc/config/mips/4600.md
new file mode 100644
index 0000000..df3f72d
--- /dev/null
+++ b/contrib/gcc/config/mips/4600.md
@@ -0,0 +1,88 @@
+;; R4600 and R4650 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+;;
+;; We handle the R4600 and R4650 in much the same way. The only difference
+;; is in the integer multiplication and division costs.
+
+(define_insn_reservation "r4600_imul" 10
+ (and (eq_attr "cpu" "r4600")
+ (eq_attr "type" "imul,imul3,imadd"))
+ "imuldiv*10")
+
+(define_insn_reservation "r4600_idiv" 42
+ (and (eq_attr "cpu" "r4600")
+ (eq_attr "type" "idiv"))
+ "imuldiv*42")
+
+
+(define_insn_reservation "r4650_imul" 4
+ (and (eq_attr "cpu" "r4650")
+ (eq_attr "type" "imul,imul3,imadd"))
+ "imuldiv*4")
+
+(define_insn_reservation "r4650_idiv" 36
+ (and (eq_attr "cpu" "r4650")
+ (eq_attr "type" "idiv"))
+ "imuldiv*36")
+
+
+(define_insn_reservation "r4600_load" 2
+ (and (eq_attr "cpu" "r4600,r4650")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "alu")
+
+(define_insn_reservation "r4600_fmove" 1
+ (and (eq_attr "cpu" "r4600,r4650")
+ (eq_attr "type" "fabs,fneg,fmove"))
+ "alu")
+
+(define_insn_reservation "r4600_fmul_single" 8
+ (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r4600_fdiv_single" 32
+ (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r4600_fdiv_double" 61
+ (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "DF")))
+ "alu")
+
+(define_insn_reservation "r4600_fsqrt_single" 31
+ (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "type" "fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r4600_fsqrt_double" 60
+ (and (eq_attr "cpu" "r4600,r4650")
+ (and (eq_attr "type" "fsqrt,frsqrt")
+ (eq_attr "mode" "DF")))
+ "alu")
diff --git a/contrib/gcc/config/mips/4k.md b/contrib/gcc/config/mips/4k.md
new file mode 100644
index 0000000..6f7d6d1
--- /dev/null
+++ b/contrib/gcc/config/mips/4k.md
@@ -0,0 +1,154 @@
+;; DFA-based pipeline descriptions for MIPS32 4K processor family
+;; Contributed by Nigel Stephens (nigel@mips.com)
+;; and David Ung (davidu@mips.com)
+;;
+;; References:
+;; "MIPS32 4K Processor Core Family Software User's Manual,
+;; Doc no: MD00016, Rev 1.18, Nov 15, 2004."
+;;
+;; 4Kc - pipelined multiplier and translation lookaside buffer (TLB)
+;; 4km - pipelined multiplier and block address translator (BAT)
+;; 4kp - non-pipelined multiplier and block address translator (BAT)
+;;
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+(define_automaton "r4k_cpu, r4k_mdu")
+
+;; Integer execution unit.
+(define_cpu_unit "r4k_ixu_arith" "r4k_cpu")
+(define_cpu_unit "r4k_ixu_mpydiv" "r4k_mdu")
+
+(define_insn_reservation "r4k_int_load" 2
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "load"))
+ "r4k_ixu_arith")
+
+(define_insn_reservation "r4k_int_prefetch" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "prefetch"))
+ "r4k_ixu_arith")
+
+(define_insn_reservation "r4k_int_store" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "store"))
+ "r4k_ixu_arith")
+
+;; 4Kc/4Km
+;; unsigned divide - 8/16/24/32 bit operand have latencies 9/17/25/33
+;; signed divide - 8/16/24/32 bit operand have latencies 10/18/26/34
+(define_insn_reservation "r4k_idiv_4kc" 34
+ (and (eq_attr "cpu" "4kc")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "!DI")))
+ "r4k_ixu_arith+(r4k_ixu_mpydiv*34)")
+
+;; 4Kp
+;; unsigned divide - 33
+;; signed divide - 33-35
+(define_insn_reservation "r4k_idiv_4kp" 35
+ (and (eq_attr "cpu" "4kp")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "!DI")))
+ "r4k_ixu_arith+(r4k_ixu_mpydiv*35)")
+
+;; 4Kc/4Km fast 32x32 multiply
+;; 16x32 is faster, but there's no way to detect this
+(define_insn_reservation "r4k_mult_4kc" 2
+ (and (eq_attr "cpu" "4kc")
+ (and (eq_attr "type" "imul,imadd")
+ (eq_attr "mode" "SI")))
+ "r4k_ixu_arith+(r4k_ixu_mpydiv*2)")
+
+;; 4Kc/4Km MUL has 2 cycle latency, but has the special property that it will
+;; stall the integer unit pipeline. MUL 16x16 or 32x16 forces 1 cycle stall,
+;; while MUL 32x32 forces 2 cycle stall. If next insn use the result, an
+;; additional stall is forced.
+(define_insn_reservation "r4k_mul_4kc" 4
+ (and (eq_attr "cpu" "4kc")
+ (and (eq_attr "type" "imul3")
+ (eq_attr "mode" "SI")))
+ "(r4k_ixu_arith+r4k_ixu_mpydiv)*3")
+
+;; 4Kp slow iterative 2-op MULT
+;; Latency of 32 if next insn is MADD/MSUB,MFHI/MFLO.
+;; Repeat rate of 33 cycles.
+(define_insn_reservation "r4k_mult_4kp" 32
+ (and (eq_attr "cpu" "4kp")
+ (and (eq_attr "type" "imul")
+ (eq_attr "mode" "SI")))
+ "r4k_ixu_arith+(r4k_ixu_mpydiv*32)")
+
+;; 4Kp slow iterative 3-op MUL
+;; Latency of 32 cycles, but stalls the whole pipeline until complete.
+(define_insn_reservation "r4k_mul_4kp" 32
+ (and (eq_attr "cpu" "4kp")
+ (and (eq_attr "type" "imul3")
+ (eq_attr "mode" "SI")))
+ "(r4k_ixu_arith+r4k_ixu_mpydiv)*32")
+
+;; 4Kp slow iterative MADD
+;; Latency of 34 if next use insn is MADD/MSUB,MFHI/MFLO.
+;; Repeat rate of 35 cycles.
+(define_insn_reservation "r4k_madd_4kp" 34
+ (and (eq_attr "cpu" "4kp")
+ (and (eq_attr "type" "imadd")
+ (eq_attr "mode" "SI")))
+ "r4k_ixu_arith+(r4k_ixu_mpydiv*34)")
+
+;; Move to HI/LO -> MADD/MSUB,MFHI/MFLO has a 1 cycle latency.
+(define_insn_reservation "r4k_int_mthilo" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "mthilo"))
+ "r4k_ixu_arith+r4k_ixu_mpydiv")
+
+;; Move from HI/LO -> integer operation has a 2 cycle latency.
+(define_insn_reservation "r4k_int_mfhilo" 2
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "mfhilo"))
+ "r4k_ixu_arith+r4k_ixu_mpydiv")
+
+;; All other integer insns.
+(define_insn_reservation "r4k_int_alu" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "arith,condmove,shift,const,nop,slt"))
+ "r4k_ixu_arith")
+
+(define_insn_reservation "r4k_int_branch" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "branch"))
+ "r4k_ixu_arith")
+
+(define_insn_reservation "r4k_int_jump_4k" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "jump,call"))
+ "r4k_ixu_arith")
+
+;; mfcx/mtcx - non FPU
+;; (Disabled until we add cop0 support)
+;; (define_insn_reservation "r4k_int_cop" 2
+;; (and (eq_attr "cpu" "4kc,4kp")
+;; (eq_attr "type" "cop0"))
+;; "r4k_ixu_arith")
+
+;; Unknown or multi - single issue
+(define_insn_reservation "r4k_unknown" 1
+ (and (eq_attr "cpu" "4kc,4kp")
+ (eq_attr "type" "unknown,multi"))
+ "r4k_ixu_arith+r4k_ixu_mpydiv")
diff --git a/contrib/gcc/config/mips/5000.md b/contrib/gcc/config/mips/5000.md
new file mode 100644
index 0000000..4d9c98c
--- /dev/null
+++ b/contrib/gcc/config/mips/5000.md
@@ -0,0 +1,81 @@
+;; VR5000 pipeline description.
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r5k_load" 2
+ (and (eq_attr "cpu" "r5000")
+ (eq_attr "type" "load,fpload,fpidxload,xfer"))
+ "alu")
+
+(define_insn_reservation "r5k_imul_si" 5
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI")))
+ "imuldiv*5")
+
+(define_insn_reservation "r5k_imul_di" 9
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI")))
+ "imuldiv*9")
+
+(define_insn_reservation "r5k_idiv_si" 36
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "imuldiv*36")
+
+(define_insn_reservation "r5k_idiv_di" 68
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "imuldiv*68")
+
+(define_insn_reservation "r5k_fmove" 1
+ (and (eq_attr "cpu" "r5000")
+ (eq_attr "type" "fcmp,fabs,fneg,fmove"))
+ "alu")
+
+(define_insn_reservation "r5k_fmul_single" 4
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r5k_fmul_double" 5
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "alu")
+
+(define_insn_reservation "r5k_fdiv_single" 21
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r5k_fsqrt_double" 36
+ (and (eq_attr "cpu" "r5000")
+ (and (eq_attr "type" "fsqrt,frsqrt")
+ (eq_attr "mode" "DF")))
+ "alu")
diff --git a/contrib/gcc/config/mips/5400.md b/contrib/gcc/config/mips/5400.md
new file mode 100644
index 0000000..8571308
--- /dev/null
+++ b/contrib/gcc/config/mips/5400.md
@@ -0,0 +1,166 @@
+;; DFA-based pipeline description for 5400
+(define_automaton "vr54")
+(define_cpu_unit "vr54_dp0" "vr54")
+(define_cpu_unit "vr54_dp1" "vr54")
+(define_cpu_unit "vr54_mem" "vr54")
+(define_cpu_unit "vr54_mac" "vr54")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+(define_insn_reservation "ir_vr54_unknown" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "unknown"))
+ "vr54_dp0+vr54_dp1+vr54_mem+vr54_mac")
+
+;; Assume prediction fails.
+(define_insn_reservation "ir_vr54_branch" 3
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "branch,jump,call"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_load" 2
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "vr54_mem")
+
+(define_insn_reservation "ir_vr54_store" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "store"))
+ "vr54_mem")
+
+(define_insn_reservation "ir_vr54_fstore" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "fpstore,fpidxstore"))
+ "vr54_mem")
+
+
+;; This reservation is for conditional move based on integer
+;; or floating point CC.
+(define_insn_reservation "ir_vr54_condmove" 4
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "condmove"))
+ "vr54_dp0|vr54_dp1")
+
+;; Move to/from FPU registers
+(define_insn_reservation "ir_vr54_xfer" 2
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "xfer"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_hilo" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "mthilo,mfhilo"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_arith" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "arith,shift,slt,clz,const,nop,trap"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imul_si" 3
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "SI")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imul_di" 4
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "DI")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_imadd_si" 3
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "imul,imul3"))
+ "vr54_mac")
+
+(define_insn_reservation "ir_vr54_idiv_si" 42
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_idiv_di" 74
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fadd" 4
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "fadd"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmul_sf" 5
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "mode" "SF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmul_df" 6
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "mode" "DF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmadd_sf" 9
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "mode" "SF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fmadd_df" 10
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "mode" "DF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fdiv_sf" 42
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "SF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fdiv_df" 72
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fabs" 2
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "fabs,fneg,fmove"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fcmp" 2
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "fcmp"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_fcvt" 6
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "fcvt"))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_frsqrt_sf" 61
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "SF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_frsqrt_df" 121
+ (and (eq_attr "cpu" "r5400")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "vr54_dp0|vr54_dp1")
+
+(define_insn_reservation "ir_vr54_multi" 1
+ (and (eq_attr "cpu" "r5400")
+ (eq_attr "type" "multi"))
+ "vr54_dp0+vr54_dp1+vr54_mem+vr54_mac")
diff --git a/contrib/gcc/config/mips/5500.md b/contrib/gcc/config/mips/5500.md
new file mode 100644
index 0000000..881cbcb
--- /dev/null
+++ b/contrib/gcc/config/mips/5500.md
@@ -0,0 +1,209 @@
+;; DFA-based pipeline description for 5500
+(define_automaton "vr55")
+(define_cpu_unit "vr55_dp0" "vr55")
+(define_cpu_unit "vr55_dp1" "vr55")
+(define_cpu_unit "vr55_mem" "vr55")
+(define_cpu_unit "vr55_mac" "vr55")
+(define_cpu_unit "vr55_fp" "vr55")
+(define_cpu_unit "vr55_bru" "vr55")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+(define_insn_reservation "ir_vr55_unknown" 1
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "unknown"))
+ "vr55_dp0+vr55_dp1+vr55_mem+vr55_mac+vr55_fp+vr55_bru")
+
+;; Assume prediction fails.
+(define_insn_reservation "ir_vr55_branch" 2
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "branch,jump,call"))
+ "vr55_bru")
+
+(define_insn_reservation "ir_vr55_load" 3
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "vr55_mem")
+
+(define_bypass 4
+ "ir_vr55_load"
+ "ir_vr55_mthilo,ir_vr55_imul_si,ir_vr55_imul_di,ir_vr55_imadd,
+ ir_vr55_idiv_si,ir_vr55_idiv_di")
+
+(define_insn_reservation "ir_vr55_store" 0
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "store,fpstore,fpidxstore"))
+ "vr55_mem")
+
+;; This reservation is for conditional move based on integer
+;; or floating point CC.
+(define_insn_reservation "ir_vr55_condmove" 2
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "condmove"))
+ "vr55_dp0|vr55_dp1")
+
+;; Move to/from FPU registers
+(define_insn_reservation "ir_vr55_xfer" 2
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "xfer"))
+ "vr55_dp0|vr55_dp1")
+
+(define_insn_reservation "ir_vr55_arith" 1
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "arith,shift,slt,clz,const,nop,trap"))
+ "vr55_dp0|vr55_dp1")
+
+(define_bypass 2
+ "ir_vr55_arith"
+ "ir_vr55_mthilo,ir_vr55_imul_si,ir_vr55_imul_di,ir_vr55_imadd,
+ ir_vr55_idiv_si,ir_vr55_idiv_di")
+
+(define_insn_reservation "ir_vr55_mthilo" 1
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "mthilo"))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_mfhilo" 5
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "mfhilo"))
+ "vr55_mac")
+
+;; The default latency is for the GPR result of a mul. Bypasses handle the
+;; latency of {mul,mult}->{mfhi,mflo}.
+(define_insn_reservation "ir_vr55_imul_si" 5
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "SI")))
+ "vr55_mac")
+
+;; The default latency is for pre-reload scheduling and handles the case
+;; where a pseudo destination will be stored in a GPR (as it usually is).
+;; The delay includes the latency of the dmult itself and the anticipated
+;; mflo or mfhi.
+;;
+;; Once the mflo or mfhi has been created, bypasses handle the latency
+;; between it and the dmult.
+(define_insn_reservation "ir_vr55_imul_di" 9
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "DI")))
+ "vr55_mac*4")
+
+;; The default latency is as for ir_vr55_imul_si.
+(define_insn_reservation "ir_vr55_imadd" 5
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "imadd"))
+ "vr55_mac")
+
+(define_bypass 1
+ "ir_vr55_imul_si,ir_vr55_imadd"
+ "ir_vr55_imadd"
+ "mips_linked_madd_p")
+
+(define_bypass 2
+ "ir_vr55_imul_si,ir_vr55_imadd"
+ "ir_vr55_mfhilo")
+
+(define_bypass 4
+ "ir_vr55_imul_di"
+ "ir_vr55_mfhilo")
+
+;; Divide algorithm is early out with best latency of 7 pcycles.
+;; Use worst case for scheduling purposes.
+(define_insn_reservation "ir_vr55_idiv_si" 42
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_idiv_di" 74
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fadd" 4
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "fadd"))
+ "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fmul_sf" 5
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "mode" "SF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmul_df" 6
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fmul")
+ (eq_attr "mode" "DF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmadd_sf" 9
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "mode" "SF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fmadd_df" 10
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "mode" "DF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fdiv_sf" 30
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "SF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fdiv_df" 59
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_fabs" 2
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "fabs,fneg,fmove"))
+ "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcmp" 2
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "fcmp"))
+ "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcvt_sf" 4
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "mode" "SF")))
+ "vr55_fp")
+
+(define_insn_reservation "ir_vr55_fcvt_df" 6
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "mode" "DF")))
+ "vr55_fp")
+
+(define_insn_reservation "ir_vr55_frsqrt_sf" 60
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "SF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_frsqrt_df" 118
+ (and (eq_attr "cpu" "r5500")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "vr55_mac")
+
+(define_insn_reservation "ir_vr55_multi" 1
+ (and (eq_attr "cpu" "r5500")
+ (eq_attr "type" "multi"))
+ "vr55_dp0+vr55_dp1+vr55_mem+vr55_mac+vr55_fp+vr55_bru")
diff --git a/contrib/gcc/config/mips/5k.md b/contrib/gcc/config/mips/5k.md
new file mode 100644
index 0000000..0fa588a
--- /dev/null
+++ b/contrib/gcc/config/mips/5k.md
@@ -0,0 +1,230 @@
+;; DFA-based pipeline descriptions for MIPS32 5K processor family
+;; Contributed by David Ung (davidu@mips.com)
+;; and Nigel Stephens (nigel@mips.com)
+;;
+;; References:
+;; "MIPS64 5K Processor Core Family Software User's Manual,
+;; Doc no: MD00012, Rev 2.09, Jan 28, 2005."
+;;
+;; 5Kc - Single issue with no floating point unit.
+;; 5kf - Separate floating point pipe which can dual-issue with the
+;; integer pipe.
+;;
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+(define_automaton "r5k_cpu, r5k_mdu, r5k_fpu")
+
+;; Integer execution unit.
+(define_cpu_unit "r5k_ixu_arith" "r5k_cpu")
+(define_cpu_unit "r5k_ixu_mpydiv" "r5k_mdu")
+(define_cpu_unit "r5kf_fpu_arith" "r5k_fpu")
+
+(define_insn_reservation "r5k_int_load" 2
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "load"))
+ "r5k_ixu_arith")
+
+(define_insn_reservation "r5k_int_prefetch" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "prefetch,prefetchx"))
+ "r5k_ixu_arith")
+
+(define_insn_reservation "r5k_int_store" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "store"))
+ "r5k_ixu_arith")
+
+;; Divides
+(define_insn_reservation "r5k_int_divsi" 34
+ (and (eq_attr "cpu" "5kc,5kf")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "!DI")))
+ "r5k_ixu_arith+(r5k_ixu_mpydiv*34)")
+
+(define_insn_reservation "r5k_int_divdi" 66
+ (and (eq_attr "cpu" "5kc,5kf")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "r5k_ixu_arith+(r5k_ixu_mpydiv*66)")
+
+;; 32x32 multiply
+;; 32x16 is faster, but there's no way to detect this
+(define_insn_reservation "r5k_int_mult" 2
+ (and (eq_attr "cpu" "5kc,5kf")
+ (and (eq_attr "type" "imul,imadd")
+ (eq_attr "mode" "SI")))
+ "r5k_ixu_arith+(r5k_ixu_mpydiv*2)")
+
+;; 64x64 multiply
+(define_insn_reservation "r5k_int_mult_64" 9
+ (and (eq_attr "cpu" "5kc,5kf")
+ (and (eq_attr "type" "imul,imadd")
+ (eq_attr "mode" "DI")))
+ "r5k_ixu_arith+(r5k_ixu_mpydiv*2)")
+
+;; 3 operand MUL 32x32
+(define_insn_reservation "r5k_int_mul" 4
+ (and (eq_attr "cpu" "5kc,5kf")
+ (and (eq_attr "type" "imul3")
+ (eq_attr "mode" "SI")))
+ "r5k_ixu_arith+(r5k_ixu_mpydiv*2)")
+
+;; Move to HI/LO -> MADD/MSUB,MFHI/MFLO has a 1 cycle latency.
+(define_insn_reservation "r5k_int_mthilo" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "mthilo"))
+ "r5k_ixu_arith+r5k_ixu_mpydiv")
+
+;; Move from HI/LO -> integer operation has a 2 cycle latency.
+(define_insn_reservation "r5k_int_mfhilo" 2
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "mfhilo"))
+ "r5k_ixu_arith+r5k_ixu_mpydiv")
+
+;; All other integer insns.
+(define_insn_reservation "r5k_int_alu" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "arith,condmove,shift,const,nop,slt"))
+ "r5k_ixu_arith")
+
+(define_insn_reservation "r5k_int_branch" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "branch"))
+ "r5k_ixu_arith")
+
+;; JR/JALR always cause one pipeline bubble because of interlock.
+(define_insn_reservation "r5k_int_jump" 2
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "jump,call"))
+ "r5k_ixu_arith")
+
+;; Any -> JR/JALR (without dependency) : 1 clock issue delay
+;; Any -> JR/JALR (with dependency) : 2 clock issue delay
+;; load -> JR/JALR (with dependency) : 3 clock issue delay
+;; mfhilo -> JR/JALR (with dependency) : 3 clock issue delay
+;; mul -> JR/JALR (with dependency) : 3 clock issue delay
+(define_bypass 2 "r5k_int_alu" "r5k_int_jump")
+(define_bypass 3 "r5k_int_load" "r5k_int_jump")
+(define_bypass 3 "r5k_int_mfhilo" "r5k_int_jump")
+(define_bypass 3 "r5k_int_mul" "r5k_int_jump")
+
+;; Unknown or multi - single issue
+(define_insn_reservation "r5k_int_unknown" 1
+ (and (eq_attr "cpu" "5kc,5kf")
+ (eq_attr "type" "unknown,multi"))
+ "r5k_ixu_arith+r5k_ixu_mpydiv")
+
+
+;; Floating Point Instructions
+;; The 5Kf is a partial dual-issue cpu which can dual issue an integer
+;; and floating-point instruction in the same cycle.
+
+;; fadd, fabs, fneg
+(define_insn_reservation "r5kf_fadd" 4
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "fadd,fabs,fneg"))
+ "r5kf_fpu_arith")
+
+;; fmove, fcmove
+(define_insn_reservation "r5kf_fmove" 4
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "fmove"))
+ "r5kf_fpu_arith")
+
+;; fload
+(define_insn_reservation "r5kf_fload" 3
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "fpload,fpidxload"))
+ "r5kf_fpu_arith")
+
+;; fstore
+(define_insn_reservation "r5kf_fstore" 1
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "fpstore"))
+ "r5kf_fpu_arith")
+
+;; fmul, fmadd
+(define_insn_reservation "r5kf_fmul_sf" 4
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "r5kf_fpu_arith")
+
+(define_insn_reservation "r5kf_fmul_df" 5
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "r5kf_fpu_arith*2")
+
+;; fdiv, fsqrt, frsqrt
+(define_insn_reservation "r5kf_fdiv_sf" 17
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "r5kf_fpu_arith*14")
+
+(define_insn_reservation "r5kf_fdiv_df" 32
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "r5kf_fpu_arith*29")
+
+;; frsqrt
+(define_insn_reservation "r5kf_frsqrt_df" 35
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "r5kf_fpu_arith*31")
+
+;; fcmp
+(define_insn_reservation "r5kf_fcmp" 2
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "fcmp"))
+ "r5kf_fpu_arith")
+
+;; fcmp -> movf.fmt & movt.fmt bypass (dependency must be on condition)
+(define_bypass 1 "r5kf_fcmp" "r5kf_fmove")
+
+;; fcvt (cvt.d.s, cvt.[sd].[wl]
+(define_insn_reservation "r5kf_fcvt_d2s" 4
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "I2S,I2D,S2D")))
+ "r5kf_fpu_arith")
+
+;; fcvt (cvt.s.d)
+(define_insn_reservation "r5kf_fcvt_s2d" 6
+ (and (eq_attr "cpu" "5kc")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "D2S")))
+ "r5kf_fpu_arith")
+
+;; fcvt (cvt.[wl].[sd], etc)
+(define_insn_reservation "r5kf_fcvt_f2i" 5
+ (and (eq_attr "cpu" "5kf")
+ (and (eq_attr "type" "fcvt")
+ (eq_attr "cnv_mode" "S2I,D2I")))
+ "r5kf_fpu_arith")
+
+;; fxfer (mfc1, mfhc1, mtc1, mthc1) - single issue
+(define_insn_reservation "r5kf_fxfer" 2
+ (and (eq_attr "cpu" "5kf")
+ (eq_attr "type" "xfer"))
+ "r5k_ixu_arith+r5kf_fpu_arith")
diff --git a/contrib/gcc/config/mips/6000.md b/contrib/gcc/config/mips/6000.md
new file mode 100644
index 0000000..ac06e7a
--- /dev/null
+++ b/contrib/gcc/config/mips/6000.md
@@ -0,0 +1,57 @@
+;; R6000 pipeline description.
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file overrides parts of generic.md. It is derived from the
+;; old define_function_unit description.
+
+(define_insn_reservation "r6k_fcmp" 2
+ (and (eq_attr "cpu" "r6000")
+ (eq_attr "type" "fcmp"))
+ "alu")
+
+(define_insn_reservation "r6k_fadd" 3
+ (and (eq_attr "cpu" "r6000")
+ (eq_attr "type" "fadd"))
+ "alu")
+
+(define_insn_reservation "r6k_fmul_single" 5
+ (and (eq_attr "cpu" "r6000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r6k_fmul_double" 6
+ (and (eq_attr "cpu" "r6000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "alu")
+
+(define_insn_reservation "r6k_fdiv_single" 15
+ (and (eq_attr "cpu" "r6000")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "SF")))
+ "alu")
+
+(define_insn_reservation "r6k_fdiv_double" 16
+ (and (eq_attr "cpu" "r6000")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "DF")))
+ "alu")
diff --git a/contrib/gcc/config/mips/7000.md b/contrib/gcc/config/mips/7000.md
new file mode 100644
index 0000000..a67851c
--- /dev/null
+++ b/contrib/gcc/config/mips/7000.md
@@ -0,0 +1,215 @@
+;; DFA-based pipeline description for the RM7000.
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+;; .........................
+;;
+;; The RM7000 is a dual-issue processor that can bundle instructions as:
+;; {arith|load|store}{arith|imul|idiv|branch|float}
+;;
+;; Reference:
+;; "RM7000 Family User Manual, PMC-2002296"
+;;
+;; .........................
+
+;; Use three automata to isolate long latency operations, reducing space.
+(define_automaton "rm7000_other, rm7000_fdiv, rm7000_idiv")
+
+;;
+;; Describe the resources.
+;;
+
+;; Global
+(define_cpu_unit "rm7_iss0,rm7_iss1" "rm7000_other")
+
+;; Integer execution unit (M-Pipe).
+(define_cpu_unit "ixum_addsub_agen" "rm7000_other")
+
+;; Integer execution unit (F-Pipe).
+(define_cpu_unit "ixuf_addsub" "rm7000_other")
+(define_cpu_unit "ixuf_branch" "rm7000_other")
+(define_cpu_unit "ixuf_mpydiv" "rm7000_other")
+(define_cpu_unit "ixuf_mpydiv_iter" "rm7000_idiv")
+;; Floating-point unit (F-Pipe).
+(define_cpu_unit "fxuf_add" "rm7000_other")
+(define_cpu_unit "fxuf_mpy" "rm7000_other")
+(define_cpu_unit "fxuf_mpy_iter" "rm7000_fdiv")
+(define_cpu_unit "fxuf_divsqrt" "rm7000_other")
+(define_cpu_unit "fxuf_divsqrt_iter" "rm7000_fdiv")
+
+(exclusion_set "ixuf_addsub"
+ "ixuf_branch,ixuf_mpydiv,fxuf_add,fxuf_mpy,fxuf_divsqrt")
+(exclusion_set "ixuf_branch" "ixuf_mpydiv,fxuf_add,fxuf_mpy,fxuf_divsqrt")
+(exclusion_set "ixuf_mpydiv" "fxuf_add,fxuf_mpy,fxuf_divsqrt")
+(exclusion_set "fxuf_add" "fxuf_mpy,fxuf_divsqrt")
+(exclusion_set "fxuf_mpy" "fxuf_divsqrt")
+
+;; After branch any insn cannot be issued.
+(absence_set "rm7_iss0,rm7_iss1" "ixuf_branch")
+
+;;
+;; Define reservations for unit name mnemonics or combinations.
+;;
+
+(define_reservation "rm7_iss" "rm7_iss0|rm7_iss1")
+(define_reservation "rm7_single_dispatch" "rm7_iss0+rm7_iss1")
+
+(define_reservation "rm7_iaddsub" "rm7_iss+(ixum_addsub_agen|ixuf_addsub)")
+(define_reservation "rm7_imem" "rm7_iss+ixum_addsub_agen")
+(define_reservation "rm7_impydiv" "rm7_iss+ixuf_mpydiv")
+(define_reservation "rm7_impydiv_iter" "ixuf_mpydiv_iter")
+(define_reservation "rm7_branch" "rm7_iss+ixuf_branch")
+
+(define_reservation "rm7_fpadd" "rm7_iss+fxuf_add")
+(define_reservation "rm7_fpmpy" "rm7_iss+fxuf_mpy")
+(define_reservation "rm7_fpmpy_iter" "fxuf_mpy_iter")
+(define_reservation "rm7_fpdivsqr" "rm7_iss+fxuf_divsqrt")
+(define_reservation "rm7_fpdivsqr_iter" "fxuf_divsqrt_iter")
+
+;;
+;; Describe instruction reservations for integer operations.
+;;
+
+(define_insn_reservation "rm7_int_other" 1
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "arith,shift,slt,clz,const,condmove,nop,trap"))
+ "rm7_iaddsub")
+
+(define_insn_reservation "rm7_ld" 2
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "rm7_imem")
+
+(define_insn_reservation "rm7_st" 1
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "store,fpstore,fpidxstore"))
+ "rm7_imem")
+
+(define_insn_reservation "rm7_idiv_si" 36
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "rm7_impydiv+(rm7_impydiv_iter*36)")
+
+(define_insn_reservation "rm7_idiv_di" 68
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "rm7_impydiv+(rm7_impydiv_iter*68)")
+
+(define_insn_reservation "rm7_impy_si_mult" 5
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "imul,imadd")
+ (eq_attr "mode" "SI")))
+ "rm7_impydiv+(rm7_impydiv_iter*3)")
+
+;; There are an additional 2 stall cycles.
+(define_insn_reservation "rm7_impy_si_mul" 2
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "imul3")
+ (eq_attr "mode" "SI")))
+ "rm7_impydiv")
+
+(define_insn_reservation "rm7_impy_di" 9
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "DI")))
+ "rm7_impydiv+(rm7_impydiv_iter*8)")
+
+;; Move to/from HI/LO.
+(define_insn_reservation "rm7_mthilo" 3
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "mthilo"))
+ "rm7_impydiv")
+
+(define_insn_reservation "rm7_mfhilo" 1
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "mfhilo"))
+ "rm7_impydiv")
+
+;; Move to/from fp coprocessor.
+(define_insn_reservation "rm7_ixfer" 2
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "xfer"))
+ "rm7_iaddsub")
+
+(define_insn_reservation "rm7_ibr" 3
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "branch,jump,call"))
+ "rm7_branch")
+
+;;
+;; Describe instruction reservations for the floating-point operations.
+;;
+(define_insn_reservation "rm7_fp_quick" 4
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "fneg,fcmp,fabs,fmove"))
+ "rm7_fpadd")
+
+(define_insn_reservation "rm7_fp_other" 4
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "fadd"))
+ "rm7_fpadd")
+
+(define_insn_reservation "rm7_fp_cvt" 4
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "fcvt"))
+ "rm7_fpadd")
+
+(define_insn_reservation "rm7_fp_divsqrt_df" 36
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "DF")))
+ "rm7_fpdivsqr+(rm7_fpdivsqr_iter*36)")
+
+(define_insn_reservation "rm7_fp_divsqrt_sf" 21
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt")
+ (eq_attr "mode" "SF")))
+ "rm7_fpdivsqr+(rm7_fpdivsqr_iter*21)")
+
+(define_insn_reservation "rm7_fp_rsqrt_df" 68
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "rm7_fpdivsqr+(rm7_fpdivsqr_iter*68)")
+
+(define_insn_reservation "rm7_fp_rsqrt_sf" 38
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "SF")))
+ "rm7_fpdivsqr+(rm7_fpdivsqr_iter*38)")
+
+(define_insn_reservation "rm7_fp_mpy_sf" 4
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "rm7_fpmpy+rm7_fpmpy_iter")
+
+(define_insn_reservation "rm7_fp_mpy_df" 5
+ (and (eq_attr "cpu" "r7000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "rm7_fpmpy+(rm7_fpmpy_iter*2)")
+
+;; Force single-dispatch for unknown or multi.
+(define_insn_reservation "rm7_unknown" 1
+ (and (eq_attr "cpu" "r7000")
+ (eq_attr "type" "unknown,multi"))
+ "rm7_single_dispatch")
diff --git a/contrib/gcc/config/mips/9000.md b/contrib/gcc/config/mips/9000.md
new file mode 100644
index 0000000..04ddc8c
--- /dev/null
+++ b/contrib/gcc/config/mips/9000.md
@@ -0,0 +1,152 @@
+;; DFA-based pipeline description for the RM9000.
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+(define_automaton "rm9k_main, rm9k_imul, rm9k_fdiv")
+
+;; These units are for insns that can issue in either pipe. We don't
+;; want to use constructs like "rm9k_m | rm9k_f_int" since that would
+;; needlessly make an insn prefer the M pipe.
+(define_cpu_unit "rm9k_any1" "rm9k_main")
+(define_cpu_unit "rm9k_any2" "rm9k_main")
+
+;; F and M pipe units, for instructions that must be issued by a
+;; particular pipe. Split the F pipe into two units so that integer
+;; instructions can issue while the FPU is busy. We don't need to
+;; split M because it is only ever reserved for a single cycle.
+(define_cpu_unit "rm9k_m" "rm9k_main")
+(define_cpu_unit "rm9k_f_int" "rm9k_main")
+(define_cpu_unit "rm9k_f_float" "rm9k_main")
+
+(exclusion_set "rm9k_f_int" "rm9k_f_float")
+
+;; Multiply/divide units.
+(define_cpu_unit "rm9k_imul" "rm9k_imul")
+(define_cpu_unit "rm9k_fdiv" "rm9k_fdiv")
+
+(define_insn_reservation "rm9k_load" 3
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "load,fpload,fpidxload"))
+ "rm9k_m")
+
+(define_insn_reservation "rm9k_store" 1
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "store,fpstore,fpidxstore"))
+ "rm9k_m")
+
+(define_insn_reservation "rm9k_int" 1
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "arith,shift,slt,clz,const,nop,trap"))
+ "rm9k_any1 | rm9k_any2")
+
+(define_insn_reservation "rm9k_int_cmove" 2
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "condmove")
+ (eq_attr "mode" "SI,DI")))
+ "rm9k_any1 | rm9k_any2")
+
+;; This applies to both 'mul' and 'mult'.
+(define_insn_reservation "rm9k_mulsi" 3
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "!DI")))
+ "rm9k_f_int")
+
+(define_insn_reservation "rm9k_muldi" 7
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI")))
+ "rm9k_f_int + rm9k_imul * 7")
+
+(define_insn_reservation "rm9k_divsi" 38
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "!DI")))
+ "rm9k_f_int + rm9k_imul * 38")
+
+(define_insn_reservation "rm9k_divdi" 70
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "rm9k_f_int + rm9k_imul * 70")
+
+(define_insn_reservation "rm9k_mfhilo" 1
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "mfhilo"))
+ "rm9k_f_int")
+
+(define_insn_reservation "rm9k_mthilo" 5
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "mthilo"))
+ "rm9k_f_int")
+
+(define_insn_reservation "rm9k_xfer" 2
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "xfer"))
+ "rm9k_m")
+
+(define_insn_reservation "rm9k_fquick" 2
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "fabs,fneg,fcmp,fmove"))
+ "rm9k_f_float")
+
+(define_insn_reservation "rm9k_fcmove" 2
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "condmove")
+ (eq_attr "mode" "SF,DF")))
+ "rm9k_m")
+
+(define_insn_reservation "rm9k_fadd" 6
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "fadd,fcvt"))
+ "rm9k_f_float")
+
+(define_insn_reservation "rm9k_fmuls" 6
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "rm9k_f_float")
+
+(define_insn_reservation "rm9k_fmuld" 9
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "rm9k_f_float * 3")
+
+(define_insn_reservation "rm9k_fdivs" 22
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "SF")))
+ "rm9k_f_float + rm9k_fdiv * 22")
+
+(define_insn_reservation "rm9k_fdivd" 37
+ (and (eq_attr "cpu" "r9000")
+ (and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
+ (eq_attr "mode" "DF")))
+ "rm9k_f_float + rm9k_fdiv * 37")
+
+(define_insn_reservation "rm9k_branch" 2
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "branch,jump,call"))
+ "rm9k_any1 | rm9k_any2")
+
+(define_insn_reservation "rm9k_unknown" 1
+ (and (eq_attr "cpu" "r9000")
+ (eq_attr "type" "unknown,multi"))
+ "rm9k_m + rm9k_f_int + rm9k_any1 + rm9k_any2")
diff --git a/contrib/gcc/config/mips/constraints.md b/contrib/gcc/config/mips/constraints.md
new file mode 100644
index 0000000..711aa15
--- /dev/null
+++ b/contrib/gcc/config/mips/constraints.md
@@ -0,0 +1,195 @@
+;; Constraint definitions for MIPS.
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Register constraints
+
+(define_register_constraint "d" "BASE_REG_CLASS"
+ "An address register. This is equivalent to @code{r} unless
+ generating MIPS16 code.")
+
+(define_register_constraint "t" "T_REG"
+ "@internal")
+
+(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
+ "A floating-point register (if available).")
+
+(define_register_constraint "h" "HI_REG"
+ "The @code{hi} register.")
+
+(define_register_constraint "l" "LO_REG"
+ "The @code{lo} register.")
+
+(define_register_constraint "x" "MD_REGS"
+ "The @code{hi} and @code{lo} registers.")
+
+(define_register_constraint "b" "ALL_REGS"
+ "@internal")
+
+(define_register_constraint "c" "TARGET_ABICALLS ? PIC_FN_ADDR_REG
+ : TARGET_MIPS16 ? M16_NA_REGS
+ : GR_REGS"
+ "A register suitable for use in an indirect jump. This will always be
+ @code{$25} for @option{-mabicalls}.")
+
+(define_register_constraint "e" "LEA_REGS"
+ "@internal")
+
+(define_register_constraint "j" "PIC_FN_ADDR_REG"
+ "@internal")
+
+(define_register_constraint "v" "V1_REG"
+ "@internal")
+
+(define_register_constraint "y" "GR_REGS"
+ "Equivalent to @code{r}; retained for backwards compatibility.")
+
+(define_register_constraint "z" "ST_REGS"
+ "A floating-point condition code register.")
+
+(define_register_constraint "A" "DSP_ACC_REGS"
+ "@internal")
+
+(define_register_constraint "a" "ACC_REGS"
+ "@internal")
+
+(define_register_constraint "B" "COP0_REGS"
+ "@internal")
+
+(define_register_constraint "C" "COP2_REGS"
+ "@internal")
+
+(define_register_constraint "D" "COP3_REGS"
+ "@internal")
+
+;; Integer constraints
+
+(define_constraint "I"
+ "A signed 16-bit constant (for arithmetic instructions)."
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND (ival)")))
+
+(define_constraint "J"
+ "Integer zero."
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "K"
+ "An unsigned 16-bit constant (for logic instructions)."
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND_UNSIGNED (ival)")))
+
+(define_constraint "L"
+ "A signed 32-bit constant in which the lower 16 bits are zero.
+ Such constants can be loaded using @code{lui}."
+ (and (match_code "const_int")
+ (match_test "LUI_OPERAND (ival)")))
+
+(define_constraint "M"
+ "A constant that cannot be loaded using @code{lui}, @code{addiu}
+ or @code{ori}."
+ (and (match_code "const_int")
+ (match_test "!SMALL_OPERAND (ival)")
+ (match_test "!SMALL_OPERAND_UNSIGNED (ival)")
+ (match_test "!LUI_OPERAND (ival)")))
+
+(define_constraint "N"
+ "A constant in the range -65535 to -1 (inclusive)."
+ (and (match_code "const_int")
+ (match_test "ival >= -0xffff && ival < 0")))
+
+(define_constraint "O"
+ "A signed 15-bit constant."
+ (and (match_code "const_int")
+ (match_test "ival >= -0x4000 && ival < 0x4000")))
+
+(define_constraint "P"
+ "A constant in the range 1 to 65535 (inclusive)."
+ (and (match_code "const_int")
+ (match_test "ival > 0 && ival < 0x10000")))
+
+;; Floating-point constraints
+
+(define_constraint "G"
+ "Floating-point zero."
+ (and (match_code "const_double")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; General constraints
+
+(define_constraint "Q"
+ "@internal"
+ (match_operand 0 "const_arith_operand"))
+
+(define_memory_constraint "R"
+ "An address that can be used in a non-macro load or store."
+ (and (match_code "mem")
+ (match_test "mips_fetch_insns (op) == 1")))
+
+(define_constraint "S"
+ "@internal
+ A constant call address."
+ (and (match_operand 0 "call_insn_operand")
+ (match_test "CONSTANT_P (op)")))
+
+(define_constraint "T"
+ "@internal
+ A constant @code{move_operand} that cannot be safely loaded into @code{$25}
+ using @code{la}."
+ (and (match_operand 0 "move_operand")
+ (match_test "CONSTANT_P (op)")
+ (match_test "mips_dangerous_for_la25_p (op)")))
+
+(define_constraint "U"
+ "@internal
+ A constant @code{move_operand} that can be safely loaded into @code{$25}
+ using @code{la}."
+ (and (match_operand 0 "move_operand")
+ (match_test "CONSTANT_P (op)")
+ (match_test "!mips_dangerous_for_la25_p (op)")))
+
+(define_memory_constraint "W"
+ "@internal
+ A memory address based on a member of @code{BASE_REG_CLASS}. This is
+ true for all non-mips16 references (although it can sometimes be implicit
+ if @samp{!TARGET_EXPLICIT_RELOCS}). For MIPS16, it excludes stack and
+ constant-pool references."
+ (and (match_code "mem")
+ (match_operand 0 "memory_operand")
+ (ior (match_test "!TARGET_MIPS16")
+ (and (not (match_operand 0 "stack_operand"))
+ (not (match_test "CONSTANT_P (XEXP (op, 0))"))))))
+
+(define_constraint "YG"
+ "@internal
+ A vector zero."
+ (and (match_code "const_vector")
+ (match_test "op == CONST0_RTX (mode)")))
+
+(define_constraint "YA"
+ "@internal
+ An unsigned 6-bit constant."
+ (and (match_code "const_int")
+ (match_test "UIMM6_OPERAND (ival)")))
+
+(define_constraint "YB"
+ "@internal
+ A signed 10-bit constant."
+ (and (match_code "const_int")
+ (match_test "IMM10_OPERAND (ival)")))
diff --git a/contrib/gcc/config/mips/crti.asm b/contrib/gcc/config/mips/crti.asm
new file mode 100644
index 0000000..f4bef6f
--- /dev/null
+++ b/contrib/gcc/config/mips/crti.asm
@@ -0,0 +1,26 @@
+/* 4 slots for argument spill area. 1 for cpreturn, 1 for stack.
+ Return spill offset of 40 and 20. Aligned to 16 bytes for n32. */
+
+ .section .init,"ax",@progbits
+ .globl _init
+ .type _init,@function
+_init:
+#ifdef __mips64
+ daddu $sp,$sp,-48
+ sd $31,40($sp)
+#else
+ addu $sp,$sp,-32
+ sw $31,20($sp)
+#endif
+
+ .section .fini,"ax",@progbits
+ .globl _fini
+ .type _fini,@function
+_fini:
+#ifdef __mips64
+ daddu $sp,$sp,-48
+ sd $31,40($sp)
+#else
+ addu $sp,$sp,-32
+ sw $31,20($sp)
+#endif
diff --git a/contrib/gcc/config/mips/crtn.asm b/contrib/gcc/config/mips/crtn.asm
new file mode 100644
index 0000000..5d41d3d
--- /dev/null
+++ b/contrib/gcc/config/mips/crtn.asm
@@ -0,0 +1,29 @@
+/* 4 slots for argument spill area. 1 for cpreturn, 1 for stack.
+ Return spill offset of 40 and 20. Aligned to 16 bytes for n32. */
+
+#ifdef __mips16
+#define RA $7
+#else
+#define RA $31
+#endif
+
+ .section .init,"ax",@progbits
+#ifdef __mips64
+ ld RA,40($sp)
+ daddu $sp,$sp,48
+#else
+ lw RA,20($sp)
+ addu $sp,$sp,32
+#endif
+ j RA
+
+ .section .fini,"ax",@progbits
+#ifdef __mips64
+ ld RA,40($sp)
+ daddu $sp,$sp,48
+#else
+ lw RA,20($sp)
+ addu $sp,$sp,32
+#endif
+ j RA
+
diff --git a/contrib/gcc/config/mips/dbxmdebug.h b/contrib/gcc/config/mips/dbxmdebug.h
new file mode 100644
index 0000000..230e2ea
--- /dev/null
+++ b/contrib/gcc/config/mips/dbxmdebug.h
@@ -0,0 +1,6 @@
+/* Definitions of target machine for GNU compiler, for MIPS running IRIX 5
+ or IRIX 6 (O32 ABI) using the GNU assembler with stabs-in-mdebug. */
+
+/* Override iris5gas.h version again to retain mips.h default. */
+#undef MDEBUG_ASM_SPEC
+#define MDEBUG_ASM_SPEC "%{!gdwarf*:-mdebug} %{gdwarf*:-no-mdebug}"
diff --git a/contrib/gcc/config/mips/elf.h b/contrib/gcc/config/mips/elf.h
new file mode 100644
index 0000000..9d7259e
--- /dev/null
+++ b/contrib/gcc/config/mips/elf.h
@@ -0,0 +1,54 @@
+/* Target macros for mips*-elf targets.
+ Copyright (C) 1994, 1997, 1999, 2000, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* MIPS assemblers don't have the usual .set foo,bar construct;
+ .set is used for assembler options instead. */
+#undef SET_ASM_OP
+#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2) \
+ do \
+ { \
+ fputc ('\t', FILE); \
+ assemble_name (FILE, LABEL1); \
+ fputs (" = ", FILE); \
+ assemble_name (FILE, LABEL2); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME mips_declare_object_name
+
+#undef ASM_FINISH_DECLARE_OBJECT
+#define ASM_FINISH_DECLARE_OBJECT mips_finish_declare_object
+
+/* Leave the linker script to choose the appropriate libraries. */
+#undef LIB_SPEC
+#define LIB_SPEC ""
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crti%O%s crtbegin%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
+
+#define NO_IMPLICIT_EXTERN_C 1
+
+#define HANDLE_PRAGMA_PACK_PUSH_POP 1
diff --git a/contrib/gcc/config/mips/elforion.h b/contrib/gcc/config/mips/elforion.h
new file mode 100644
index 0000000..9ff3a4f
--- /dev/null
+++ b/contrib/gcc/config/mips/elforion.h
@@ -0,0 +1,22 @@
+/* Definitions of target machine for GNU compiler. MIPS ORION version with
+ GOFAST floating point library.
+ Copyright (C) 1994, 1998 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#define MIPS_CPU_STRING_DEFAULT "orion"
diff --git a/contrib/gcc/config/mips/generic.md b/contrib/gcc/config/mips/generic.md
new file mode 100644
index 0000000..f5641a9
--- /dev/null
+++ b/contrib/gcc/config/mips/generic.md
@@ -0,0 +1,106 @@
+;; Generic DFA-based pipeline description for MIPS targets
+;; Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+
+;; This file is derived from the old define_function_unit description.
+;; Each reservation can be overridden on a processor-by-processor basis.
+
+(define_insn_reservation "generic_alu" 1
+ (eq_attr "type" "unknown,prefetch,prefetchx,condmove,const,arith,
+ shift,slt,clz,trap,multi,nop")
+ "alu")
+
+(define_insn_reservation "generic_load" 3
+ (eq_attr "type" "load,fpload,fpidxload")
+ "alu")
+
+(define_insn_reservation "generic_store" 1
+ (eq_attr "type" "store,fpstore,fpidxstore")
+ "alu")
+
+(define_insn_reservation "generic_xfer" 2
+ (eq_attr "type" "xfer")
+ "alu")
+
+(define_insn_reservation "generic_branch" 1
+ (eq_attr "type" "branch,jump,call")
+ "alu")
+
+(define_insn_reservation "generic_hilo" 1
+ (eq_attr "type" "mfhilo,mthilo")
+ "imuldiv*3")
+
+(define_insn_reservation "generic_imul" 17
+ (eq_attr "type" "imul,imul3,imadd")
+ "imuldiv*17")
+
+(define_insn_reservation "generic_idiv" 38
+ (eq_attr "type" "idiv")
+ "imuldiv*38")
+
+(define_insn_reservation "generic_fcvt" 1
+ (eq_attr "type" "fcvt")
+ "alu")
+
+(define_insn_reservation "generic_fmove" 2
+ (eq_attr "type" "fabs,fneg,fmove")
+ "alu")
+
+(define_insn_reservation "generic_fcmp" 3
+ (eq_attr "type" "fcmp")
+ "alu")
+
+(define_insn_reservation "generic_fadd" 4
+ (eq_attr "type" "fadd")
+ "alu")
+
+(define_insn_reservation "generic_fmul_single" 7
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF"))
+ "alu")
+
+(define_insn_reservation "generic_fmul_double" 8
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF"))
+ "alu")
+
+(define_insn_reservation "generic_fdiv_single" 23
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "SF"))
+ "alu")
+
+(define_insn_reservation "generic_fdiv_double" 36
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "DF"))
+ "alu")
+
+(define_insn_reservation "generic_fsqrt_single" 54
+ (and (eq_attr "type" "fsqrt,frsqrt")
+ (eq_attr "mode" "SF"))
+ "alu")
+
+(define_insn_reservation "generic_fsqrt_double" 112
+ (and (eq_attr "type" "fsqrt,frsqrt")
+ (eq_attr "mode" "DF"))
+ "alu")
+
+(define_insn_reservation "generic_frecip_fsqrt_step" 5
+ (eq_attr "type" "frdiv1,frdiv2,frsqrt1,frsqrt2")
+ "alu")
diff --git a/contrib/gcc/config/mips/iris.h b/contrib/gcc/config/mips/iris.h
new file mode 100644
index 0000000..dbde9d1
--- /dev/null
+++ b/contrib/gcc/config/mips/iris.h
@@ -0,0 +1,222 @@
+/* Definitions of target machine for GNU compiler. Generic IRIX version.
+ Copyright (C) 1993, 1995, 1996, 1998, 2000,
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* We are compiling for IRIX now. */
+#undef TARGET_IRIX
+#define TARGET_IRIX 1
+
+/* The size in bytes of a DWARF field indicating an offset or length
+ relative to a debug info section, specified to be 4 bytes in the DWARF-2
+ specification. The SGI/MIPS ABI defines it to be the same as PTR_SIZE. */
+#define DWARF_OFFSET_SIZE PTR_SIZE
+
+/* The size in bytes of the initial length field in a debug info
+ section. The DWARF 3 (draft) specification defines this to be
+ either 4 or 12 (with a 4-byte "escape" word when it's 12), but the
+ SGI/MIPS ABI predates this standard and defines it to be the same
+ as DWARF_OFFSET_SIZE. */
+#define DWARF_INITIAL_LENGTH_SIZE DWARF_OFFSET_SIZE
+
+/* MIPS assemblers don't have the usual .set foo,bar construct;
+ .set is used for assembler options instead. */
+#undef SET_ASM_OP
+#define ASM_OUTPUT_DEF(FILE, LABEL1, LABEL2) \
+ do \
+ { \
+ fputc ('\t', FILE); \
+ assemble_name (FILE, LABEL1); \
+ fputs (" = ", FILE); \
+ assemble_name (FILE, LABEL2); \
+ fputc ('\n', FILE); \
+ } \
+ while (0)
+
+/* The MIPSpro o32 linker warns about not linking .comment sections. */
+#undef IDENT_ASM_OP
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX (TARGET_NEWABI ? "." : "$")
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME mips_declare_object_name
+
+#undef ASM_FINISH_DECLARE_OBJECT
+#define ASM_FINISH_DECLARE_OBJECT mips_finish_declare_object
+
+/* Also do this for libcalls. */
+#undef TARGET_ASM_EXTERNAL_LIBCALL
+#define TARGET_ASM_EXTERNAL_LIBCALL irix_output_external_libcall
+
+/* The linker needs a space after "-o". */
+#define SWITCHES_NEED_SPACES "o"
+
+/* Specify wchar_t types. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE (Pmode == DImode ? "int" : "long int")
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE INT_TYPE_SIZE
+
+/* Same for wint_t. */
+#undef WINT_TYPE
+#define WINT_TYPE (Pmode == DImode ? "int" : "long int")
+
+#undef WINT_TYPE_SIZE
+#define WINT_TYPE_SIZE 32
+
+/* Plain char is unsigned in the SGI compiler. */
+#undef DEFAULT_SIGNED_CHAR
+#define DEFAULT_SIGNED_CHAR 0
+
+#define WORD_SWITCH_TAKES_ARG(STR) \
+ (DEFAULT_WORD_SWITCH_TAKES_ARG (STR) \
+ || strcmp (STR, "rpath") == 0)
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("host_mips"); \
+ builtin_define_std ("sgi"); \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("SYSTYPE_SVR4"); \
+ builtin_define ("_MODERN_C"); \
+ builtin_define ("_SVR4_SOURCE"); \
+ builtin_define ("__DSO__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ builtin_assert ("machine=sgi"); \
+ \
+ if (mips_abi == ABI_32) \
+ { \
+ builtin_define ("_ABIO32=1"); \
+ builtin_define ("_MIPS_SIM=_ABIO32"); \
+ builtin_define ("_MIPS_SZINT=32"); \
+ builtin_define ("_MIPS_SZLONG=32"); \
+ builtin_define ("_MIPS_SZPTR=32"); \
+ } \
+ else if (mips_abi == ABI_64) \
+ { \
+ builtin_define ("_ABI64=3"); \
+ builtin_define ("_MIPS_SIM=_ABI64"); \
+ builtin_define ("_MIPS_SZINT=32"); \
+ builtin_define ("_MIPS_SZLONG=64"); \
+ builtin_define ("_MIPS_SZPTR=64"); \
+ } \
+ else \
+ { \
+ builtin_define ("_ABIN32=2"); \
+ builtin_define ("_MIPS_SIM=_ABIN32"); \
+ builtin_define ("_MIPS_SZINT=32"); \
+ builtin_define ("_MIPS_SZLONG=32"); \
+ builtin_define ("_MIPS_SZPTR=32"); \
+ } \
+ \
+ if (!ISA_MIPS1 && !ISA_MIPS2) \
+ builtin_define ("_COMPILER_VERSION=601"); \
+ \
+ if (!TARGET_FLOAT64) \
+ builtin_define ("_MIPS_FPSET=16"); \
+ else \
+ builtin_define ("_MIPS_FPSET=32"); \
+ \
+ /* We must always define _LONGLONG, even when -ansi is \
+ used, because IRIX 5 system header files require it. \
+ This is OK, because gcc never warns when long long \
+ is used in system header files. \
+ \
+ An alternative would be to support the SGI builtin \
+ type __long_long. */ \
+ builtin_define ("_LONGLONG"); \
+ \
+ /* IRIX 6.5.18 and above provide many ISO C99 \
+ features protected by the __c99 macro. \
+ libstdc++ v3 needs them as well. */ \
+ if (TARGET_IRIX6) \
+ if (flag_isoc99 || c_dialect_cxx ()) \
+ builtin_define ("__c99"); \
+ \
+ /* The GNU C++ standard library requires that \
+ __EXTENSIONS__ and _SGI_SOURCE be defined on at \
+ least IRIX 6.2 and probably all IRIX 6 prior to 6.5. \
+ We don't need this on IRIX 6.5 itself, but it \
+ shouldn't hurt other than the namespace pollution. */ \
+ if (!flag_iso || (TARGET_IRIX6 && c_dialect_cxx ())) \
+ { \
+ builtin_define ("__EXTENSIONS__"); \
+ builtin_define ("_SGI_SOURCE"); \
+ } \
+ } \
+ while (0)
+
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC "%{static: -mno-abicalls}"
+
+#undef INIT_SECTION_ASM_OP
+#define INIT_SECTION_ASM_OP "\t.section\t.gcc_init,\"ax\",@progbits"
+
+#undef FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP "\t.section\t.gcc_fini,\"ax\",@progbits"
+
+#ifdef IRIX_USING_GNU_LD
+#define IRIX_NO_UNRESOLVED ""
+#else
+#define IRIX_NO_UNRESOLVED "-no_unresolved"
+#endif
+
+/* Generic part of the LINK_SPEC. */
+#undef LINK_SPEC
+#define LINK_SPEC "\
+%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
+%{bestGnum} %{shared} %{non_shared} \
+%{call_shared} %{no_archive} %{exact_version} \
+%{!shared: \
+ %{!non_shared: %{!call_shared:%{!r: -call_shared " IRIX_NO_UNRESOLVED "}}}} \
+%{rpath} -init __gcc_init -fini __gcc_fini " IRIX_SUBTARGET_LINK_SPEC
+
+/* A linker error can empirically be avoided by removing duplicate
+ library search directories. */
+#define LINK_ELIMINATE_DUPLICATE_LDIRECTORIES 1
+
+/* Add -g to mips.h default to avoid confusing gas with local symbols
+ generated from stabs info. */
+#undef NM_FLAGS
+#define NM_FLAGS "-Bng"
+
+/* The system header files are C++ aware. */
+/* ??? Unfortunately, most but not all of the headers are C++ aware.
+ Specifically, curses.h is not, and as a consequence, defining this
+ used to prevent libg++ building. This is no longer the case so
+ define it again to prevent other problems, e.g. with getopt in
+ unistd.h. We still need some way to fix just those files that need
+ fixing. */
+#define NO_IMPLICIT_EXTERN_C 1
+
+/* -G is incompatible with -KPIC which is the default, so only allow objects
+ in the small data section if the user explicitly asks for it. */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
+
+/* The native o32 IRIX linker does not support merging without a
+ special elspec(5) file. */
+#ifndef IRIX_USING_GNU_LD
+#undef HAVE_GAS_SHF_MERGE
+#define HAVE_GAS_SHF_MERGE 0
+#endif
diff --git a/contrib/gcc/config/mips/iris5.h b/contrib/gcc/config/mips/iris5.h
new file mode 100644
index 0000000..10c2830
--- /dev/null
+++ b/contrib/gcc/config/mips/iris5.h
@@ -0,0 +1,45 @@
+/* Definitions of target machine for GNU compiler. IRIX version 5.
+ Copyright (C) 1993, 1995, 1996, 1998, 2000,
+ 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifdef IRIX_USING_GNU_LD
+#define IRIX_SUBTARGET_LINK_SPEC "-melf32bsmip"
+#else
+#define IRIX_SUBTARGET_LINK_SPEC "-_SYSTYPE_SVR4"
+#endif
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "\
+%{!static: \
+ %{!shared:%{pg:gcrt1.o%s}%{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}}} \
+%{static: \
+ %{pg:gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib/nonshared/mcrt1.o%s libprof1.a%s} \
+ %{!p:/usr/lib/nonshared/crt1.o%s}}} \
+irix-crti.o%s crtbegin.o%s"
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!shared:%{p:-lprof1} %{pg:-lprof1} -lc}"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s irix-crtn.o%s %{!shared:crtn.o%s}"
+
+#undef MACHINE_TYPE
+#define MACHINE_TYPE "SGI running IRIX 5.x"
diff --git a/contrib/gcc/config/mips/iris6.h b/contrib/gcc/config/mips/iris6.h
new file mode 100644
index 0000000..8686b14
--- /dev/null
+++ b/contrib/gcc/config/mips/iris6.h
@@ -0,0 +1,118 @@
+/* Definitions of target machine for GNU compiler. IRIX version 6.
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004,
+ 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Allow some special handling for IRIX 6. */
+#undef TARGET_IRIX6
+#define TARGET_IRIX6 1
+
+/* Default to -mabi=n32 and -mips3. */
+#undef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS { "mabi=n32" }
+
+/* Force the default ABI onto the command line in order to make the specs
+ easier to write. Default to the mips2 ISA for the O32 ABI. */
+#define DRIVER_SELF_SPECS \
+ "%{!mabi=*: -mabi=n32}", \
+ "%{mabi=32: %{!mips*: %{!march*: -mips2}}}"
+
+/* Force the generation of dwarf .debug_frame sections even if not
+ compiling -g. This guarantees that we can unwind the stack. */
+#define DWARF2_FRAME_INFO 1
+
+/* The system unwinder in libexc requires a specific dwarf return address
+ column to work. */
+#undef DWARF_FRAME_RETURN_COLUMN
+#define DWARF_FRAME_RETURN_COLUMN (FP_REG_LAST + 1)
+
+#undef MACHINE_TYPE
+#define MACHINE_TYPE "SGI running IRIX 6.x"
+
+#ifdef IRIX_USING_GNU_LD
+#define IRIX_SUBTARGET_LINK_SPEC \
+ "%{mabi=32: -melf32bsmip}%{mabi=n32: -melf32bmipn32}%{mabi=64: -melf64bmip}"
+#else
+#define IRIX_SUBTARGET_LINK_SPEC \
+ "%{w} -_SYSTYPE_SVR4 -woff 131 \
+ %{mabi=32: -32}%{mabi=n32: -n32}%{mabi=64: -64}%{!mabi*: -n32}"
+#endif
+
+/* Profiling is supported via libprof1.a not -lc_p as in IRIX 3. */
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC \
+ "%{!shared: \
+ %{mabi=32:%{pg:gcrt1.o%s} \
+ %{!pg:%{p:mcrt1.o%s libprof1.a%s}%{!p:crt1.o%s}}} \
+ %{mabi=n32: \
+ %{mips4:%{pg:/usr/lib32/mips4/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips4/mcrt1.o%s /usr/lib32/mips4/libprof1.a%s} \
+ %{!p:/usr/lib32/mips4/crt1.o%s}}} \
+ %{!mips4:%{pg:/usr/lib32/mips3/gcrt1.o%s} \
+ %{!pg:%{p:/usr/lib32/mips3/mcrt1.o%s /usr/lib32/mips3/libprof1.a%s} \
+ %{!p:/usr/lib32/mips3/crt1.o%s}}}} \
+ %{mabi=64: \
+ %{mips4:%{pg:/usr/lib64/mips4/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips4/mcrt1.o /usr/lib64/mips4/libprof1.a} \
+ %{!p:/usr/lib64/mips4/crt1.o}}} \
+ %{!mips4:%{pg:/usr/lib64/mips3/gcrt1.o} \
+ %{!pg:%{p:/usr/lib64/mips3/mcrt1.o /usr/lib64/mips3/libprof1.a} \
+ %{!p:/usr/lib64/mips3/crt1.o}}}}} \
+ irix-crti.o%s crtbegin.o%s"
+
+#ifdef IRIX_USING_GNU_LD
+#define SUBTARGET_DONT_WARN_UNUSED_SPEC ""
+#define SUBTARGET_WARN_UNUSED_SPEC ""
+#else
+#define SUBTARGET_DONT_WARN_UNUSED_SPEC "-dont_warn_unused"
+#define SUBTARGET_WARN_UNUSED_SPEC "-warn_unused"
+#endif
+
+#undef LIB_SPEC
+#define LIB_SPEC \
+ "%{mabi=n32: %{mips4:-L/usr/lib32/mips4} %{!mips4:-L/usr/lib32/mips3} \
+ -L/usr/lib32} \
+ %{mabi=64: %{mips4:-L/usr/lib64/mips4} %{!mips4:-L/usr/lib64/mips3} \
+ -L/usr/lib64} \
+ %{!shared:" \
+ SUBTARGET_DONT_WARN_UNUSED_SPEC \
+ " %{pthread:-lpthread} %{p:libprof1.a%s}%{pg:libprof1.a%s} -lc " \
+ SUBTARGET_WARN_UNUSED_SPEC "}"
+
+/* Avoid getting two warnings for libgcc.a everytime we link. */
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC \
+ SUBTARGET_DONT_WARN_UNUSED_SPEC " -lgcc " SUBTARGET_WARN_UNUSED_SPEC
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "crtend.o%s irix-crtn.o%s \
+ %{!shared: \
+ %{mabi=32:crtn.o%s}\
+ %{mabi=n32:%{mips4:/usr/lib32/mips4/crtn.o%s}\
+ %{!mips4:/usr/lib32/mips3/crtn.o%s}}\
+ %{mabi=64:%{mips4:/usr/lib64/mips4/crtn.o%s}\
+ %{!mips4:/usr/lib64/mips3/crtn.o%s}}}"
+
+#define MIPS_TFMODE_FORMAT mips_extended_format
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "%{pthread:-D_REENTRANT}"
+
diff --git a/contrib/gcc/config/mips/irix-crti.asm b/contrib/gcc/config/mips/irix-crti.asm
new file mode 100644
index 0000000..d6888bb
--- /dev/null
+++ b/contrib/gcc/config/mips/irix-crti.asm
@@ -0,0 +1,51 @@
+ .abicalls
+ .set noreorder
+ .set nomacro
+
+/* The GNU and SGI linkers differ in their implementation of -init and -fini.
+ With the GNU linker, there can only be a single -init option, and the
+ linker simply sets DT_INIT to that value. gcc's initialization and
+ finalization code can go directly in .init, with the prologue and
+ epilogue of the main initialization routine being provided by external
+ object files (*crti.o and *crtn.o in this case).
+
+ The SGI linker instead accepts several -init options. It will set DT_INIT
+ to a linker-created function (placed in .init) that calls each of the -init
+ functions in turn. If there is any user code in .init, this linker-created
+ function will be placed after it. Note that such user code is not treated
+ specially; it will only be called if the -init options arrange for it to
+ be called.
+
+ In theory, the SGI model should allow the crti, crtn and intermediate code
+ to go in .init, just like it can with the GNU linker. However, doing this
+ seems to confuse the linker and triggers an internal error:
+
+ ld32: FATAL 2 : Internal: at ../../ld/mips_code.c mips_code_fixup()
+ text section overflow!
+
+ (seen with MIPSpro 7.30). We therefore put everything in a special
+ .gcc_init section instead. */
+
+ .section .gcc_init,"ax",@progbits
+ .globl __gcc_init
+__gcc_init:
+#if _MIPS_SIM == _ABIO32
+ addiu $sp,$sp,-16
+ sw $31,0($sp)
+#else
+ daddiu $sp,$sp,-16
+ sd $31,0($sp)
+ sd $28,8($sp)
+#endif
+
+ .section .gcc_fini,"ax",@progbits
+ .globl __gcc_fini
+__gcc_fini:
+#if _MIPS_SIM == _ABIO32
+ addiu $sp,$sp,-16
+ sw $31,0($sp)
+#else
+ daddiu $sp,$sp,-16
+ sd $31,0($sp)
+ sd $28,8($sp)
+#endif
diff --git a/contrib/gcc/config/mips/irix-crtn.asm b/contrib/gcc/config/mips/irix-crtn.asm
new file mode 100644
index 0000000..600576c
--- /dev/null
+++ b/contrib/gcc/config/mips/irix-crtn.asm
@@ -0,0 +1,27 @@
+ .abicalls
+ .set noreorder
+ .set nomacro
+
+ .section .gcc_init,"ax",@progbits
+#if _MIPS_SIM == _ABIO32
+ lw $31,0($sp)
+ jr $31
+ addiu $sp,$sp,16
+#else
+ ld $31,0($sp)
+ ld $28,8($sp)
+ jr $31
+ daddiu $sp,$sp,16
+#endif
+
+ .section .gcc_fini,"ax",@progbits
+#if _MIPS_SIM == _ABIO32
+ lw $31,0($sp)
+ jr $31
+ addiu $sp,$sp,16
+#else
+ ld $31,0($sp)
+ ld $28,8($sp)
+ jr $31
+ daddiu $sp,$sp,16
+#endif
diff --git a/contrib/gcc/config/mips/linux-unwind.h b/contrib/gcc/config/mips/linux-unwind.h
new file mode 100644
index 0000000..4f96e95
--- /dev/null
+++ b/contrib/gcc/config/mips/linux-unwind.h
@@ -0,0 +1,112 @@
+/* DWARF2 EH unwinding support for MIPS Linux.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 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 with other programs, and to distribute
+those programs 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 another program.)
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef inhibit_libc
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#include <signal.h>
+#include <asm/unistd.h>
+
+/* The third parameter to the signal handler points to something with
+ * this structure defined in asm/ucontext.h, but the name clashes with
+ * struct ucontext from sys/ucontext.h so this private copy is used. */
+typedef struct _sig_ucontext {
+ unsigned long uc_flags;
+ struct _sig_ucontext *uc_link;
+ stack_t uc_stack;
+ struct sigcontext uc_mcontext;
+ sigset_t uc_sigmask;
+} _sig_ucontext_t;
+
+#define MD_FALLBACK_FRAME_STATE_FOR mips_fallback_frame_state
+
+static _Unwind_Reason_Code
+mips_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ u_int32_t *pc = (u_int32_t *) context->ra;
+ struct sigcontext *sc;
+ _Unwind_Ptr new_cfa;
+ int i;
+
+ /* 24021061 li v0, 0x1061 (rt_sigreturn)*/
+ /* 0000000c syscall */
+ /* or */
+ /* 24021017 li v0, 0x1017 (sigreturn) */
+ /* 0000000c syscall */
+ if (pc[1] != 0x0000000c)
+ return _URC_END_OF_STACK;
+#if _MIPS_SIM == _ABIO32
+ if (pc[0] == (0x24020000 | __NR_sigreturn))
+ {
+ struct sigframe {
+ u_int32_t trampoline[2];
+ struct sigcontext sigctx;
+ } *rt_ = context->ra;
+ sc = &rt_->sigctx;
+ }
+ else
+#endif
+ if (pc[0] == (0x24020000 | __NR_rt_sigreturn))
+ {
+ struct rt_sigframe {
+ u_int32_t trampoline[2];
+ struct siginfo info;
+ _sig_ucontext_t uc;
+ } *rt_ = context->ra;
+ sc = &rt_->uc.uc_mcontext;
+ }
+ else
+ return _URC_END_OF_STACK;
+
+ new_cfa = (_Unwind_Ptr)sc;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = STACK_POINTER_REGNUM;
+ fs->cfa_offset = new_cfa - (_Unwind_Ptr) context->cfa;
+
+#if _MIPS_SIM == _ABIO32 && defined __MIPSEB__
+ /* On o32 Linux, the register save slots in the sigcontext are
+ eight bytes. We need the lower half of each register slot,
+ so slide our view of the structure back four bytes. */
+ new_cfa -= 4;
+#endif
+
+ for (i = 0; i < 32; i++) {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset
+ = (_Unwind_Ptr)&(sc->sc_regs[i]) - new_cfa;
+ }
+ fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].how = REG_SAVED_OFFSET;
+ fs->regs.reg[SIGNAL_UNWIND_RETURN_COLUMN].loc.offset
+ = (_Unwind_Ptr)&(sc->sc_pc) - new_cfa;
+ fs->retaddr_column = SIGNAL_UNWIND_RETURN_COLUMN;
+
+ return _URC_NO_REASON;
+}
+#endif
diff --git a/contrib/gcc/config/mips/linux.h b/contrib/gcc/config/mips/linux.h
new file mode 100644
index 0000000..ff268d4
--- /dev/null
+++ b/contrib/gcc/config/mips/linux.h
@@ -0,0 +1,181 @@
+/* Definitions for MIPS running Linux-based GNU systems with ELF format.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* If defined, a C expression whose value is a string containing the
+ assembler operation to identify the following data as
+ uninitialized global data. If not defined, and neither
+ `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
+ uninitialized global data will be output in the data section if
+ `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
+ used. */
+#define BSS_SECTION_ASM_OP "\t.section\t.bss"
+
+#define ASM_OUTPUT_ALIGNED_BSS mips_output_aligned_bss
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME mips_declare_object_name
+
+#undef TARGET_VERSION
+#if TARGET_ENDIAN_DEFAULT == 0
+#define TARGET_VERSION fprintf (stderr, " (MIPSel GNU/Linux with ELF)");
+#else
+#define TARGET_VERSION fprintf (stderr, " (MIPS GNU/Linux with ELF)");
+#endif
+
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+/* If we don't set MASK_ABICALLS, we can't default to PIC. */
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT MASK_ABICALLS
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ LINUX_TARGET_OS_CPP_BUILTINS(); \
+ /* The GNU C++ standard library requires this. */ \
+ if (c_dialect_cxx ()) \
+ builtin_define ("_GNU_SOURCE"); \
+ \
+ if (mips_abi == ABI_N32) \
+ { \
+ builtin_define ("_ABIN32=2"); \
+ builtin_define ("_MIPS_SIM=_ABIN32"); \
+ builtin_define ("_MIPS_SZLONG=32"); \
+ builtin_define ("_MIPS_SZPTR=32"); \
+ } \
+ else if (mips_abi == ABI_64) \
+ { \
+ builtin_define ("_ABI64=3"); \
+ builtin_define ("_MIPS_SIM=_ABI64"); \
+ builtin_define ("_MIPS_SZLONG=64"); \
+ builtin_define ("_MIPS_SZPTR=64"); \
+ } \
+ else \
+ { \
+ builtin_define ("_ABIO32=1"); \
+ builtin_define ("_MIPS_SIM=_ABIO32"); \
+ builtin_define ("_MIPS_SZLONG=32"); \
+ builtin_define ("_MIPS_SZPTR=32"); \
+ } \
+ if (TARGET_FLOAT64) \
+ builtin_define ("_MIPS_FPSET=32"); \
+ else \
+ builtin_define ("_MIPS_FPSET=16"); \
+ \
+ builtin_define ("_MIPS_SZINT=32"); \
+ } while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
+
+/* A standard GNU/Linux mapping. On most targets, it is included in
+ CC1_SPEC itself by config/linux.h, but mips.h overrides CC1_SPEC
+ and provides this hook instead. */
+#undef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC "%{profile:-p}"
+
+/* From iris5.h */
+/* -G is incompatible with -KPIC which is the default, so only allow objects
+ in the small data section if the user explicitly asks for it. */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
+
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+
+/* Borrowed from sparc/linux.h */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%(endian_spec) \
+ %{shared:-shared} \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "}} \
+ %{static:-static}}}"
+
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "%{mabi=64: -64} %{!mno-abicalls:-KPIC}"
+
+/* 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_DEF
+#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2) \
+ do { \
+ fputc ( '\t', FILE); \
+ assemble_name (FILE, LABEL1); \
+ fputs ( " = ", FILE); \
+ assemble_name (FILE, LABEL2); \
+ fputc ( '\n', FILE); \
+ } 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); \
+ } \
+ ASM_OUTPUT_TYPE_DIRECTIVE (STREAM, NAME, "function"); \
+ 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. */
+#undef FUNCTION_NAME_ALREADY_DECLARED
+#define FUNCTION_NAME_ALREADY_DECLARED 1
+
+/* The glibc _mcount stub will save $v0 for us. Don't mess with saving
+ it, since ASM_OUTPUT_REG_PUSH/ASM_OUTPUT_REG_POP do not work in the
+ presence of $gp-relative calls. */
+#undef ASM_OUTPUT_REG_PUSH
+#undef ASM_OUTPUT_REG_POP
+
+#undef LIB_SPEC
+#define LIB_SPEC "\
+%{shared: -lc} \
+%{!shared: %{pthread:-lpthread} \
+ %{profile:-lc_p} %{!profile: -lc}}"
+
+#define MD_UNWIND_SUPPORT "config/mips/linux-unwind.h"
diff --git a/contrib/gcc/config/mips/linux64.h b/contrib/gcc/config/mips/linux64.h
new file mode 100644
index 0000000..4ccf938
--- /dev/null
+++ b/contrib/gcc/config/mips/linux64.h
@@ -0,0 +1,72 @@
+/* Definitions for MIPS running Linux-based GNU systems with ELF format
+ using n32/64 abi.
+ Copyright 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Force the default endianness and ABI flags onto the command line
+ in order to make the other specs easier to write. */
+#define DRIVER_SELF_SPECS \
+"%{!EB:%{!EL:%(endian_spec)}}", \
+"%{!mabi=*: -mabi=n32}"
+
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "\
+%{!fno-PIC:%{!fno-pic:-KPIC}} \
+%{fno-PIC:-non_shared} %{fno-pic:-non_shared}"
+
+#undef LIB_SPEC
+#define LIB_SPEC "\
+%{shared: -lc} \
+%{!shared: %{pthread:-lpthread} \
+ %{profile:-lc_p} %{!profile: -lc}}"
+
+#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld.so.1"
+#define GLIBC_DYNAMIC_LINKERN32 "/lib32/ld.so.1"
+#define UCLIBC_DYNAMIC_LINKERN32 "/lib32/ld-uClibc.so.0"
+#define LINUX_DYNAMIC_LINKERN32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERN32, UCLIBC_DYNAMIC_LINKERN32)
+
+#undef LINK_SPEC
+#define LINK_SPEC "\
+%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} %{mips4} \
+%{bestGnum} %{shared} %{non_shared} \
+%{call_shared} %{no_archive} %{exact_version} \
+ %(endian_spec) \
+ %{!shared: \
+ %{!ibcs: \
+ %{!static: \
+ %{rdynamic:-export-dynamic} \
+ %{!dynamic-linker: \
+ %{mabi=n32: -dynamic-linker " LINUX_DYNAMIC_LINKERN32 "} \
+ %{mabi=64: -dynamic-linker " LINUX_DYNAMIC_LINKER64 "} \
+ %{mabi=32: -dynamic-linker " LINUX_DYNAMIC_LINKER32 "}}} \
+ %{static:-static}}} \
+%{mabi=n32:-melf32%{EB:b}%{EL:l}tsmipn32} \
+%{mabi=64:-melf64%{EB:b}%{EL:l}tsmip} \
+%{mabi=32:-melf32%{EB:b}%{EL:l}tsmip}"
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX (TARGET_OLDABI ? "$" : ".")
+
+/* GNU/Linux doesn't use the same floating-point format that IRIX uses
+ for long double. There's no need to override this here, since
+ ieee_quad_format is the default, but let's put this here to make
+ sure nobody thinks we just forgot to set it to something else. */
+#define MIPS_TFMODE_FORMAT mips_quad_format
diff --git a/contrib/gcc/config/mips/mips-dsp.md b/contrib/gcc/config/mips/mips-dsp.md
new file mode 100644
index 0000000..3fdcc59
--- /dev/null
+++ b/contrib/gcc/config/mips/mips-dsp.md
@@ -0,0 +1,1057 @@
+(define_constants
+ [(CCDSP_PO_REGNUM 182)
+ (CCDSP_SC_REGNUM 183)
+ (CCDSP_CA_REGNUM 184)
+ (CCDSP_OU_REGNUM 185)
+ (CCDSP_CC_REGNUM 186)
+ (CCDSP_EF_REGNUM 187)])
+
+;; This mode macro allows si, v2hi, v4qi for all possible modes in DSP ASE.
+(define_mode_macro DSP [(SI "TARGET_DSP")
+ (V2HI "TARGET_DSP")
+ (V4QI "TARGET_DSP")])
+
+;; This mode macro allows v2hi, v4qi for vector/SIMD data.
+(define_mode_macro DSPV [(V2HI "TARGET_DSP")
+ (V4QI "TARGET_DSP")])
+
+;; This mode macro allows si, v2hi for Q31 and V2Q15 fixed-point data.
+(define_mode_macro DSPQ [(SI "TARGET_DSP")
+ (V2HI "TARGET_DSP")])
+
+;; DSP instructions use q for fixed-point data, and u for integer in the infix.
+(define_mode_attr dspfmt1 [(SI "q") (V2HI "q") (V4QI "u")])
+
+;; DSP instructions use nothing for fixed-point data, and u for integer in
+;; the infix.
+(define_mode_attr dspfmt1_1 [(SI "") (V2HI "") (V4QI "u")])
+
+;; DSP instructions use w, ph, qb in the postfix.
+(define_mode_attr dspfmt2 [(SI "w") (V2HI "ph") (V4QI "qb")])
+
+;; DSP shift masks for SI, V2HI, V4QI.
+(define_mode_attr dspshift_mask [(SI "0x1f") (V2HI "0xf") (V4QI "0x7")])
+
+;; MIPS DSP ASE Revision 0.98 3/24/2005
+;; Table 2-1. MIPS DSP ASE Instructions: Arithmetic
+;; ADDQ*
+(define_insn "add<DSPV:mode>3"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (plus:DSPV (match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ))])]
+ ""
+ "add<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_add<DSP:dspfmt1>_s_<DSP:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSP 0 "register_operand" "=d")
+ (unspec:DSP [(match_operand:DSP 1 "register_operand" "d")
+ (match_operand:DSP 2 "register_operand" "d")]
+ UNSPEC_ADDQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDQ_S))])]
+ ""
+ "add<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; SUBQ*
+(define_insn "sub<DSPV:mode>3"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (minus:DSPV (match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ))])]
+ "TARGET_DSP"
+ "sub<DSPV:dspfmt1>.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_sub<DSP:dspfmt1>_s_<DSP:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSP 0 "register_operand" "=d")
+ (unspec:DSP [(match_operand:DSP 1 "register_operand" "d")
+ (match_operand:DSP 2 "register_operand" "d")]
+ UNSPEC_SUBQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SUBQ_S))])]
+ "TARGET_DSP"
+ "sub<DSP:dspfmt1>_s.<DSP:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ADDSC
+(define_insn "mips_addsc"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_ADDSC))
+ (set (reg:CCDSP CCDSP_CA_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDSC))])]
+ "TARGET_DSP"
+ "addsc\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ADDWC
+(define_insn "mips_addwc"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_CA_REGNUM)]
+ UNSPEC_ADDWC))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_ADDWC))])]
+ "TARGET_DSP"
+ "addwc\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; MODSUB
+(define_insn "mips_modsub"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_MODSUB))]
+ "TARGET_DSP"
+ "modsub\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; RADDU*
+(define_insn "mips_raddu_w_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_RADDU_W_QB))]
+ "TARGET_DSP"
+ "raddu.w.qb\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; ABSQ*
+(define_insn "mips_absq_s_<DSPQ:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPQ 0 "register_operand" "=d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d")]
+ UNSPEC_ABSQ_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1)] UNSPEC_ABSQ_S))])]
+ "TARGET_DSP"
+ "absq_s.<DSPQ:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECRQ*
+(define_insn "mips_precrq_qb_ph"
+ [(set (match_operand:V4QI 0 "register_operand" "=d")
+ (unspec:V4QI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_QB_PH))]
+ "TARGET_DSP"
+ "precrq.qb.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precrq_ph_w"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_PH_W))]
+ "TARGET_DSP"
+ "precrq.ph.w\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precrq_rs_ph_w"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d")]
+ UNSPEC_PRECRQ_RS_PH_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)]
+ UNSPEC_PRECRQ_RS_PH_W))])]
+ "TARGET_DSP"
+ "precrq_rs.ph.w\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECRQU*
+(define_insn "mips_precrqu_s_qb_ph"
+ [(parallel
+ [(set (match_operand:V4QI 0 "register_operand" "=d")
+ (unspec:V4QI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PRECRQU_S_QB_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)]
+ UNSPEC_PRECRQU_S_QB_PH))])]
+ "TARGET_DSP"
+ "precrqu_s.qb.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEQ*
+(define_insn "mips_preceq_w_phl"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")]
+ UNSPEC_PRECEQ_W_PHL))]
+ "TARGET_DSP"
+ "preceq.w.phl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceq_w_phr"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")]
+ UNSPEC_PRECEQ_W_PHR))]
+ "TARGET_DSP"
+ "preceq.w.phr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEQU*
+(define_insn "mips_precequ_ph_qbl"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBL))]
+ "TARGET_DSP"
+ "precequ.ph.qbl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbr"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBR))]
+ "TARGET_DSP"
+ "precequ.ph.qbr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbla"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBLA))]
+ "TARGET_DSP"
+ "precequ.ph.qbla\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_precequ_ph_qbra"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEQU_PH_QBRA))]
+ "TARGET_DSP"
+ "precequ.ph.qbra\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PRECEU*
+(define_insn "mips_preceu_ph_qbl"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBL))]
+ "TARGET_DSP"
+ "preceu.ph.qbl\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbr"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBR))]
+ "TARGET_DSP"
+ "preceu.ph.qbr\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbla"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBLA))]
+ "TARGET_DSP"
+ "preceu.ph.qbla\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_preceu_ph_qbra"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")]
+ UNSPEC_PRECEU_PH_QBRA))]
+ "TARGET_DSP"
+ "preceu.ph.qbra\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-2. MIPS DSP ASE Instructions: Shift
+;; SHLL*
+(define_insn "mips_shll_<DSPV:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPV 0 "register_operand" "=d,d")
+ (unspec:DSPV [(match_operand:DSPV 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHLL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SHLL))])]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPV:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPV:dspshift_mask>);
+ return "shll.<DSPV:dspfmt2>\t%0,%1,%2";
+ }
+ return "shllv.<DSPV:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_shll_s_<DSPQ:dspfmt2>"
+ [(parallel
+ [(set (match_operand:DSPQ 0 "register_operand" "=d,d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHLL_S))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_SHLL_S))])]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPQ:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPQ:dspshift_mask>);
+ return "shll_s.<DSPQ:dspfmt2>\t%0,%1,%2";
+ }
+ return "shllv_s.<DSPQ:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; SHRL*
+(define_insn "mips_shrl_qb"
+ [(set (match_operand:V4QI 0 "register_operand" "=d,d")
+ (unspec:V4QI [(match_operand:V4QI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRL_QB))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x7)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x7);
+ return "shrl.qb\t%0,%1,%2";
+ }
+ return "shrlv.qb\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; SHRA*
+(define_insn "mips_shra_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d,d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRA_PH))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0xf)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xf);
+ return "shra.ph\t%0,%1,%2";
+ }
+ return "shrav.ph\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_shra_r_<DSPQ:dspfmt2>"
+ [(set (match_operand:DSPQ 0 "register_operand" "=d,d")
+ (unspec:DSPQ [(match_operand:DSPQ 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHRA_R))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2])
+ & ~(unsigned HOST_WIDE_INT) <DSPQ:dspshift_mask>)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & <DSPQ:dspshift_mask>);
+ return "shra_r.<DSPQ:dspfmt2>\t%0,%1,%2";
+ }
+ return "shrav_r.<DSPQ:dspfmt2>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+;; Table 2-3. MIPS DSP ASE Instructions: Multiply
+;; MULEU*
+(define_insn "mips_muleu_s_ph_qbl"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEU_S_PH_QBL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEU_S_PH_QBL))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleu_s.ph.qbl\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_muleu_s_ph_qbr"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEU_S_PH_QBR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEU_S_PH_QBR))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleu_s.ph.qbr\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; MULQ*
+(define_insn "mips_mulq_rs_ph"
+ [(parallel
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULQ_RS_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULQ_RS_PH))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "mulq_rs.ph\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; MULEQ*
+(define_insn "mips_muleq_s_w_phl"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEQ_S_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEQ_S_W_PHL))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleq_s.w.phl\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_muleq_s_w_phr"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_MULEQ_S_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_MULEQ_S_W_PHR))
+ (clobber (match_scratch:DI 3 "=x"))])]
+ "TARGET_DSP"
+ "muleq_s.w.phr\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "SI")])
+
+;; DPAU*
+(define_insn "mips_dpau_h_qbl"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPAU_H_QBL))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpau.h.qbl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_dpau_h_qbr"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPAU_H_QBR))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpau.h.qbr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSU*
+(define_insn "mips_dpsu_h_qbl"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPSU_H_QBL))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsu.h.qbl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_dpsu_h_qbr"
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V4QI 2 "register_operand" "d")
+ (match_operand:V4QI 3 "register_operand" "d")]
+ UNSPEC_DPSU_H_QBR))]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsu.h.qbr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPAQ*
+(define_insn "mips_dpaq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_DPAQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPAQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpaq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSQ*
+(define_insn "mips_dpsq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_DPSQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPSQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MULSAQ*
+(define_insn "mips_mulsaq_s_w_ph"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MULSAQ_S_W_PH))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MULSAQ_S_W_PH))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "mulsaq_s.w.ph\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPAQ*
+(define_insn "mips_dpaq_sa_l_w"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")]
+ UNSPEC_DPAQ_SA_L_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPAQ_SA_L_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpaq_sa.l.w\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; DPSQ*
+(define_insn "mips_dpsq_sa_l_w"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d")]
+ UNSPEC_DPSQ_SA_L_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_DPSQ_SA_L_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "dpsq_sa.l.w\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MAQ*
+(define_insn "mips_maq_s_w_phl"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_S_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_S_W_PHL))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_s.w.phl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_maq_s_w_phr"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_S_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_S_W_PHR))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_s.w.phr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; MAQ_SA*
+(define_insn "mips_maq_sa_w_phl"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_SA_W_PHL))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_SA_W_PHL))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_sa.w.phl\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_maq_sa_w_phr"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:V2HI 2 "register_operand" "d")
+ (match_operand:V2HI 3 "register_operand" "d")]
+ UNSPEC_MAQ_SA_W_PHR))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2) (match_dup 3)]
+ UNSPEC_MAQ_SA_W_PHR))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "maq_sa.w.phr\t%q0,%2,%3"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; Table 2-4. MIPS DSP ASE Instructions: General Bit/Manipulation
+;; BITREV
+(define_insn "mips_bitrev"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "d")]
+ UNSPEC_BITREV))]
+ "TARGET_DSP"
+ "bitrev\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; INSV
+(define_insn "mips_insv"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_SC_REGNUM)
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_INSV))]
+ "TARGET_DSP"
+ "insv\t%0,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; REPL*
+(define_insn "mips_repl_qb"
+ [(set (match_operand:V4QI 0 "register_operand" "=d,d")
+ (unspec:V4QI [(match_operand:SI 1 "arith_operand" "I,d")]
+ UNSPEC_REPL_QB))]
+ "TARGET_DSP"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[1]) & ~(unsigned HOST_WIDE_INT) 0xff)
+ operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
+ return "repl.qb\t%0,%1";
+ }
+ return "replv.qb\t%0,%1";
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_repl_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d,d")
+ (unspec:V2HI [(match_operand:SI 1 "reg_imm10_operand" "YB,d")]
+ UNSPEC_REPL_PH))]
+ "TARGET_DSP"
+ "@
+ repl.ph\t%0,%1
+ replv.ph\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-5. MIPS DSP ASE Instructions: Compare-Pick
+;; CMPU.* CMP.*
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_eq_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_EQ))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.eq.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_lt_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_LT))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.lt.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmp<DSPV:dspfmt1_1>_le_<DSPV:dspfmt2>"
+ [(set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_operand:DSPV 0 "register_operand" "d")
+ (match_operand:DSPV 1 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_CMP_LE))]
+ "TARGET_DSP"
+ "cmp<DSPV:dspfmt1_1>.le.<DSPV:dspfmt2>\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_eq_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_EQ_QB))]
+ "TARGET_DSP"
+ "cmpgu.eq.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_lt_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_LT_QB))]
+ "TARGET_DSP"
+ "cmpgu.lt.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_cmpgu_le_qb"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:V4QI 1 "register_operand" "d")
+ (match_operand:V4QI 2 "register_operand" "d")]
+ UNSPEC_CMPGU_LE_QB))]
+ "TARGET_DSP"
+ "cmpgu.le.qb\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PICK*
+(define_insn "mips_pick_<DSPV:dspfmt2>"
+ [(set (match_operand:DSPV 0 "register_operand" "=d")
+ (unspec:DSPV [(match_operand:DSPV 1 "register_operand" "d")
+ (match_operand:DSPV 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_CC_REGNUM)]
+ UNSPEC_PICK))]
+ "TARGET_DSP"
+ "pick.<DSPV:dspfmt2>\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; PACKRL*
+(define_insn "mips_packrl_ph"
+ [(set (match_operand:V2HI 0 "register_operand" "=d")
+ (unspec:V2HI [(match_operand:V2HI 1 "register_operand" "d")
+ (match_operand:V2HI 2 "register_operand" "d")]
+ UNSPEC_PACKRL_PH))]
+ "TARGET_DSP"
+ "packrl.ph\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-6. MIPS DSP ASE Instructions: Accumulator and DSPControl Access
+;; EXTR*
+(define_insn "mips_extr_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr.w\t%0,%q1,%2";
+ }
+ return "extrv.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extr_r_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_R_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_R_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_r.w\t%0,%q1,%2";
+ }
+ return "extrv_r.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extr_rs_w"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_RS_W))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_RS_W))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_rs.w\t%0,%q1,%2";
+ }
+ return "extrv_rs.w\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; EXTR*_S.H
+(define_insn "mips_extr_s_h"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_EXTR_S_H))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTR_S_H))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extr_s.h\t%0,%q1,%2";
+ }
+ return "extrv_s.h\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; EXTP*
+(define_insn "mips_extp"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_EXTP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extp\t%0,%q1,%2";
+ }
+ return "extpv\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+(define_insn "mips_extpdp"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (unspec:SI [(match_operand:DI 1 "register_operand" "a,a")
+ (match_operand:SI 2 "arith_operand" "I,d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_EXTPDP))
+ (set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)
+ (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_EXTPDP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)] UNSPEC_EXTPDP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) & ~(unsigned HOST_WIDE_INT) 0x1f)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "extpdp\t%0,%q1,%2";
+ }
+ return "extpdpv\t%0,%q1,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; SHILO*
+(define_insn "mips_shilo"
+ [(set (match_operand:DI 0 "register_operand" "=a,a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "arith_operand" "I,d")]
+ UNSPEC_SHILO))]
+ "TARGET_DSP && !TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ {
+ if (INTVAL (operands[2]) < -32 || INTVAL (operands[2]) > 31)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
+ return "shilo\t%q0,%2";
+ }
+ return "shilov\t%q0,%2";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; MTHLIP*
+(define_insn "mips_mthlip"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "=a")
+ (unspec:DI [(match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "register_operand" "d")
+ (reg:CCDSP CCDSP_PO_REGNUM)]
+ UNSPEC_MTHLIP))
+ (set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_dup 1) (match_dup 2)
+ (reg:CCDSP CCDSP_PO_REGNUM)] UNSPEC_MTHLIP))])]
+ "TARGET_DSP && !TARGET_64BIT"
+ "mthlip\t%2,%q0"
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "SI")])
+
+;; WRDSP
+(define_insn "mips_wrdsp"
+ [(parallel
+ [(set (reg:CCDSP CCDSP_PO_REGNUM)
+ (unspec:CCDSP [(match_operand:SI 0 "register_operand" "d")
+ (match_operand:SI 1 "const_uimm6_operand" "YA")]
+ UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_SC_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_CA_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_OU_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_CC_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))
+ (set (reg:CCDSP CCDSP_EF_REGNUM)
+ (unspec:CCDSP [(match_dup 0) (match_dup 1)] UNSPEC_WRDSP))])]
+ "TARGET_DSP"
+ "wrdsp\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; RDDSP
+(define_insn "mips_rddsp"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_operand:SI 1 "const_uimm6_operand" "YA")
+ (reg:CCDSP CCDSP_PO_REGNUM)
+ (reg:CCDSP CCDSP_SC_REGNUM)
+ (reg:CCDSP CCDSP_CA_REGNUM)
+ (reg:CCDSP CCDSP_OU_REGNUM)
+ (reg:CCDSP CCDSP_CC_REGNUM)
+ (reg:CCDSP CCDSP_EF_REGNUM)]
+ UNSPEC_RDDSP))]
+ "TARGET_DSP"
+ "rddsp\t%0,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Table 2-7. MIPS DSP ASE Instructions: Indexed-Load
+;; L*X
+(define_insn "mips_lbux"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (mem:QI (plus:SI (match_operand:SI 1
+ "register_operand" "d")
+ (match_operand:SI 2
+ "register_operand" "d")))))]
+ "TARGET_DSP"
+ "lbux\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+(define_insn "mips_lhx"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI (mem:HI (plus:SI (match_operand:SI 1
+ "register_operand" "d")
+ (match_operand:SI 2
+ "register_operand" "d")))))]
+ "TARGET_DSP"
+ "lhx\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+(define_insn "mips_lwx"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (mem:SI (plus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "TARGET_DSP"
+ "lwx\t%0,%2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4")])
+
+;; Table 2-8. MIPS DSP ASE Instructions: Branch
+;; BPOSGE32
+(define_insn "mips_bposge"
+ [(set (pc)
+ (if_then_else (ge (reg:CCDSP CCDSP_PO_REGNUM)
+ (match_operand:SI 0 "immediate_operand" "I"))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_DSP"
+ "%*bposge%0\t%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
diff --git a/contrib/gcc/config/mips/mips-modes.def b/contrib/gcc/config/mips/mips-modes.def
new file mode 100644
index 0000000..39c2f16
--- /dev/null
+++ b/contrib/gcc/config/mips/mips-modes.def
@@ -0,0 +1,43 @@
+/* MIPS extra machine modes.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* MIPS has a quirky almost-IEEE format for all its
+ floating point. */
+RESET_FLOAT_FORMAT (SF, mips_single_format);
+RESET_FLOAT_FORMAT (DF, mips_double_format);
+
+/* Irix6 will override this via MIPS_TFMODE_FORMAT. */
+FLOAT_MODE (TF, 16, mips_quad_format);
+
+/* Vector modes. */
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
+
+/* Paired single comparison instructions use 2 or 4 CC. */
+CC_MODE (CCV2);
+ADJUST_BYTESIZE (CCV2, 8);
+ADJUST_ALIGNMENT (CCV2, 8);
+
+CC_MODE (CCV4);
+ADJUST_BYTESIZE (CCV4, 16);
+ADJUST_ALIGNMENT (CCV4, 16);
+
+/* For MIPS DSP control registers. */
+CC_MODE (CCDSP);
diff --git a/contrib/gcc/config/mips/mips-protos.h b/contrib/gcc/config/mips/mips-protos.h
new file mode 100644
index 0000000..da1ccea
--- /dev/null
+++ b/contrib/gcc/config/mips/mips-protos.h
@@ -0,0 +1,255 @@
+/* Prototypes of target machine for GNU compiler. MIPS version.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Contributed by A. Lichnewsky (lich@inria.inria.fr).
+ Changed by Michael Meissner (meissner@osf.org).
+ 64 bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
+ Brendan Eich (brendan@microunity.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#ifndef GCC_MIPS_PROTOS_H
+#define GCC_MIPS_PROTOS_H
+
+/* Classifies a SYMBOL_REF, LABEL_REF or UNSPEC address.
+
+ SYMBOL_GENERAL
+ Used when none of the below apply.
+
+ SYMBOL_SMALL_DATA
+ The symbol refers to something in a small data section.
+
+ SYMBOL_CONSTANT_POOL
+ The symbol refers to something in the mips16 constant pool.
+
+ SYMBOL_GOT_LOCAL
+ The symbol refers to local data that will be found using
+ the global offset table.
+
+ SYMBOL_GOT_GLOBAL
+ Likewise non-local data.
+
+ SYMBOL_GOTOFF_PAGE
+ An UNSPEC wrapper around a SYMBOL_GOT_LOCAL. It represents the
+ offset from _gp of a GOT page entry.
+
+ SYMBOL_GOTOFF_GLOBAL
+ An UNSPEC wrapper around a SYMBOL_GOT_GLOBAL. It represents the
+ the offset from _gp of the symbol's GOT entry.
+
+ SYMBOL_GOTOFF_CALL
+ Like SYMBOL_GOTOFF_GLOBAL, but used when calling a global function.
+ The GOT entry is allowed to point to a stub rather than to the
+ function itself.
+
+ SYMBOL_GOTOFF_LOADGP
+ An UNSPEC wrapper around a function's address. It represents the
+ offset of _gp from the start of the function.
+
+ SYMBOL_TLS
+ A thread-local symbol.
+
+ SYMBOL_TLSGD
+ SYMBOL_TLSLDM
+ SYMBOL_DTPREL
+ SYMBOL_GOTTPREL
+ SYMBOL_TPREL
+ UNSPEC wrappers around SYMBOL_TLS, corresponding to the
+ thread-local storage relocation operators.
+
+ SYMBOL_64_HIGH
+ For a 64-bit symbolic address X, this is the value of
+ (%highest(X) << 16) + %higher(X).
+
+ SYMBOL_64_MID
+ For a 64-bit symbolic address X, this is the value of
+ (%higher(X) << 16) + %hi(X).
+
+ SYMBOL_64_LOW
+ For a 64-bit symbolic address X, this is the value of
+ (%hi(X) << 16) + %lo(X). */
+enum mips_symbol_type {
+ SYMBOL_GENERAL,
+ SYMBOL_SMALL_DATA,
+ SYMBOL_CONSTANT_POOL,
+ SYMBOL_GOT_LOCAL,
+ SYMBOL_GOT_GLOBAL,
+ SYMBOL_GOTOFF_PAGE,
+ SYMBOL_GOTOFF_GLOBAL,
+ SYMBOL_GOTOFF_CALL,
+ SYMBOL_GOTOFF_LOADGP,
+ SYMBOL_TLS,
+ SYMBOL_TLSGD,
+ SYMBOL_TLSLDM,
+ SYMBOL_DTPREL,
+ SYMBOL_GOTTPREL,
+ SYMBOL_TPREL,
+ SYMBOL_64_HIGH,
+ SYMBOL_64_MID,
+ SYMBOL_64_LOW
+};
+#define NUM_SYMBOL_TYPES (SYMBOL_64_LOW + 1)
+
+/* Identifiers a style of $gp initialization sequence.
+
+ LOADGP_NONE
+ No initialization sequence is needed.
+
+ LOADGP_OLDABI
+ The o32 and o64 PIC sequence (the kind traditionally generated
+ by .cpload).
+
+ LOADGP_NEWABI
+ The n32 and n64 PIC sequence (the kind traditionally generated
+ by .cpsetup).
+
+ LOADGP_ABSOLUTE
+ The GNU absolute sequence, as generated by loadgp_noshared. */
+enum mips_loadgp_style {
+ LOADGP_NONE,
+ LOADGP_OLDABI,
+ LOADGP_NEWABI,
+ LOADGP_ABSOLUTE
+};
+
+extern bool mips_symbolic_constant_p (rtx, enum mips_symbol_type *);
+extern int mips_regno_mode_ok_for_base_p (int, enum machine_mode, int);
+extern bool mips_stack_address_p (rtx, enum machine_mode);
+extern int mips_address_insns (rtx, enum machine_mode);
+extern int mips_const_insns (rtx);
+extern int mips_fetch_insns (rtx);
+extern int mips_idiv_insns (void);
+extern int fp_register_operand (rtx, enum machine_mode);
+extern int lo_operand (rtx, enum machine_mode);
+extern bool mips_legitimate_address_p (enum machine_mode, rtx, int);
+extern rtx mips_split_symbol (rtx, rtx);
+extern rtx mips_unspec_address (rtx, enum mips_symbol_type);
+extern bool mips_legitimize_address (rtx *, enum machine_mode);
+extern void mips_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
+extern bool mips_legitimize_move (enum machine_mode, rtx, rtx);
+
+extern int m16_uimm3_b (rtx, enum machine_mode);
+extern int m16_simm4_1 (rtx, enum machine_mode);
+extern int m16_nsimm4_1 (rtx, enum machine_mode);
+extern int m16_simm5_1 (rtx, enum machine_mode);
+extern int m16_nsimm5_1 (rtx, enum machine_mode);
+extern int m16_uimm5_4 (rtx, enum machine_mode);
+extern int m16_nuimm5_4 (rtx, enum machine_mode);
+extern int m16_simm8_1 (rtx, enum machine_mode);
+extern int m16_nsimm8_1 (rtx, enum machine_mode);
+extern int m16_uimm8_1 (rtx, enum machine_mode);
+extern int m16_nuimm8_1 (rtx, enum machine_mode);
+extern int m16_uimm8_m1_1 (rtx, enum machine_mode);
+extern int m16_uimm8_4 (rtx, enum machine_mode);
+extern int m16_nuimm8_4 (rtx, enum machine_mode);
+extern int m16_simm8_8 (rtx, enum machine_mode);
+extern int m16_nsimm8_8 (rtx, enum machine_mode);
+
+extern rtx mips_subword (rtx, int);
+extern bool mips_split_64bit_move_p (rtx, rtx);
+extern void mips_split_64bit_move (rtx, rtx);
+extern const char *mips_output_move (rtx, rtx);
+extern void mips_restore_gp (void);
+#ifdef RTX_CODE
+extern bool mips_emit_scc (enum rtx_code, rtx);
+extern void gen_conditional_branch (rtx *, enum rtx_code);
+extern void mips_expand_vcondv2sf (rtx, rtx, rtx, enum rtx_code, rtx, rtx);
+#endif
+extern void gen_conditional_move (rtx *);
+extern void mips_gen_conditional_trap (rtx *);
+extern void mips_expand_call (rtx, rtx, rtx, rtx, int);
+extern void mips_emit_fcc_reload (rtx, rtx, rtx);
+extern void mips_set_return_address (rtx, rtx);
+extern bool mips_expand_block_move (rtx, rtx, rtx);
+
+extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx);
+extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int);
+extern struct rtx_def *function_arg (const CUMULATIVE_ARGS *,
+ enum machine_mode, tree, int);
+extern int function_arg_boundary (enum machine_mode, tree);
+extern bool mips_pad_arg_upward (enum machine_mode, tree);
+extern bool mips_pad_reg_upward (enum machine_mode, tree);
+extern void mips_va_start (tree, rtx);
+
+extern bool mips_expand_unaligned_load (rtx, rtx, unsigned int, int);
+extern bool mips_expand_unaligned_store (rtx, rtx, unsigned int, int);
+extern bool mips_mem_fits_mode_p (enum machine_mode mode, rtx x);
+extern void override_options (void);
+extern void mips_conditional_register_usage (void);
+extern void mips_order_regs_for_local_alloc (void);
+extern HOST_WIDE_INT mips_debugger_offset (rtx, HOST_WIDE_INT);
+
+extern void print_operand (FILE *, rtx, int);
+extern void print_operand_address (FILE *, rtx);
+extern int mips_output_external (FILE *, tree, const char *);
+extern void mips_output_filename (FILE *, const char *);
+extern void mips_output_ascii (FILE *, const char *, size_t, const char *);
+extern void mips_output_aligned_bss (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT, int);
+extern void mips_output_aligned_decl_common (FILE *, tree, const char *,
+ unsigned HOST_WIDE_INT,
+ unsigned int);
+extern void mips_declare_common_object (FILE *, const char *,
+ const char *, unsigned HOST_WIDE_INT,
+ unsigned int, bool);
+extern void mips_declare_object (FILE *, const char *, const char *,
+ const char *, ...) ATTRIBUTE_PRINTF_4;
+extern void mips_declare_object_name (FILE *, const char *, tree);
+extern void mips_finish_declare_object (FILE *, tree, int, int);
+
+extern bool mips_small_data_pattern_p (rtx);
+extern rtx mips_rewrite_small_data (rtx);
+extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT);
+extern HOST_WIDE_INT mips_initial_elimination_offset (int, int);
+extern rtx mips_return_addr (int, rtx);
+extern enum mips_loadgp_style mips_current_loadgp_style (void);
+extern void mips_expand_prologue (void);
+extern void mips_expand_epilogue (int);
+extern int mips_can_use_return_insn (void);
+extern struct rtx_def *mips_function_value (tree, tree, enum machine_mode);
+
+extern bool mips_cannot_change_mode_class (enum machine_mode,
+ enum machine_mode, enum reg_class);
+extern bool mips_dangerous_for_la25_p (rtx);
+extern enum reg_class mips_preferred_reload_class (rtx, enum reg_class);
+extern enum reg_class mips_secondary_reload_class (enum reg_class,
+ enum machine_mode,
+ rtx, int);
+extern int mips_class_max_nregs (enum reg_class, enum machine_mode);
+extern int build_mips16_call_stub (rtx, rtx, rtx, int);
+extern int mips_register_move_cost (enum machine_mode, enum reg_class,
+ enum reg_class);
+
+extern int mips_adjust_insn_length (rtx, int);
+extern const char *mips_output_load_label (void);
+extern const char *mips_output_conditional_branch (rtx, rtx *, const char *,
+ const char *);
+extern const char *mips_output_order_conditional_branch (rtx, rtx *, bool);
+extern const char *mips_output_division (const char *, rtx *);
+extern unsigned int mips_hard_regno_nregs (int, enum machine_mode);
+extern bool mips_linked_madd_p (rtx, rtx);
+extern int mips_store_data_bypass_p (rtx, rtx);
+extern rtx mips_prefetch_cookie (rtx, rtx);
+
+extern void irix_asm_output_align (FILE *, unsigned);
+extern const char *current_section_name (void);
+extern unsigned int current_section_flags (void);
+extern bool mips_use_ins_ext_p (rtx, rtx, rtx);
+
+#endif /* ! GCC_MIPS_PROTOS_H */
diff --git a/contrib/gcc/config/mips/mips-ps-3d.md b/contrib/gcc/config/mips/mips-ps-3d.md
new file mode 100644
index 0000000..c817f4d
--- /dev/null
+++ b/contrib/gcc/config/mips/mips-ps-3d.md
@@ -0,0 +1,618 @@
+;; MIPS Paired-Single Floating and MIPS-3D Instructions.
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_insn "*movcc_v2sf_<mode>"
+ [(set (match_operand:V2SF 0 "register_operand" "=f,f")
+ (if_then_else:V2SF
+ (match_operator:GPR 4 "equality_operator"
+ [(match_operand:GPR 1 "register_operand" "d,d")
+ (const_int 0)])
+ (match_operand:V2SF 2 "register_operand" "f,0")
+ (match_operand:V2SF 3 "register_operand" "0,f")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "@
+ mov%T4.ps\t%0,%2,%1
+ mov%t4.ps\t%0,%3,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "SF")])
+
+(define_insn "mips_cond_move_tf_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f,f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f,0")
+ (match_operand:V2SF 2 "register_operand" "0,f")
+ (match_operand:CCV2 3 "register_operand" "z,z")]
+ UNSPEC_MOVE_TF_PS))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "@
+ movt.ps\t%0,%1,%3
+ movf.ps\t%0,%2,%3"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "SF")])
+
+(define_expand "movv2sfcc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator"))
+ (set (match_operand:V2SF 0 "register_operand")
+ (if_then_else:V2SF (match_dup 5)
+ (match_operand:V2SF 2 "register_operand")
+ (match_operand:V2SF 3 "register_operand")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ /* We can only support MOVN.PS and MOVZ.PS.
+ NOTE: MOVT.PS and MOVF.PS have different semantics from MOVN.PS and
+ MOVZ.PS. MOVT.PS and MOVF.PS depend on two CC values and move
+ each item independently. */
+
+ if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
+ FAIL;
+
+ gen_conditional_move (operands);
+ DONE;
+})
+
+; pul.ps - Pair Upper Lower
+(define_insn "mips_pul_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (vec_merge:V2SF
+ (match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (const_int 2)))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "pul.ps\t%0,%1,%2"
+ [(set_attr "type" "fmove")
+ (set_attr "mode" "SF")])
+
+; puu.ps - Pair upper upper
+(define_insn "mips_puu_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (vec_merge:V2SF
+ (match_operand:V2SF 1 "register_operand" "f")
+ (vec_select:V2SF (match_operand:V2SF 2 "register_operand" "f")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (const_int 2)))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "puu.ps\t%0,%1,%2"
+ [(set_attr "type" "fmove")
+ (set_attr "mode" "SF")])
+
+; pll.ps - Pair Lower Lower
+(define_insn "mips_pll_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (vec_merge:V2SF
+ (vec_select:V2SF (match_operand:V2SF 1 "register_operand" "f")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (match_operand:V2SF 2 "register_operand" "f")
+ (const_int 2)))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "pll.ps\t%0,%1,%2"
+ [(set_attr "type" "fmove")
+ (set_attr "mode" "SF")])
+
+; plu.ps - Pair Lower Upper
+(define_insn "mips_plu_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (vec_merge:V2SF
+ (vec_select:V2SF (match_operand:V2SF 1 "register_operand" "f")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (vec_select:V2SF (match_operand:V2SF 2 "register_operand" "f")
+ (parallel [(const_int 1)
+ (const_int 0)]))
+ (const_int 2)))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "plu.ps\t%0,%1,%2"
+ [(set_attr "type" "fmove")
+ (set_attr "mode" "SF")])
+
+; vec_init
+(define_expand "vec_initv2sf"
+ [(match_operand:V2SF 0 "register_operand")
+ (match_operand:V2SF 1 "")]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ rtx op0 = force_reg (SFmode, XVECEXP (operands[1], 0, 0));
+ rtx op1 = force_reg (SFmode, XVECEXP (operands[1], 0, 1));
+ emit_insn (gen_vec_initv2sf_internal (operands[0], op0, op1));
+ DONE;
+})
+
+(define_insn "vec_initv2sf_internal"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (vec_concat:V2SF
+ (match_operand:SF 1 "register_operand" "f")
+ (match_operand:SF 2 "register_operand" "f")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ if (BYTES_BIG_ENDIAN)
+ return "cvt.ps.s\t%0,%1,%2";
+ else
+ return "cvt.ps.s\t%0,%2,%1";
+}
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")])
+
+;; ??? This is only generated if we perform a vector operation that has to be
+;; emulated. There is no other way to get a vector mode bitfield extract
+;; currently.
+
+(define_insn "vec_extractv2sf"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (vec_select:SF (match_operand:V2SF 1 "register_operand" "f")
+ (parallel
+ [(match_operand 2 "const_0_or_1_operand" "")])))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN)
+ return "cvt.s.pu\t%0,%1";
+ else
+ return "cvt.s.pl\t%0,%1";
+}
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")])
+
+;; ??? This is only generated if we disable the vec_init pattern. There is
+;; no other way to get a vector mode bitfield store currently.
+
+(define_expand "vec_setv2sf"
+ [(match_operand:V2SF 0 "register_operand")
+ (match_operand:SF 1 "register_operand")
+ (match_operand 2 "const_0_or_1_operand")]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ rtx temp;
+
+ /* We don't have an insert instruction, so we duplicate the float, and
+ then use a PUL instruction. */
+ temp = gen_reg_rtx (V2SFmode);
+ emit_insn (gen_mips_cvt_ps_s (temp, operands[1], operands[1]));
+ if (INTVAL (operands[2]) == !BYTES_BIG_ENDIAN)
+ emit_insn (gen_mips_pul_ps (operands[0], temp, operands[0]));
+ else
+ emit_insn (gen_mips_pul_ps (operands[0], operands[0], temp));
+ DONE;
+})
+
+; cvt.ps.s - Floating Point Convert Pair to Paired Single
+(define_expand "mips_cvt_ps_s"
+ [(match_operand:V2SF 0 "register_operand")
+ (match_operand:SF 1 "register_operand")
+ (match_operand:SF 2 "register_operand")]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ if (BYTES_BIG_ENDIAN)
+ emit_insn (gen_vec_initv2sf_internal (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_vec_initv2sf_internal (operands[0], operands[2],
+ operands[1]));
+ DONE;
+})
+
+; cvt.s.pl - Floating Point Convert Pair Lower to Single Floating Point
+(define_expand "mips_cvt_s_pl"
+ [(set (match_operand:SF 0 "register_operand")
+ (vec_select:SF (match_operand:V2SF 1 "register_operand")
+ (parallel [(match_dup 2)])))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ { operands[2] = GEN_INT (BYTES_BIG_ENDIAN); })
+
+; cvt.s.pu - Floating Point Convert Pair Upper to Single Floating Point
+(define_expand "mips_cvt_s_pu"
+ [(set (match_operand:SF 0 "register_operand")
+ (vec_select:SF (match_operand:V2SF 1 "register_operand")
+ (parallel [(match_dup 2)])))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ { operands[2] = GEN_INT (!BYTES_BIG_ENDIAN); })
+
+; alnv.ps - Floating Point Align Variable
+(define_insn "mips_alnv_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (match_operand:SI 3 "register_operand" "d")]
+ UNSPEC_ALNV_PS))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "alnv.ps\t%0,%1,%2,%3"
+ [(set_attr "type" "fmove")
+ (set_attr "mode" "SF")])
+
+; addr.ps - Floating Point Reduction Add
+(define_insn "mips_addr_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")]
+ UNSPEC_ADDR_PS))]
+ "TARGET_MIPS3D"
+ "addr.ps\t%0,%1,%2"
+ [(set_attr "type" "fadd")
+ (set_attr "mode" "SF")])
+
+; cvt.pw.ps - Floating Point Convert Paired Single to Paired Word
+(define_insn "mips_cvt_pw_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
+ UNSPEC_CVT_PW_PS))]
+ "TARGET_MIPS3D"
+ "cvt.pw.ps\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")])
+
+; cvt.ps.pw - Floating Point Convert Paired Word to Paired Single
+(define_insn "mips_cvt_ps_pw"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
+ UNSPEC_CVT_PS_PW))]
+ "TARGET_MIPS3D"
+ "cvt.ps.pw\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")])
+
+; mulr.ps - Floating Point Reduction Multiply
+(define_insn "mips_mulr_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")]
+ UNSPEC_MULR_PS))]
+ "TARGET_MIPS3D"
+ "mulr.ps\t%0,%1,%2"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "SF")])
+
+; abs.ps
+(define_expand "mips_abs_ps"
+ [(set (match_operand:V2SF 0 "register_operand")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand")]
+ UNSPEC_ABS_PS))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ /* If we can ignore NaNs, this operation is equivalent to the
+ rtl ABS code. */
+ if (!HONOR_NANS (V2SFmode))
+ {
+ emit_insn (gen_absv2sf2 (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "*mips_abs_ps"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "f")]
+ UNSPEC_ABS_PS))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "abs.ps\t%0,%1"
+ [(set_attr "type" "fabs")
+ (set_attr "mode" "SF")])
+
+;----------------------------------------------------------------------------
+; Floating Point Comparisons for Scalars
+;----------------------------------------------------------------------------
+
+(define_insn "mips_cabs_cond_<fmt>"
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (unspec:CC [(match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")
+ (match_operand 3 "const_int_operand" "")]
+ UNSPEC_CABS))]
+ "TARGET_MIPS3D"
+ "cabs.%Y3.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+
+;----------------------------------------------------------------------------
+; Floating Point Comparisons for Four Singles
+;----------------------------------------------------------------------------
+
+(define_insn_and_split "mips_c_cond_4s"
+ [(set (match_operand:CCV4 0 "register_operand" "=z")
+ (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (match_operand:V2SF 3 "register_operand" "f")
+ (match_operand:V2SF 4 "register_operand" "f")
+ (match_operand 5 "const_int_operand" "")]
+ UNSPEC_C))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 6)
+ (unspec:CCV2 [(match_dup 1)
+ (match_dup 2)
+ (match_dup 5)]
+ UNSPEC_C))
+ (set (match_dup 7)
+ (unspec:CCV2 [(match_dup 3)
+ (match_dup 4)
+ (match_dup 5)]
+ UNSPEC_C))]
+{
+ operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
+ operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
+}
+ [(set_attr "type" "fcmp")
+ (set_attr "length" "8")
+ (set_attr "mode" "FPSW")])
+
+(define_insn_and_split "mips_cabs_cond_4s"
+ [(set (match_operand:CCV4 0 "register_operand" "=z")
+ (unspec:CCV4 [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (match_operand:V2SF 3 "register_operand" "f")
+ (match_operand:V2SF 4 "register_operand" "f")
+ (match_operand 5 "const_int_operand" "")]
+ UNSPEC_CABS))]
+ "TARGET_MIPS3D"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 6)
+ (unspec:CCV2 [(match_dup 1)
+ (match_dup 2)
+ (match_dup 5)]
+ UNSPEC_CABS))
+ (set (match_dup 7)
+ (unspec:CCV2 [(match_dup 3)
+ (match_dup 4)
+ (match_dup 5)]
+ UNSPEC_CABS))]
+{
+ operands[6] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 0);
+ operands[7] = simplify_gen_subreg (CCV2mode, operands[0], CCV4mode, 8);
+}
+ [(set_attr "type" "fcmp")
+ (set_attr "length" "8")
+ (set_attr "mode" "FPSW")])
+
+
+;----------------------------------------------------------------------------
+; Floating Point Comparisons for Paired Singles
+;----------------------------------------------------------------------------
+
+(define_insn "mips_c_cond_ps"
+ [(set (match_operand:CCV2 0 "register_operand" "=z")
+ (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (match_operand 3 "const_int_operand" "")]
+ UNSPEC_C))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "c.%Y3.ps\t%0,%1,%2"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+(define_insn "mips_cabs_cond_ps"
+ [(set (match_operand:CCV2 0 "register_operand" "=z")
+ (unspec:CCV2 [(match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")
+ (match_operand 3 "const_int_operand" "")]
+ UNSPEC_CABS))]
+ "TARGET_MIPS3D"
+ "cabs.%Y3.ps\t%0,%1,%2"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+;; An expander for generating an scc operation.
+(define_expand "scc_ps"
+ [(set (match_operand:CCV2 0)
+ (unspec:CCV2 [(match_operand 1)] UNSPEC_SCC))])
+
+(define_insn "s<code>_ps"
+ [(set (match_operand:CCV2 0 "register_operand" "=z")
+ (unspec:CCV2
+ [(fcond (match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f"))]
+ UNSPEC_SCC))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "c.<fcond>.ps\t%0,%1,%2"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+(define_insn "s<code>_ps"
+ [(set (match_operand:CCV2 0 "register_operand" "=z")
+ (unspec:CCV2
+ [(swapped_fcond (match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f"))]
+ UNSPEC_SCC))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "c.<swapped_fcond>.ps\t%0,%2,%1"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+;----------------------------------------------------------------------------
+; Floating Point Branch Instructions.
+;----------------------------------------------------------------------------
+
+; Branch on Any of Four Floating Point Condition Codes True
+(define_insn "bc1any4t"
+ [(set (pc)
+ (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_MIPS3D"
+ "%*bc1any4t\t%0,%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+; Branch on Any of Four Floating Point Condition Codes False
+(define_insn "bc1any4f"
+ [(set (pc)
+ (if_then_else (ne (match_operand:CCV4 0 "register_operand" "z")
+ (const_int -1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_MIPS3D"
+ "%*bc1any4f\t%0,%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+; Branch on Any of Two Floating Point Condition Codes True
+(define_insn "bc1any2t"
+ [(set (pc)
+ (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_MIPS3D"
+ "%*bc1any2t\t%0,%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+; Branch on Any of Two Floating Point Condition Codes False
+(define_insn "bc1any2f"
+ [(set (pc)
+ (if_then_else (ne (match_operand:CCV2 0 "register_operand" "z")
+ (const_int -1))
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_MIPS3D"
+ "%*bc1any2f\t%0,%1%/"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+; Used to access one register in a CCV2 pair. Operand 0 is the register
+; pair and operand 1 is the index of the register we want (a CONST_INT).
+(define_expand "single_cc"
+ [(ne (unspec:CC [(match_operand 0) (match_operand 1)] UNSPEC_SINGLE_CC)
+ (const_int 0))])
+
+; This is a normal floating-point branch pattern, but rather than check
+; a single CCmode register, it checks one register in a CCV2 pair.
+; Operand 2 is the register pair and operand 3 is the index of the
+; register we want.
+(define_insn "*branch_upper_lower"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
+ (match_operand 3 "const_int_operand")]
+ UNSPEC_SINGLE_CC)
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_HARD_FLOAT"
+{
+ operands[2]
+ = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%F0", "%2,%1"),
+ MIPS_BRANCH ("b%W0", "%2,%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+; As above, but with the sense of the condition reversed.
+(define_insn "*branch_upper_lower_inverted"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(unspec:CC [(match_operand:CCV2 2 "register_operand" "z")
+ (match_operand 3 "const_int_operand")]
+ UNSPEC_SINGLE_CC)
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "TARGET_HARD_FLOAT"
+{
+ operands[2]
+ = gen_rtx_REG (CCmode, REGNO (operands[2]) + INTVAL (operands[3]));
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%W0", "%2,%1"),
+ MIPS_BRANCH ("b%F0", "%2,%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+;----------------------------------------------------------------------------
+; Floating Point Reduced Precision Reciprocal Square Root Instructions.
+;----------------------------------------------------------------------------
+
+(define_insn "mips_rsqrt1_<fmt>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
+ UNSPEC_RSQRT1))]
+ "TARGET_MIPS3D"
+ "rsqrt1.<fmt>\t%0,%1"
+ [(set_attr "type" "frsqrt1")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "mips_rsqrt2_<fmt>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f")]
+ UNSPEC_RSQRT2))]
+ "TARGET_MIPS3D"
+ "rsqrt2.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "frsqrt2")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "mips_recip1_<fmt>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")]
+ UNSPEC_RECIP1))]
+ "TARGET_MIPS3D"
+ "recip1.<fmt>\t%0,%1"
+ [(set_attr "type" "frdiv1")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "mips_recip2_<fmt>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (unspec:ANYF [(match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f")]
+ UNSPEC_RECIP2))]
+ "TARGET_MIPS3D"
+ "recip2.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "frdiv2")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_expand "vcondv2sf"
+ [(set (match_operand:V2SF 0 "register_operand")
+ (if_then_else:V2SF
+ (match_operator 3 ""
+ [(match_operand:V2SF 4 "register_operand")
+ (match_operand:V2SF 5 "register_operand")])
+ (match_operand:V2SF 1 "register_operand")
+ (match_operand:V2SF 2 "register_operand")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
+ GET_CODE (operands[3]), operands[4], operands[5]);
+ DONE;
+})
+
+(define_expand "sminv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand")
+ (smin:V2SF (match_operand:V2SF 1 "register_operand")
+ (match_operand:V2SF 2 "register_operand")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
+ LE, operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "smaxv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand")
+ (smax:V2SF (match_operand:V2SF 1 "register_operand")
+ (match_operand:V2SF 2 "register_operand")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ mips_expand_vcondv2sf (operands[0], operands[1], operands[2],
+ LE, operands[2], operands[1]);
+ DONE;
+})
diff --git a/contrib/gcc/config/mips/mips.c b/contrib/gcc/config/mips/mips.c
new file mode 100644
index 0000000..05498c2
--- /dev/null
+++ b/contrib/gcc/config/mips/mips.c
@@ -0,0 +1,10840 @@
+/* Subroutines used for MIPS code generation.
+ Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Contributed by A. Lichnewsky, lich@inria.inria.fr.
+ Changes by Michael Meissner, meissner@osf.org.
+ 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
+ Brendan Eich, brendan@microunity.com.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include <signal.h>
+#include "rtl.h"
+#include "regs.h"
+#include "hard-reg-set.h"
+#include "real.h"
+#include "insn-config.h"
+#include "conditions.h"
+#include "insn-attr.h"
+#include "recog.h"
+#include "toplev.h"
+#include "output.h"
+#include "tree.h"
+#include "function.h"
+#include "expr.h"
+#include "optabs.h"
+#include "flags.h"
+#include "reload.h"
+#include "tm_p.h"
+#include "ggc.h"
+#include "gstab.h"
+#include "hashtab.h"
+#include "debug.h"
+#include "target.h"
+#include "target-def.h"
+#include "integrate.h"
+#include "langhooks.h"
+#include "cfglayout.h"
+#include "sched-int.h"
+#include "tree-gimple.h"
+#include "bitmap.h"
+
+/* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */
+#define UNSPEC_ADDRESS_P(X) \
+ (GET_CODE (X) == UNSPEC \
+ && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \
+ && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES)
+
+/* Extract the symbol or label from UNSPEC wrapper X. */
+#define UNSPEC_ADDRESS(X) \
+ XVECEXP (X, 0, 0)
+
+/* Extract the symbol type from UNSPEC wrapper X. */
+#define UNSPEC_ADDRESS_TYPE(X) \
+ ((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST))
+
+/* The maximum distance between the top of the stack frame and the
+ value $sp has when we save & restore registers.
+
+ Use a maximum gap of 0x100 in the mips16 case. We can then use
+ unextended instructions to save and restore registers, and to
+ allocate and deallocate the top part of the frame.
+
+ The value in the !mips16 case must be a SMALL_OPERAND and must
+ preserve the maximum stack alignment. */
+#define MIPS_MAX_FIRST_STACK_STEP (TARGET_MIPS16 ? 0x100 : 0x7ff0)
+
+/* True if INSN is a mips.md pattern or asm statement. */
+#define USEFUL_INSN_P(INSN) \
+ (INSN_P (INSN) \
+ && GET_CODE (PATTERN (INSN)) != USE \
+ && GET_CODE (PATTERN (INSN)) != CLOBBER \
+ && GET_CODE (PATTERN (INSN)) != ADDR_VEC \
+ && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC)
+
+/* If INSN is a delayed branch sequence, return the first instruction
+ in the sequence, otherwise return INSN itself. */
+#define SEQ_BEGIN(INSN) \
+ (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
+ ? XVECEXP (PATTERN (INSN), 0, 0) \
+ : (INSN))
+
+/* Likewise for the last instruction in a delayed branch sequence. */
+#define SEQ_END(INSN) \
+ (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \
+ ? XVECEXP (PATTERN (INSN), 0, XVECLEN (PATTERN (INSN), 0) - 1) \
+ : (INSN))
+
+/* Execute the following loop body with SUBINSN set to each instruction
+ between SEQ_BEGIN (INSN) and SEQ_END (INSN) inclusive. */
+#define FOR_EACH_SUBINSN(SUBINSN, INSN) \
+ for ((SUBINSN) = SEQ_BEGIN (INSN); \
+ (SUBINSN) != NEXT_INSN (SEQ_END (INSN)); \
+ (SUBINSN) = NEXT_INSN (SUBINSN))
+
+/* Classifies an address.
+
+ ADDRESS_REG
+ A natural register + offset address. The register satisfies
+ mips_valid_base_register_p and the offset is a const_arith_operand.
+
+ ADDRESS_LO_SUM
+ A LO_SUM rtx. The first operand is a valid base register and
+ the second operand is a symbolic address.
+
+ ADDRESS_CONST_INT
+ A signed 16-bit constant address.
+
+ ADDRESS_SYMBOLIC:
+ A constant symbolic address (equivalent to CONSTANT_SYMBOLIC). */
+enum mips_address_type {
+ ADDRESS_REG,
+ ADDRESS_LO_SUM,
+ ADDRESS_CONST_INT,
+ ADDRESS_SYMBOLIC
+};
+
+/* Classifies the prototype of a builtin function. */
+enum mips_function_type
+{
+ MIPS_V2SF_FTYPE_V2SF,
+ MIPS_V2SF_FTYPE_V2SF_V2SF,
+ MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
+ MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF,
+ MIPS_V2SF_FTYPE_SF_SF,
+ MIPS_INT_FTYPE_V2SF_V2SF,
+ MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF,
+ MIPS_INT_FTYPE_SF_SF,
+ MIPS_INT_FTYPE_DF_DF,
+ MIPS_SF_FTYPE_V2SF,
+ MIPS_SF_FTYPE_SF,
+ MIPS_SF_FTYPE_SF_SF,
+ MIPS_DF_FTYPE_DF,
+ MIPS_DF_FTYPE_DF_DF,
+
+ /* For MIPS DSP ASE */
+ MIPS_DI_FTYPE_DI_SI,
+ MIPS_DI_FTYPE_DI_SI_SI,
+ MIPS_DI_FTYPE_DI_V2HI_V2HI,
+ MIPS_DI_FTYPE_DI_V4QI_V4QI,
+ MIPS_SI_FTYPE_DI_SI,
+ MIPS_SI_FTYPE_PTR_SI,
+ MIPS_SI_FTYPE_SI,
+ MIPS_SI_FTYPE_SI_SI,
+ MIPS_SI_FTYPE_V2HI,
+ MIPS_SI_FTYPE_V2HI_V2HI,
+ MIPS_SI_FTYPE_V4QI,
+ MIPS_SI_FTYPE_V4QI_V4QI,
+ MIPS_SI_FTYPE_VOID,
+ MIPS_V2HI_FTYPE_SI,
+ MIPS_V2HI_FTYPE_SI_SI,
+ MIPS_V2HI_FTYPE_V2HI,
+ MIPS_V2HI_FTYPE_V2HI_SI,
+ MIPS_V2HI_FTYPE_V2HI_V2HI,
+ MIPS_V2HI_FTYPE_V4QI,
+ MIPS_V2HI_FTYPE_V4QI_V2HI,
+ MIPS_V4QI_FTYPE_SI,
+ MIPS_V4QI_FTYPE_V2HI_V2HI,
+ MIPS_V4QI_FTYPE_V4QI_SI,
+ MIPS_V4QI_FTYPE_V4QI_V4QI,
+ MIPS_VOID_FTYPE_SI_SI,
+ MIPS_VOID_FTYPE_V2HI_V2HI,
+ MIPS_VOID_FTYPE_V4QI_V4QI,
+
+ /* The last type. */
+ MIPS_MAX_FTYPE_MAX
+};
+
+/* Specifies how a builtin function should be converted into rtl. */
+enum mips_builtin_type
+{
+ /* The builtin corresponds directly to an .md pattern. The return
+ value is mapped to operand 0 and the arguments are mapped to
+ operands 1 and above. */
+ MIPS_BUILTIN_DIRECT,
+
+ /* The builtin corresponds directly to an .md pattern. There is no return
+ value and the arguments are mapped to operands 0 and above. */
+ MIPS_BUILTIN_DIRECT_NO_TARGET,
+
+ /* The builtin corresponds to a comparison instruction followed by
+ a mips_cond_move_tf_ps pattern. The first two arguments are the
+ values to compare and the second two arguments are the vector
+ operands for the movt.ps or movf.ps instruction (in assembly order). */
+ MIPS_BUILTIN_MOVF,
+ MIPS_BUILTIN_MOVT,
+
+ /* The builtin corresponds to a V2SF comparison instruction. Operand 0
+ of this instruction is the result of the comparison, which has mode
+ CCV2 or CCV4. The function arguments are mapped to operands 1 and
+ above. The function's return value is an SImode boolean that is
+ true under the following conditions:
+
+ MIPS_BUILTIN_CMP_ANY: one of the registers is true
+ MIPS_BUILTIN_CMP_ALL: all of the registers are true
+ MIPS_BUILTIN_CMP_LOWER: the first register is true
+ MIPS_BUILTIN_CMP_UPPER: the second register is true. */
+ MIPS_BUILTIN_CMP_ANY,
+ MIPS_BUILTIN_CMP_ALL,
+ MIPS_BUILTIN_CMP_UPPER,
+ MIPS_BUILTIN_CMP_LOWER,
+
+ /* As above, but the instruction only sets a single $fcc register. */
+ MIPS_BUILTIN_CMP_SINGLE,
+
+ /* For generating bposge32 branch instructions in MIPS32 DSP ASE. */
+ MIPS_BUILTIN_BPOSGE32
+};
+
+/* Invokes MACRO (COND) for each c.cond.fmt condition. */
+#define MIPS_FP_CONDITIONS(MACRO) \
+ MACRO (f), \
+ MACRO (un), \
+ MACRO (eq), \
+ MACRO (ueq), \
+ MACRO (olt), \
+ MACRO (ult), \
+ MACRO (ole), \
+ MACRO (ule), \
+ MACRO (sf), \
+ MACRO (ngle), \
+ MACRO (seq), \
+ MACRO (ngl), \
+ MACRO (lt), \
+ MACRO (nge), \
+ MACRO (le), \
+ MACRO (ngt)
+
+/* Enumerates the codes above as MIPS_FP_COND_<X>. */
+#define DECLARE_MIPS_COND(X) MIPS_FP_COND_ ## X
+enum mips_fp_condition {
+ MIPS_FP_CONDITIONS (DECLARE_MIPS_COND)
+};
+
+/* Index X provides the string representation of MIPS_FP_COND_<X>. */
+#define STRINGIFY(X) #X
+static const char *const mips_fp_conditions[] = {
+ MIPS_FP_CONDITIONS (STRINGIFY)
+};
+
+/* A function to save or store a register. The first argument is the
+ register and the second is the stack slot. */
+typedef void (*mips_save_restore_fn) (rtx, rtx);
+
+struct mips16_constant;
+struct mips_arg_info;
+struct mips_address_info;
+struct mips_integer_op;
+struct mips_sim;
+
+static enum mips_symbol_type mips_classify_symbol (rtx);
+static void mips_split_const (rtx, rtx *, HOST_WIDE_INT *);
+static bool mips_offset_within_object_p (rtx, HOST_WIDE_INT);
+static bool mips_valid_base_register_p (rtx, enum machine_mode, int);
+static bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode);
+static bool mips_classify_address (struct mips_address_info *, rtx,
+ enum machine_mode, int);
+static bool mips_cannot_force_const_mem (rtx);
+static bool mips_use_blocks_for_constant_p (enum machine_mode, rtx);
+static int mips_symbol_insns (enum mips_symbol_type);
+static bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx);
+static rtx mips_force_temporary (rtx, rtx);
+static rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type);
+static rtx mips_add_offset (rtx, rtx, HOST_WIDE_INT);
+static unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT);
+static unsigned int mips_build_lower (struct mips_integer_op *,
+ unsigned HOST_WIDE_INT);
+static unsigned int mips_build_integer (struct mips_integer_op *,
+ unsigned HOST_WIDE_INT);
+static void mips_legitimize_const_move (enum machine_mode, rtx, rtx);
+static int m16_check_op (rtx, int, int, int);
+static bool mips_rtx_costs (rtx, int, int, int *);
+static int mips_address_cost (rtx);
+static void mips_emit_compare (enum rtx_code *, rtx *, rtx *, bool);
+static void mips_load_call_address (rtx, rtx, int);
+static bool mips_function_ok_for_sibcall (tree, tree);
+static void mips_block_move_straight (rtx, rtx, HOST_WIDE_INT);
+static void mips_adjust_block_mem (rtx, HOST_WIDE_INT, rtx *, rtx *);
+static void mips_block_move_loop (rtx, rtx, HOST_WIDE_INT);
+static void mips_arg_info (const CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int, struct mips_arg_info *);
+static bool mips_get_unaligned_mem (rtx *, unsigned int, int, rtx *, rtx *);
+static void mips_set_architecture (const struct mips_cpu_info *);
+static void mips_set_tune (const struct mips_cpu_info *);
+static bool mips_handle_option (size_t, const char *, int);
+static struct machine_function *mips_init_machine_status (void);
+static void print_operand_reloc (FILE *, rtx, const char **);
+#if TARGET_IRIX
+static void irix_output_external_libcall (rtx);
+#endif
+static void mips_file_start (void);
+static void mips_file_end (void);
+static bool mips_rewrite_small_data_p (rtx);
+static int mips_small_data_pattern_1 (rtx *, void *);
+static int mips_rewrite_small_data_1 (rtx *, void *);
+static bool mips_function_has_gp_insn (void);
+static unsigned int mips_global_pointer (void);
+static bool mips_save_reg_p (unsigned int);
+static void mips_save_restore_reg (enum machine_mode, int, HOST_WIDE_INT,
+ mips_save_restore_fn);
+static void mips_for_each_saved_reg (HOST_WIDE_INT, mips_save_restore_fn);
+static void mips_output_cplocal (void);
+static void mips_emit_loadgp (void);
+static void mips_output_function_prologue (FILE *, HOST_WIDE_INT);
+static void mips_set_frame_expr (rtx);
+static rtx mips_frame_set (rtx, rtx);
+static void mips_save_reg (rtx, rtx);
+static void mips_output_function_epilogue (FILE *, HOST_WIDE_INT);
+static void mips_restore_reg (rtx, rtx);
+static void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
+ HOST_WIDE_INT, tree);
+static int symbolic_expression_p (rtx);
+static section *mips_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
+static section *mips_function_rodata_section (tree);
+static bool mips_in_small_data_p (tree);
+static bool mips_use_anchors_for_symbol_p (rtx);
+static int mips_fpr_return_fields (tree, tree *);
+static bool mips_return_in_msb (tree);
+static rtx mips_return_fpr_pair (enum machine_mode mode,
+ enum machine_mode mode1, HOST_WIDE_INT,
+ enum machine_mode mode2, HOST_WIDE_INT);
+static rtx mips16_gp_pseudo_reg (void);
+static void mips16_fp_args (FILE *, int, int);
+static void build_mips16_function_stub (FILE *);
+static rtx dump_constants_1 (enum machine_mode, rtx, rtx);
+static void dump_constants (struct mips16_constant *, rtx);
+static int mips16_insn_length (rtx);
+static int mips16_rewrite_pool_refs (rtx *, void *);
+static void mips16_lay_out_constants (void);
+static void mips_sim_reset (struct mips_sim *);
+static void mips_sim_init (struct mips_sim *, state_t);
+static void mips_sim_next_cycle (struct mips_sim *);
+static void mips_sim_wait_reg (struct mips_sim *, rtx, rtx);
+static int mips_sim_wait_regs_2 (rtx *, void *);
+static void mips_sim_wait_regs_1 (rtx *, void *);
+static void mips_sim_wait_regs (struct mips_sim *, rtx);
+static void mips_sim_wait_units (struct mips_sim *, rtx);
+static void mips_sim_wait_insn (struct mips_sim *, rtx);
+static void mips_sim_record_set (rtx, rtx, void *);
+static void mips_sim_issue_insn (struct mips_sim *, rtx);
+static void mips_sim_issue_nop (struct mips_sim *);
+static void mips_sim_finish_insn (struct mips_sim *, rtx);
+static void vr4130_avoid_branch_rt_conflict (rtx);
+static void vr4130_align_insns (void);
+static void mips_avoid_hazard (rtx, rtx, int *, rtx *, rtx);
+static void mips_avoid_hazards (void);
+static void mips_reorg (void);
+static bool mips_strict_matching_cpu_name_p (const char *, const char *);
+static bool mips_matching_cpu_name_p (const char *, const char *);
+static const struct mips_cpu_info *mips_parse_cpu (const char *);
+static const struct mips_cpu_info *mips_cpu_info_from_isa (int);
+static bool mips_return_in_memory (tree, tree);
+static bool mips_strict_argument_naming (CUMULATIVE_ARGS *);
+static void mips_macc_chains_record (rtx);
+static void mips_macc_chains_reorder (rtx *, int);
+static void vr4130_true_reg_dependence_p_1 (rtx, rtx, void *);
+static bool vr4130_true_reg_dependence_p (rtx);
+static bool vr4130_swap_insns_p (rtx, rtx);
+static void vr4130_reorder (rtx *, int);
+static void mips_promote_ready (rtx *, int, int);
+static int mips_sched_reorder (FILE *, int, rtx *, int *, int);
+static int mips_variable_issue (FILE *, int, rtx, int);
+static int mips_adjust_cost (rtx, rtx, rtx, int);
+static int mips_issue_rate (void);
+static int mips_multipass_dfa_lookahead (void);
+static void mips_init_libfuncs (void);
+static void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, int *, int);
+static tree mips_build_builtin_va_list (void);
+static tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *);
+static bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode,
+ tree, bool);
+static bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode,
+ tree, bool);
+static int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode,
+ tree, bool);
+static bool mips_valid_pointer_mode (enum machine_mode);
+static bool mips_vector_mode_supported_p (enum machine_mode);
+static rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *);
+static rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx);
+static rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static void mips_init_builtins (void);
+static rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool);
+static rtx mips_expand_builtin_movtf (enum mips_builtin_type,
+ enum insn_code, enum mips_fp_condition,
+ rtx, tree);
+static rtx mips_expand_builtin_compare (enum mips_builtin_type,
+ enum insn_code, enum mips_fp_condition,
+ rtx, tree);
+static rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx);
+static void mips_encode_section_info (tree, rtx, int);
+static void mips_extra_live_on_entry (bitmap);
+static int mips_mode_rep_extended (enum machine_mode, enum machine_mode);
+
+/* Structure to be filled in by compute_frame_size with register
+ save masks, and offsets for the current function. */
+
+struct mips_frame_info GTY(())
+{
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
+ HOST_WIDE_INT var_size; /* # bytes that variables take up */
+ HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */
+ HOST_WIDE_INT cprestore_size; /* # bytes that the .cprestore slot takes up */
+ HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */
+ HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */
+ unsigned int mask; /* mask of saved gp registers */
+ unsigned int fmask; /* mask of saved fp registers */
+ HOST_WIDE_INT gp_save_offset; /* offset from vfp to store gp registers */
+ HOST_WIDE_INT fp_save_offset; /* offset from vfp to store fp registers */
+ HOST_WIDE_INT gp_sp_offset; /* offset from new sp to store gp registers */
+ HOST_WIDE_INT fp_sp_offset; /* offset from new sp to store fp registers */
+ bool initialized; /* true if frame size already calculated */
+ int num_gp; /* number of gp registers saved */
+ int num_fp; /* number of fp registers saved */
+};
+
+struct machine_function GTY(()) {
+ /* Pseudo-reg holding the value of $28 in a mips16 function which
+ refers to GP relative global variables. */
+ rtx mips16_gp_pseudo_rtx;
+
+ /* The number of extra stack bytes taken up by register varargs.
+ This area is allocated by the callee at the very top of the frame. */
+ int varargs_size;
+
+ /* Current frame information, calculated by compute_frame_size. */
+ struct mips_frame_info frame;
+
+ /* The register to use as the global pointer within this function. */
+ unsigned int global_pointer;
+
+ /* True if mips_adjust_insn_length should ignore an instruction's
+ hazard attribute. */
+ bool ignore_hazard_length_p;
+
+ /* True if the whole function is suitable for .set noreorder and
+ .set nomacro. */
+ bool all_noreorder_p;
+
+ /* True if the function is known to have an instruction that needs $gp. */
+ bool has_gp_insn_p;
+};
+
+/* Information about a single argument. */
+struct mips_arg_info
+{
+ /* True if the argument is passed in a floating-point register, or
+ would have been if we hadn't run out of registers. */
+ bool fpr_p;
+
+ /* The number of words passed in registers, rounded up. */
+ unsigned int reg_words;
+
+ /* For EABI, the offset of the first register from GP_ARG_FIRST or
+ FP_ARG_FIRST. For other ABIs, the offset of the first register from
+ the start of the ABI's argument structure (see the CUMULATIVE_ARGS
+ comment for details).
+
+ The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely
+ on the stack. */
+ unsigned int reg_offset;
+
+ /* The number of words that must be passed on the stack, rounded up. */
+ unsigned int stack_words;
+
+ /* The offset from the start of the stack overflow area of the argument's
+ first stack word. Only meaningful when STACK_WORDS is nonzero. */
+ unsigned int stack_offset;
+};
+
+
+/* Information about an address described by mips_address_type.
+
+ ADDRESS_CONST_INT
+ No fields are used.
+
+ ADDRESS_REG
+ REG is the base register and OFFSET is the constant offset.
+
+ ADDRESS_LO_SUM
+ REG is the register that contains the high part of the address,
+ OFFSET is the symbolic address being referenced and SYMBOL_TYPE
+ is the type of OFFSET's symbol.
+
+ ADDRESS_SYMBOLIC
+ SYMBOL_TYPE is the type of symbol being referenced. */
+
+struct mips_address_info
+{
+ enum mips_address_type type;
+ rtx reg;
+ rtx offset;
+ enum mips_symbol_type symbol_type;
+};
+
+
+/* One stage in a constant building sequence. These sequences have
+ the form:
+
+ A = VALUE[0]
+ A = A CODE[1] VALUE[1]
+ A = A CODE[2] VALUE[2]
+ ...
+
+ where A is an accumulator, each CODE[i] is a binary rtl operation
+ and each VALUE[i] is a constant integer. */
+struct mips_integer_op {
+ enum rtx_code code;
+ unsigned HOST_WIDE_INT value;
+};
+
+
+/* The largest number of operations needed to load an integer constant.
+ The worst accepted case for 64-bit constants is LUI,ORI,SLL,ORI,SLL,ORI.
+ When the lowest bit is clear, we can try, but reject a sequence with
+ an extra SLL at the end. */
+#define MIPS_MAX_INTEGER_OPS 7
+
+
+/* Global variables for machine-dependent things. */
+
+/* Threshold for data being put into the small data/bss area, instead
+ of the normal data area. */
+int mips_section_threshold = -1;
+
+/* Count the number of .file directives, so that .loc is up to date. */
+int num_source_filenames = 0;
+
+/* Count the number of sdb related labels are generated (to find block
+ start and end boundaries). */
+int sdb_label_count = 0;
+
+/* Next label # for each statement for Silicon Graphics IRIS systems. */
+int sym_lineno = 0;
+
+/* Linked list of all externals that are to be emitted when optimizing
+ for the global pointer if they haven't been declared by the end of
+ the program with an appropriate .comm or initialization. */
+
+struct extern_list GTY (())
+{
+ struct extern_list *next; /* next external */
+ const char *name; /* name of the external */
+ int size; /* size in bytes */
+};
+
+static GTY (()) struct extern_list *extern_head = 0;
+
+/* Name of the file containing the current function. */
+const char *current_function_file = "";
+
+/* Number of nested .set noreorder, noat, nomacro, and volatile requests. */
+int set_noreorder;
+int set_noat;
+int set_nomacro;
+int set_volatile;
+
+/* The next branch instruction is a branch likely, not branch normal. */
+int mips_branch_likely;
+
+/* The operands passed to the last cmpMM expander. */
+rtx cmp_operands[2];
+
+/* The target cpu for code generation. */
+enum processor_type mips_arch;
+const struct mips_cpu_info *mips_arch_info;
+
+/* The target cpu for optimization and scheduling. */
+enum processor_type mips_tune;
+const struct mips_cpu_info *mips_tune_info;
+
+/* Which instruction set architecture to use. */
+int mips_isa;
+
+/* Which ABI to use. */
+int mips_abi = MIPS_ABI_DEFAULT;
+
+/* Cost information to use. */
+const struct mips_rtx_cost_data *mips_cost;
+
+/* Whether we are generating mips16 hard float code. In mips16 mode
+ we always set TARGET_SOFT_FLOAT; this variable is nonzero if
+ -msoft-float was not specified by the user, which means that we
+ should arrange to call mips32 hard floating point code. */
+int mips16_hard_float;
+
+/* The architecture selected by -mipsN. */
+static const struct mips_cpu_info *mips_isa_info;
+
+/* If TRUE, we split addresses into their high and low parts in the RTL. */
+int mips_split_addresses;
+
+/* Mode used for saving/restoring general purpose registers. */
+static enum machine_mode gpr_mode;
+
+/* Array giving truth value on whether or not a given hard register
+ can support a given mode. */
+char mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
+
+/* List of all MIPS punctuation characters used by print_operand. */
+char mips_print_operand_punct[256];
+
+/* Map GCC register number to debugger register number. */
+int mips_dbx_regno[FIRST_PSEUDO_REGISTER];
+
+/* A copy of the original flag_delayed_branch: see override_options. */
+static int mips_flag_delayed_branch;
+
+static GTY (()) int mips_output_filename_first_time = 1;
+
+/* mips_split_p[X] is true if symbols of type X can be split by
+ mips_split_symbol(). */
+bool mips_split_p[NUM_SYMBOL_TYPES];
+
+/* mips_lo_relocs[X] is the relocation to use when a symbol of type X
+ appears in a LO_SUM. It can be null if such LO_SUMs aren't valid or
+ if they are matched by a special .md file pattern. */
+static const char *mips_lo_relocs[NUM_SYMBOL_TYPES];
+
+/* Likewise for HIGHs. */
+static const char *mips_hi_relocs[NUM_SYMBOL_TYPES];
+
+/* Map hard register number to register class */
+const enum reg_class mips_regno_to_class[] =
+{
+ LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG,
+ M16_REGS, M16_REGS, M16_REGS, M16_REGS,
+ LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
+ LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
+ M16_NA_REGS, M16_NA_REGS, LEA_REGS, LEA_REGS,
+ LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
+ T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS,
+ LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ FP_REGS, FP_REGS, FP_REGS, FP_REGS,
+ HI_REG, LO_REG, NO_REGS, ST_REGS,
+ ST_REGS, ST_REGS, ST_REGS, ST_REGS,
+ ST_REGS, ST_REGS, ST_REGS, NO_REGS,
+ NO_REGS, ALL_REGS, ALL_REGS, NO_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS,
+ DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS,
+ ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS
+};
+
+/* Table of machine dependent attributes. */
+const struct attribute_spec mips_attribute_table[] =
+{
+ { "long_call", 0, 0, false, true, true, NULL },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
+/* A table describing all the processors gcc knows about. Names are
+ matched in the order listed. The first mention of an ISA level is
+ taken as the canonical name for that ISA.
+
+ To ease comparison, please keep this table in the same order as
+ gas's mips_cpu_info_table[]. */
+const struct mips_cpu_info mips_cpu_info_table[] = {
+ /* Entries for generic ISAs */
+ { "mips1", PROCESSOR_R3000, 1 },
+ { "mips2", PROCESSOR_R6000, 2 },
+ { "mips3", PROCESSOR_R4000, 3 },
+ { "mips4", PROCESSOR_R8000, 4 },
+ { "mips32", PROCESSOR_4KC, 32 },
+ { "mips32r2", PROCESSOR_M4K, 33 },
+ { "mips64", PROCESSOR_5KC, 64 },
+
+ /* MIPS I */
+ { "r3000", PROCESSOR_R3000, 1 },
+ { "r2000", PROCESSOR_R3000, 1 }, /* = r3000 */
+ { "r3900", PROCESSOR_R3900, 1 },
+
+ /* MIPS II */
+ { "r6000", PROCESSOR_R6000, 2 },
+
+ /* MIPS III */
+ { "r4000", PROCESSOR_R4000, 3 },
+ { "vr4100", PROCESSOR_R4100, 3 },
+ { "vr4111", PROCESSOR_R4111, 3 },
+ { "vr4120", PROCESSOR_R4120, 3 },
+ { "vr4130", PROCESSOR_R4130, 3 },
+ { "vr4300", PROCESSOR_R4300, 3 },
+ { "r4400", PROCESSOR_R4000, 3 }, /* = r4000 */
+ { "r4600", PROCESSOR_R4600, 3 },
+ { "orion", PROCESSOR_R4600, 3 }, /* = r4600 */
+ { "r4650", PROCESSOR_R4650, 3 },
+
+ /* MIPS IV */
+ { "r8000", PROCESSOR_R8000, 4 },
+ { "vr5000", PROCESSOR_R5000, 4 },
+ { "vr5400", PROCESSOR_R5400, 4 },
+ { "vr5500", PROCESSOR_R5500, 4 },
+ { "rm7000", PROCESSOR_R7000, 4 },
+ { "rm9000", PROCESSOR_R9000, 4 },
+
+ /* MIPS32 */
+ { "4kc", PROCESSOR_4KC, 32 },
+ { "4km", PROCESSOR_4KC, 32 }, /* = 4kc */
+ { "4kp", PROCESSOR_4KP, 32 },
+
+ /* MIPS32 Release 2 */
+ { "m4k", PROCESSOR_M4K, 33 },
+ { "24k", PROCESSOR_24K, 33 },
+ { "24kc", PROCESSOR_24K, 33 }, /* 24K no FPU */
+ { "24kf", PROCESSOR_24K, 33 }, /* 24K 1:2 FPU */
+ { "24kx", PROCESSOR_24KX, 33 }, /* 24K 1:1 FPU */
+
+ /* MIPS64 */
+ { "5kc", PROCESSOR_5KC, 64 },
+ { "5kf", PROCESSOR_5KF, 64 },
+ { "20kc", PROCESSOR_20KC, 64 },
+ { "sb1", PROCESSOR_SB1, 64 },
+ { "sb1a", PROCESSOR_SB1A, 64 },
+ { "sr71000", PROCESSOR_SR71000, 64 },
+
+ /* End marker */
+ { 0, 0, 0 }
+};
+
+/* Default costs. If these are used for a processor we should look
+ up the actual costs. */
+#define DEFAULT_COSTS COSTS_N_INSNS (6), /* fp_add */ \
+ COSTS_N_INSNS (7), /* fp_mult_sf */ \
+ COSTS_N_INSNS (8), /* fp_mult_df */ \
+ COSTS_N_INSNS (23), /* fp_div_sf */ \
+ COSTS_N_INSNS (36), /* fp_div_df */ \
+ COSTS_N_INSNS (10), /* int_mult_si */ \
+ COSTS_N_INSNS (10), /* int_mult_di */ \
+ COSTS_N_INSNS (69), /* int_div_si */ \
+ COSTS_N_INSNS (69), /* int_div_di */ \
+ 2, /* branch_cost */ \
+ 4 /* memory_latency */
+
+/* Need to replace these with the costs of calling the appropriate
+ libgcc routine. */
+#define SOFT_FP_COSTS COSTS_N_INSNS (256), /* fp_add */ \
+ COSTS_N_INSNS (256), /* fp_mult_sf */ \
+ COSTS_N_INSNS (256), /* fp_mult_df */ \
+ COSTS_N_INSNS (256), /* fp_div_sf */ \
+ COSTS_N_INSNS (256) /* fp_div_df */
+
+static struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] =
+ {
+ { /* R3000 */
+ COSTS_N_INSNS (2), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (12), /* fp_div_sf */
+ COSTS_N_INSNS (19), /* fp_div_df */
+ COSTS_N_INSNS (12), /* int_mult_si */
+ COSTS_N_INSNS (12), /* int_mult_di */
+ COSTS_N_INSNS (35), /* int_div_si */
+ COSTS_N_INSNS (35), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+
+ },
+ { /* 4KC */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (6), /* int_mult_si */
+ COSTS_N_INSNS (6), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (36), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 4KP */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (36), /* int_mult_si */
+ COSTS_N_INSNS (36), /* int_mult_di */
+ COSTS_N_INSNS (37), /* int_div_si */
+ COSTS_N_INSNS (37), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 5KC */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (11), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 5KF */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (11), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 20KC */
+ DEFAULT_COSTS
+ },
+ { /* 24k */
+ COSTS_N_INSNS (8), /* fp_add */
+ COSTS_N_INSNS (8), /* fp_mult_sf */
+ COSTS_N_INSNS (10), /* fp_mult_df */
+ COSTS_N_INSNS (34), /* fp_div_sf */
+ COSTS_N_INSNS (64), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (41), /* int_div_si */
+ COSTS_N_INSNS (41), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* 24kx */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (17), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (41), /* int_div_si */
+ COSTS_N_INSNS (41), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* M4k */
+ DEFAULT_COSTS
+ },
+ { /* R3900 */
+ COSTS_N_INSNS (2), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (12), /* fp_div_sf */
+ COSTS_N_INSNS (19), /* fp_div_df */
+ COSTS_N_INSNS (2), /* int_mult_si */
+ COSTS_N_INSNS (2), /* int_mult_di */
+ COSTS_N_INSNS (35), /* int_div_si */
+ COSTS_N_INSNS (35), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R6000 */
+ COSTS_N_INSNS (3), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (15), /* fp_div_sf */
+ COSTS_N_INSNS (16), /* fp_div_df */
+ COSTS_N_INSNS (17), /* int_mult_si */
+ COSTS_N_INSNS (17), /* int_mult_di */
+ COSTS_N_INSNS (38), /* int_div_si */
+ COSTS_N_INSNS (38), /* int_div_di */
+ 2, /* branch_cost */
+ 6 /* memory_latency */
+ },
+ { /* R4000 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (10), /* int_mult_si */
+ COSTS_N_INSNS (10), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 2, /* branch_cost */
+ 6 /* memory_latency */
+ },
+ { /* R4100 */
+ DEFAULT_COSTS
+ },
+ { /* R4111 */
+ DEFAULT_COSTS
+ },
+ { /* R4120 */
+ DEFAULT_COSTS
+ },
+ { /* R4130 */
+ /* The only costs that appear to be updated here are
+ integer multiplication. */
+ SOFT_FP_COSTS,
+ COSTS_N_INSNS (4), /* int_mult_si */
+ COSTS_N_INSNS (6), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R4300 */
+ DEFAULT_COSTS
+ },
+ { /* R4600 */
+ DEFAULT_COSTS
+ },
+ { /* R4650 */
+ DEFAULT_COSTS
+ },
+ { /* R5000 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (5), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (5), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (36), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R5400 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (30), /* fp_div_sf */
+ COSTS_N_INSNS (59), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (42), /* int_div_si */
+ COSTS_N_INSNS (74), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R5500 */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (5), /* fp_mult_sf */
+ COSTS_N_INSNS (6), /* fp_mult_df */
+ COSTS_N_INSNS (30), /* fp_div_sf */
+ COSTS_N_INSNS (59), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (9), /* int_mult_di */
+ COSTS_N_INSNS (42), /* int_div_si */
+ COSTS_N_INSNS (74), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R7000 */
+ /* The only costs that are changed here are
+ integer multiplication. */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (5), /* int_mult_si */
+ COSTS_N_INSNS (9), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* R8000 */
+ DEFAULT_COSTS
+ },
+ { /* R9000 */
+ /* The only costs that are changed here are
+ integer multiplication. */
+ COSTS_N_INSNS (6), /* fp_add */
+ COSTS_N_INSNS (7), /* fp_mult_sf */
+ COSTS_N_INSNS (8), /* fp_mult_df */
+ COSTS_N_INSNS (23), /* fp_div_sf */
+ COSTS_N_INSNS (36), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (8), /* int_mult_di */
+ COSTS_N_INSNS (69), /* int_div_si */
+ COSTS_N_INSNS (69), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* SB1 */
+ /* These costs are the same as the SB-1A below. */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (4), /* fp_mult_df */
+ COSTS_N_INSNS (24), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* SB1-A */
+ /* These costs are the same as the SB-1 above. */
+ COSTS_N_INSNS (4), /* fp_add */
+ COSTS_N_INSNS (4), /* fp_mult_sf */
+ COSTS_N_INSNS (4), /* fp_mult_df */
+ COSTS_N_INSNS (24), /* fp_div_sf */
+ COSTS_N_INSNS (32), /* fp_div_df */
+ COSTS_N_INSNS (3), /* int_mult_si */
+ COSTS_N_INSNS (4), /* int_mult_di */
+ COSTS_N_INSNS (36), /* int_div_si */
+ COSTS_N_INSNS (68), /* int_div_di */
+ 1, /* branch_cost */
+ 4 /* memory_latency */
+ },
+ { /* SR71000 */
+ DEFAULT_COSTS
+ },
+ };
+
+
+/* Nonzero if -march should decide the default value of MASK_SOFT_FLOAT. */
+#ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT
+#define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0
+#endif
+
+/* Initialize the GCC target structure. */
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
+#undef TARGET_ASM_ALIGNED_SI_OP
+#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
+#undef TARGET_ASM_ALIGNED_DI_OP
+#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
+
+#undef TARGET_ASM_FUNCTION_PROLOGUE
+#define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
+#undef TARGET_ASM_FUNCTION_EPILOGUE
+#define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue
+#undef TARGET_ASM_SELECT_RTX_SECTION
+#define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section
+#undef TARGET_ASM_FUNCTION_RODATA_SECTION
+#define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section
+
+#undef TARGET_SCHED_REORDER
+#define TARGET_SCHED_REORDER mips_sched_reorder
+#undef TARGET_SCHED_VARIABLE_ISSUE
+#define TARGET_SCHED_VARIABLE_ISSUE mips_variable_issue
+#undef TARGET_SCHED_ADJUST_COST
+#define TARGET_SCHED_ADJUST_COST mips_adjust_cost
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE mips_issue_rate
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \
+ mips_multipass_dfa_lookahead
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (TARGET_DEFAULT \
+ | TARGET_CPU_DEFAULT \
+ | TARGET_ENDIAN_DEFAULT \
+ | TARGET_FP_EXCEPTIONS_DEFAULT \
+ | MASK_CHECK_ZERO_DIV \
+ | MASK_FUSED_MADD)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION mips_handle_option
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall
+
+#undef TARGET_VALID_POINTER_MODE
+#define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS mips_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST mips_address_cost
+
+#undef TARGET_IN_SMALL_DATA_P
+#define TARGET_IN_SMALL_DATA_P mips_in_small_data_p
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG mips_reorg
+
+#undef TARGET_ASM_FILE_START
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_START mips_file_start
+#define TARGET_ASM_FILE_END mips_file_end
+#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE
+#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS mips_init_libfuncs
+
+#undef TARGET_BUILD_BUILTIN_VA_LIST
+#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr
+
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY mips_return_in_memory
+#undef TARGET_RETURN_IN_MSB
+#define TARGET_RETURN_IN_MSB mips_return_in_msb
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK mips_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS mips_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING mips_strict_argument_naming
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE mips_pass_by_reference
+#undef TARGET_CALLEE_COPIES
+#define TARGET_CALLEE_COPIES mips_callee_copies
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes
+
+#undef TARGET_MODE_REP_EXTENDED
+#define TARGET_MODE_REP_EXTENDED mips_mode_rep_extended
+
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS mips_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN mips_expand_builtin
+
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS HAVE_AS_TLS
+
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO mips_encode_section_info
+
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE mips_attribute_table
+
+#undef TARGET_EXTRA_LIVE_ON_ENTRY
+#define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry
+
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET -32768
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET 32767
+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P mips_use_blocks_for_constant_p
+#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
+#define TARGET_USE_ANCHORS_FOR_SYMBOL_P mips_use_anchors_for_symbol_p
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */
+
+static enum mips_symbol_type
+mips_classify_symbol (rtx x)
+{
+ if (GET_CODE (x) == LABEL_REF)
+ {
+ if (TARGET_MIPS16)
+ return SYMBOL_CONSTANT_POOL;
+ if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
+ return SYMBOL_GOT_LOCAL;
+ return SYMBOL_GENERAL;
+ }
+
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
+
+ if (SYMBOL_REF_TLS_MODEL (x))
+ return SYMBOL_TLS;
+
+ if (CONSTANT_POOL_ADDRESS_P (x))
+ {
+ if (TARGET_MIPS16)
+ return SYMBOL_CONSTANT_POOL;
+
+ if (GET_MODE_SIZE (get_pool_mode (x)) <= mips_section_threshold)
+ return SYMBOL_SMALL_DATA;
+ }
+
+ /* Do not use small-data accesses for weak symbols; they may end up
+ being zero. */
+ if (SYMBOL_REF_SMALL_P (x)
+ && !SYMBOL_REF_WEAK (x))
+ return SYMBOL_SMALL_DATA;
+
+ if (TARGET_ABICALLS)
+ {
+ if (SYMBOL_REF_DECL (x) == 0)
+ {
+ if (!SYMBOL_REF_LOCAL_P (x))
+ return SYMBOL_GOT_GLOBAL;
+ }
+ else
+ {
+ /* Don't use GOT accesses for locally-binding symbols if
+ TARGET_ABSOLUTE_ABICALLS. Otherwise, there are three
+ cases to consider:
+
+ - o32 PIC (either with or without explicit relocs)
+ - n32/n64 PIC without explicit relocs
+ - n32/n64 PIC with explicit relocs
+
+ In the first case, both local and global accesses will use an
+ R_MIPS_GOT16 relocation. We must correctly predict which of
+ the two semantics (local or global) the assembler and linker
+ will apply. The choice doesn't depend on the symbol's
+ visibility, so we deliberately ignore decl_visibility and
+ binds_local_p here.
+
+ In the second case, the assembler will not use R_MIPS_GOT16
+ relocations, but it chooses between local and global accesses
+ in the same way as for o32 PIC.
+
+ In the third case we have more freedom since both forms of
+ access will work for any kind of symbol. However, there seems
+ little point in doing things differently. */
+ if (DECL_P (SYMBOL_REF_DECL (x))
+ && TREE_PUBLIC (SYMBOL_REF_DECL (x))
+ && !(TARGET_ABSOLUTE_ABICALLS
+ && targetm.binds_local_p (SYMBOL_REF_DECL (x))))
+ return SYMBOL_GOT_GLOBAL;
+ }
+
+ if (!TARGET_ABSOLUTE_ABICALLS)
+ return SYMBOL_GOT_LOCAL;
+ }
+
+ return SYMBOL_GENERAL;
+}
+
+
+/* Split X into a base and a constant offset, storing them in *BASE
+ and *OFFSET respectively. */
+
+static void
+mips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset)
+{
+ *offset = 0;
+
+ if (GET_CODE (x) == CONST)
+ {
+ x = XEXP (x, 0);
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ *offset += INTVAL (XEXP (x, 1));
+ x = XEXP (x, 0);
+ }
+ }
+ *base = x;
+}
+
+
+/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points
+ to the same object as SYMBOL, or to the same object_block. */
+
+static bool
+mips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset)
+{
+ if (GET_CODE (symbol) != SYMBOL_REF)
+ return false;
+
+ if (CONSTANT_POOL_ADDRESS_P (symbol)
+ && offset >= 0
+ && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol)))
+ return true;
+
+ if (SYMBOL_REF_DECL (symbol) != 0
+ && offset >= 0
+ && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol))))
+ return true;
+
+ if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol)
+ && SYMBOL_REF_BLOCK (symbol)
+ && SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0
+ && ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol)
+ < (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size))
+ return true;
+
+ return false;
+}
+
+
+/* Return true if X is a symbolic constant that can be calculated in
+ the same way as a bare symbol. If it is, store the type of the
+ symbol in *SYMBOL_TYPE. */
+
+bool
+mips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type)
+{
+ HOST_WIDE_INT offset;
+
+ mips_split_const (x, &x, &offset);
+ if (UNSPEC_ADDRESS_P (x))
+ *symbol_type = UNSPEC_ADDRESS_TYPE (x);
+ else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF)
+ {
+ *symbol_type = mips_classify_symbol (x);
+ if (*symbol_type == SYMBOL_TLS)
+ return false;
+ }
+ else
+ return false;
+
+ if (offset == 0)
+ return true;
+
+ /* Check whether a nonzero offset is valid for the underlying
+ relocations. */
+ switch (*symbol_type)
+ {
+ case SYMBOL_GENERAL:
+ case SYMBOL_64_HIGH:
+ case SYMBOL_64_MID:
+ case SYMBOL_64_LOW:
+ /* If the target has 64-bit pointers and the object file only
+ supports 32-bit symbols, the values of those symbols will be
+ sign-extended. In this case we can't allow an arbitrary offset
+ in case the 32-bit value X + OFFSET has a different sign from X. */
+ if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS)
+ return mips_offset_within_object_p (x, offset);
+
+ /* In other cases the relocations can handle any offset. */
+ return true;
+
+ case SYMBOL_CONSTANT_POOL:
+ /* Allow constant pool references to be converted to LABEL+CONSTANT.
+ In this case, we no longer have access to the underlying constant,
+ but the original symbol-based access was known to be valid. */
+ if (GET_CODE (x) == LABEL_REF)
+ return true;
+
+ /* Fall through. */
+
+ case SYMBOL_SMALL_DATA:
+ /* Make sure that the offset refers to something within the
+ underlying object. This should guarantee that the final
+ PC- or GP-relative offset is within the 16-bit limit. */
+ return mips_offset_within_object_p (x, offset);
+
+ case SYMBOL_GOT_LOCAL:
+ case SYMBOL_GOTOFF_PAGE:
+ /* The linker should provide enough local GOT entries for a
+ 16-bit offset. Larger offsets may lead to GOT overflow. */
+ return SMALL_OPERAND (offset);
+
+ case SYMBOL_GOT_GLOBAL:
+ case SYMBOL_GOTOFF_GLOBAL:
+ case SYMBOL_GOTOFF_CALL:
+ case SYMBOL_GOTOFF_LOADGP:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_TPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TLS:
+ return false;
+ }
+ gcc_unreachable ();
+}
+
+
+/* This function is used to implement REG_MODE_OK_FOR_BASE_P. */
+
+int
+mips_regno_mode_ok_for_base_p (int regno, enum machine_mode mode, int strict)
+{
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ {
+ if (!strict)
+ return true;
+ regno = reg_renumber[regno];
+ }
+
+ /* These fake registers will be eliminated to either the stack or
+ hard frame pointer, both of which are usually valid base registers.
+ Reload deals with the cases where the eliminated form isn't valid. */
+ if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM)
+ return true;
+
+ /* In mips16 mode, the stack pointer can only address word and doubleword
+ values, nothing smaller. There are two problems here:
+
+ (a) Instantiating virtual registers can introduce new uses of the
+ stack pointer. If these virtual registers are valid addresses,
+ the stack pointer should be too.
+
+ (b) Most uses of the stack pointer are not made explicit until
+ FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM have been eliminated.
+ We don't know until that stage whether we'll be eliminating to the
+ stack pointer (which needs the restriction) or the hard frame
+ pointer (which doesn't).
+
+ All in all, it seems more consistent to only enforce this restriction
+ during and after reload. */
+ if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM)
+ return !strict || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+
+ return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
+}
+
+
+/* Return true if X is a valid base register for the given mode.
+ Allow only hard registers if STRICT. */
+
+static bool
+mips_valid_base_register_p (rtx x, enum machine_mode mode, int strict)
+{
+ if (!strict && GET_CODE (x) == SUBREG)
+ x = SUBREG_REG (x);
+
+ return (REG_P (x)
+ && mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict));
+}
+
+
+/* Return true if symbols of type SYMBOL_TYPE can directly address a value
+ with mode MODE. This is used for both symbolic and LO_SUM addresses. */
+
+static bool
+mips_symbolic_address_p (enum mips_symbol_type symbol_type,
+ enum machine_mode mode)
+{
+ switch (symbol_type)
+ {
+ case SYMBOL_GENERAL:
+ return !TARGET_MIPS16;
+
+ case SYMBOL_SMALL_DATA:
+ return true;
+
+ case SYMBOL_CONSTANT_POOL:
+ /* PC-relative addressing is only available for lw and ld. */
+ return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8;
+
+ case SYMBOL_GOT_LOCAL:
+ return true;
+
+ case SYMBOL_GOT_GLOBAL:
+ /* The address will have to be loaded from the GOT first. */
+ return false;
+
+ case SYMBOL_GOTOFF_PAGE:
+ case SYMBOL_GOTOFF_GLOBAL:
+ case SYMBOL_GOTOFF_CALL:
+ case SYMBOL_GOTOFF_LOADGP:
+ case SYMBOL_TLS:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TPREL:
+ case SYMBOL_64_HIGH:
+ case SYMBOL_64_MID:
+ case SYMBOL_64_LOW:
+ return true;
+ }
+ gcc_unreachable ();
+}
+
+
+/* Return true if X is a valid address for machine mode MODE. If it is,
+ fill in INFO appropriately. STRICT is true if we should only accept
+ hard base registers. */
+
+static bool
+mips_classify_address (struct mips_address_info *info, rtx x,
+ enum machine_mode mode, int strict)
+{
+ switch (GET_CODE (x))
+ {
+ case REG:
+ case SUBREG:
+ info->type = ADDRESS_REG;
+ info->reg = x;
+ info->offset = const0_rtx;
+ return mips_valid_base_register_p (info->reg, mode, strict);
+
+ case PLUS:
+ info->type = ADDRESS_REG;
+ info->reg = XEXP (x, 0);
+ info->offset = XEXP (x, 1);
+ return (mips_valid_base_register_p (info->reg, mode, strict)
+ && const_arith_operand (info->offset, VOIDmode));
+
+ case LO_SUM:
+ info->type = ADDRESS_LO_SUM;
+ info->reg = XEXP (x, 0);
+ info->offset = XEXP (x, 1);
+ return (mips_valid_base_register_p (info->reg, mode, strict)
+ && mips_symbolic_constant_p (info->offset, &info->symbol_type)
+ && mips_symbolic_address_p (info->symbol_type, mode)
+ && mips_lo_relocs[info->symbol_type] != 0);
+
+ case CONST_INT:
+ /* Small-integer addresses don't occur very often, but they
+ are legitimate if $0 is a valid base register. */
+ info->type = ADDRESS_CONST_INT;
+ return !TARGET_MIPS16 && SMALL_INT (x);
+
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ info->type = ADDRESS_SYMBOLIC;
+ return (mips_symbolic_constant_p (x, &info->symbol_type)
+ && mips_symbolic_address_p (info->symbol_type, mode)
+ && !mips_split_p[info->symbol_type]);
+
+ default:
+ return false;
+ }
+}
+
+/* Return true if X is a thread-local symbol. */
+
+static bool
+mips_tls_operand_p (rtx x)
+{
+ return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+/* Return true if X can not be forced into a constant pool. */
+
+static int
+mips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ return mips_tls_operand_p (*x);
+}
+
+/* Return true if X can not be forced into a constant pool. */
+
+static bool
+mips_cannot_force_const_mem (rtx x)
+{
+ rtx base;
+ HOST_WIDE_INT offset;
+
+ if (!TARGET_MIPS16)
+ {
+ /* As an optimization, reject constants that mips_legitimize_move
+ can expand inline.
+
+ Suppose we have a multi-instruction sequence that loads constant C
+ into register R. If R does not get allocated a hard register, and
+ R is used in an operand that allows both registers and memory
+ references, reload will consider forcing C into memory and using
+ one of the instruction's memory alternatives. Returning false
+ here will force it to use an input reload instead. */
+ if (GET_CODE (x) == CONST_INT)
+ return true;
+
+ mips_split_const (x, &base, &offset);
+ if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset))
+ return true;
+ }
+
+ if (TARGET_HAVE_TLS && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0))
+ return true;
+
+ return false;
+}
+
+/* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P. MIPS16 uses per-function
+ constant pools, but normal-mode code doesn't need to. */
+
+static bool
+mips_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx x ATTRIBUTE_UNUSED)
+{
+ return !TARGET_MIPS16;
+}
+
+/* Return the number of instructions needed to load a symbol of the
+ given type into a register. If valid in an address, the same number
+ of instructions are needed for loads and stores. Treat extended
+ mips16 instructions as two instructions. */
+
+static int
+mips_symbol_insns (enum mips_symbol_type type)
+{
+ switch (type)
+ {
+ case SYMBOL_GENERAL:
+ /* In mips16 code, general symbols must be fetched from the
+ constant pool. */
+ if (TARGET_MIPS16)
+ return 0;
+
+ /* When using 64-bit symbols, we need 5 preparatory instructions,
+ such as:
+
+ lui $at,%highest(symbol)
+ daddiu $at,$at,%higher(symbol)
+ dsll $at,$at,16
+ daddiu $at,$at,%hi(symbol)
+ dsll $at,$at,16
+
+ The final address is then $at + %lo(symbol). With 32-bit
+ symbols we just need a preparatory lui. */
+ return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2);
+
+ case SYMBOL_SMALL_DATA:
+ return 1;
+
+ case SYMBOL_CONSTANT_POOL:
+ /* This case is for mips16 only. Assume we'll need an
+ extended instruction. */
+ return 2;
+
+ case SYMBOL_GOT_LOCAL:
+ case SYMBOL_GOT_GLOBAL:
+ /* Unless -funit-at-a-time is in effect, we can't be sure whether
+ the local/global classification is accurate. See override_options
+ for details.
+
+ The worst cases are:
+
+ (1) For local symbols when generating o32 or o64 code. The assembler
+ will use:
+
+ lw $at,%got(symbol)
+ nop
+
+ ...and the final address will be $at + %lo(symbol).
+
+ (2) For global symbols when -mxgot. The assembler will use:
+
+ lui $at,%got_hi(symbol)
+ (d)addu $at,$at,$gp
+
+ ...and the final address will be $at + %got_lo(symbol). */
+ return 3;
+
+ case SYMBOL_GOTOFF_PAGE:
+ case SYMBOL_GOTOFF_GLOBAL:
+ case SYMBOL_GOTOFF_CALL:
+ case SYMBOL_GOTOFF_LOADGP:
+ case SYMBOL_64_HIGH:
+ case SYMBOL_64_MID:
+ case SYMBOL_64_LOW:
+ case SYMBOL_TLSGD:
+ case SYMBOL_TLSLDM:
+ case SYMBOL_DTPREL:
+ case SYMBOL_GOTTPREL:
+ case SYMBOL_TPREL:
+ /* Check whether the offset is a 16- or 32-bit value. */
+ return mips_split_p[type] ? 2 : 1;
+
+ case SYMBOL_TLS:
+ /* We don't treat a bare TLS symbol as a constant. */
+ return 0;
+ }
+ gcc_unreachable ();
+}
+
+/* Return true if X is a legitimate $sp-based address for mode MDOE. */
+
+bool
+mips_stack_address_p (rtx x, enum machine_mode mode)
+{
+ struct mips_address_info addr;
+
+ return (mips_classify_address (&addr, x, mode, false)
+ && addr.type == ADDRESS_REG
+ && addr.reg == stack_pointer_rtx);
+}
+
+/* Return true if a value at OFFSET bytes from BASE can be accessed
+ using an unextended mips16 instruction. MODE is the mode of the
+ value.
+
+ Usually the offset in an unextended instruction is a 5-bit field.
+ The offset is unsigned and shifted left once for HIs, twice
+ for SIs, and so on. An exception is SImode accesses off the
+ stack pointer, which have an 8-bit immediate field. */
+
+static bool
+mips16_unextended_reference_p (enum machine_mode mode, rtx base, rtx offset)
+{
+ if (TARGET_MIPS16
+ && GET_CODE (offset) == CONST_INT
+ && INTVAL (offset) >= 0
+ && (INTVAL (offset) & (GET_MODE_SIZE (mode) - 1)) == 0)
+ {
+ if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
+ return INTVAL (offset) < 256 * GET_MODE_SIZE (mode);
+ return INTVAL (offset) < 32 * GET_MODE_SIZE (mode);
+ }
+ return false;
+}
+
+
+/* Return the number of instructions needed to load or store a value
+ of mode MODE at X. Return 0 if X isn't valid for MODE.
+
+ For mips16 code, count extended instructions as two instructions. */
+
+int
+mips_address_insns (rtx x, enum machine_mode mode)
+{
+ struct mips_address_info addr;
+ int factor;
+
+ if (mode == BLKmode)
+ /* BLKmode is used for single unaligned loads and stores. */
+ factor = 1;
+ else
+ /* Each word of a multi-word value will be accessed individually. */
+ factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+ if (mips_classify_address (&addr, x, mode, false))
+ switch (addr.type)
+ {
+ case ADDRESS_REG:
+ if (TARGET_MIPS16
+ && !mips16_unextended_reference_p (mode, addr.reg, addr.offset))
+ return factor * 2;
+ return factor;
+
+ case ADDRESS_LO_SUM:
+ return (TARGET_MIPS16 ? factor * 2 : factor);
+
+ case ADDRESS_CONST_INT:
+ return factor;
+
+ case ADDRESS_SYMBOLIC:
+ return factor * mips_symbol_insns (addr.symbol_type);
+ }
+ return 0;
+}
+
+
+/* Likewise for constant X. */
+
+int
+mips_const_insns (rtx x)
+{
+ struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
+ enum mips_symbol_type symbol_type;
+ HOST_WIDE_INT offset;
+
+ switch (GET_CODE (x))
+ {
+ case HIGH:
+ if (TARGET_MIPS16
+ || !mips_symbolic_constant_p (XEXP (x, 0), &symbol_type)
+ || !mips_split_p[symbol_type])
+ return 0;
+
+ return 1;
+
+ case CONST_INT:
+ if (TARGET_MIPS16)
+ /* Unsigned 8-bit constants can be loaded using an unextended
+ LI instruction. Unsigned 16-bit constants can be loaded
+ using an extended LI. Negative constants must be loaded
+ using LI and then negated. */
+ return (INTVAL (x) >= 0 && INTVAL (x) < 256 ? 1
+ : SMALL_OPERAND_UNSIGNED (INTVAL (x)) ? 2
+ : INTVAL (x) > -256 && INTVAL (x) < 0 ? 2
+ : SMALL_OPERAND_UNSIGNED (-INTVAL (x)) ? 3
+ : 0);
+
+ return mips_build_integer (codes, INTVAL (x));
+
+ case CONST_DOUBLE:
+ case CONST_VECTOR:
+ return (!TARGET_MIPS16 && x == CONST0_RTX (GET_MODE (x)) ? 1 : 0);
+
+ case CONST:
+ if (CONST_GP_P (x))
+ return 1;
+
+ /* See if we can refer to X directly. */
+ if (mips_symbolic_constant_p (x, &symbol_type))
+ return mips_symbol_insns (symbol_type);
+
+ /* Otherwise try splitting the constant into a base and offset.
+ 16-bit offsets can be added using an extra addiu. Larger offsets
+ must be calculated separately and then added to the base. */
+ mips_split_const (x, &x, &offset);
+ if (offset != 0)
+ {
+ int n = mips_const_insns (x);
+ if (n != 0)
+ {
+ if (SMALL_OPERAND (offset))
+ return n + 1;
+ else
+ return n + 1 + mips_build_integer (codes, offset);
+ }
+ }
+ return 0;
+
+ case SYMBOL_REF:
+ case LABEL_REF:
+ return mips_symbol_insns (mips_classify_symbol (x));
+
+ default:
+ return 0;
+ }
+}
+
+
+/* Return the number of instructions needed for memory reference X.
+ Count extended mips16 instructions as two instructions. */
+
+int
+mips_fetch_insns (rtx x)
+{
+ gcc_assert (MEM_P (x));
+ return mips_address_insns (XEXP (x, 0), GET_MODE (x));
+}
+
+
+/* Return the number of instructions needed for an integer division. */
+
+int
+mips_idiv_insns (void)
+{
+ int count;
+
+ count = 1;
+ if (TARGET_CHECK_ZERO_DIV)
+ {
+ if (GENERATE_DIVIDE_TRAPS)
+ count++;
+ else
+ count += 2;
+ }
+
+ if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
+ count++;
+ return count;
+}
+
+/* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It
+ returns a nonzero value if X is a legitimate address for a memory
+ operand of the indicated MODE. STRICT is nonzero if this function
+ is called during reload. */
+
+bool
+mips_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
+{
+ struct mips_address_info addr;
+
+ return mips_classify_address (&addr, x, mode, strict);
+}
+
+
+/* Copy VALUE to a register and return that register. If new psuedos
+ are allowed, copy it into a new register, otherwise use DEST. */
+
+static rtx
+mips_force_temporary (rtx dest, rtx value)
+{
+ if (!no_new_pseudos)
+ return force_reg (Pmode, value);
+ else
+ {
+ emit_move_insn (copy_rtx (dest), value);
+ return dest;
+ }
+}
+
+
+/* Return a LO_SUM expression for ADDR. TEMP is as for mips_force_temporary
+ and is used to load the high part into a register. */
+
+rtx
+mips_split_symbol (rtx temp, rtx addr)
+{
+ rtx high;
+
+ if (TARGET_MIPS16)
+ high = mips16_gp_pseudo_reg ();
+ else
+ high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr)));
+ return gen_rtx_LO_SUM (Pmode, high, addr);
+}
+
+
+/* Return an UNSPEC address with underlying address ADDRESS and symbol
+ type SYMBOL_TYPE. */
+
+rtx
+mips_unspec_address (rtx address, enum mips_symbol_type symbol_type)
+{
+ rtx base;
+ HOST_WIDE_INT offset;
+
+ mips_split_const (address, &base, &offset);
+ base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base),
+ UNSPEC_ADDRESS_FIRST + symbol_type);
+ return plus_constant (gen_rtx_CONST (Pmode, base), offset);
+}
+
+
+/* If mips_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the
+ high part to BASE and return the result. Just return BASE otherwise.
+ TEMP is available as a temporary register if needed.
+
+ The returned expression can be used as the first operand to a LO_SUM. */
+
+static rtx
+mips_unspec_offset_high (rtx temp, rtx base, rtx addr,
+ enum mips_symbol_type symbol_type)
+{
+ if (mips_split_p[symbol_type])
+ {
+ addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type));
+ addr = mips_force_temporary (temp, addr);
+ return mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base));
+ }
+ return base;
+}
+
+
+/* Return a legitimate address for REG + OFFSET. TEMP is as for
+ mips_force_temporary; it is only needed when OFFSET is not a
+ SMALL_OPERAND. */
+
+static rtx
+mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
+{
+ if (!SMALL_OPERAND (offset))
+ {
+ rtx high;
+ if (TARGET_MIPS16)
+ {
+ /* Load the full offset into a register so that we can use
+ an unextended instruction for the address itself. */
+ high = GEN_INT (offset);
+ offset = 0;
+ }
+ else
+ {
+ /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. */
+ high = GEN_INT (CONST_HIGH_PART (offset));
+ offset = CONST_LOW_PART (offset);
+ }
+ high = mips_force_temporary (temp, high);
+ reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg));
+ }
+ return plus_constant (reg, offset);
+}
+
+/* Emit a call to __tls_get_addr. SYM is the TLS symbol we are
+ referencing, and TYPE is the symbol type to use (either global
+ dynamic or local dynamic). V0 is an RTX for the return value
+ location. The entire insn sequence is returned. */
+
+static GTY(()) rtx mips_tls_symbol;
+
+static rtx
+mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
+{
+ rtx insn, loc, tga, a0;
+
+ a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+
+ if (!mips_tls_symbol)
+ mips_tls_symbol = init_one_libfunc ("__tls_get_addr");
+
+ loc = mips_unspec_address (sym, type);
+
+ start_sequence ();
+
+ emit_insn (gen_rtx_SET (Pmode, a0,
+ gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc)));
+ tga = gen_rtx_MEM (Pmode, mips_tls_symbol);
+ insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx));
+ CONST_OR_PURE_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0);
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0);
+ insn = get_insns ();
+
+ end_sequence ();
+
+ return insn;
+}
+
+/* Generate the code to access LOC, a thread local SYMBOL_REF. The
+ return value will be a valid address and move_operand (either a REG
+ or a LO_SUM). */
+
+static rtx
+mips_legitimize_tls_address (rtx loc)
+{
+ rtx dest, insn, v0, v1, tmp1, tmp2, eqv;
+ enum tls_model model;
+
+ v0 = gen_rtx_REG (Pmode, GP_RETURN);
+ v1 = gen_rtx_REG (Pmode, GP_RETURN + 1);
+
+ model = SYMBOL_REF_TLS_MODEL (loc);
+ /* Only TARGET_ABICALLS code can have more than one module; other
+ code must be be static and should not use a GOT. All TLS models
+ reduce to local exec in this situation. */
+ if (!TARGET_ABICALLS)
+ model = TLS_MODEL_LOCAL_EXEC;
+
+ switch (model)
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insn, dest, v0, loc);
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
+ tmp1 = gen_reg_rtx (Pmode);
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LDM result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLS_LDM);
+ emit_libcall_block (insn, tmp1, v0, eqv);
+
+ tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
+ dest = gen_rtx_LO_SUM (Pmode, tmp2,
+ mips_unspec_address (loc, SYMBOL_DTPREL));
+ break;
+
+ case TLS_MODEL_INITIAL_EXEC:
+ tmp1 = gen_reg_rtx (Pmode);
+ tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL);
+ if (Pmode == DImode)
+ {
+ emit_insn (gen_tls_get_tp_di (v1));
+ emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2));
+ }
+ else
+ {
+ emit_insn (gen_tls_get_tp_si (v1));
+ emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2));
+ }
+ dest = gen_reg_rtx (Pmode);
+ emit_insn (gen_add3_insn (dest, tmp1, v1));
+ break;
+
+ case TLS_MODEL_LOCAL_EXEC:
+ if (Pmode == DImode)
+ emit_insn (gen_tls_get_tp_di (v1));
+ else
+ emit_insn (gen_tls_get_tp_si (v1));
+
+ tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL);
+ dest = gen_rtx_LO_SUM (Pmode, tmp1,
+ mips_unspec_address (loc, SYMBOL_TPREL));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return dest;
+}
+
+/* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can
+ be legitimized in a way that the generic machinery might not expect,
+ put the new address in *XLOC and return true. MODE is the mode of
+ the memory being accessed. */
+
+bool
+mips_legitimize_address (rtx *xloc, enum machine_mode mode)
+{
+ enum mips_symbol_type symbol_type;
+
+ if (mips_tls_operand_p (*xloc))
+ {
+ *xloc = mips_legitimize_tls_address (*xloc);
+ return true;
+ }
+
+ /* See if the address can split into a high part and a LO_SUM. */
+ if (mips_symbolic_constant_p (*xloc, &symbol_type)
+ && mips_symbolic_address_p (symbol_type, mode)
+ && mips_split_p[symbol_type])
+ {
+ *xloc = mips_split_symbol (0, *xloc);
+ return true;
+ }
+
+ if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT)
+ {
+ /* Handle REG + CONSTANT using mips_add_offset. */
+ rtx reg;
+
+ reg = XEXP (*xloc, 0);
+ if (!mips_valid_base_register_p (reg, mode, 0))
+ reg = copy_to_mode_reg (Pmode, reg);
+ *xloc = mips_add_offset (0, reg, INTVAL (XEXP (*xloc, 1)));
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Subroutine of mips_build_integer (with the same interface).
+ Assume that the final action in the sequence should be a left shift. */
+
+static unsigned int
+mips_build_shift (struct mips_integer_op *codes, HOST_WIDE_INT value)
+{
+ unsigned int i, shift;
+
+ /* Shift VALUE right until its lowest bit is set. Shift arithmetically
+ since signed numbers are easier to load than unsigned ones. */
+ shift = 0;
+ while ((value & 1) == 0)
+ value /= 2, shift++;
+
+ i = mips_build_integer (codes, value);
+ codes[i].code = ASHIFT;
+ codes[i].value = shift;
+ return i + 1;
+}
+
+
+/* As for mips_build_shift, but assume that the final action will be
+ an IOR or PLUS operation. */
+
+static unsigned int
+mips_build_lower (struct mips_integer_op *codes, unsigned HOST_WIDE_INT value)
+{
+ unsigned HOST_WIDE_INT high;
+ unsigned int i;
+
+ high = value & ~(unsigned HOST_WIDE_INT) 0xffff;
+ if (!LUI_OPERAND (high) && (value & 0x18000) == 0x18000)
+ {
+ /* The constant is too complex to load with a simple lui/ori pair
+ so our goal is to clear as many trailing zeros as possible.
+ In this case, we know bit 16 is set and that the low 16 bits
+ form a negative number. If we subtract that number from VALUE,
+ we will clear at least the lowest 17 bits, maybe more. */
+ i = mips_build_integer (codes, CONST_HIGH_PART (value));
+ codes[i].code = PLUS;
+ codes[i].value = CONST_LOW_PART (value);
+ }
+ else
+ {
+ i = mips_build_integer (codes, high);
+ codes[i].code = IOR;
+ codes[i].value = value & 0xffff;
+ }
+ return i + 1;
+}
+
+
+/* Fill CODES with a sequence of rtl operations to load VALUE.
+ Return the number of operations needed. */
+
+static unsigned int
+mips_build_integer (struct mips_integer_op *codes,
+ unsigned HOST_WIDE_INT value)
+{
+ if (SMALL_OPERAND (value)
+ || SMALL_OPERAND_UNSIGNED (value)
+ || LUI_OPERAND (value))
+ {
+ /* The value can be loaded with a single instruction. */
+ codes[0].code = UNKNOWN;
+ codes[0].value = value;
+ return 1;
+ }
+ else if ((value & 1) != 0 || LUI_OPERAND (CONST_HIGH_PART (value)))
+ {
+ /* Either the constant is a simple LUI/ORI combination or its
+ lowest bit is set. We don't want to shift in this case. */
+ return mips_build_lower (codes, value);
+ }
+ else if ((value & 0xffff) == 0)
+ {
+ /* The constant will need at least three actions. The lowest
+ 16 bits are clear, so the final action will be a shift. */
+ return mips_build_shift (codes, value);
+ }
+ else
+ {
+ /* The final action could be a shift, add or inclusive OR.
+ Rather than use a complex condition to select the best
+ approach, try both mips_build_shift and mips_build_lower
+ and pick the one that gives the shortest sequence.
+ Note that this case is only used once per constant. */
+ struct mips_integer_op alt_codes[MIPS_MAX_INTEGER_OPS];
+ unsigned int cost, alt_cost;
+
+ cost = mips_build_shift (codes, value);
+ alt_cost = mips_build_lower (alt_codes, value);
+ if (alt_cost < cost)
+ {
+ memcpy (codes, alt_codes, alt_cost * sizeof (codes[0]));
+ cost = alt_cost;
+ }
+ return cost;
+ }
+}
+
+
+/* Load VALUE into DEST, using TEMP as a temporary register if need be. */
+
+void
+mips_move_integer (rtx dest, rtx temp, unsigned HOST_WIDE_INT value)
+{
+ struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS];
+ enum machine_mode mode;
+ unsigned int i, cost;
+ rtx x;
+
+ mode = GET_MODE (dest);
+ cost = mips_build_integer (codes, value);
+
+ /* Apply each binary operation to X. Invariant: X is a legitimate
+ source operand for a SET pattern. */
+ x = GEN_INT (codes[0].value);
+ for (i = 1; i < cost; i++)
+ {
+ if (no_new_pseudos)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, temp, x));
+ x = temp;
+ }
+ else
+ x = force_reg (mode, x);
+ x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value));
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode, dest, x));
+}
+
+
+/* Subroutine of mips_legitimize_move. Move constant SRC into register
+ DEST given that SRC satisfies immediate_operand but doesn't satisfy
+ move_operand. */
+
+static void
+mips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src)
+{
+ rtx base;
+ HOST_WIDE_INT offset;
+
+ /* Split moves of big integers into smaller pieces. */
+ if (splittable_const_int_operand (src, mode))
+ {
+ mips_move_integer (dest, dest, INTVAL (src));
+ return;
+ }
+
+ /* Split moves of symbolic constants into high/low pairs. */
+ if (splittable_symbolic_operand (src, mode))
+ {
+ emit_insn (gen_rtx_SET (VOIDmode, dest, mips_split_symbol (dest, src)));
+ return;
+ }
+
+ if (mips_tls_operand_p (src))
+ {
+ emit_move_insn (dest, mips_legitimize_tls_address (src));
+ return;
+ }
+
+ /* If we have (const (plus symbol offset)), load the symbol first
+ and then add in the offset. This is usually better than forcing
+ the constant into memory, at least in non-mips16 code. */
+ mips_split_const (src, &base, &offset);
+ if (!TARGET_MIPS16
+ && offset != 0
+ && (!no_new_pseudos || SMALL_OPERAND (offset)))
+ {
+ base = mips_force_temporary (dest, base);
+ emit_move_insn (dest, mips_add_offset (0, base, offset));
+ return;
+ }
+
+ src = force_const_mem (mode, src);
+
+ /* When using explicit relocs, constant pool references are sometimes
+ not legitimate addresses. */
+ if (!memory_operand (src, VOIDmode))
+ src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0)));
+ emit_move_insn (dest, src);
+}
+
+
+/* If (set DEST SRC) is not a valid instruction, emit an equivalent
+ sequence that is valid. */
+
+bool
+mips_legitimize_move (enum machine_mode mode, rtx dest, rtx src)
+{
+ if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
+ {
+ emit_move_insn (dest, force_reg (mode, src));
+ return true;
+ }
+
+ /* Check for individual, fully-reloaded mflo and mfhi instructions. */
+ if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
+ && REG_P (src) && MD_REG_P (REGNO (src))
+ && REG_P (dest) && GP_REG_P (REGNO (dest)))
+ {
+ int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM;
+ if (GET_MODE_SIZE (mode) <= 4)
+ emit_insn (gen_mfhilo_si (gen_rtx_REG (SImode, REGNO (dest)),
+ gen_rtx_REG (SImode, REGNO (src)),
+ gen_rtx_REG (SImode, other_regno)));
+ else
+ emit_insn (gen_mfhilo_di (gen_rtx_REG (DImode, REGNO (dest)),
+ gen_rtx_REG (DImode, REGNO (src)),
+ gen_rtx_REG (DImode, other_regno)));
+ return true;
+ }
+
+ /* We need to deal with constants that would be legitimate
+ immediate_operands but not legitimate move_operands. */
+ if (CONSTANT_P (src) && !move_operand (src, mode))
+ {
+ mips_legitimize_const_move (mode, dest, src);
+ set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src));
+ return true;
+ }
+ return false;
+}
+
+/* We need a lot of little routines to check constant values on the
+ mips16. These are used to figure out how long the instruction will
+ be. It would be much better to do this using constraints, but
+ there aren't nearly enough letters available. */
+
+static int
+m16_check_op (rtx op, int low, int high, int mask)
+{
+ return (GET_CODE (op) == CONST_INT
+ && INTVAL (op) >= low
+ && INTVAL (op) <= high
+ && (INTVAL (op) & mask) == 0);
+}
+
+int
+m16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, 0x1, 0x8, 0);
+}
+
+int
+m16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x8, 0x7, 0);
+}
+
+int
+m16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x7, 0x8, 0);
+}
+
+int
+m16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x10, 0xf, 0);
+}
+
+int
+m16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0xf, 0x10, 0);
+}
+
+int
+m16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3);
+}
+
+int
+m16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3);
+}
+
+int
+m16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x80, 0x7f, 0);
+}
+
+int
+m16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x7f, 0x80, 0);
+}
+
+int
+m16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, 0x0, 0xff, 0);
+}
+
+int
+m16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0xff, 0x0, 0);
+}
+
+int
+m16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, - 0x1, 0xfe, 0);
+}
+
+int
+m16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, 0x0, 0xff << 2, 3);
+}
+
+int
+m16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, (- 0xff) << 2, 0x0, 3);
+}
+
+int
+m16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7);
+}
+
+int
+m16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+{
+ return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7);
+}
+
+static bool
+mips_rtx_costs (rtx x, int code, int outer_code, int *total)
+{
+ enum machine_mode mode = GET_MODE (x);
+ bool float_mode_p = FLOAT_MODE_P (mode);
+
+ switch (code)
+ {
+ case CONST_INT:
+ if (TARGET_MIPS16)
+ {
+ /* A number between 1 and 8 inclusive is efficient for a shift.
+ Otherwise, we will need an extended instruction. */
+ if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT
+ || (outer_code) == LSHIFTRT)
+ {
+ if (INTVAL (x) >= 1 && INTVAL (x) <= 8)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+
+ /* We can use cmpi for an xor with an unsigned 16 bit value. */
+ if ((outer_code) == XOR
+ && INTVAL (x) >= 0 && INTVAL (x) < 0x10000)
+ {
+ *total = 0;
+ return true;
+ }
+
+ /* We may be able to use slt or sltu for a comparison with a
+ signed 16 bit value. (The boundary conditions aren't quite
+ right, but this is just a heuristic anyhow.) */
+ if (((outer_code) == LT || (outer_code) == LE
+ || (outer_code) == GE || (outer_code) == GT
+ || (outer_code) == LTU || (outer_code) == LEU
+ || (outer_code) == GEU || (outer_code) == GTU)
+ && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000)
+ {
+ *total = 0;
+ return true;
+ }
+
+ /* Equality comparisons with 0 are cheap. */
+ if (((outer_code) == EQ || (outer_code) == NE)
+ && INTVAL (x) == 0)
+ {
+ *total = 0;
+ return true;
+ }
+
+ /* Constants in the range 0...255 can be loaded with an unextended
+ instruction. They are therefore as cheap as a register move.
+
+ Given the choice between "li R1,0...255" and "move R1,R2"
+ (where R2 is a known constant), it is usually better to use "li",
+ since we do not want to unnecessarily extend the lifetime
+ of R2. */
+ if (outer_code == SET
+ && INTVAL (x) >= 0
+ && INTVAL (x) < 256)
+ {
+ *total = 0;
+ return true;
+ }
+ }
+ else
+ {
+ /* These can be used anywhere. */
+ *total = 0;
+ return true;
+ }
+
+ /* Otherwise fall through to the handling below because
+ we'll need to construct the constant. */
+
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ case CONST_DOUBLE:
+ if (LEGITIMATE_CONSTANT_P (x))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ else
+ {
+ /* The value will need to be fetched from the constant pool. */
+ *total = CONSTANT_POOL_COST;
+ return true;
+ }
+
+ case MEM:
+ {
+ /* If the address is legitimate, return the number of
+ instructions it needs, otherwise use the default handling. */
+ int n = mips_address_insns (XEXP (x, 0), GET_MODE (x));
+ if (n > 0)
+ {
+ *total = COSTS_N_INSNS (n + 1);
+ return true;
+ }
+ return false;
+ }
+
+ case FFS:
+ *total = COSTS_N_INSNS (6);
+ return true;
+
+ case NOT:
+ *total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1);
+ return true;
+
+ case AND:
+ case IOR:
+ case XOR:
+ if (mode == DImode && !TARGET_64BIT)
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+ return false;
+
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ if (mode == DImode && !TARGET_64BIT)
+ {
+ *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT)
+ ? 4 : 12);
+ return true;
+ }
+ return false;
+
+ case ABS:
+ if (float_mode_p)
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (4);
+ return true;
+
+ case LO_SUM:
+ *total = COSTS_N_INSNS (1);
+ return true;
+
+ case PLUS:
+ case MINUS:
+ if (float_mode_p)
+ {
+ *total = mips_cost->fp_add;
+ return true;
+ }
+
+ else if (mode == DImode && !TARGET_64BIT)
+ {
+ *total = COSTS_N_INSNS (4);
+ return true;
+ }
+ return false;
+
+ case NEG:
+ if (mode == DImode && !TARGET_64BIT)
+ {
+ *total = COSTS_N_INSNS (4);
+ return true;
+ }
+ return false;
+
+ case MULT:
+ if (mode == SFmode)
+ *total = mips_cost->fp_mult_sf;
+
+ else if (mode == DFmode)
+ *total = mips_cost->fp_mult_df;
+
+ else if (mode == SImode)
+ *total = mips_cost->int_mult_si;
+
+ else
+ *total = mips_cost->int_mult_di;
+
+ return true;
+
+ case DIV:
+ case MOD:
+ if (float_mode_p)
+ {
+ if (mode == SFmode)
+ *total = mips_cost->fp_div_sf;
+ else
+ *total = mips_cost->fp_div_df;
+
+ return true;
+ }
+ /* Fall through. */
+
+ case UDIV:
+ case UMOD:
+ if (mode == DImode)
+ *total = mips_cost->int_div_di;
+ else
+ *total = mips_cost->int_div_si;
+
+ return true;
+
+ case SIGN_EXTEND:
+ /* A sign extend from SImode to DImode in 64 bit mode is often
+ zero instructions, because the result can often be used
+ directly by another instruction; we'll call it one. */
+ if (TARGET_64BIT && mode == DImode
+ && GET_MODE (XEXP (x, 0)) == SImode)
+ *total = COSTS_N_INSNS (1);
+ else
+ *total = COSTS_N_INSNS (2);
+ return true;
+
+ case ZERO_EXTEND:
+ if (TARGET_64BIT && mode == DImode
+ && GET_MODE (XEXP (x, 0)) == SImode)
+ *total = COSTS_N_INSNS (2);
+ else
+ *total = COSTS_N_INSNS (1);
+ return true;
+
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ case SQRT:
+ *total = mips_cost->fp_add;
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Provide the costs of an addressing mode that contains ADDR.
+ If ADDR is not a valid address, its cost is irrelevant. */
+
+static int
+mips_address_cost (rtx addr)
+{
+ return mips_address_insns (addr, SImode);
+}
+
+/* Return one word of double-word value OP, taking into account the fixed
+ endianness of certain registers. HIGH_P is true to select the high part,
+ false to select the low part. */
+
+rtx
+mips_subword (rtx op, int high_p)
+{
+ unsigned int byte;
+ enum machine_mode mode;
+
+ mode = GET_MODE (op);
+ if (mode == VOIDmode)
+ mode = DImode;
+
+ if (TARGET_BIG_ENDIAN ? !high_p : high_p)
+ byte = UNITS_PER_WORD;
+ else
+ byte = 0;
+
+ if (REG_P (op))
+ {
+ if (FP_REG_P (REGNO (op)))
+ return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op));
+ if (ACC_HI_REG_P (REGNO (op)))
+ return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1);
+ }
+
+ if (MEM_P (op))
+ return mips_rewrite_small_data (adjust_address (op, word_mode, byte));
+
+ return simplify_gen_subreg (word_mode, op, mode, byte);
+}
+
+
+/* Return true if a 64-bit move from SRC to DEST should be split into two. */
+
+bool
+mips_split_64bit_move_p (rtx dest, rtx src)
+{
+ if (TARGET_64BIT)
+ return false;
+
+ /* FP->FP moves can be done in a single instruction. */
+ if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest))
+ return false;
+
+ /* Check for floating-point loads and stores. They can be done using
+ ldc1 and sdc1 on MIPS II and above. */
+ if (mips_isa > 1)
+ {
+ if (FP_REG_RTX_P (dest) && MEM_P (src))
+ return false;
+ if (FP_REG_RTX_P (src) && MEM_P (dest))
+ return false;
+ }
+ return true;
+}
+
+
+/* Split a 64-bit move from SRC to DEST assuming that
+ mips_split_64bit_move_p holds.
+
+ Moves into and out of FPRs cause some difficulty here. Such moves
+ will always be DFmode, since paired FPRs are not allowed to store
+ DImode values. The most natural representation would be two separate
+ 32-bit moves, such as:
+
+ (set (reg:SI $f0) (mem:SI ...))
+ (set (reg:SI $f1) (mem:SI ...))
+
+ However, the second insn is invalid because odd-numbered FPRs are
+ not allowed to store independent values. Use the patterns load_df_low,
+ load_df_high and store_df_high instead. */
+
+void
+mips_split_64bit_move (rtx dest, rtx src)
+{
+ if (FP_REG_RTX_P (dest))
+ {
+ /* Loading an FPR from memory or from GPRs. */
+ emit_insn (gen_load_df_low (copy_rtx (dest), mips_subword (src, 0)));
+ emit_insn (gen_load_df_high (dest, mips_subword (src, 1),
+ copy_rtx (dest)));
+ }
+ else if (FP_REG_RTX_P (src))
+ {
+ /* Storing an FPR into memory or GPRs. */
+ emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0));
+ emit_insn (gen_store_df_high (mips_subword (dest, 1), src));
+ }
+ else
+ {
+ /* The operation can be split into two normal moves. Decide in
+ which order to do them. */
+ rtx low_dest;
+
+ low_dest = mips_subword (dest, 0);
+ if (REG_P (low_dest)
+ && reg_overlap_mentioned_p (low_dest, src))
+ {
+ emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
+ emit_move_insn (low_dest, mips_subword (src, 0));
+ }
+ else
+ {
+ emit_move_insn (low_dest, mips_subword (src, 0));
+ emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1));
+ }
+ }
+}
+
+/* Return the appropriate instructions to move SRC into DEST. Assume
+ that SRC is operand 1 and DEST is operand 0. */
+
+const char *
+mips_output_move (rtx dest, rtx src)
+{
+ enum rtx_code dest_code, src_code;
+ bool dbl_p;
+
+ dest_code = GET_CODE (dest);
+ src_code = GET_CODE (src);
+ dbl_p = (GET_MODE_SIZE (GET_MODE (dest)) == 8);
+
+ if (dbl_p && mips_split_64bit_move_p (dest, src))
+ return "#";
+
+ if ((src_code == REG && GP_REG_P (REGNO (src)))
+ || (!TARGET_MIPS16 && src == CONST0_RTX (GET_MODE (dest))))
+ {
+ if (dest_code == REG)
+ {
+ if (GP_REG_P (REGNO (dest)))
+ return "move\t%0,%z1";
+
+ if (MD_REG_P (REGNO (dest)))
+ return "mt%0\t%z1";
+
+ if (DSP_ACC_REG_P (REGNO (dest)))
+ {
+ static char retval[] = "mt__\t%z1,%q0";
+ retval[2] = reg_names[REGNO (dest)][4];
+ retval[3] = reg_names[REGNO (dest)][5];
+ return retval;
+ }
+
+ if (FP_REG_P (REGNO (dest)))
+ return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0");
+
+ if (ALL_COP_REG_P (REGNO (dest)))
+ {
+ static char retval[] = "dmtc_\t%z1,%0";
+
+ retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
+ return (dbl_p ? retval : retval + 1);
+ }
+ }
+ if (dest_code == MEM)
+ return (dbl_p ? "sd\t%z1,%0" : "sw\t%z1,%0");
+ }
+ if (dest_code == REG && GP_REG_P (REGNO (dest)))
+ {
+ if (src_code == REG)
+ {
+ if (DSP_ACC_REG_P (REGNO (src)))
+ {
+ static char retval[] = "mf__\t%0,%q1";
+ retval[2] = reg_names[REGNO (src)][4];
+ retval[3] = reg_names[REGNO (src)][5];
+ return retval;
+ }
+
+ if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC)
+ return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1";
+
+ if (FP_REG_P (REGNO (src)))
+ return (dbl_p ? "dmfc1\t%0,%1" : "mfc1\t%0,%1");
+
+ if (ALL_COP_REG_P (REGNO (src)))
+ {
+ static char retval[] = "dmfc_\t%0,%1";
+
+ retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
+ return (dbl_p ? retval : retval + 1);
+ }
+ }
+
+ if (src_code == MEM)
+ return (dbl_p ? "ld\t%0,%1" : "lw\t%0,%1");
+
+ if (src_code == CONST_INT)
+ {
+ /* Don't use the X format, because that will give out of
+ range numbers for 64 bit hosts and 32 bit targets. */
+ if (!TARGET_MIPS16)
+ return "li\t%0,%1\t\t\t# %X1";
+
+ if (INTVAL (src) >= 0 && INTVAL (src) <= 0xffff)
+ return "li\t%0,%1";
+
+ if (INTVAL (src) < 0 && INTVAL (src) >= -0xffff)
+ return "#";
+ }
+
+ if (src_code == HIGH)
+ return "lui\t%0,%h1";
+
+ if (CONST_GP_P (src))
+ return "move\t%0,%1";
+
+ if (symbolic_operand (src, VOIDmode))
+ return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1");
+ }
+ if (src_code == REG && FP_REG_P (REGNO (src)))
+ {
+ if (dest_code == REG && FP_REG_P (REGNO (dest)))
+ {
+ if (GET_MODE (dest) == V2SFmode)
+ return "mov.ps\t%0,%1";
+ else
+ return (dbl_p ? "mov.d\t%0,%1" : "mov.s\t%0,%1");
+ }
+
+ if (dest_code == MEM)
+ return (dbl_p ? "sdc1\t%1,%0" : "swc1\t%1,%0");
+ }
+ if (dest_code == REG && FP_REG_P (REGNO (dest)))
+ {
+ if (src_code == MEM)
+ return (dbl_p ? "ldc1\t%0,%1" : "lwc1\t%0,%1");
+ }
+ if (dest_code == REG && ALL_COP_REG_P (REGNO (dest)) && src_code == MEM)
+ {
+ static char retval[] = "l_c_\t%0,%1";
+
+ retval[1] = (dbl_p ? 'd' : 'w');
+ retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest));
+ return retval;
+ }
+ if (dest_code == MEM && src_code == REG && ALL_COP_REG_P (REGNO (src)))
+ {
+ static char retval[] = "s_c_\t%1,%0";
+
+ retval[1] = (dbl_p ? 'd' : 'w');
+ retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src));
+ return retval;
+ }
+ gcc_unreachable ();
+}
+
+/* Restore $gp from its save slot. Valid only when using o32 or
+ o64 abicalls. */
+
+void
+mips_restore_gp (void)
+{
+ rtx address, slot;
+
+ gcc_assert (TARGET_ABICALLS && TARGET_OLDABI);
+
+ address = mips_add_offset (pic_offset_table_rtx,
+ frame_pointer_needed
+ ? hard_frame_pointer_rtx
+ : stack_pointer_rtx,
+ current_function_outgoing_args_size);
+ slot = gen_rtx_MEM (Pmode, address);
+
+ emit_move_insn (pic_offset_table_rtx, slot);
+ if (!TARGET_EXPLICIT_RELOCS)
+ emit_insn (gen_blockage ());
+}
+
+/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
+
+static void
+mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
+{
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1)));
+}
+
+/* Return true if CMP1 is a suitable second operand for relational
+ operator CODE. See also the *sCC patterns in mips.md. */
+
+static bool
+mips_relational_operand_ok_p (enum rtx_code code, rtx cmp1)
+{
+ switch (code)
+ {
+ case GT:
+ case GTU:
+ return reg_or_0_operand (cmp1, VOIDmode);
+
+ case GE:
+ case GEU:
+ return !TARGET_MIPS16 && cmp1 == const1_rtx;
+
+ case LT:
+ case LTU:
+ return arith_operand (cmp1, VOIDmode);
+
+ case LE:
+ return sle_operand (cmp1, VOIDmode);
+
+ case LEU:
+ return sleu_operand (cmp1, VOIDmode);
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Canonicalize LE or LEU comparisons into LT comparisons when
+ possible to avoid extra instructions or inverting the
+ comparison. */
+
+static bool
+mips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1,
+ enum machine_mode mode)
+{
+ HOST_WIDE_INT original, plus_one;
+
+ if (GET_CODE (*cmp1) != CONST_INT)
+ return false;
+
+ original = INTVAL (*cmp1);
+ plus_one = trunc_int_for_mode ((unsigned HOST_WIDE_INT) original + 1, mode);
+
+ switch (*code)
+ {
+ case LE:
+ if (original < plus_one)
+ {
+ *code = LT;
+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
+ return true;
+ }
+ break;
+
+ case LEU:
+ if (plus_one != 0)
+ {
+ *code = LTU;
+ *cmp1 = force_reg (mode, GEN_INT (plus_one));
+ return true;
+ }
+ break;
+
+ default:
+ return false;
+ }
+
+ return false;
+
+}
+
+/* Compare CMP0 and CMP1 using relational operator CODE and store the
+ result in TARGET. CMP0 and TARGET are register_operands that have
+ the same integer mode. If INVERT_PTR is nonnull, it's OK to set
+ TARGET to the inverse of the result and flip *INVERT_PTR instead. */
+
+static void
+mips_emit_int_relational (enum rtx_code code, bool *invert_ptr,
+ rtx target, rtx cmp0, rtx cmp1)
+{
+ /* First see if there is a MIPS instruction that can do this operation
+ with CMP1 in its current form. If not, try to canonicalize the
+ comparison to LT. If that fails, try doing the same for the
+ inverse operation. If that also fails, force CMP1 into a register
+ and try again. */
+ if (mips_relational_operand_ok_p (code, cmp1))
+ mips_emit_binary (code, target, cmp0, cmp1);
+ else if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target)))
+ mips_emit_binary (code, target, cmp0, cmp1);
+ else
+ {
+ enum rtx_code inv_code = reverse_condition (code);
+ if (!mips_relational_operand_ok_p (inv_code, cmp1))
+ {
+ cmp1 = force_reg (GET_MODE (cmp0), cmp1);
+ mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1);
+ }
+ else if (invert_ptr == 0)
+ {
+ rtx inv_target = gen_reg_rtx (GET_MODE (target));
+ mips_emit_binary (inv_code, inv_target, cmp0, cmp1);
+ mips_emit_binary (XOR, target, inv_target, const1_rtx);
+ }
+ else
+ {
+ *invert_ptr = !*invert_ptr;
+ mips_emit_binary (inv_code, target, cmp0, cmp1);
+ }
+ }
+}
+
+/* Return a register that is zero iff CMP0 and CMP1 are equal.
+ The register will have the same mode as CMP0. */
+
+static rtx
+mips_zero_if_equal (rtx cmp0, rtx cmp1)
+{
+ if (cmp1 == const0_rtx)
+ return cmp0;
+
+ if (uns_arith_operand (cmp1, VOIDmode))
+ return expand_binop (GET_MODE (cmp0), xor_optab,
+ cmp0, cmp1, 0, 0, OPTAB_DIRECT);
+
+ return expand_binop (GET_MODE (cmp0), sub_optab,
+ cmp0, cmp1, 0, 0, OPTAB_DIRECT);
+}
+
+/* Convert *CODE into a code that can be used in a floating-point
+ scc instruction (c.<cond>.<fmt>). Return true if the values of
+ the condition code registers will be inverted, with 0 indicating
+ that the condition holds. */
+
+static bool
+mips_reverse_fp_cond_p (enum rtx_code *code)
+{
+ switch (*code)
+ {
+ case NE:
+ case LTGT:
+ case ORDERED:
+ *code = reverse_condition_maybe_unordered (*code);
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+/* Convert a comparison into something that can be used in a branch or
+ conditional move. cmp_operands[0] and cmp_operands[1] are the values
+ being compared and *CODE is the code used to compare them.
+
+ Update *CODE, *OP0 and *OP1 so that they describe the final comparison.
+ If NEED_EQ_NE_P, then only EQ/NE comparisons against zero are possible,
+ otherwise any standard branch condition can be used. The standard branch
+ conditions are:
+
+ - EQ/NE between two registers.
+ - any comparison between a register and zero. */
+
+static void
+mips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p)
+{
+ if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT)
+ {
+ if (!need_eq_ne_p && cmp_operands[1] == const0_rtx)
+ {
+ *op0 = cmp_operands[0];
+ *op1 = cmp_operands[1];
+ }
+ else if (*code == EQ || *code == NE)
+ {
+ if (need_eq_ne_p)
+ {
+ *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
+ *op1 = const0_rtx;
+ }
+ else
+ {
+ *op0 = cmp_operands[0];
+ *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]);
+ }
+ }
+ else
+ {
+ /* The comparison needs a separate scc instruction. Store the
+ result of the scc in *OP0 and compare it against zero. */
+ bool invert = false;
+ *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0]));
+ *op1 = const0_rtx;
+ mips_emit_int_relational (*code, &invert, *op0,
+ cmp_operands[0], cmp_operands[1]);
+ *code = (invert ? EQ : NE);
+ }
+ }
+ else
+ {
+ enum rtx_code cmp_code;
+
+ /* Floating-point tests use a separate c.cond.fmt comparison to
+ set a condition code register. The branch or conditional move
+ will then compare that register against zero.
+
+ Set CMP_CODE to the code of the comparison instruction and
+ *CODE to the code that the branch or move should use. */
+ cmp_code = *code;
+ *code = mips_reverse_fp_cond_p (&cmp_code) ? EQ : NE;
+ *op0 = (ISA_HAS_8CC
+ ? gen_reg_rtx (CCmode)
+ : gen_rtx_REG (CCmode, FPSW_REGNUM));
+ *op1 = const0_rtx;
+ mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]);
+ }
+}
+
+/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE.
+ Store the result in TARGET and return true if successful.
+
+ On 64-bit targets, TARGET may be wider than cmp_operands[0]. */
+
+bool
+mips_emit_scc (enum rtx_code code, rtx target)
+{
+ if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT)
+ return false;
+
+ target = gen_lowpart (GET_MODE (cmp_operands[0]), target);
+ if (code == EQ || code == NE)
+ {
+ rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]);
+ mips_emit_binary (code, target, zie, const0_rtx);
+ }
+ else
+ mips_emit_int_relational (code, 0, target,
+ cmp_operands[0], cmp_operands[1]);
+ return true;
+}
+
+/* Emit the common code for doing conditional branches.
+ operand[0] is the label to jump to.
+ The comparison operands are saved away by cmp{si,di,sf,df}. */
+
+void
+gen_conditional_branch (rtx *operands, enum rtx_code code)
+{
+ rtx op0, op1, condition;
+
+ mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16);
+ condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
+ emit_jump_insn (gen_condjump (condition, operands[0]));
+}
+
+/* Implement:
+
+ (set temp (COND:CCV2 CMP_OP0 CMP_OP1))
+ (set DEST (unspec [TRUE_SRC FALSE_SRC temp] UNSPEC_MOVE_TF_PS)) */
+
+void
+mips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src,
+ enum rtx_code cond, rtx cmp_op0, rtx cmp_op1)
+{
+ rtx cmp_result;
+ bool reversed_p;
+
+ reversed_p = mips_reverse_fp_cond_p (&cond);
+ cmp_result = gen_reg_rtx (CCV2mode);
+ emit_insn (gen_scc_ps (cmp_result,
+ gen_rtx_fmt_ee (cond, VOIDmode, cmp_op0, cmp_op1)));
+ if (reversed_p)
+ emit_insn (gen_mips_cond_move_tf_ps (dest, false_src, true_src,
+ cmp_result));
+ else
+ emit_insn (gen_mips_cond_move_tf_ps (dest, true_src, false_src,
+ cmp_result));
+}
+
+/* Emit the common code for conditional moves. OPERANDS is the array
+ of operands passed to the conditional move define_expand. */
+
+void
+gen_conditional_move (rtx *operands)
+{
+ enum rtx_code code;
+ rtx op0, op1;
+
+ code = GET_CODE (operands[1]);
+ mips_emit_compare (&code, &op0, &op1, true);
+ emit_insn (gen_rtx_SET (VOIDmode, operands[0],
+ gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]),
+ gen_rtx_fmt_ee (code,
+ GET_MODE (op0),
+ op0, op1),
+ operands[2], operands[3])));
+}
+
+/* Emit a conditional trap. OPERANDS is the array of operands passed to
+ the conditional_trap expander. */
+
+void
+mips_gen_conditional_trap (rtx *operands)
+{
+ rtx op0, op1;
+ enum rtx_code cmp_code = GET_CODE (operands[0]);
+ enum machine_mode mode = GET_MODE (cmp_operands[0]);
+
+ /* MIPS conditional trap machine instructions don't have GT or LE
+ flavors, so we must invert the comparison and convert to LT and
+ GE, respectively. */
+ switch (cmp_code)
+ {
+ case GT: cmp_code = LT; break;
+ case LE: cmp_code = GE; break;
+ case GTU: cmp_code = LTU; break;
+ case LEU: cmp_code = GEU; break;
+ default: break;
+ }
+ if (cmp_code == GET_CODE (operands[0]))
+ {
+ op0 = cmp_operands[0];
+ op1 = cmp_operands[1];
+ }
+ else
+ {
+ op0 = cmp_operands[1];
+ op1 = cmp_operands[0];
+ }
+ op0 = force_reg (mode, op0);
+ if (!arith_operand (op1, mode))
+ op1 = force_reg (mode, op1);
+
+ emit_insn (gen_rtx_TRAP_IF (VOIDmode,
+ gen_rtx_fmt_ee (cmp_code, mode, op0, op1),
+ operands[1]));
+}
+
+/* Load function address ADDR into register DEST. SIBCALL_P is true
+ if the address is needed for a sibling call. */
+
+static void
+mips_load_call_address (rtx dest, rtx addr, int sibcall_p)
+{
+ /* If we're generating PIC, and this call is to a global function,
+ try to allow its address to be resolved lazily. This isn't
+ possible for NewABI sibcalls since the value of $gp on entry
+ to the stub would be our caller's gp, not ours. */
+ if (TARGET_EXPLICIT_RELOCS
+ && !(sibcall_p && TARGET_NEWABI)
+ && global_got_operand (addr, VOIDmode))
+ {
+ rtx high, lo_sum_symbol;
+
+ high = mips_unspec_offset_high (dest, pic_offset_table_rtx,
+ addr, SYMBOL_GOTOFF_CALL);
+ lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL);
+ if (Pmode == SImode)
+ emit_insn (gen_load_callsi (dest, high, lo_sum_symbol));
+ else
+ emit_insn (gen_load_calldi (dest, high, lo_sum_symbol));
+ }
+ else
+ emit_move_insn (dest, addr);
+}
+
+
+/* Expand a call or call_value instruction. RESULT is where the
+ result will go (null for calls), ADDR is the address of the
+ function, ARGS_SIZE is the size of the arguments and AUX is
+ the value passed to us by mips_function_arg. SIBCALL_P is true
+ if we are expanding a sibling call, false if we're expanding
+ a normal call. */
+
+void
+mips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p)
+{
+ rtx orig_addr, pattern, insn;
+
+ orig_addr = addr;
+ if (!call_insn_operand (addr, VOIDmode))
+ {
+ addr = gen_reg_rtx (Pmode);
+ mips_load_call_address (addr, orig_addr, sibcall_p);
+ }
+
+ if (TARGET_MIPS16
+ && mips16_hard_float
+ && build_mips16_call_stub (result, addr, args_size,
+ aux == 0 ? 0 : (int) GET_MODE (aux)))
+ return;
+
+ if (result == 0)
+ pattern = (sibcall_p
+ ? gen_sibcall_internal (addr, args_size)
+ : gen_call_internal (addr, args_size));
+ else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2)
+ {
+ rtx reg1, reg2;
+
+ reg1 = XEXP (XVECEXP (result, 0, 0), 0);
+ reg2 = XEXP (XVECEXP (result, 0, 1), 0);
+ pattern =
+ (sibcall_p
+ ? gen_sibcall_value_multiple_internal (reg1, addr, args_size, reg2)
+ : gen_call_value_multiple_internal (reg1, addr, args_size, reg2));
+ }
+ else
+ pattern = (sibcall_p
+ ? gen_sibcall_value_internal (result, addr, args_size)
+ : gen_call_value_internal (result, addr, args_size));
+
+ insn = emit_call_insn (pattern);
+
+ /* Lazy-binding stubs require $gp to be valid on entry. */
+ if (global_got_operand (orig_addr, VOIDmode))
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+}
+
+
+/* We can handle any sibcall when TARGET_SIBCALLS is true. */
+
+static bool
+mips_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
+ tree exp ATTRIBUTE_UNUSED)
+{
+ return TARGET_SIBCALLS;
+}
+
+/* Emit code to move general operand SRC into condition-code
+ register DEST. SCRATCH is a scratch TFmode float register.
+ The sequence is:
+
+ FP1 = SRC
+ FP2 = 0.0f
+ DEST = FP2 < FP1
+
+ where FP1 and FP2 are single-precision float registers
+ taken from SCRATCH. */
+
+void
+mips_emit_fcc_reload (rtx dest, rtx src, rtx scratch)
+{
+ rtx fp1, fp2;
+
+ /* Change the source to SFmode. */
+ if (MEM_P (src))
+ src = adjust_address (src, SFmode, 0);
+ else if (REG_P (src) || GET_CODE (src) == SUBREG)
+ src = gen_rtx_REG (SFmode, true_regnum (src));
+
+ fp1 = gen_rtx_REG (SFmode, REGNO (scratch));
+ fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC);
+
+ emit_move_insn (copy_rtx (fp1), src);
+ emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode));
+ emit_insn (gen_slt_sf (dest, fp2, fp1));
+}
+
+/* Emit code to change the current function's return address to
+ ADDRESS. SCRATCH is available as a scratch register, if needed.
+ ADDRESS and SCRATCH are both word-mode GPRs. */
+
+void
+mips_set_return_address (rtx address, rtx scratch)
+{
+ rtx slot_address;
+
+ compute_frame_size (get_frame_size ());
+ gcc_assert ((cfun->machine->frame.mask >> 31) & 1);
+ slot_address = mips_add_offset (scratch, stack_pointer_rtx,
+ cfun->machine->frame.gp_sp_offset);
+
+ emit_move_insn (gen_rtx_MEM (GET_MODE (address), slot_address), address);
+}
+
+/* Emit straight-line code to move LENGTH bytes from SRC to DEST.
+ Assume that the areas do not overlap. */
+
+static void
+mips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length)
+{
+ HOST_WIDE_INT offset, delta;
+ unsigned HOST_WIDE_INT bits;
+ int i;
+ enum machine_mode mode;
+ rtx *regs;
+
+ /* Work out how many bits to move at a time. If both operands have
+ half-word alignment, it is usually better to move in half words.
+ For instance, lh/lh/sh/sh is usually better than lwl/lwr/swl/swr
+ and lw/lw/sw/sw is usually better than ldl/ldr/sdl/sdr.
+ Otherwise move word-sized chunks. */
+ if (MEM_ALIGN (src) == BITS_PER_WORD / 2
+ && MEM_ALIGN (dest) == BITS_PER_WORD / 2)
+ bits = BITS_PER_WORD / 2;
+ else
+ bits = BITS_PER_WORD;
+
+ mode = mode_for_size (bits, MODE_INT, 0);
+ delta = bits / BITS_PER_UNIT;
+
+ /* Allocate a buffer for the temporary registers. */
+ regs = alloca (sizeof (rtx) * length / delta);
+
+ /* Load as many BITS-sized chunks as possible. Use a normal load if
+ the source has enough alignment, otherwise use left/right pairs. */
+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
+ {
+ regs[i] = gen_reg_rtx (mode);
+ if (MEM_ALIGN (src) >= bits)
+ emit_move_insn (regs[i], adjust_address (src, mode, offset));
+ else
+ {
+ rtx part = adjust_address (src, BLKmode, offset);
+ if (!mips_expand_unaligned_load (regs[i], part, bits, 0))
+ gcc_unreachable ();
+ }
+ }
+
+ /* Copy the chunks to the destination. */
+ for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++)
+ if (MEM_ALIGN (dest) >= bits)
+ emit_move_insn (adjust_address (dest, mode, offset), regs[i]);
+ else
+ {
+ rtx part = adjust_address (dest, BLKmode, offset);
+ if (!mips_expand_unaligned_store (part, regs[i], bits, 0))
+ gcc_unreachable ();
+ }
+
+ /* Mop up any left-over bytes. */
+ if (offset < length)
+ {
+ src = adjust_address (src, BLKmode, offset);
+ dest = adjust_address (dest, BLKmode, offset);
+ move_by_pieces (dest, src, length - offset,
+ MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0);
+ }
+}
+
+#define MAX_MOVE_REGS 4
+#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD)
+
+
+/* Helper function for doing a loop-based block operation on memory
+ reference MEM. Each iteration of the loop will operate on LENGTH
+ bytes of MEM.
+
+ Create a new base register for use within the loop and point it to
+ the start of MEM. Create a new memory reference that uses this
+ register. Store them in *LOOP_REG and *LOOP_MEM respectively. */
+
+static void
+mips_adjust_block_mem (rtx mem, HOST_WIDE_INT length,
+ rtx *loop_reg, rtx *loop_mem)
+{
+ *loop_reg = copy_addr_to_reg (XEXP (mem, 0));
+
+ /* Although the new mem does not refer to a known location,
+ it does keep up to LENGTH bytes of alignment. */
+ *loop_mem = change_address (mem, BLKmode, *loop_reg);
+ set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT));
+}
+
+
+/* Move LENGTH bytes from SRC to DEST using a loop that moves MAX_MOVE_BYTES
+ per iteration. LENGTH must be at least MAX_MOVE_BYTES. Assume that the
+ memory regions do not overlap. */
+
+static void
+mips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length)
+{
+ rtx label, src_reg, dest_reg, final_src;
+ HOST_WIDE_INT leftover;
+
+ leftover = length % MAX_MOVE_BYTES;
+ length -= leftover;
+
+ /* Create registers and memory references for use within the loop. */
+ mips_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src);
+ mips_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest);
+
+ /* Calculate the value that SRC_REG should have after the last iteration
+ of the loop. */
+ final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length),
+ 0, 0, OPTAB_WIDEN);
+
+ /* Emit the start of the loop. */
+ label = gen_label_rtx ();
+ emit_label (label);
+
+ /* Emit the loop body. */
+ mips_block_move_straight (dest, src, MAX_MOVE_BYTES);
+
+ /* Move on to the next block. */
+ emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES));
+ emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES));
+
+ /* Emit the loop condition. */
+ if (Pmode == DImode)
+ emit_insn (gen_cmpdi (src_reg, final_src));
+ else
+ emit_insn (gen_cmpsi (src_reg, final_src));
+ emit_jump_insn (gen_bne (label));
+
+ /* Mop up any left-over bytes. */
+ if (leftover)
+ mips_block_move_straight (dest, src, leftover);
+}
+
+/* Expand a movmemsi instruction. */
+
+bool
+mips_expand_block_move (rtx dest, rtx src, rtx length)
+{
+ if (GET_CODE (length) == CONST_INT)
+ {
+ if (INTVAL (length) <= 2 * MAX_MOVE_BYTES)
+ {
+ mips_block_move_straight (dest, src, INTVAL (length));
+ return true;
+ }
+ else if (optimize)
+ {
+ mips_block_move_loop (dest, src, INTVAL (length));
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Argument support functions. */
+
+/* Initialize CUMULATIVE_ARGS for a function. */
+
+void
+init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
+ rtx libname ATTRIBUTE_UNUSED)
+{
+ static CUMULATIVE_ARGS zero_cum;
+ tree param, next_param;
+
+ *cum = zero_cum;
+ cum->prototype = (fntype && TYPE_ARG_TYPES (fntype));
+
+ /* Determine if this function has variable arguments. This is
+ indicated by the last argument being 'void_type_mode' if there
+ are no variable arguments. The standard MIPS calling sequence
+ passes all arguments in the general purpose registers in this case. */
+
+ for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0;
+ param != 0; param = next_param)
+ {
+ next_param = TREE_CHAIN (param);
+ if (next_param == 0 && TREE_VALUE (param) != void_type_node)
+ cum->gp_reg_found = 1;
+ }
+}
+
+
+/* Fill INFO with information about a single argument. CUM is the
+ cumulative state for earlier arguments. MODE is the mode of this
+ argument and TYPE is its type (if known). NAMED is true if this
+ is a named (fixed) argument rather than a variable one. */
+
+static void
+mips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named, struct mips_arg_info *info)
+{
+ bool doubleword_aligned_p;
+ unsigned int num_bytes, num_words, max_regs;
+
+ /* Work out the size of the argument. */
+ num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+ num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+ /* Decide whether it should go in a floating-point register, assuming
+ one is free. Later code checks for availability.
+
+ The checks against UNITS_PER_FPVALUE handle the soft-float and
+ single-float cases. */
+ switch (mips_abi)
+ {
+ case ABI_EABI:
+ /* The EABI conventions have traditionally been defined in terms
+ of TYPE_MODE, regardless of the actual type. */
+ info->fpr_p = ((GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
+ break;
+
+ case ABI_32:
+ case ABI_O64:
+ /* Only leading floating-point scalars are passed in
+ floating-point registers. We also handle vector floats the same
+ say, which is OK because they are not covered by the standard ABI. */
+ info->fpr_p = (!cum->gp_reg_found
+ && cum->arg_number < 2
+ && (type == 0 || SCALAR_FLOAT_TYPE_P (type)
+ || VECTOR_FLOAT_TYPE_P (type))
+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE);
+ break;
+
+ case ABI_N32:
+ case ABI_64:
+ /* Scalar and complex floating-point types are passed in
+ floating-point registers. */
+ info->fpr_p = (named
+ && (type == 0 || FLOAT_TYPE_P (type))
+ && (GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE);
+
+ /* ??? According to the ABI documentation, the real and imaginary
+ parts of complex floats should be passed in individual registers.
+ The real and imaginary parts of stack arguments are supposed
+ to be contiguous and there should be an extra word of padding
+ at the end.
+
+ This has two problems. First, it makes it impossible to use a
+ single "void *" va_list type, since register and stack arguments
+ are passed differently. (At the time of writing, MIPSpro cannot
+ handle complex float varargs correctly.) Second, it's unclear
+ what should happen when there is only one register free.
+
+ For now, we assume that named complex floats should go into FPRs
+ if there are two FPRs free, otherwise they should be passed in the
+ same way as a struct containing two floats. */
+ if (info->fpr_p
+ && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE)
+ {
+ if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1)
+ info->fpr_p = false;
+ else
+ num_words = 2;
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* See whether the argument has doubleword alignment. */
+ doubleword_aligned_p = FUNCTION_ARG_BOUNDARY (mode, type) > BITS_PER_WORD;
+
+ /* Set REG_OFFSET to the register count we're interested in.
+ The EABI allocates the floating-point registers separately,
+ but the other ABIs allocate them like integer registers. */
+ info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p
+ ? cum->num_fprs
+ : cum->num_gprs);
+
+ /* Advance to an even register if the argument is doubleword-aligned. */
+ if (doubleword_aligned_p)
+ info->reg_offset += info->reg_offset & 1;
+
+ /* Work out the offset of a stack argument. */
+ info->stack_offset = cum->stack_words;
+ if (doubleword_aligned_p)
+ info->stack_offset += info->stack_offset & 1;
+
+ max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset;
+
+ /* Partition the argument between registers and stack. */
+ info->reg_words = MIN (num_words, max_regs);
+ info->stack_words = num_words - info->reg_words;
+}
+
+
+/* Implement FUNCTION_ARG_ADVANCE. */
+
+void
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ struct mips_arg_info info;
+
+ mips_arg_info (cum, mode, type, named, &info);
+
+ if (!info.fpr_p)
+ cum->gp_reg_found = true;
+
+ /* See the comment above the cumulative args structure in mips.h
+ for an explanation of what this code does. It assumes the O32
+ ABI, which passes at most 2 arguments in float registers. */
+ if (cum->arg_number < 2 && info.fpr_p)
+ cum->fp_code += (mode == SFmode ? 1 : 2) << ((cum->arg_number - 1) * 2);
+
+ if (mips_abi != ABI_EABI || !info.fpr_p)
+ cum->num_gprs = info.reg_offset + info.reg_words;
+ else if (info.reg_words > 0)
+ cum->num_fprs += FP_INC;
+
+ if (info.stack_words > 0)
+ cum->stack_words = info.stack_offset + info.stack_words;
+
+ cum->arg_number++;
+}
+
+/* Implement FUNCTION_ARG. */
+
+struct rtx_def *
+function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named)
+{
+ struct mips_arg_info info;
+
+ /* We will be called with a mode of VOIDmode after the last argument
+ has been seen. Whatever we return will be passed to the call
+ insn. If we need a mips16 fp_code, return a REG with the code
+ stored as the mode. */
+ if (mode == VOIDmode)
+ {
+ if (TARGET_MIPS16 && cum->fp_code != 0)
+ return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0);
+
+ else
+ return 0;
+ }
+
+ mips_arg_info (cum, mode, type, named, &info);
+
+ /* Return straight away if the whole argument is passed on the stack. */
+ if (info.reg_offset == MAX_ARGS_IN_REGISTERS)
+ return 0;
+
+ if (type != 0
+ && TREE_CODE (type) == RECORD_TYPE
+ && TARGET_NEWABI
+ && TYPE_SIZE_UNIT (type)
+ && host_integerp (TYPE_SIZE_UNIT (type), 1)
+ && named)
+ {
+ /* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the
+ structure contains a double in its entirety, then that 64 bit
+ chunk is passed in a floating point register. */
+ tree field;
+
+ /* First check to see if there is any such field. */
+ for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD
+ && host_integerp (bit_position (field), 0)
+ && int_bit_position (field) % BITS_PER_WORD == 0)
+ break;
+
+ if (field != 0)
+ {
+ /* Now handle the special case by returning a PARALLEL
+ indicating where each 64 bit chunk goes. INFO.REG_WORDS
+ chunks are passed in registers. */
+ unsigned int i;
+ HOST_WIDE_INT bitpos;
+ rtx ret;
+
+ /* assign_parms checks the mode of ENTRY_PARM, so we must
+ use the actual mode here. */
+ ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words));
+
+ bitpos = 0;
+ field = TYPE_FIELDS (type);
+ for (i = 0; i < info.reg_words; i++)
+ {
+ rtx reg;
+
+ for (; field; field = TREE_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL
+ && int_bit_position (field) >= bitpos)
+ break;
+
+ if (field
+ && int_bit_position (field) == bitpos
+ && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE
+ && !TARGET_SOFT_FLOAT
+ && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD)
+ reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i);
+ else
+ reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i);
+
+ XVECEXP (ret, 0, i)
+ = gen_rtx_EXPR_LIST (VOIDmode, reg,
+ GEN_INT (bitpos / BITS_PER_UNIT));
+
+ bitpos += BITS_PER_WORD;
+ }
+ return ret;
+ }
+ }
+
+ /* Handle the n32/n64 conventions for passing complex floating-point
+ arguments in FPR pairs. The real part goes in the lower register
+ and the imaginary part goes in the upper register. */
+ if (TARGET_NEWABI
+ && info.fpr_p
+ && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ {
+ rtx real, imag;
+ enum machine_mode inner;
+ int reg;
+
+ inner = GET_MODE_INNER (mode);
+ reg = FP_ARG_FIRST + info.reg_offset;
+ if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner))
+ {
+ /* Real part in registers, imaginary part on stack. */
+ gcc_assert (info.stack_words == info.reg_words);
+ return gen_rtx_REG (inner, reg);
+ }
+ else
+ {
+ gcc_assert (info.stack_words == 0);
+ real = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (inner, reg),
+ const0_rtx);
+ imag = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (inner,
+ reg + info.reg_words / 2),
+ GEN_INT (GET_MODE_SIZE (inner)));
+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag));
+ }
+ }
+
+ if (!info.fpr_p)
+ return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset);
+ else if (info.reg_offset == 1)
+ /* This code handles the special o32 case in which the second word
+ of the argument structure is passed in floating-point registers. */
+ return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC);
+ else
+ return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset);
+}
+
+
+/* Implement TARGET_ARG_PARTIAL_BYTES. */
+
+static int
+mips_arg_partial_bytes (CUMULATIVE_ARGS *cum,
+ enum machine_mode mode, tree type, bool named)
+{
+ struct mips_arg_info info;
+
+ mips_arg_info (cum, mode, type, named, &info);
+ return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0;
+}
+
+
+/* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least
+ PARM_BOUNDARY bits of alignment, but will be given anything up
+ to STACK_BOUNDARY bits if the type requires it. */
+
+int
+function_arg_boundary (enum machine_mode mode, tree type)
+{
+ unsigned int alignment;
+
+ alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode);
+ if (alignment < PARM_BOUNDARY)
+ alignment = PARM_BOUNDARY;
+ if (alignment > STACK_BOUNDARY)
+ alignment = STACK_BOUNDARY;
+ return alignment;
+}
+
+/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return
+ upward rather than downward. In other words, return true if the
+ first byte of the stack slot has useful data, false if the last
+ byte does. */
+
+bool
+mips_pad_arg_upward (enum machine_mode mode, tree type)
+{
+ /* On little-endian targets, the first byte of every stack argument
+ is passed in the first byte of the stack slot. */
+ if (!BYTES_BIG_ENDIAN)
+ return true;
+
+ /* Otherwise, integral types are padded downward: the last byte of a
+ stack argument is passed in the last byte of the stack slot. */
+ if (type != 0
+ ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
+ : GET_MODE_CLASS (mode) == MODE_INT)
+ return false;
+
+ /* Big-endian o64 pads floating-point arguments downward. */
+ if (mips_abi == ABI_O64)
+ if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
+ return false;
+
+ /* Other types are padded upward for o32, o64, n32 and n64. */
+ if (mips_abi != ABI_EABI)
+ return true;
+
+ /* Arguments smaller than a stack slot are padded downward. */
+ if (mode != BLKmode)
+ return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY);
+ else
+ return (int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT));
+}
+
+
+/* Likewise BLOCK_REG_PADDING (MODE, TYPE, ...). Return !BYTES_BIG_ENDIAN
+ if the least significant byte of the register has useful data. Return
+ the opposite if the most significant byte does. */
+
+bool
+mips_pad_reg_upward (enum machine_mode mode, tree type)
+{
+ /* No shifting is required for floating-point arguments. */
+ if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT)
+ return !BYTES_BIG_ENDIAN;
+
+ /* Otherwise, apply the same padding to register arguments as we do
+ to stack arguments. */
+ return mips_pad_arg_upward (mode, type);
+}
+
+static void
+mips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int *pretend_size ATTRIBUTE_UNUSED,
+ int no_rtl)
+{
+ CUMULATIVE_ARGS local_cum;
+ int gp_saved, fp_saved;
+
+ /* The caller has advanced CUM up to, but not beyond, the last named
+ argument. Advance a local copy of CUM past the last "real" named
+ argument, to find out how many registers are left over. */
+
+ local_cum = *cum;
+ FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
+
+ /* Found out how many registers we need to save. */
+ gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs;
+ fp_saved = (EABI_FLOAT_VARARGS_P
+ ? MAX_ARGS_IN_REGISTERS - local_cum.num_fprs
+ : 0);
+
+ if (!no_rtl)
+ {
+ if (gp_saved > 0)
+ {
+ rtx ptr, mem;
+
+ ptr = plus_constant (virtual_incoming_args_rtx,
+ REG_PARM_STACK_SPACE (cfun->decl)
+ - gp_saved * UNITS_PER_WORD);
+ mem = gen_rtx_MEM (BLKmode, ptr);
+ set_mem_alias_set (mem, get_varargs_alias_set ());
+
+ move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST,
+ mem, gp_saved);
+ }
+ if (fp_saved > 0)
+ {
+ /* We can't use move_block_from_reg, because it will use
+ the wrong mode. */
+ enum machine_mode mode;
+ int off, i;
+
+ /* Set OFF to the offset from virtual_incoming_args_rtx of
+ the first float register. The FP save area lies below
+ the integer one, and is aligned to UNITS_PER_FPVALUE bytes. */
+ off = -gp_saved * UNITS_PER_WORD;
+ off &= ~(UNITS_PER_FPVALUE - 1);
+ off -= fp_saved * UNITS_PER_FPREG;
+
+ mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode;
+
+ for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC)
+ {
+ rtx ptr, mem;
+
+ ptr = plus_constant (virtual_incoming_args_rtx, off);
+ mem = gen_rtx_MEM (mode, ptr);
+ set_mem_alias_set (mem, get_varargs_alias_set ());
+ emit_move_insn (mem, gen_rtx_REG (mode, FP_ARG_FIRST + i));
+ off += UNITS_PER_HWFPVALUE;
+ }
+ }
+ }
+ if (REG_PARM_STACK_SPACE (cfun->decl) == 0)
+ cfun->machine->varargs_size = (gp_saved * UNITS_PER_WORD
+ + fp_saved * UNITS_PER_FPREG);
+}
+
+/* Create the va_list data type.
+ We keep 3 pointers, and two offsets.
+ Two pointers are to the overflow area, which starts at the CFA.
+ One of these is constant, for addressing into the GPR save area below it.
+ The other is advanced up the stack through the overflow region.
+ The third pointer is to the GPR save area. Since the FPR save area
+ is just below it, we can address FPR slots off this pointer.
+ We also keep two one-byte offsets, which are to be subtracted from the
+ constant pointers to yield addresses in the GPR and FPR save areas.
+ These are downcounted as float or non-float arguments are used,
+ and when they get to zero, the argument must be obtained from the
+ overflow region.
+ If !EABI_FLOAT_VARARGS_P, then no FPR save area exists, and a single
+ pointer is enough. It's started at the GPR save area, and is
+ advanced, period.
+ Note that the GPR save area is not constant size, due to optimization
+ in the prologue. Hence, we can't use a design with two pointers
+ and two offsets, although we could have designed this with two pointers
+ and three offsets. */
+
+static tree
+mips_build_builtin_va_list (void)
+{
+ if (EABI_FLOAT_VARARGS_P)
+ {
+ tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff, f_res, record;
+ tree array, index;
+
+ record = (*lang_hooks.types.make_type) (RECORD_TYPE);
+
+ f_ovfl = build_decl (FIELD_DECL, get_identifier ("__overflow_argptr"),
+ ptr_type_node);
+ f_gtop = build_decl (FIELD_DECL, get_identifier ("__gpr_top"),
+ ptr_type_node);
+ f_ftop = build_decl (FIELD_DECL, get_identifier ("__fpr_top"),
+ ptr_type_node);
+ f_goff = build_decl (FIELD_DECL, get_identifier ("__gpr_offset"),
+ unsigned_char_type_node);
+ f_foff = build_decl (FIELD_DECL, get_identifier ("__fpr_offset"),
+ unsigned_char_type_node);
+ /* Explicitly pad to the size of a pointer, so that -Wpadded won't
+ warn on every user file. */
+ index = build_int_cst (NULL_TREE, GET_MODE_SIZE (ptr_mode) - 2 - 1);
+ array = build_array_type (unsigned_char_type_node,
+ build_index_type (index));
+ f_res = build_decl (FIELD_DECL, get_identifier ("__reserved"), array);
+
+ DECL_FIELD_CONTEXT (f_ovfl) = record;
+ DECL_FIELD_CONTEXT (f_gtop) = record;
+ DECL_FIELD_CONTEXT (f_ftop) = record;
+ DECL_FIELD_CONTEXT (f_goff) = record;
+ DECL_FIELD_CONTEXT (f_foff) = record;
+ DECL_FIELD_CONTEXT (f_res) = record;
+
+ TYPE_FIELDS (record) = f_ovfl;
+ TREE_CHAIN (f_ovfl) = f_gtop;
+ TREE_CHAIN (f_gtop) = f_ftop;
+ TREE_CHAIN (f_ftop) = f_goff;
+ TREE_CHAIN (f_goff) = f_foff;
+ TREE_CHAIN (f_foff) = f_res;
+
+ layout_type (record);
+ return record;
+ }
+ else if (TARGET_IRIX && TARGET_IRIX6)
+ /* On IRIX 6, this type is 'char *'. */
+ return build_pointer_type (char_type_node);
+ else
+ /* Otherwise, we use 'void *'. */
+ return ptr_type_node;
+}
+
+/* Implement va_start. */
+
+void
+mips_va_start (tree valist, rtx nextarg)
+{
+ if (EABI_FLOAT_VARARGS_P)
+ {
+ const CUMULATIVE_ARGS *cum;
+ tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
+ tree ovfl, gtop, ftop, goff, foff;
+ tree t;
+ int gpr_save_area_size;
+ int fpr_save_area_size;
+ int fpr_offset;
+
+ cum = &current_function_args_info;
+ gpr_save_area_size
+ = (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD;
+ fpr_save_area_size
+ = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG;
+
+ f_ovfl = TYPE_FIELDS (va_list_type_node);
+ f_gtop = TREE_CHAIN (f_ovfl);
+ f_ftop = TREE_CHAIN (f_gtop);
+ f_goff = TREE_CHAIN (f_ftop);
+ f_foff = TREE_CHAIN (f_goff);
+
+ ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+ NULL_TREE);
+ gtop = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+ NULL_TREE);
+ ftop = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+ NULL_TREE);
+ goff = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+ NULL_TREE);
+ foff = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+ NULL_TREE);
+
+ /* Emit code to initialize OVFL, which points to the next varargs
+ stack argument. CUM->STACK_WORDS gives the number of stack
+ words used by named arguments. */
+ t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx);
+ if (cum->stack_words > 0)
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), t,
+ build_int_cst (NULL_TREE,
+ cum->stack_words * UNITS_PER_WORD));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize GTOP, the top of the GPR save area. */
+ t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx);
+ t = build2 (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize FTOP, the top of the FPR save area.
+ This address is gpr_save_area_bytes below GTOP, rounded
+ down to the next fp-aligned boundary. */
+ t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx);
+ fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1;
+ fpr_offset &= ~(UNITS_PER_FPVALUE - 1);
+ if (fpr_offset)
+ t = build2 (PLUS_EXPR, TREE_TYPE (ftop), t,
+ build_int_cst (NULL_TREE, -fpr_offset));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t);
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Emit code to initialize GOFF, the offset from GTOP of the
+ next GPR argument. */
+ t = build2 (MODIFY_EXPR, TREE_TYPE (goff), goff,
+ build_int_cst (NULL_TREE, gpr_save_area_size));
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+
+ /* Likewise emit code to initialize FOFF, the offset from FTOP
+ of the next FPR argument. */
+ t = build2 (MODIFY_EXPR, TREE_TYPE (foff), foff,
+ build_int_cst (NULL_TREE, fpr_save_area_size));
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
+ else
+ {
+ nextarg = plus_constant (nextarg, -cfun->machine->varargs_size);
+ std_expand_builtin_va_start (valist, nextarg);
+ }
+}
+
+/* Implement va_arg. */
+
+static tree
+mips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p)
+{
+ HOST_WIDE_INT size, rsize;
+ tree addr;
+ bool indirect;
+
+ indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0);
+
+ if (indirect)
+ type = build_pointer_type (type);
+
+ size = int_size_in_bytes (type);
+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+
+ if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P)
+ addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
+ else
+ {
+ /* Not a simple merged stack. */
+
+ tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff;
+ tree ovfl, top, off, align;
+ HOST_WIDE_INT osize;
+ tree t, u;
+
+ f_ovfl = TYPE_FIELDS (va_list_type_node);
+ f_gtop = TREE_CHAIN (f_ovfl);
+ f_ftop = TREE_CHAIN (f_gtop);
+ f_goff = TREE_CHAIN (f_ftop);
+ f_foff = TREE_CHAIN (f_goff);
+
+ /* We maintain separate pointers and offsets for floating-point
+ and integer arguments, but we need similar code in both cases.
+ Let:
+
+ TOP be the top of the register save area;
+ OFF be the offset from TOP of the next register;
+ ADDR_RTX be the address of the argument;
+ RSIZE be the number of bytes used to store the argument
+ when it's in the register save area;
+ OSIZE be the number of bytes used to store it when it's
+ in the stack overflow area; and
+ PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0)
+
+ The code we want is:
+
+ 1: off &= -rsize; // round down
+ 2: if (off != 0)
+ 3: {
+ 4: addr_rtx = top - off;
+ 5: off -= rsize;
+ 6: }
+ 7: else
+ 8: {
+ 9: ovfl += ((intptr_t) ovfl + osize - 1) & -osize;
+ 10: addr_rtx = ovfl + PADDING;
+ 11: ovfl += osize;
+ 14: }
+
+ [1] and [9] can sometimes be optimized away. */
+
+ ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl,
+ NULL_TREE);
+
+ if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT
+ && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE)
+ {
+ top = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop,
+ NULL_TREE);
+ off = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff,
+ NULL_TREE);
+
+ /* When floating-point registers are saved to the stack,
+ each one will take up UNITS_PER_HWFPVALUE bytes, regardless
+ of the float's precision. */
+ rsize = UNITS_PER_HWFPVALUE;
+
+ /* Overflow arguments are padded to UNITS_PER_WORD bytes
+ (= PARM_BOUNDARY bits). This can be different from RSIZE
+ in two cases:
+
+ (1) On 32-bit targets when TYPE is a structure such as:
+
+ struct s { float f; };
+
+ Such structures are passed in paired FPRs, so RSIZE
+ will be 8 bytes. However, the structure only takes
+ up 4 bytes of memory, so OSIZE will only be 4.
+
+ (2) In combinations such as -mgp64 -msingle-float
+ -fshort-double. Doubles passed in registers
+ will then take up 4 (UNITS_PER_HWFPVALUE) bytes,
+ but those passed on the stack take up
+ UNITS_PER_WORD bytes. */
+ osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD);
+ }
+ else
+ {
+ top = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop,
+ NULL_TREE);
+ off = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff,
+ NULL_TREE);
+ if (rsize > UNITS_PER_WORD)
+ {
+ /* [1] Emit code for: off &= -rsize. */
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (off), off,
+ build_int_cst (NULL_TREE, -rsize));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (off), off, t);
+ gimplify_and_add (t, pre_p);
+ }
+ osize = rsize;
+ }
+
+ /* [2] Emit code to branch if off == 0. */
+ t = build2 (NE_EXPR, boolean_type_node, off,
+ build_int_cst (TREE_TYPE (off), 0));
+ addr = build3 (COND_EXPR, ptr_type_node, t, NULL_TREE, NULL_TREE);
+
+ /* [5] Emit code for: off -= rsize. We do this as a form of
+ post-increment not available to C. Also widen for the
+ coming pointer arithmetic. */
+ t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize));
+ t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t);
+ t = fold_convert (sizetype, t);
+ t = fold_convert (TREE_TYPE (top), t);
+
+ /* [4] Emit code for: addr_rtx = top - off. On big endian machines,
+ the argument has RSIZE - SIZE bytes of leading padding. */
+ t = build2 (MINUS_EXPR, TREE_TYPE (top), top, t);
+ if (BYTES_BIG_ENDIAN && rsize > size)
+ {
+ u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE,
+ rsize - size));
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
+ }
+ COND_EXPR_THEN (addr) = t;
+
+ if (osize > UNITS_PER_WORD)
+ {
+ /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */
+ u = fold_convert (TREE_TYPE (ovfl),
+ build_int_cst (NULL_TREE, osize - 1));
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u);
+ u = fold_convert (TREE_TYPE (ovfl),
+ build_int_cst (NULL_TREE, -osize));
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u);
+ align = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t);
+ }
+ else
+ align = NULL;
+
+ /* [10, 11]. Emit code to store ovfl in addr_rtx, then
+ post-increment ovfl by osize. On big-endian machines,
+ the argument has OSIZE - SIZE bytes of leading padding. */
+ u = fold_convert (TREE_TYPE (ovfl),
+ build_int_cst (NULL_TREE, osize));
+ t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u);
+ if (BYTES_BIG_ENDIAN && osize > size)
+ {
+ u = fold_convert (TREE_TYPE (t),
+ build_int_cst (NULL_TREE, osize - size));
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u);
+ }
+
+ /* String [9] and [10,11] together. */
+ if (align)
+ t = build2 (COMPOUND_EXPR, TREE_TYPE (t), align, t);
+ COND_EXPR_ELSE (addr) = t;
+
+ addr = fold_convert (build_pointer_type (type), addr);
+ addr = build_va_arg_indirect_ref (addr);
+ }
+
+ if (indirect)
+ addr = build_va_arg_indirect_ref (addr);
+
+ return addr;
+}
+
+/* Return true if it is possible to use left/right accesses for a
+ bitfield of WIDTH bits starting BITPOS bits into *OP. When
+ returning true, update *OP, *LEFT and *RIGHT as follows:
+
+ *OP is a BLKmode reference to the whole field.
+
+ *LEFT is a QImode reference to the first byte if big endian or
+ the last byte if little endian. This address can be used in the
+ left-side instructions (lwl, swl, ldl, sdl).
+
+ *RIGHT is a QImode reference to the opposite end of the field and
+ can be used in the patterning right-side instruction. */
+
+static bool
+mips_get_unaligned_mem (rtx *op, unsigned int width, int bitpos,
+ rtx *left, rtx *right)
+{
+ rtx first, last;
+
+ /* Check that the operand really is a MEM. Not all the extv and
+ extzv predicates are checked. */
+ if (!MEM_P (*op))
+ return false;
+
+ /* Check that the size is valid. */
+ if (width != 32 && (!TARGET_64BIT || width != 64))
+ return false;
+
+ /* We can only access byte-aligned values. Since we are always passed
+ a reference to the first byte of the field, it is not necessary to
+ do anything with BITPOS after this check. */
+ if (bitpos % BITS_PER_UNIT != 0)
+ return false;
+
+ /* Reject aligned bitfields: we want to use a normal load or store
+ instead of a left/right pair. */
+ if (MEM_ALIGN (*op) >= width)
+ return false;
+
+ /* Adjust *OP to refer to the whole field. This also has the effect
+ of legitimizing *OP's address for BLKmode, possibly simplifying it. */
+ *op = adjust_address (*op, BLKmode, 0);
+ set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT));
+
+ /* Get references to both ends of the field. We deliberately don't
+ use the original QImode *OP for FIRST since the new BLKmode one
+ might have a simpler address. */
+ first = adjust_address (*op, QImode, 0);
+ last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1);
+
+ /* Allocate to LEFT and RIGHT according to endianness. LEFT should
+ be the upper word and RIGHT the lower word. */
+ if (TARGET_BIG_ENDIAN)
+ *left = first, *right = last;
+ else
+ *left = last, *right = first;
+
+ return true;
+}
+
+
+/* Try to emit the equivalent of (set DEST (zero_extract SRC WIDTH BITPOS)).
+ Return true on success. We only handle cases where zero_extract is
+ equivalent to sign_extract. */
+
+bool
+mips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos)
+{
+ rtx left, right, temp;
+
+ /* If TARGET_64BIT, the destination of a 32-bit load will be a
+ paradoxical word_mode subreg. This is the only case in which
+ we allow the destination to be larger than the source. */
+ if (GET_CODE (dest) == SUBREG
+ && GET_MODE (dest) == DImode
+ && SUBREG_BYTE (dest) == 0
+ && GET_MODE (SUBREG_REG (dest)) == SImode)
+ dest = SUBREG_REG (dest);
+
+ /* After the above adjustment, the destination must be the same
+ width as the source. */
+ if (GET_MODE_BITSIZE (GET_MODE (dest)) != width)
+ return false;
+
+ if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right))
+ return false;
+
+ temp = gen_reg_rtx (GET_MODE (dest));
+ if (GET_MODE (dest) == DImode)
+ {
+ emit_insn (gen_mov_ldl (temp, src, left));
+ emit_insn (gen_mov_ldr (dest, copy_rtx (src), right, temp));
+ }
+ else
+ {
+ emit_insn (gen_mov_lwl (temp, src, left));
+ emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp));
+ }
+ return true;
+}
+
+
+/* Try to expand (set (zero_extract DEST WIDTH BITPOS) SRC). Return
+ true on success. */
+
+bool
+mips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos)
+{
+ rtx left, right;
+ enum machine_mode mode;
+
+ if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right))
+ return false;
+
+ mode = mode_for_size (width, MODE_INT, 0);
+ src = gen_lowpart (mode, src);
+
+ if (mode == DImode)
+ {
+ emit_insn (gen_mov_sdl (dest, src, left));
+ emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right));
+ }
+ else
+ {
+ emit_insn (gen_mov_swl (dest, src, left));
+ emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right));
+ }
+ return true;
+}
+
+/* Return true if X is a MEM with the same size as MODE. */
+
+bool
+mips_mem_fits_mode_p (enum machine_mode mode, rtx x)
+{
+ rtx size;
+
+ if (!MEM_P (x))
+ return false;
+
+ size = MEM_SIZE (x);
+ return size && INTVAL (size) == GET_MODE_SIZE (mode);
+}
+
+/* Return true if (zero_extract OP SIZE POSITION) can be used as the
+ source of an "ext" instruction or the destination of an "ins"
+ instruction. OP must be a register operand and the following
+ conditions must hold:
+
+ 0 <= POSITION < GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+ 0 < POSITION + SIZE <= GET_MODE_BITSIZE (GET_MODE (op))
+
+ Also reject lengths equal to a word as they are better handled
+ by the move patterns. */
+
+bool
+mips_use_ins_ext_p (rtx op, rtx size, rtx position)
+{
+ HOST_WIDE_INT len, pos;
+
+ if (!ISA_HAS_EXT_INS
+ || !register_operand (op, VOIDmode)
+ || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD)
+ return false;
+
+ len = INTVAL (size);
+ pos = INTVAL (position);
+
+ if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op))
+ || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op)))
+ return false;
+
+ return true;
+}
+
+/* Set up globals to generate code for the ISA or processor
+ described by INFO. */
+
+static void
+mips_set_architecture (const struct mips_cpu_info *info)
+{
+ if (info != 0)
+ {
+ mips_arch_info = info;
+ mips_arch = info->cpu;
+ mips_isa = info->isa;
+ }
+}
+
+
+/* Likewise for tuning. */
+
+static void
+mips_set_tune (const struct mips_cpu_info *info)
+{
+ if (info != 0)
+ {
+ mips_tune_info = info;
+ mips_tune = info->cpu;
+ }
+}
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+mips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_mabi_:
+ if (strcmp (arg, "32") == 0)
+ mips_abi = ABI_32;
+ else if (strcmp (arg, "o64") == 0)
+ mips_abi = ABI_O64;
+ else if (strcmp (arg, "n32") == 0)
+ mips_abi = ABI_N32;
+ else if (strcmp (arg, "64") == 0)
+ mips_abi = ABI_64;
+ else if (strcmp (arg, "eabi") == 0)
+ mips_abi = ABI_EABI;
+ else
+ return false;
+ return true;
+
+ case OPT_march_:
+ case OPT_mtune_:
+ return mips_parse_cpu (arg) != 0;
+
+ case OPT_mips:
+ mips_isa_info = mips_parse_cpu (ACONCAT (("mips", arg, NULL)));
+ return mips_isa_info != 0;
+
+ case OPT_mno_flush_func:
+ mips_cache_flush_func = NULL;
+ return true;
+
+ default:
+ return true;
+ }
+}
+
+/* Set up the threshold for data to go into the small data area, instead
+ of the normal data area, and detect any conflicts in the switches. */
+
+void
+override_options (void)
+{
+ int i, start, regno;
+ enum machine_mode mode;
+
+ mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE;
+
+ /* The following code determines the architecture and register size.
+ Similar code was added to GAS 2.14 (see tc-mips.c:md_after_parse_args()).
+ The GAS and GCC code should be kept in sync as much as possible. */
+
+ if (mips_arch_string != 0)
+ mips_set_architecture (mips_parse_cpu (mips_arch_string));
+
+ if (mips_isa_info != 0)
+ {
+ if (mips_arch_info == 0)
+ mips_set_architecture (mips_isa_info);
+ else if (mips_arch_info->isa != mips_isa_info->isa)
+ error ("-%s conflicts with the other architecture options, "
+ "which specify a %s processor",
+ mips_isa_info->name,
+ mips_cpu_info_from_isa (mips_arch_info->isa)->name);
+ }
+
+ if (mips_arch_info == 0)
+ {
+#ifdef MIPS_CPU_STRING_DEFAULT
+ mips_set_architecture (mips_parse_cpu (MIPS_CPU_STRING_DEFAULT));
+#else
+ mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT));
+#endif
+ }
+
+ if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS)
+ error ("-march=%s is not compatible with the selected ABI",
+ mips_arch_info->name);
+
+ /* Optimize for mips_arch, unless -mtune selects a different processor. */
+ if (mips_tune_string != 0)
+ mips_set_tune (mips_parse_cpu (mips_tune_string));
+
+ if (mips_tune_info == 0)
+ mips_set_tune (mips_arch_info);
+
+ /* Set cost structure for the processor. */
+ mips_cost = &mips_rtx_cost_data[mips_tune];
+
+ if ((target_flags_explicit & MASK_64BIT) != 0)
+ {
+ /* The user specified the size of the integer registers. Make sure
+ it agrees with the ABI and ISA. */
+ if (TARGET_64BIT && !ISA_HAS_64BIT_REGS)
+ error ("-mgp64 used with a 32-bit processor");
+ else if (!TARGET_64BIT && ABI_NEEDS_64BIT_REGS)
+ error ("-mgp32 used with a 64-bit ABI");
+ else if (TARGET_64BIT && ABI_NEEDS_32BIT_REGS)
+ error ("-mgp64 used with a 32-bit ABI");
+ }
+ else
+ {
+ /* Infer the integer register size from the ABI and processor.
+ Restrict ourselves to 32-bit registers if that's all the
+ processor has, or if the ABI cannot handle 64-bit registers. */
+ if (ABI_NEEDS_32BIT_REGS || !ISA_HAS_64BIT_REGS)
+ target_flags &= ~MASK_64BIT;
+ else
+ target_flags |= MASK_64BIT;
+ }
+
+ if ((target_flags_explicit & MASK_FLOAT64) != 0)
+ {
+ /* Really, -mfp32 and -mfp64 are ornamental options. There's
+ only one right answer here. */
+ if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64)
+ error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float");
+ else if (!TARGET_64BIT && TARGET_FLOAT64)
+ error ("unsupported combination: %s", "-mgp32 -mfp64");
+ else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64)
+ error ("unsupported combination: %s", "-mfp64 -msingle-float");
+ }
+ else
+ {
+ /* -msingle-float selects 32-bit float registers. Otherwise the
+ float registers should be the same size as the integer ones. */
+ if (TARGET_64BIT && TARGET_DOUBLE_FLOAT)
+ target_flags |= MASK_FLOAT64;
+ else
+ target_flags &= ~MASK_FLOAT64;
+ }
+
+ /* End of code shared with GAS. */
+
+ if ((target_flags_explicit & MASK_LONG64) == 0)
+ {
+ if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64)
+ target_flags |= MASK_LONG64;
+ else
+ target_flags &= ~MASK_LONG64;
+ }
+
+ if (MIPS_MARCH_CONTROLS_SOFT_FLOAT
+ && (target_flags_explicit & MASK_SOFT_FLOAT) == 0)
+ {
+ /* For some configurations, it is useful to have -march control
+ the default setting of MASK_SOFT_FLOAT. */
+ switch ((int) mips_arch)
+ {
+ case PROCESSOR_R4100:
+ case PROCESSOR_R4111:
+ case PROCESSOR_R4120:
+ case PROCESSOR_R4130:
+ target_flags |= MASK_SOFT_FLOAT;
+ break;
+
+ default:
+ target_flags &= ~MASK_SOFT_FLOAT;
+ break;
+ }
+ }
+
+ if (!TARGET_OLDABI)
+ flag_pcc_struct_return = 0;
+
+ if ((target_flags_explicit & MASK_BRANCHLIKELY) == 0)
+ {
+ /* If neither -mbranch-likely nor -mno-branch-likely was given
+ on the command line, set MASK_BRANCHLIKELY based on the target
+ architecture.
+
+ By default, we enable use of Branch Likely instructions on
+ all architectures which support them with the following
+ exceptions: when creating MIPS32 or MIPS64 code, and when
+ tuning for architectures where their use tends to hurt
+ performance.
+
+ The MIPS32 and MIPS64 architecture specifications say "Software
+ is strongly encouraged to avoid use of Branch Likely
+ instructions, as they will be removed from a future revision
+ of the [MIPS32 and MIPS64] architecture." Therefore, we do not
+ issue those instructions unless instructed to do so by
+ -mbranch-likely. */
+ if (ISA_HAS_BRANCHLIKELY
+ && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64)
+ && !(TUNE_MIPS5500 || TUNE_SB1))
+ target_flags |= MASK_BRANCHLIKELY;
+ else
+ target_flags &= ~MASK_BRANCHLIKELY;
+ }
+ if (TARGET_BRANCHLIKELY && !ISA_HAS_BRANCHLIKELY)
+ warning (0, "generation of Branch Likely instructions enabled, but not supported by architecture");
+
+ /* The effect of -mabicalls isn't defined for the EABI. */
+ if (mips_abi == ABI_EABI && TARGET_ABICALLS)
+ {
+ error ("unsupported combination: %s", "-mabicalls -mabi=eabi");
+ target_flags &= ~MASK_ABICALLS;
+ }
+
+ if (TARGET_ABICALLS)
+ {
+ /* We need to set flag_pic for executables as well as DSOs
+ because we may reference symbols that are not defined in
+ the final executable. (MIPS does not use things like
+ copy relocs, for example.)
+
+ Also, there is a body of code that uses __PIC__ to distinguish
+ between -mabicalls and -mno-abicalls code. */
+ flag_pic = 1;
+ if (mips_section_threshold > 0)
+ warning (0, "%<-G%> is incompatible with %<-mabicalls%>");
+ }
+
+ /* mips_split_addresses is a half-way house between explicit
+ relocations and the traditional assembler macros. It can
+ split absolute 32-bit symbolic constants into a high/lo_sum
+ pair but uses macros for other sorts of access.
+
+ Like explicit relocation support for REL targets, it relies
+ on GNU extensions in the assembler and the linker.
+
+ Although this code should work for -O0, it has traditionally
+ been treated as an optimization. */
+ if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES
+ && optimize && !flag_pic
+ && !ABI_HAS_64BIT_SYMBOLS)
+ mips_split_addresses = 1;
+ else
+ mips_split_addresses = 0;
+
+ /* -mvr4130-align is a "speed over size" optimization: it usually produces
+ faster code, but at the expense of more nops. Enable it at -O3 and
+ above. */
+ if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0)
+ target_flags |= MASK_VR4130_ALIGN;
+
+ /* When compiling for the mips16, we cannot use floating point. We
+ record the original hard float value in mips16_hard_float. */
+ if (TARGET_MIPS16)
+ {
+ if (TARGET_SOFT_FLOAT)
+ mips16_hard_float = 0;
+ else
+ mips16_hard_float = 1;
+ target_flags |= MASK_SOFT_FLOAT;
+
+ /* Don't run the scheduler before reload, since it tends to
+ increase register pressure. */
+ flag_schedule_insns = 0;
+
+ /* Don't do hot/cold partitioning. The constant layout code expects
+ the whole function to be in a single section. */
+ flag_reorder_blocks_and_partition = 0;
+
+ /* Silently disable -mexplicit-relocs since it doesn't apply
+ to mips16 code. Even so, it would overly pedantic to warn
+ about "-mips16 -mexplicit-relocs", especially given that
+ we use a %gprel() operator. */
+ target_flags &= ~MASK_EXPLICIT_RELOCS;
+ }
+
+ /* When using explicit relocs, we call dbr_schedule from within
+ mips_reorg. */
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ mips_flag_delayed_branch = flag_delayed_branch;
+ flag_delayed_branch = 0;
+ }
+
+#ifdef MIPS_TFMODE_FORMAT
+ REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT;
+#endif
+
+ /* Make sure that the user didn't turn off paired single support when
+ MIPS-3D support is requested. */
+ if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE_FLOAT)
+ && !TARGET_PAIRED_SINGLE_FLOAT)
+ error ("-mips3d requires -mpaired-single");
+
+ /* If TARGET_MIPS3D, enable MASK_PAIRED_SINGLE_FLOAT. */
+ if (TARGET_MIPS3D)
+ target_flags |= MASK_PAIRED_SINGLE_FLOAT;
+
+ /* Make sure that when TARGET_PAIRED_SINGLE_FLOAT is true, TARGET_FLOAT64
+ and TARGET_HARD_FLOAT are both true. */
+ if (TARGET_PAIRED_SINGLE_FLOAT && !(TARGET_FLOAT64 && TARGET_HARD_FLOAT))
+ error ("-mips3d/-mpaired-single must be used with -mfp64 -mhard-float");
+
+ /* Make sure that the ISA supports TARGET_PAIRED_SINGLE_FLOAT when it is
+ enabled. */
+ if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64)
+ error ("-mips3d/-mpaired-single must be used with -mips64");
+
+ if (TARGET_MIPS16 && TARGET_DSP)
+ error ("-mips16 and -mdsp cannot be used together");
+
+ mips_print_operand_punct['?'] = 1;
+ mips_print_operand_punct['#'] = 1;
+ mips_print_operand_punct['/'] = 1;
+ mips_print_operand_punct['&'] = 1;
+ mips_print_operand_punct['!'] = 1;
+ mips_print_operand_punct['*'] = 1;
+ mips_print_operand_punct['@'] = 1;
+ mips_print_operand_punct['.'] = 1;
+ mips_print_operand_punct['('] = 1;
+ mips_print_operand_punct[')'] = 1;
+ mips_print_operand_punct['['] = 1;
+ mips_print_operand_punct[']'] = 1;
+ mips_print_operand_punct['<'] = 1;
+ mips_print_operand_punct['>'] = 1;
+ mips_print_operand_punct['{'] = 1;
+ mips_print_operand_punct['}'] = 1;
+ mips_print_operand_punct['^'] = 1;
+ mips_print_operand_punct['$'] = 1;
+ mips_print_operand_punct['+'] = 1;
+ mips_print_operand_punct['~'] = 1;
+
+ /* Set up array to map GCC register number to debug register number.
+ Ignore the special purpose register numbers. */
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ mips_dbx_regno[i] = -1;
+
+ start = GP_DBX_FIRST - GP_REG_FIRST;
+ for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++)
+ mips_dbx_regno[i] = i + start;
+
+ start = FP_DBX_FIRST - FP_REG_FIRST;
+ for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++)
+ mips_dbx_regno[i] = i + start;
+
+ mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0;
+ mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1;
+
+ /* Set up array giving whether a given register can hold a given mode. */
+
+ for (mode = VOIDmode;
+ mode != MAX_MACHINE_MODE;
+ mode = (enum machine_mode) ((int)mode + 1))
+ {
+ register int size = GET_MODE_SIZE (mode);
+ register enum mode_class class = GET_MODE_CLASS (mode);
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ {
+ register int temp;
+
+ if (mode == CCV2mode)
+ temp = (ISA_HAS_8CC
+ && ST_REG_P (regno)
+ && (regno - ST_REG_FIRST) % 2 == 0);
+
+ else if (mode == CCV4mode)
+ temp = (ISA_HAS_8CC
+ && ST_REG_P (regno)
+ && (regno - ST_REG_FIRST) % 4 == 0);
+
+ else if (mode == CCmode)
+ {
+ if (! ISA_HAS_8CC)
+ temp = (regno == FPSW_REGNUM);
+ else
+ temp = (ST_REG_P (regno) || GP_REG_P (regno)
+ || FP_REG_P (regno));
+ }
+
+ else if (GP_REG_P (regno))
+ temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD);
+
+ else if (FP_REG_P (regno))
+ temp = ((regno % FP_INC) == 0)
+ && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT
+ || class == MODE_VECTOR_FLOAT)
+ && size <= UNITS_PER_FPVALUE)
+ /* Allow integer modes that fit into a single
+ register. We need to put integers into FPRs
+ when using instructions like cvt and trunc.
+ We can't allow sizes smaller than a word,
+ the FPU has no appropriate load/store
+ instructions for those. */
+ || (class == MODE_INT
+ && size >= MIN_UNITS_PER_WORD
+ && size <= UNITS_PER_FPREG)
+ /* Allow TFmode for CCmode reloads. */
+ || (ISA_HAS_8CC && mode == TFmode));
+
+ else if (ACC_REG_P (regno))
+ temp = (INTEGRAL_MODE_P (mode)
+ && (size <= UNITS_PER_WORD
+ || (ACC_HI_REG_P (regno)
+ && size == 2 * UNITS_PER_WORD)));
+
+ else if (ALL_COP_REG_P (regno))
+ temp = (class == MODE_INT && size <= UNITS_PER_WORD);
+ else
+ temp = 0;
+
+ mips_hard_regno_mode_ok[(int)mode][regno] = temp;
+ }
+ }
+
+ /* Save GPR registers in word_mode sized hunks. word_mode hasn't been
+ initialized yet, so we can't use that here. */
+ gpr_mode = TARGET_64BIT ? DImode : SImode;
+
+ /* Provide default values for align_* for 64-bit targets. */
+ if (TARGET_64BIT && !TARGET_MIPS16)
+ {
+ if (align_loops == 0)
+ align_loops = 8;
+ if (align_jumps == 0)
+ align_jumps = 8;
+ if (align_functions == 0)
+ align_functions = 8;
+ }
+
+ /* Function to allocate machine-dependent function status. */
+ init_machine_status = &mips_init_machine_status;
+
+ if (ABI_HAS_64BIT_SYMBOLS)
+ {
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ mips_split_p[SYMBOL_64_HIGH] = true;
+ mips_hi_relocs[SYMBOL_64_HIGH] = "%highest(";
+ mips_lo_relocs[SYMBOL_64_HIGH] = "%higher(";
+
+ mips_split_p[SYMBOL_64_MID] = true;
+ mips_hi_relocs[SYMBOL_64_MID] = "%higher(";
+ mips_lo_relocs[SYMBOL_64_MID] = "%hi(";
+
+ mips_split_p[SYMBOL_64_LOW] = true;
+ mips_hi_relocs[SYMBOL_64_LOW] = "%hi(";
+ mips_lo_relocs[SYMBOL_64_LOW] = "%lo(";
+
+ mips_split_p[SYMBOL_GENERAL] = true;
+ mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
+ }
+ }
+ else
+ {
+ if (TARGET_EXPLICIT_RELOCS || mips_split_addresses)
+ {
+ mips_split_p[SYMBOL_GENERAL] = true;
+ mips_hi_relocs[SYMBOL_GENERAL] = "%hi(";
+ mips_lo_relocs[SYMBOL_GENERAL] = "%lo(";
+ }
+ }
+
+ if (TARGET_MIPS16)
+ {
+ /* The high part is provided by a pseudo copy of $gp. */
+ mips_split_p[SYMBOL_SMALL_DATA] = true;
+ mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel(";
+ }
+
+ if (TARGET_EXPLICIT_RELOCS)
+ {
+ /* Small data constants are kept whole until after reload,
+ then lowered by mips_rewrite_small_data. */
+ mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel(";
+
+ mips_split_p[SYMBOL_GOT_LOCAL] = true;
+ if (TARGET_NEWABI)
+ {
+ mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page(";
+ mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%got_ofst(";
+ }
+ else
+ {
+ mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got(";
+ mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%lo(";
+ }
+
+ if (TARGET_XGOT)
+ {
+ /* The HIGH and LO_SUM are matched by special .md patterns. */
+ mips_split_p[SYMBOL_GOT_GLOBAL] = true;
+
+ mips_split_p[SYMBOL_GOTOFF_GLOBAL] = true;
+ mips_hi_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_hi(";
+ mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_lo(";
+
+ mips_split_p[SYMBOL_GOTOFF_CALL] = true;
+ mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi(";
+ mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo(";
+ }
+ else
+ {
+ if (TARGET_NEWABI)
+ mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_disp(";
+ else
+ mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got(";
+ mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16(";
+ }
+ }
+
+ if (TARGET_NEWABI)
+ {
+ mips_split_p[SYMBOL_GOTOFF_LOADGP] = true;
+ mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel(";
+ mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel(";
+ }
+
+ /* Thread-local relocation operators. */
+ mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd(";
+ mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm(";
+ mips_split_p[SYMBOL_DTPREL] = 1;
+ mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi(";
+ mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo(";
+ mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel(";
+ mips_split_p[SYMBOL_TPREL] = 1;
+ mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi(";
+ mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo(";
+
+ /* We don't have a thread pointer access instruction on MIPS16, or
+ appropriate TLS relocations. */
+ if (TARGET_MIPS16)
+ targetm.have_tls = false;
+
+ /* Default to working around R4000 errata only if the processor
+ was selected explicitly. */
+ if ((target_flags_explicit & MASK_FIX_R4000) == 0
+ && mips_matching_cpu_name_p (mips_arch_info->name, "r4000"))
+ target_flags |= MASK_FIX_R4000;
+
+ /* Default to working around R4400 errata only if the processor
+ was selected explicitly. */
+ if ((target_flags_explicit & MASK_FIX_R4400) == 0
+ && mips_matching_cpu_name_p (mips_arch_info->name, "r4400"))
+ target_flags |= MASK_FIX_R4400;
+}
+
+/* Implement CONDITIONAL_REGISTER_USAGE. */
+
+void
+mips_conditional_register_usage (void)
+{
+ if (!TARGET_DSP)
+ {
+ int regno;
+
+ for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ }
+ if (!TARGET_HARD_FLOAT)
+ {
+ int regno;
+
+ for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ }
+ else if (! ISA_HAS_8CC)
+ {
+ int regno;
+
+ /* We only have a single condition code register. We
+ implement this by hiding all the condition code registers,
+ and generating RTL that refers directly to ST_REG_FIRST. */
+ for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
+ fixed_regs[regno] = call_used_regs[regno] = 1;
+ }
+ /* In mips16 mode, we permit the $t temporary registers to be used
+ for reload. We prohibit the unused $s registers, since they
+ are caller saved, and saving them via a mips16 register would
+ probably waste more time than just reloading the value. */
+ if (TARGET_MIPS16)
+ {
+ fixed_regs[18] = call_used_regs[18] = 1;
+ fixed_regs[19] = call_used_regs[19] = 1;
+ fixed_regs[20] = call_used_regs[20] = 1;
+ fixed_regs[21] = call_used_regs[21] = 1;
+ fixed_regs[22] = call_used_regs[22] = 1;
+ fixed_regs[23] = call_used_regs[23] = 1;
+ fixed_regs[26] = call_used_regs[26] = 1;
+ fixed_regs[27] = call_used_regs[27] = 1;
+ fixed_regs[30] = call_used_regs[30] = 1;
+ }
+ /* fp20-23 are now caller saved. */
+ if (mips_abi == ABI_64)
+ {
+ int regno;
+ for (regno = FP_REG_FIRST + 20; regno < FP_REG_FIRST + 24; regno++)
+ call_really_used_regs[regno] = call_used_regs[regno] = 1;
+ }
+ /* Odd registers from fp21 to fp31 are now caller saved. */
+ if (mips_abi == ABI_N32)
+ {
+ int regno;
+ for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2)
+ call_really_used_regs[regno] = call_used_regs[regno] = 1;
+ }
+}
+
+/* Allocate a chunk of memory for per-function machine-dependent data. */
+static struct machine_function *
+mips_init_machine_status (void)
+{
+ return ((struct machine_function *)
+ ggc_alloc_cleared (sizeof (struct machine_function)));
+}
+
+/* On the mips16, we want to allocate $24 (T_REG) before other
+ registers for instructions for which it is possible. This helps
+ avoid shuffling registers around in order to set up for an xor,
+ encouraging the compiler to use a cmp instead. */
+
+void
+mips_order_regs_for_local_alloc (void)
+{
+ register int i;
+
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ reg_alloc_order[i] = i;
+
+ if (TARGET_MIPS16)
+ {
+ /* It really doesn't matter where we put register 0, since it is
+ a fixed register anyhow. */
+ reg_alloc_order[0] = 24;
+ reg_alloc_order[24] = 0;
+ }
+}
+
+
+/* The MIPS debug format wants all automatic variables and arguments
+ to be in terms of the virtual frame pointer (stack pointer before
+ any adjustment in the function), while the MIPS 3.0 linker wants
+ the frame pointer to be the stack pointer after the initial
+ adjustment. So, we do the adjustment here. The arg pointer (which
+ is eliminated) points to the virtual frame pointer, while the frame
+ pointer (which may be eliminated) points to the stack pointer after
+ the initial adjustments. */
+
+HOST_WIDE_INT
+mips_debugger_offset (rtx addr, HOST_WIDE_INT offset)
+{
+ rtx offset2 = const0_rtx;
+ rtx reg = eliminate_constant_term (addr, &offset2);
+
+ if (offset == 0)
+ offset = INTVAL (offset2);
+
+ if (reg == stack_pointer_rtx || reg == frame_pointer_rtx
+ || reg == hard_frame_pointer_rtx)
+ {
+ HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized)
+ ? compute_frame_size (get_frame_size ())
+ : cfun->machine->frame.total_size;
+
+ /* MIPS16 frame is smaller */
+ if (frame_pointer_needed && TARGET_MIPS16)
+ frame_size -= cfun->machine->frame.args_size;
+
+ offset = offset - frame_size;
+ }
+
+ /* sdbout_parms does not want this to crash for unrecognized cases. */
+#if 0
+ else if (reg != arg_pointer_rtx)
+ fatal_insn ("mips_debugger_offset called with non stack/frame/arg pointer",
+ addr);
+#endif
+
+ return offset;
+}
+
+/* Implement the PRINT_OPERAND macro. The MIPS-specific operand codes are:
+
+ 'X' OP is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x",
+ 'x' OP is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x",
+ 'h' OP is HIGH, prints %hi(X),
+ 'd' output integer constant in decimal,
+ 'z' if the operand is 0, use $0 instead of normal operand.
+ 'D' print second part of double-word register or memory operand.
+ 'L' print low-order register of double-word register operand.
+ 'M' print high-order register of double-word register operand.
+ 'C' print part of opcode for a branch condition.
+ 'F' print part of opcode for a floating-point branch condition.
+ 'N' print part of opcode for a branch condition, inverted.
+ 'W' print part of opcode for a floating-point branch condition, inverted.
+ 'T' print 'f' for (eq:CC ...), 't' for (ne:CC ...),
+ 'z' for (eq:?I ...), 'n' for (ne:?I ...).
+ 't' like 'T', but with the EQ/NE cases reversed
+ 'Y' for a CONST_INT X, print mips_fp_conditions[X]
+ 'Z' print the operand and a comma for ISA_HAS_8CC, otherwise print nothing
+ 'R' print the reloc associated with LO_SUM
+ 'q' print DSP accumulator registers
+
+ The punctuation characters are:
+
+ '(' Turn on .set noreorder
+ ')' Turn on .set reorder
+ '[' Turn on .set noat
+ ']' Turn on .set at
+ '<' Turn on .set nomacro
+ '>' Turn on .set macro
+ '{' Turn on .set volatile (not GAS)
+ '}' Turn on .set novolatile (not GAS)
+ '&' Turn on .set noreorder if filling delay slots
+ '*' Turn on both .set noreorder and .set nomacro if filling delay slots
+ '!' Turn on .set nomacro if filling delay slots
+ '#' Print nop if in a .set noreorder section.
+ '/' Like '#', but does nothing within a delayed branch sequence
+ '?' Print 'l' if we are to use a branch likely instead of normal branch.
+ '@' Print the name of the assembler temporary register (at or $1).
+ '.' Print the name of the register with a hard-wired zero (zero or $0).
+ '^' Print the name of the pic call-through register (t9 or $25).
+ '$' Print the name of the stack pointer register (sp or $29).
+ '+' Print the name of the gp register (usually gp or $28).
+ '~' Output a branch alignment to LABEL_ALIGN(NULL). */
+
+void
+print_operand (FILE *file, rtx op, int letter)
+{
+ register enum rtx_code code;
+
+ if (PRINT_OPERAND_PUNCT_VALID_P (letter))
+ {
+ switch (letter)
+ {
+ case '?':
+ if (mips_branch_likely)
+ putc ('l', file);
+ break;
+
+ case '@':
+ fputs (reg_names [GP_REG_FIRST + 1], file);
+ break;
+
+ case '^':
+ fputs (reg_names [PIC_FUNCTION_ADDR_REGNUM], file);
+ break;
+
+ case '.':
+ fputs (reg_names [GP_REG_FIRST + 0], file);
+ break;
+
+ case '$':
+ fputs (reg_names[STACK_POINTER_REGNUM], file);
+ break;
+
+ case '+':
+ fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file);
+ break;
+
+ case '&':
+ if (final_sequence != 0 && set_noreorder++ == 0)
+ fputs (".set\tnoreorder\n\t", file);
+ break;
+
+ case '*':
+ if (final_sequence != 0)
+ {
+ if (set_noreorder++ == 0)
+ fputs (".set\tnoreorder\n\t", file);
+
+ if (set_nomacro++ == 0)
+ fputs (".set\tnomacro\n\t", file);
+ }
+ break;
+
+ case '!':
+ if (final_sequence != 0 && set_nomacro++ == 0)
+ fputs ("\n\t.set\tnomacro", file);
+ break;
+
+ case '#':
+ if (set_noreorder != 0)
+ fputs ("\n\tnop", file);
+ break;
+
+ case '/':
+ /* Print an extra newline so that the delayed insn is separated
+ from the following ones. This looks neater and is consistent
+ with non-nop delayed sequences. */
+ if (set_noreorder != 0 && final_sequence == 0)
+ fputs ("\n\tnop\n", file);
+ break;
+
+ case '(':
+ if (set_noreorder++ == 0)
+ fputs (".set\tnoreorder\n\t", file);
+ break;
+
+ case ')':
+ if (set_noreorder == 0)
+ error ("internal error: %%) found without a %%( in assembler pattern");
+
+ else if (--set_noreorder == 0)
+ fputs ("\n\t.set\treorder", file);
+
+ break;
+
+ case '[':
+ if (set_noat++ == 0)
+ fputs (".set\tnoat\n\t", file);
+ break;
+
+ case ']':
+ if (set_noat == 0)
+ error ("internal error: %%] found without a %%[ in assembler pattern");
+ else if (--set_noat == 0)
+ fputs ("\n\t.set\tat", file);
+
+ break;
+
+ case '<':
+ if (set_nomacro++ == 0)
+ fputs (".set\tnomacro\n\t", file);
+ break;
+
+ case '>':
+ if (set_nomacro == 0)
+ error ("internal error: %%> found without a %%< in assembler pattern");
+ else if (--set_nomacro == 0)
+ fputs ("\n\t.set\tmacro", file);
+
+ break;
+
+ case '{':
+ if (set_volatile++ == 0)
+ fputs ("#.set\tvolatile\n\t", file);
+ break;
+
+ case '}':
+ if (set_volatile == 0)
+ error ("internal error: %%} found without a %%{ in assembler pattern");
+ else if (--set_volatile == 0)
+ fputs ("\n\t#.set\tnovolatile", file);
+
+ break;
+
+ case '~':
+ {
+ if (align_labels_log > 0)
+ ASM_OUTPUT_ALIGN (file, align_labels_log);
+ }
+ break;
+
+ default:
+ error ("PRINT_OPERAND: unknown punctuation '%c'", letter);
+ break;
+ }
+
+ return;
+ }
+
+ if (! op)
+ {
+ error ("PRINT_OPERAND null pointer");
+ return;
+ }
+
+ code = GET_CODE (op);
+
+ if (letter == 'C')
+ switch (code)
+ {
+ case EQ: fputs ("eq", file); break;
+ case NE: fputs ("ne", file); break;
+ case GT: fputs ("gt", file); break;
+ case GE: fputs ("ge", file); break;
+ case LT: fputs ("lt", file); break;
+ case LE: fputs ("le", file); break;
+ case GTU: fputs ("gtu", file); break;
+ case GEU: fputs ("geu", file); break;
+ case LTU: fputs ("ltu", file); break;
+ case LEU: fputs ("leu", file); break;
+ default:
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op);
+ }
+
+ else if (letter == 'N')
+ switch (code)
+ {
+ case EQ: fputs ("ne", file); break;
+ case NE: fputs ("eq", file); break;
+ case GT: fputs ("le", file); break;
+ case GE: fputs ("lt", file); break;
+ case LT: fputs ("ge", file); break;
+ case LE: fputs ("gt", file); break;
+ case GTU: fputs ("leu", file); break;
+ case GEU: fputs ("ltu", file); break;
+ case LTU: fputs ("geu", file); break;
+ case LEU: fputs ("gtu", file); break;
+ default:
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op);
+ }
+
+ else if (letter == 'F')
+ switch (code)
+ {
+ case EQ: fputs ("c1f", file); break;
+ case NE: fputs ("c1t", file); break;
+ default:
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%F", op);
+ }
+
+ else if (letter == 'W')
+ switch (code)
+ {
+ case EQ: fputs ("c1t", file); break;
+ case NE: fputs ("c1f", file); break;
+ default:
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%W", op);
+ }
+
+ else if (letter == 'h')
+ {
+ if (GET_CODE (op) == HIGH)
+ op = XEXP (op, 0);
+
+ print_operand_reloc (file, op, mips_hi_relocs);
+ }
+
+ else if (letter == 'R')
+ print_operand_reloc (file, op, mips_lo_relocs);
+
+ else if (letter == 'Y')
+ {
+ if (GET_CODE (op) == CONST_INT
+ && ((unsigned HOST_WIDE_INT) INTVAL (op)
+ < ARRAY_SIZE (mips_fp_conditions)))
+ fputs (mips_fp_conditions[INTVAL (op)], file);
+ else
+ output_operand_lossage ("invalid %%Y value");
+ }
+
+ else if (letter == 'Z')
+ {
+ if (ISA_HAS_8CC)
+ {
+ print_operand (file, op, 0);
+ fputc (',', file);
+ }
+ }
+
+ else if (letter == 'q')
+ {
+ int regnum;
+
+ if (code != REG)
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
+
+ regnum = REGNO (op);
+ if (MD_REG_P (regnum))
+ fprintf (file, "$ac0");
+ else if (DSP_ACC_REG_P (regnum))
+ fprintf (file, "$ac%c", reg_names[regnum][3]);
+ else
+ fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op);
+ }
+
+ else if (code == REG || code == SUBREG)
+ {
+ register int regnum;
+
+ if (code == REG)
+ regnum = REGNO (op);
+ else
+ regnum = true_regnum (op);
+
+ if ((letter == 'M' && ! WORDS_BIG_ENDIAN)
+ || (letter == 'L' && WORDS_BIG_ENDIAN)
+ || letter == 'D')
+ regnum++;
+
+ fprintf (file, "%s", reg_names[regnum]);
+ }
+
+ else if (code == MEM)
+ {
+ if (letter == 'D')
+ output_address (plus_constant (XEXP (op, 0), 4));
+ else
+ output_address (XEXP (op, 0));
+ }
+
+ else if (letter == 'x' && GET_CODE (op) == CONST_INT)
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op));
+
+ else if (letter == 'X' && GET_CODE(op) == CONST_INT)
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op));
+
+ else if (letter == 'd' && GET_CODE(op) == CONST_INT)
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op)));
+
+ else if (letter == 'z' && op == CONST0_RTX (GET_MODE (op)))
+ fputs (reg_names[GP_REG_FIRST], file);
+
+ else if (letter == 'd' || letter == 'x' || letter == 'X')
+ output_operand_lossage ("invalid use of %%d, %%x, or %%X");
+
+ else if (letter == 'T' || letter == 't')
+ {
+ int truth = (code == NE) == (letter == 'T');
+ fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file);
+ }
+
+ else if (CONST_GP_P (op))
+ fputs (reg_names[GLOBAL_POINTER_REGNUM], file);
+
+ else
+ output_addr_const (file, op);
+}
+
+
+/* Print symbolic operand OP, which is part of a HIGH or LO_SUM.
+ RELOCS is the array of relocations to use. */
+
+static void
+print_operand_reloc (FILE *file, rtx op, const char **relocs)
+{
+ enum mips_symbol_type symbol_type;
+ const char *p;
+ rtx base;
+ HOST_WIDE_INT offset;
+
+ if (!mips_symbolic_constant_p (op, &symbol_type) || relocs[symbol_type] == 0)
+ fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op);
+
+ /* If OP uses an UNSPEC address, we want to print the inner symbol. */
+ mips_split_const (op, &base, &offset);
+ if (UNSPEC_ADDRESS_P (base))
+ op = plus_constant (UNSPEC_ADDRESS (base), offset);
+
+ fputs (relocs[symbol_type], file);
+ output_addr_const (file, op);
+ for (p = relocs[symbol_type]; *p != 0; p++)
+ if (*p == '(')
+ fputc (')', file);
+}
+
+/* Output address operand X to FILE. */
+
+void
+print_operand_address (FILE *file, rtx x)
+{
+ struct mips_address_info addr;
+
+ if (mips_classify_address (&addr, x, word_mode, true))
+ switch (addr.type)
+ {
+ case ADDRESS_REG:
+ print_operand (file, addr.offset, 0);
+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
+ return;
+
+ case ADDRESS_LO_SUM:
+ print_operand (file, addr.offset, 'R');
+ fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]);
+ return;
+
+ case ADDRESS_CONST_INT:
+ output_addr_const (file, x);
+ fprintf (file, "(%s)", reg_names[0]);
+ return;
+
+ case ADDRESS_SYMBOLIC:
+ output_addr_const (file, x);
+ return;
+ }
+ gcc_unreachable ();
+}
+
+/* When using assembler macros, keep track of all of small-data externs
+ so that mips_file_end can emit the appropriate declarations for them.
+
+ In most cases it would be safe (though pointless) to emit .externs
+ for other symbols too. One exception is when an object is within
+ the -G limit but declared by the user to be in a section other
+ than .sbss or .sdata. */
+
+int
+mips_output_external (FILE *file ATTRIBUTE_UNUSED, tree decl, const char *name)
+{
+ register struct extern_list *p;
+
+ if (!TARGET_EXPLICIT_RELOCS && mips_in_small_data_p (decl))
+ {
+ p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
+ p->next = extern_head;
+ p->name = name;
+ p->size = int_size_in_bytes (TREE_TYPE (decl));
+ extern_head = p;
+ }
+
+ if (TARGET_IRIX && mips_abi == ABI_32 && TREE_CODE (decl) == FUNCTION_DECL)
+ {
+ p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
+ p->next = extern_head;
+ p->name = name;
+ p->size = -1;
+ extern_head = p;
+ }
+
+ return 0;
+}
+
+#if TARGET_IRIX
+static void
+irix_output_external_libcall (rtx fun)
+{
+ register struct extern_list *p;
+
+ if (mips_abi == ABI_32)
+ {
+ p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list));
+ p->next = extern_head;
+ p->name = XSTR (fun, 0);
+ p->size = -1;
+ extern_head = p;
+ }
+}
+#endif
+
+/* Emit a new filename to a stream. If we are smuggling stabs, try to
+ put out a MIPS ECOFF file and a stab. */
+
+void
+mips_output_filename (FILE *stream, const char *name)
+{
+
+ /* If we are emitting DWARF-2, let dwarf2out handle the ".file"
+ directives. */
+ if (write_symbols == DWARF2_DEBUG)
+ return;
+ else if (mips_output_filename_first_time)
+ {
+ mips_output_filename_first_time = 0;
+ num_source_filenames += 1;
+ current_function_file = name;
+ fprintf (stream, "\t.file\t%d ", num_source_filenames);
+ output_quoted_string (stream, name);
+ putc ('\n', stream);
+ }
+
+ /* If we are emitting stabs, let dbxout.c handle this (except for
+ the mips_output_filename_first_time case). */
+ else if (write_symbols == DBX_DEBUG)
+ return;
+
+ else if (name != current_function_file
+ && strcmp (name, current_function_file) != 0)
+ {
+ num_source_filenames += 1;
+ current_function_file = name;
+ fprintf (stream, "\t.file\t%d ", num_source_filenames);
+ output_quoted_string (stream, name);
+ putc ('\n', stream);
+ }
+}
+
+/* Output an ASCII string, in a space-saving way. PREFIX is the string
+ that should be written before the opening quote, such as "\t.ascii\t"
+ for real string data or "\t# " for a comment. */
+
+void
+mips_output_ascii (FILE *stream, const char *string_param, size_t len,
+ const char *prefix)
+{
+ size_t i;
+ int cur_pos = 17;
+ register const unsigned char *string =
+ (const unsigned char *)string_param;
+
+ fprintf (stream, "%s\"", prefix);
+ for (i = 0; i < len; i++)
+ {
+ register int c = string[i];
+
+ if (ISPRINT (c))
+ {
+ if (c == '\\' || c == '\"')
+ {
+ putc ('\\', stream);
+ cur_pos++;
+ }
+ putc (c, stream);
+ cur_pos++;
+ }
+ else
+ {
+ fprintf (stream, "\\%03o", c);
+ cur_pos += 4;
+ }
+
+ if (cur_pos > 72 && i+1 < len)
+ {
+ cur_pos = 17;
+ fprintf (stream, "\"\n%s\"", prefix);
+ }
+ }
+ fprintf (stream, "\"\n");
+}
+
+/* Implement TARGET_ASM_FILE_START. */
+
+static void
+mips_file_start (void)
+{
+ default_file_start ();
+
+ if (!TARGET_IRIX)
+ {
+ /* Generate a special section to describe the ABI switches used to
+ produce the resultant binary. This used to be done by the assembler
+ setting bits in the ELF header's flags field, but we have run out of
+ bits. GDB needs this information in order to be able to correctly
+ debug these binaries. See the function mips_gdbarch_init() in
+ gdb/mips-tdep.c. This is unnecessary for the IRIX 5/6 ABIs and
+ causes unnecessary IRIX 6 ld warnings. */
+ const char * abi_string = NULL;
+
+ switch (mips_abi)
+ {
+ case ABI_32: abi_string = "abi32"; break;
+ case ABI_N32: abi_string = "abiN32"; break;
+ case ABI_64: abi_string = "abi64"; break;
+ case ABI_O64: abi_string = "abiO64"; break;
+ case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break;
+ default:
+ gcc_unreachable ();
+ }
+ /* Note - we use fprintf directly rather than calling switch_to_section
+ because in this way we can avoid creating an allocated section. We
+ do not want this section to take up any space in the running
+ executable. */
+ fprintf (asm_out_file, "\t.section .mdebug.%s\n", abi_string);
+
+ /* There is no ELF header flag to distinguish long32 forms of the
+ EABI from long64 forms. Emit a special section to help tools
+ such as GDB. Do the same for o64, which is sometimes used with
+ -mlong64. */
+ if (mips_abi == ABI_EABI || mips_abi == ABI_O64)
+ fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n",
+ TARGET_LONG64 ? 64 : 32);
+
+ /* Restore the default section. */
+ fprintf (asm_out_file, "\t.previous\n");
+ }
+
+ /* Generate the pseudo ops that System V.4 wants. */
+ if (TARGET_ABICALLS)
+ fprintf (asm_out_file, "\t.abicalls\n");
+
+ if (TARGET_MIPS16)
+ fprintf (asm_out_file, "\t.set\tmips16\n");
+
+ if (flag_verbose_asm)
+ fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n",
+ ASM_COMMENT_START,
+ mips_section_threshold, mips_arch_info->name, mips_isa);
+}
+
+#ifdef BSS_SECTION_ASM_OP
+/* Implement ASM_OUTPUT_ALIGNED_BSS. This differs from the default only
+ in the use of sbss. */
+
+void
+mips_output_aligned_bss (FILE *stream, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size, int align)
+{
+ extern tree last_assemble_variable_decl;
+
+ if (mips_in_small_data_p (decl))
+ switch_to_section (get_named_section (NULL, ".sbss", 0));
+ else
+ switch_to_section (bss_section);
+ ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
+ last_assemble_variable_decl = decl;
+ ASM_DECLARE_OBJECT_NAME (stream, name, decl);
+ ASM_OUTPUT_SKIP (stream, size != 0 ? size : 1);
+}
+#endif
+
+/* Implement TARGET_ASM_FILE_END. When using assembler macros, emit
+ .externs for any small-data variables that turned out to be external. */
+
+static void
+mips_file_end (void)
+{
+ tree name_tree;
+ struct extern_list *p;
+
+ if (extern_head)
+ {
+ fputs ("\n", asm_out_file);
+
+ for (p = extern_head; p != 0; p = p->next)
+ {
+ name_tree = get_identifier (p->name);
+
+ /* Positively ensure only one .extern for any given symbol. */
+ if (!TREE_ASM_WRITTEN (name_tree)
+ && TREE_SYMBOL_REFERENCED (name_tree))
+ {
+ TREE_ASM_WRITTEN (name_tree) = 1;
+ /* In IRIX 5 or IRIX 6 for the O32 ABI, we must output a
+ `.global name .text' directive for every used but
+ undefined function. If we don't, the linker may perform
+ an optimization (skipping over the insns that set $gp)
+ when it is unsafe. */
+ if (TARGET_IRIX && mips_abi == ABI_32 && p->size == -1)
+ {
+ fputs ("\t.globl ", asm_out_file);
+ assemble_name (asm_out_file, p->name);
+ fputs (" .text\n", asm_out_file);
+ }
+ else
+ {
+ fputs ("\t.extern\t", asm_out_file);
+ assemble_name (asm_out_file, p->name);
+ fprintf (asm_out_file, ", %d\n", p->size);
+ }
+ }
+ }
+ }
+}
+
+/* Implement ASM_OUTPUT_ALIGNED_DECL_COMMON. This is usually the same as the
+ elfos.h version, but we also need to handle -muninit-const-in-rodata. */
+
+void
+mips_output_aligned_decl_common (FILE *stream, tree decl, const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned int align)
+{
+ /* If the target wants uninitialized const declarations in
+ .rdata then don't put them in .comm. */
+ if (TARGET_EMBEDDED_DATA && TARGET_UNINIT_CONST_IN_RODATA
+ && TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl)
+ && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
+ {
+ if (TREE_PUBLIC (decl) && DECL_NAME (decl))
+ targetm.asm_out.globalize_label (stream, name);
+
+ switch_to_section (readonly_data_section);
+ ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT));
+ mips_declare_object (stream, name, "",
+ ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n",
+ size);
+ }
+ else
+ mips_declare_common_object (stream, name, "\n\t.comm\t",
+ size, align, true);
+}
+
+/* Declare a common object of SIZE bytes using asm directive INIT_STRING.
+ NAME is the name of the object and ALIGN is the required alignment
+ in bytes. TAKES_ALIGNMENT_P is true if the directive takes a third
+ alignment argument. */
+
+void
+mips_declare_common_object (FILE *stream, const char *name,
+ const char *init_string,
+ unsigned HOST_WIDE_INT size,
+ unsigned int align, bool takes_alignment_p)
+{
+ if (!takes_alignment_p)
+ {
+ size += (align / BITS_PER_UNIT) - 1;
+ size -= size % (align / BITS_PER_UNIT);
+ mips_declare_object (stream, name, init_string,
+ "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size);
+ }
+ else
+ mips_declare_object (stream, name, init_string,
+ "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n",
+ size, align / BITS_PER_UNIT);
+}
+
+/* Emit either a label, .comm, or .lcomm directive. When using assembler
+ macros, mark the symbol as written so that mips_file_end won't emit an
+ .extern for it. STREAM is the output file, NAME is the name of the
+ symbol, INIT_STRING is the string that should be written before the
+ symbol and FINAL_STRING is the string that should be written after it.
+ FINAL_STRING is a printf() format that consumes the remaining arguments. */
+
+void
+mips_declare_object (FILE *stream, const char *name, const char *init_string,
+ const char *final_string, ...)
+{
+ va_list ap;
+
+ fputs (init_string, stream);
+ assemble_name (stream, name);
+ va_start (ap, final_string);
+ vfprintf (stream, final_string, ap);
+ va_end (ap);
+
+ if (!TARGET_EXPLICIT_RELOCS)
+ {
+ tree name_tree = get_identifier (name);
+ TREE_ASM_WRITTEN (name_tree) = 1;
+ }
+}
+
+#ifdef ASM_OUTPUT_SIZE_DIRECTIVE
+extern int size_directive_output;
+
+/* Implement ASM_DECLARE_OBJECT_NAME. This is like most of the standard ELF
+ definitions except that it uses mips_declare_object() to emit the label. */
+
+void
+mips_declare_object_name (FILE *stream, const char *name,
+ tree decl ATTRIBUTE_UNUSED)
+{
+#ifdef ASM_OUTPUT_TYPE_DIRECTIVE
+ ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
+#endif
+
+ size_directive_output = 0;
+ if (!flag_inhibit_size_directive && DECL_SIZE (decl))
+ {
+ HOST_WIDE_INT size;
+
+ size_directive_output = 1;
+ size = int_size_in_bytes (TREE_TYPE (decl));
+ ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
+ }
+
+ mips_declare_object (stream, name, "", ":\n");
+}
+
+/* Implement ASM_FINISH_DECLARE_OBJECT. This is generic ELF stuff. */
+
+void
+mips_finish_declare_object (FILE *stream, tree decl, int top_level, int at_end)
+{
+ const char *name;
+
+ name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ if (!flag_inhibit_size_directive
+ && DECL_SIZE (decl) != 0
+ && !at_end && top_level
+ && DECL_INITIAL (decl) == error_mark_node
+ && !size_directive_output)
+ {
+ HOST_WIDE_INT size;
+
+ size_directive_output = 1;
+ size = int_size_in_bytes (TREE_TYPE (decl));
+ ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
+ }
+}
+#endif
+
+/* Return true if X is a small data address that can be rewritten
+ as a LO_SUM. */
+
+static bool
+mips_rewrite_small_data_p (rtx x)
+{
+ enum mips_symbol_type symbol_type;
+
+ return (TARGET_EXPLICIT_RELOCS
+ && mips_symbolic_constant_p (x, &symbol_type)
+ && symbol_type == SYMBOL_SMALL_DATA);
+}
+
+
+/* A for_each_rtx callback for mips_small_data_pattern_p. */
+
+static int
+mips_small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+ if (GET_CODE (*loc) == LO_SUM)
+ return -1;
+
+ return mips_rewrite_small_data_p (*loc);
+}
+
+/* Return true if OP refers to small data symbols directly, not through
+ a LO_SUM. */
+
+bool
+mips_small_data_pattern_p (rtx op)
+{
+ return for_each_rtx (&op, mips_small_data_pattern_1, 0);
+}
+
+/* A for_each_rtx callback, used by mips_rewrite_small_data. */
+
+static int
+mips_rewrite_small_data_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+ if (mips_rewrite_small_data_p (*loc))
+ *loc = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, *loc);
+
+ if (GET_CODE (*loc) == LO_SUM)
+ return -1;
+
+ return 0;
+}
+
+/* If possible, rewrite OP so that it refers to small data using
+ explicit relocations. */
+
+rtx
+mips_rewrite_small_data (rtx op)
+{
+ op = copy_insn (op);
+ for_each_rtx (&op, mips_rewrite_small_data_1, 0);
+ return op;
+}
+
+/* Return true if the current function has an insn that implicitly
+ refers to $gp. */
+
+static bool
+mips_function_has_gp_insn (void)
+{
+ /* Don't bother rechecking if we found one last time. */
+ if (!cfun->machine->has_gp_insn_p)
+ {
+ rtx insn;
+
+ push_topmost_sequence ();
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && (get_attr_got (insn) != GOT_UNSET
+ || small_data_pattern (PATTERN (insn), VOIDmode)))
+ break;
+ pop_topmost_sequence ();
+
+ cfun->machine->has_gp_insn_p = (insn != 0);
+ }
+ return cfun->machine->has_gp_insn_p;
+}
+
+
+/* Return the register that should be used as the global pointer
+ within this function. Return 0 if the function doesn't need
+ a global pointer. */
+
+static unsigned int
+mips_global_pointer (void)
+{
+ unsigned int regno;
+
+ /* $gp is always available in non-abicalls code. */
+ if (!TARGET_ABICALLS)
+ return GLOBAL_POINTER_REGNUM;
+
+ /* We must always provide $gp when it is used implicitly. */
+ if (!TARGET_EXPLICIT_RELOCS)
+ return GLOBAL_POINTER_REGNUM;
+
+ /* FUNCTION_PROFILER includes a jal macro, so we need to give it
+ a valid gp. */
+ if (current_function_profile)
+ return GLOBAL_POINTER_REGNUM;
+
+ /* If the function has a nonlocal goto, $gp must hold the correct
+ global pointer for the target function. */
+ if (current_function_has_nonlocal_goto)
+ return GLOBAL_POINTER_REGNUM;
+
+ /* If the gp is never referenced, there's no need to initialize it.
+ Note that reload can sometimes introduce constant pool references
+ into a function that otherwise didn't need them. For example,
+ suppose we have an instruction like:
+
+ (set (reg:DF R1) (float:DF (reg:SI R2)))
+
+ If R2 turns out to be constant such as 1, the instruction may have a
+ REG_EQUAL note saying that R1 == 1.0. Reload then has the option of
+ using this constant if R2 doesn't get allocated to a register.
+
+ In cases like these, reload will have added the constant to the pool
+ but no instruction will yet refer to it. */
+ if (!regs_ever_live[GLOBAL_POINTER_REGNUM]
+ && !current_function_uses_const_pool
+ && !mips_function_has_gp_insn ())
+ return 0;
+
+ /* We need a global pointer, but perhaps we can use a call-clobbered
+ register instead of $gp. */
+ if (TARGET_NEWABI && current_function_is_leaf)
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ if (!regs_ever_live[regno]
+ && call_used_regs[regno]
+ && !fixed_regs[regno]
+ && regno != PIC_FUNCTION_ADDR_REGNUM)
+ return regno;
+
+ return GLOBAL_POINTER_REGNUM;
+}
+
+
+/* Return true if the current function must save REGNO. */
+
+static bool
+mips_save_reg_p (unsigned int regno)
+{
+ /* We only need to save $gp for NewABI PIC. */
+ if (regno == GLOBAL_POINTER_REGNUM)
+ return (TARGET_ABICALLS && TARGET_NEWABI
+ && cfun->machine->global_pointer == regno);
+
+ /* Check call-saved registers. */
+ if (regs_ever_live[regno] && !call_used_regs[regno])
+ return true;
+
+ /* We need to save the old frame pointer before setting up a new one. */
+ if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
+ return true;
+
+ /* We need to save the incoming return address if it is ever clobbered
+ within the function. */
+ if (regno == GP_REG_FIRST + 31 && regs_ever_live[regno])
+ return true;
+
+ if (TARGET_MIPS16)
+ {
+ tree return_type;
+
+ return_type = DECL_RESULT (current_function_decl);
+
+ /* $18 is a special case in mips16 code. It may be used to call
+ a function which returns a floating point value, but it is
+ marked in call_used_regs. */
+ if (regno == GP_REG_FIRST + 18 && regs_ever_live[regno])
+ return true;
+
+ /* $31 is also a special case. It will be used to copy a return
+ value into the floating point registers if the return value is
+ floating point. */
+ if (regno == GP_REG_FIRST + 31
+ && mips16_hard_float
+ && !aggregate_value_p (return_type, current_function_decl)
+ && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
+ && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
+ return true;
+ }
+
+ return false;
+}
+
+
+/* Return the bytes needed to compute the frame pointer from the current
+ stack pointer. SIZE is the size (in bytes) of the local variables.
+
+ MIPS stack frames look like:
+
+ Before call After call
+ +-----------------------+ +-----------------------+
+ high | | | |
+ mem. | | | |
+ | caller's temps. | | caller's temps. |
+ | | | |
+ +-----------------------+ +-----------------------+
+ | | | |
+ | arguments on stack. | | arguments on stack. |
+ | | | |
+ +-----------------------+ +-----------------------+
+ | 4 words to save | | 4 words to save |
+ | arguments passed | | arguments passed |
+ | in registers, even | | in registers, even |
+ SP->| if not passed. | VFP->| if not passed. |
+ +-----------------------+ +-----------------------+
+ | |
+ | fp register save |
+ | |
+ +-----------------------+
+ | |
+ | gp register save |
+ | |
+ +-----------------------+
+ | |
+ | local variables |
+ | |
+ +-----------------------+
+ | |
+ | alloca allocations |
+ | |
+ +-----------------------+
+ | |
+ | GP save for V.4 abi |
+ | |
+ +-----------------------+
+ | |
+ | arguments on stack |
+ | |
+ +-----------------------+
+ | 4 words to save |
+ | arguments passed |
+ | in registers, even |
+ low SP->| if not passed. |
+ memory +-----------------------+
+
+*/
+
+HOST_WIDE_INT
+compute_frame_size (HOST_WIDE_INT size)
+{
+ unsigned int regno;
+ HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
+ HOST_WIDE_INT var_size; /* # bytes that variables take up */
+ HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */
+ HOST_WIDE_INT cprestore_size; /* # bytes that the cprestore slot takes up */
+ HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding */
+ HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */
+ HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */
+ unsigned int mask; /* mask of saved gp registers */
+ unsigned int fmask; /* mask of saved fp registers */
+
+ cfun->machine->global_pointer = mips_global_pointer ();
+
+ gp_reg_size = 0;
+ fp_reg_size = 0;
+ mask = 0;
+ fmask = 0;
+ var_size = MIPS_STACK_ALIGN (size);
+ args_size = current_function_outgoing_args_size;
+ cprestore_size = MIPS_STACK_ALIGN (STARTING_FRAME_OFFSET) - args_size;
+
+ /* The space set aside by STARTING_FRAME_OFFSET isn't needed in leaf
+ functions. If the function has local variables, we're committed
+ to allocating it anyway. Otherwise reclaim it here. */
+ if (var_size == 0 && current_function_is_leaf)
+ cprestore_size = args_size = 0;
+
+ /* The MIPS 3.0 linker does not like functions that dynamically
+ allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
+ looks like we are trying to create a second frame pointer to the
+ function, so allocate some stack space to make it happy. */
+
+ if (args_size == 0 && current_function_calls_alloca)
+ args_size = 4 * UNITS_PER_WORD;
+
+ total_size = var_size + args_size + cprestore_size;
+
+ /* Calculate space needed for gp registers. */
+ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++)
+ if (mips_save_reg_p (regno))
+ {
+ gp_reg_size += GET_MODE_SIZE (gpr_mode);
+ mask |= 1 << (regno - GP_REG_FIRST);
+ }
+
+ /* We need to restore these for the handler. */
+ if (current_function_calls_eh_return)
+ {
+ unsigned 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 |= 1 << (regno - GP_REG_FIRST);
+ }
+ }
+
+ /* This loop must iterate over the same space as its companion in
+ save_restore_insns. */
+ for (regno = (FP_REG_LAST - FP_INC + 1);
+ regno >= FP_REG_FIRST;
+ regno -= FP_INC)
+ {
+ if (mips_save_reg_p (regno))
+ {
+ fp_reg_size += FP_INC * UNITS_PER_FPREG;
+ fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST);
+ }
+ }
+
+ gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size);
+ total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size);
+
+ /* Add in the space required for saving incoming register arguments. */
+ total_size += current_function_pretend_args_size;
+ total_size += MIPS_STACK_ALIGN (cfun->machine->varargs_size);
+
+ /* Save other computed information. */
+ cfun->machine->frame.total_size = total_size;
+ cfun->machine->frame.var_size = var_size;
+ cfun->machine->frame.args_size = args_size;
+ cfun->machine->frame.cprestore_size = cprestore_size;
+ cfun->machine->frame.gp_reg_size = gp_reg_size;
+ cfun->machine->frame.fp_reg_size = fp_reg_size;
+ cfun->machine->frame.mask = mask;
+ cfun->machine->frame.fmask = fmask;
+ cfun->machine->frame.initialized = reload_completed;
+ cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD;
+ cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG);
+
+ if (mask)
+ {
+ HOST_WIDE_INT offset;
+
+ offset = (args_size + cprestore_size + var_size
+ + gp_reg_size - GET_MODE_SIZE (gpr_mode));
+ cfun->machine->frame.gp_sp_offset = offset;
+ cfun->machine->frame.gp_save_offset = offset - total_size;
+ }
+ else
+ {
+ cfun->machine->frame.gp_sp_offset = 0;
+ cfun->machine->frame.gp_save_offset = 0;
+ }
+
+ if (fmask)
+ {
+ HOST_WIDE_INT offset;
+
+ offset = (args_size + cprestore_size + var_size
+ + gp_reg_rounded + fp_reg_size
+ - FP_INC * UNITS_PER_FPREG);
+ cfun->machine->frame.fp_sp_offset = offset;
+ cfun->machine->frame.fp_save_offset = offset - total_size;
+ }
+ else
+ {
+ cfun->machine->frame.fp_sp_offset = 0;
+ cfun->machine->frame.fp_save_offset = 0;
+ }
+
+ /* Ok, we're done. */
+ return total_size;
+}
+
+/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame
+ pointer or argument pointer. TO is either the stack pointer or
+ hard frame pointer. */
+
+HOST_WIDE_INT
+mips_initial_elimination_offset (int from, int to)
+{
+ HOST_WIDE_INT offset;
+
+ compute_frame_size (get_frame_size ());
+
+ /* Set OFFSET to the offset from the stack pointer. */
+ switch (from)
+ {
+ case FRAME_POINTER_REGNUM:
+ offset = 0;
+ break;
+
+ case ARG_POINTER_REGNUM:
+ offset = (cfun->machine->frame.total_size
+ - current_function_pretend_args_size);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM)
+ offset -= cfun->machine->frame.args_size;
+
+ return offset;
+}
+
+/* Implement RETURN_ADDR_RTX. Note, we do not support moving
+ back to a previous frame. */
+rtx
+mips_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
+{
+ if (count != 0)
+ return const0_rtx;
+
+ return get_hard_reg_initial_val (Pmode, GP_REG_FIRST + 31);
+}
+
+/* Use FN to save or restore register REGNO. MODE is the register's
+ mode and OFFSET is the offset of its save slot from the current
+ stack pointer. */
+
+static void
+mips_save_restore_reg (enum machine_mode mode, int regno,
+ HOST_WIDE_INT offset, mips_save_restore_fn fn)
+{
+ rtx mem;
+
+ mem = gen_frame_mem (mode, plus_constant (stack_pointer_rtx, offset));
+
+ fn (gen_rtx_REG (mode, regno), mem);
+}
+
+
+/* Call FN for each register that is saved by the current function.
+ SP_OFFSET is the offset of the current stack pointer from the start
+ of the frame. */
+
+static void
+mips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn)
+{
+#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0)
+
+ enum machine_mode fpr_mode;
+ HOST_WIDE_INT offset;
+ int regno;
+
+ /* Save registers starting from high to low. The debuggers prefer at least
+ the return register be stored at func+4, and also it allows us not to
+ need a nop in the epilog if at least one register is reloaded in
+ addition to return address. */
+ offset = cfun->machine->frame.gp_sp_offset - sp_offset;
+ for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--)
+ if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST))
+ {
+ mips_save_restore_reg (gpr_mode, regno, offset, fn);
+ offset -= GET_MODE_SIZE (gpr_mode);
+ }
+
+ /* This loop must iterate over the same space as its companion in
+ compute_frame_size. */
+ offset = cfun->machine->frame.fp_sp_offset - sp_offset;
+ fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode);
+ for (regno = (FP_REG_LAST - FP_INC + 1);
+ regno >= FP_REG_FIRST;
+ regno -= FP_INC)
+ if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST))
+ {
+ mips_save_restore_reg (fpr_mode, regno, offset, fn);
+ offset -= GET_MODE_SIZE (fpr_mode);
+ }
+#undef BITSET_P
+}
+
+/* If we're generating n32 or n64 abicalls, and the current function
+ does not use $28 as its global pointer, emit a cplocal directive.
+ Use pic_offset_table_rtx as the argument to the directive. */
+
+static void
+mips_output_cplocal (void)
+{
+ if (!TARGET_EXPLICIT_RELOCS
+ && cfun->machine->global_pointer > 0
+ && cfun->machine->global_pointer != GLOBAL_POINTER_REGNUM)
+ output_asm_insn (".cplocal %+", 0);
+}
+
+/* Return the style of GP load sequence that is being used for the
+ current function. */
+
+enum mips_loadgp_style
+mips_current_loadgp_style (void)
+{
+ if (!TARGET_ABICALLS || cfun->machine->global_pointer == 0)
+ return LOADGP_NONE;
+
+ if (TARGET_ABSOLUTE_ABICALLS)
+ return LOADGP_ABSOLUTE;
+
+ return TARGET_NEWABI ? LOADGP_NEWABI : LOADGP_OLDABI;
+}
+
+/* The __gnu_local_gp symbol. */
+
+static GTY(()) rtx mips_gnu_local_gp;
+
+/* If we're generating n32 or n64 abicalls, emit instructions
+ to set up the global pointer. */
+
+static void
+mips_emit_loadgp (void)
+{
+ rtx addr, offset, incoming_address;
+
+ switch (mips_current_loadgp_style ())
+ {
+ case LOADGP_ABSOLUTE:
+ if (mips_gnu_local_gp == NULL)
+ {
+ mips_gnu_local_gp = gen_rtx_SYMBOL_REF (Pmode, "__gnu_local_gp");
+ SYMBOL_REF_FLAGS (mips_gnu_local_gp) |= SYMBOL_FLAG_LOCAL;
+ }
+ emit_insn (gen_loadgp_noshared (mips_gnu_local_gp));
+ break;
+
+ case LOADGP_NEWABI:
+ addr = XEXP (DECL_RTL (current_function_decl), 0);
+ offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP);
+ incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
+ emit_insn (gen_loadgp (offset, incoming_address));
+ if (!TARGET_EXPLICIT_RELOCS)
+ emit_insn (gen_loadgp_blockage ());
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* Set up the stack and frame (if desired) for the function. */
+
+static void
+mips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ const char *fnname;
+ HOST_WIDE_INT tsize = cfun->machine->frame.total_size;
+
+#ifdef SDB_DEBUGGING_INFO
+ if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG)
+ SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl));
+#endif
+
+ /* In mips16 mode, we may need to generate a 32 bit to handle
+ floating point arguments. The linker will arrange for any 32 bit
+ functions to call this stub, which will then jump to the 16 bit
+ function proper. */
+ if (TARGET_MIPS16 && !TARGET_SOFT_FLOAT
+ && current_function_args_info.fp_code != 0)
+ build_mips16_function_stub (file);
+
+ if (!FUNCTION_NAME_ALREADY_DECLARED)
+ {
+ /* Get the function name the same way that toplev.c does before calling
+ assemble_start_function. This is needed so that the name used here
+ exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+
+ if (!flag_inhibit_size_directive)
+ {
+ fputs ("\t.ent\t", file);
+ assemble_name (file, fnname);
+ fputs ("\n", file);
+ }
+
+ assemble_name (file, fnname);
+ fputs (":\n", file);
+ }
+
+ /* Stop mips_file_end from treating this function as external. */
+ if (TARGET_IRIX && mips_abi == ABI_32)
+ TREE_ASM_WRITTEN (DECL_NAME (cfun->decl)) = 1;
+
+ if (!flag_inhibit_size_directive)
+ {
+ /* .frame FRAMEREG, FRAMESIZE, RETREG */
+ fprintf (file,
+ "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s\t\t"
+ "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d/%d"
+ ", args= " HOST_WIDE_INT_PRINT_DEC
+ ", gp= " HOST_WIDE_INT_PRINT_DEC "\n",
+ (reg_names[(frame_pointer_needed)
+ ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]),
+ ((frame_pointer_needed && TARGET_MIPS16)
+ ? tsize - cfun->machine->frame.args_size
+ : tsize),
+ reg_names[GP_REG_FIRST + 31],
+ cfun->machine->frame.var_size,
+ cfun->machine->frame.num_gp,
+ cfun->machine->frame.num_fp,
+ cfun->machine->frame.args_size,
+ cfun->machine->frame.cprestore_size);
+
+ /* .mask MASK, GPOFFSET; .fmask FPOFFSET */
+ fprintf (file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
+ cfun->machine->frame.mask,
+ cfun->machine->frame.gp_save_offset);
+ fprintf (file, "\t.fmask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n",
+ cfun->machine->frame.fmask,
+ cfun->machine->frame.fp_save_offset);
+
+ /* Require:
+ OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg.
+ HIGHEST_GP_SAVED == *FRAMEREG + FRAMESIZE + GPOFFSET => can find saved regs. */
+ }
+
+ if (mips_current_loadgp_style () == LOADGP_OLDABI)
+ {
+ /* Handle the initialization of $gp for SVR4 PIC. */
+ if (!cfun->machine->all_noreorder_p)
+ output_asm_insn ("%(.cpload\t%^%)", 0);
+ else
+ output_asm_insn ("%(.cpload\t%^\n\t%<", 0);
+ }
+ else if (cfun->machine->all_noreorder_p)
+ output_asm_insn ("%(%<", 0);
+
+ /* Tell the assembler which register we're using as the global
+ pointer. This is needed for thunks, since they can use either
+ explicit relocs or assembler macros. */
+ mips_output_cplocal ();
+}
+
+/* Make the last instruction frame related and note that it performs
+ the operation described by FRAME_PATTERN. */
+
+static void
+mips_set_frame_expr (rtx frame_pattern)
+{
+ rtx insn;
+
+ insn = get_last_insn ();
+ RTX_FRAME_RELATED_P (insn) = 1;
+ REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ frame_pattern,
+ REG_NOTES (insn));
+}
+
+
+/* Return a frame-related rtx that stores REG at MEM.
+ REG must be a single register. */
+
+static rtx
+mips_frame_set (rtx mem, rtx reg)
+{
+ rtx set;
+
+ /* If we're saving the return address register and the dwarf return
+ address column differs from the hard register number, adjust the
+ note reg to refer to the former. */
+ if (REGNO (reg) == GP_REG_FIRST + 31
+ && DWARF_FRAME_RETURN_COLUMN != GP_REG_FIRST + 31)
+ reg = gen_rtx_REG (GET_MODE (reg), DWARF_FRAME_RETURN_COLUMN);
+
+ set = gen_rtx_SET (VOIDmode, mem, reg);
+ RTX_FRAME_RELATED_P (set) = 1;
+
+ return set;
+}
+
+
+/* Save register REG to MEM. Make the instruction frame-related. */
+
+static void
+mips_save_reg (rtx reg, rtx mem)
+{
+ if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64)
+ {
+ rtx x1, x2;
+
+ if (mips_split_64bit_move_p (mem, reg))
+ mips_split_64bit_move (mem, reg);
+ else
+ emit_move_insn (mem, reg);
+
+ x1 = mips_frame_set (mips_subword (mem, 0), mips_subword (reg, 0));
+ x2 = mips_frame_set (mips_subword (mem, 1), mips_subword (reg, 1));
+ mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2)));
+ }
+ else
+ {
+ if (TARGET_MIPS16
+ && REGNO (reg) != GP_REG_FIRST + 31
+ && !M16_REG_P (REGNO (reg)))
+ {
+ /* Save a non-mips16 register by moving it through a temporary.
+ We don't need to do this for $31 since there's a special
+ instruction for it. */
+ emit_move_insn (MIPS_PROLOGUE_TEMP (GET_MODE (reg)), reg);
+ emit_move_insn (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg)));
+ }
+ else
+ emit_move_insn (mem, reg);
+
+ mips_set_frame_expr (mips_frame_set (mem, reg));
+ }
+}
+
+
+/* Expand the prologue into a bunch of separate insns. */
+
+void
+mips_expand_prologue (void)
+{
+ HOST_WIDE_INT size;
+
+ if (cfun->machine->global_pointer > 0)
+ REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer;
+
+ size = compute_frame_size (get_frame_size ());
+
+ /* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP
+ bytes beforehand; this is enough to cover the register save area
+ without going out of range. */
+ if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
+ {
+ HOST_WIDE_INT step1;
+
+ step1 = MIN (size, MIPS_MAX_FIRST_STACK_STEP);
+ RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-step1)))) = 1;
+ size -= step1;
+ mips_for_each_saved_reg (size, mips_save_reg);
+ }
+
+ /* Allocate the rest of the frame. */
+ if (size > 0)
+ {
+ if (SMALL_OPERAND (-size))
+ RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-size)))) = 1;
+ else
+ {
+ emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), GEN_INT (size));
+ if (TARGET_MIPS16)
+ {
+ /* There are no instructions to add or subtract registers
+ from the stack pointer, so use the frame pointer as a
+ temporary. We should always be using a frame pointer
+ in this case anyway. */
+ gcc_assert (frame_pointer_needed);
+ emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ emit_insn (gen_sub3_insn (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx,
+ MIPS_PROLOGUE_TEMP (Pmode)));
+ emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
+ }
+ else
+ emit_insn (gen_sub3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ MIPS_PROLOGUE_TEMP (Pmode)));
+
+ /* Describe the combined effect of the previous instructions. */
+ mips_set_frame_expr
+ (gen_rtx_SET (VOIDmode, stack_pointer_rtx,
+ plus_constant (stack_pointer_rtx, -size)));
+ }
+ }
+
+ /* Set up the frame pointer, if we're using one. In mips16 code,
+ we point the frame pointer ahead of the outgoing argument area.
+ This should allow more variables & incoming arguments to be
+ accessed with unextended instructions. */
+ if (frame_pointer_needed)
+ {
+ if (TARGET_MIPS16 && cfun->machine->frame.args_size != 0)
+ {
+ rtx offset = GEN_INT (cfun->machine->frame.args_size);
+ if (SMALL_OPERAND (cfun->machine->frame.args_size))
+ RTX_FRAME_RELATED_P
+ (emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+ stack_pointer_rtx,
+ offset))) = 1;
+ else
+ {
+ emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), offset);
+ emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
+ emit_insn (gen_add3_insn (hard_frame_pointer_rtx,
+ hard_frame_pointer_rtx,
+ MIPS_PROLOGUE_TEMP (Pmode)));
+ mips_set_frame_expr
+ (gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx,
+ plus_constant (stack_pointer_rtx,
+ cfun->machine->frame.args_size)));
+ }
+ }
+ else
+ RTX_FRAME_RELATED_P (emit_move_insn (hard_frame_pointer_rtx,
+ stack_pointer_rtx)) = 1;
+ }
+
+ mips_emit_loadgp ();
+
+ /* If generating o32/o64 abicalls, save $gp on the stack. */
+ if (TARGET_ABICALLS && !TARGET_NEWABI && !current_function_is_leaf)
+ emit_insn (gen_cprestore (GEN_INT (current_function_outgoing_args_size)));
+
+ /* If we are profiling, make sure no instructions are scheduled before
+ the call to mcount. */
+
+ if (current_function_profile)
+ emit_insn (gen_blockage ());
+}
+
+/* Do any necessary cleanup after a function to restore stack, frame,
+ and regs. */
+
+#define RA_MASK BITMASK_HIGH /* 1 << 31 */
+
+static void
+mips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ /* Reinstate the normal $gp. */
+ REGNO (pic_offset_table_rtx) = GLOBAL_POINTER_REGNUM;
+ mips_output_cplocal ();
+
+ if (cfun->machine->all_noreorder_p)
+ {
+ /* Avoid using %>%) since it adds excess whitespace. */
+ output_asm_insn (".set\tmacro", 0);
+ output_asm_insn (".set\treorder", 0);
+ set_noreorder = set_nomacro = 0;
+ }
+
+ if (!FUNCTION_NAME_ALREADY_DECLARED && !flag_inhibit_size_directive)
+ {
+ const char *fnname;
+
+ /* Get the function name the same way that toplev.c does before calling
+ assemble_start_function. This is needed so that the name used here
+ exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ fputs ("\t.end\t", file);
+ assemble_name (file, fnname);
+ fputs ("\n", file);
+ }
+}
+
+/* Emit instructions to restore register REG from slot MEM. */
+
+static void
+mips_restore_reg (rtx reg, rtx mem)
+{
+ /* There's no mips16 instruction to load $31 directly. Load into
+ $7 instead and adjust the return insn appropriately. */
+ if (TARGET_MIPS16 && REGNO (reg) == GP_REG_FIRST + 31)
+ reg = gen_rtx_REG (GET_MODE (reg), 7);
+
+ if (TARGET_MIPS16 && !M16_REG_P (REGNO (reg)))
+ {
+ /* Can't restore directly; move through a temporary. */
+ emit_move_insn (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem);
+ emit_move_insn (reg, MIPS_EPILOGUE_TEMP (GET_MODE (reg)));
+ }
+ else
+ emit_move_insn (reg, mem);
+}
+
+
+/* Expand the epilogue into a bunch of separate insns. SIBCALL_P is true
+ if this epilogue precedes a sibling call, false if it is for a normal
+ "epilogue" pattern. */
+
+void
+mips_expand_epilogue (int sibcall_p)
+{
+ HOST_WIDE_INT step1, step2;
+ rtx base, target;
+
+ if (!sibcall_p && mips_can_use_return_insn ())
+ {
+ emit_jump_insn (gen_return ());
+ return;
+ }
+
+ /* Split the frame into two. STEP1 is the amount of stack we should
+ deallocate before restoring the registers. STEP2 is the amount we
+ should deallocate afterwards.
+
+ Start off by assuming that no registers need to be restored. */
+ step1 = cfun->machine->frame.total_size;
+ step2 = 0;
+
+ /* Work out which register holds the frame address. Account for the
+ frame pointer offset used by mips16 code. */
+ if (!frame_pointer_needed)
+ base = stack_pointer_rtx;
+ else
+ {
+ base = hard_frame_pointer_rtx;
+ if (TARGET_MIPS16)
+ step1 -= cfun->machine->frame.args_size;
+ }
+
+ /* If we need to restore registers, deallocate as much stack as
+ possible in the second step without going out of range. */
+ if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0)
+ {
+ step2 = MIN (step1, MIPS_MAX_FIRST_STACK_STEP);
+ step1 -= step2;
+ }
+
+ /* Set TARGET to BASE + STEP1. */
+ target = base;
+ if (step1 > 0)
+ {
+ rtx adjust;
+
+ /* Get an rtx for STEP1 that we can add to BASE. */
+ adjust = GEN_INT (step1);
+ if (!SMALL_OPERAND (step1))
+ {
+ emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), adjust);
+ adjust = MIPS_EPILOGUE_TEMP (Pmode);
+ }
+
+ /* Normal mode code can copy the result straight into $sp. */
+ if (!TARGET_MIPS16)
+ target = stack_pointer_rtx;
+
+ emit_insn (gen_add3_insn (target, base, adjust));
+ }
+
+ /* Copy TARGET into the stack pointer. */
+ if (target != stack_pointer_rtx)
+ emit_move_insn (stack_pointer_rtx, target);
+
+ /* If we're using addressing macros for n32/n64 abicalls, $gp is
+ implicitly used by all SYMBOL_REFs. We must emit a blockage
+ insn before restoring it. */
+ if (TARGET_ABICALLS && TARGET_NEWABI && !TARGET_EXPLICIT_RELOCS)
+ emit_insn (gen_blockage ());
+
+ /* Restore the registers. */
+ mips_for_each_saved_reg (cfun->machine->frame.total_size - step2,
+ mips_restore_reg);
+
+ /* Deallocate the final bit of the frame. */
+ if (step2 > 0)
+ emit_insn (gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (step2)));
+
+ /* Add in the __builtin_eh_return stack adjustment. We need to
+ use a temporary in mips16 code. */
+ if (current_function_calls_eh_return)
+ {
+ if (TARGET_MIPS16)
+ {
+ emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), stack_pointer_rtx);
+ emit_insn (gen_add3_insn (MIPS_EPILOGUE_TEMP (Pmode),
+ MIPS_EPILOGUE_TEMP (Pmode),
+ EH_RETURN_STACKADJ_RTX));
+ emit_move_insn (stack_pointer_rtx, MIPS_EPILOGUE_TEMP (Pmode));
+ }
+ else
+ emit_insn (gen_add3_insn (stack_pointer_rtx,
+ stack_pointer_rtx,
+ EH_RETURN_STACKADJ_RTX));
+ }
+
+ if (!sibcall_p)
+ {
+ /* The mips16 loads the return address into $7, not $31. */
+ if (TARGET_MIPS16 && (cfun->machine->frame.mask & RA_MASK) != 0)
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
+ GP_REG_FIRST + 7)));
+ else
+ emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode,
+ GP_REG_FIRST + 31)));
+ }
+}
+
+/* Return nonzero if this function is known to have a null epilogue.
+ This allows the optimizer to omit jumps to jumps if no stack
+ was created. */
+
+int
+mips_can_use_return_insn (void)
+{
+ tree return_type;
+
+ if (! reload_completed)
+ return 0;
+
+ if (regs_ever_live[31] || current_function_profile)
+ return 0;
+
+ return_type = DECL_RESULT (current_function_decl);
+
+ /* In mips16 mode, a function which returns a floating point value
+ needs to arrange to copy the return value into the floating point
+ registers. */
+ if (TARGET_MIPS16
+ && mips16_hard_float
+ && ! aggregate_value_p (return_type, current_function_decl)
+ && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
+ && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
+ return 0;
+
+ if (cfun->machine->frame.initialized)
+ return cfun->machine->frame.total_size == 0;
+
+ return compute_frame_size (get_frame_size ()) == 0;
+}
+
+/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text
+ in order to avoid duplicating too much logic from elsewhere. */
+
+static void
+mips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+ tree function)
+{
+ rtx this, temp1, temp2, insn, fnaddr;
+
+ /* Pretend to be a post-reload pass while generating rtl. */
+ no_new_pseudos = 1;
+ reload_completed = 1;
+ reset_block_changes ();
+
+ /* Pick a global pointer for -mabicalls. Use $15 rather than $28
+ for TARGET_NEWABI since the latter is a call-saved register. */
+ if (TARGET_ABICALLS)
+ cfun->machine->global_pointer
+ = REGNO (pic_offset_table_rtx)
+ = TARGET_NEWABI ? 15 : GLOBAL_POINTER_REGNUM;
+
+ /* Set up the global pointer for n32 or n64 abicalls. */
+ mips_emit_loadgp ();
+
+ /* We need two temporary registers in some cases. */
+ temp1 = gen_rtx_REG (Pmode, 2);
+ temp2 = gen_rtx_REG (Pmode, 3);
+
+ /* Find out which register contains the "this" pointer. */
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
+ this = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1);
+ else
+ this = gen_rtx_REG (Pmode, GP_ARG_FIRST);
+
+ /* Add DELTA to THIS. */
+ if (delta != 0)
+ {
+ rtx offset = GEN_INT (delta);
+ if (!SMALL_OPERAND (delta))
+ {
+ emit_move_insn (temp1, offset);
+ offset = temp1;
+ }
+ emit_insn (gen_add3_insn (this, this, offset));
+ }
+
+ /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
+ if (vcall_offset != 0)
+ {
+ rtx addr;
+
+ /* Set TEMP1 to *THIS. */
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, this));
+
+ /* Set ADDR to a legitimate address for *THIS + VCALL_OFFSET. */
+ addr = mips_add_offset (temp2, temp1, vcall_offset);
+
+ /* Load the offset and add it to THIS. */
+ emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr));
+ emit_insn (gen_add3_insn (this, this, temp1));
+ }
+
+ /* Jump to the target function. Use a sibcall if direct jumps are
+ allowed, otherwise load the address into a register first. */
+ fnaddr = XEXP (DECL_RTL (function), 0);
+ if (TARGET_MIPS16 || TARGET_ABICALLS || TARGET_LONG_CALLS)
+ {
+ /* This is messy. gas treats "la $25,foo" as part of a call
+ sequence and may allow a global "foo" to be lazily bound.
+ The general move patterns therefore reject this combination.
+
+ In this context, lazy binding would actually be OK for o32 and o64,
+ but it's still wrong for n32 and n64; see mips_load_call_address.
+ We must therefore load the address via a temporary register if
+ mips_dangerous_for_la25_p.
+
+ If we jump to the temporary register rather than $25, the assembler
+ can use the move insn to fill the jump's delay slot. */
+ if (TARGET_ABICALLS && !mips_dangerous_for_la25_p (fnaddr))
+ temp1 = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
+ mips_load_call_address (temp1, fnaddr, true);
+
+ if (TARGET_ABICALLS && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM)
+ emit_move_insn (gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM), temp1);
+ emit_jump_insn (gen_indirect_jump (temp1));
+ }
+ else
+ {
+ insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx));
+ SIBLING_CALL_P (insn) = 1;
+ }
+
+ /* Run just enough of rest_of_compilation. This sequence was
+ "borrowed" from alpha.c. */
+ insn = get_insns ();
+ insn_locators_initialize ();
+ split_all_insns_noflow ();
+ if (TARGET_MIPS16)
+ mips16_lay_out_constants ();
+ shorten_branches (insn);
+ final_start_function (insn, file, 1);
+ final (insn, file, 1);
+ final_end_function ();
+
+ /* Clean up the vars set above. Note that final_end_function resets
+ the global pointer for us. */
+ reload_completed = 0;
+ no_new_pseudos = 0;
+}
+
+/* Returns nonzero if X contains a SYMBOL_REF. */
+
+static int
+symbolic_expression_p (rtx x)
+{
+ if (GET_CODE (x) == SYMBOL_REF)
+ return 1;
+
+ if (GET_CODE (x) == CONST)
+ return symbolic_expression_p (XEXP (x, 0));
+
+ if (UNARY_P (x))
+ return symbolic_expression_p (XEXP (x, 0));
+
+ if (ARITHMETIC_P (x))
+ return (symbolic_expression_p (XEXP (x, 0))
+ || symbolic_expression_p (XEXP (x, 1)));
+
+ return 0;
+}
+
+/* Choose the section to use for the constant rtx expression X that has
+ mode MODE. */
+
+static section *
+mips_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
+{
+ if (TARGET_MIPS16)
+ {
+ /* In mips16 mode, the constant table always goes in the same section
+ as the function, so that constants can be loaded using PC relative
+ addressing. */
+ return function_section (current_function_decl);
+ }
+ else if (TARGET_EMBEDDED_DATA)
+ {
+ /* For embedded applications, always put constants in read-only data,
+ in order to reduce RAM usage. */
+ return mergeable_constant_section (mode, align, 0);
+ }
+ else
+ {
+ /* For hosted applications, always put constants in small data if
+ possible, as this gives the best performance. */
+ /* ??? Consider using mergeable small data sections. */
+
+ if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold
+ && mips_section_threshold > 0)
+ return get_named_section (NULL, ".sdata", 0);
+ else if (flag_pic && symbolic_expression_p (x))
+ return get_named_section (NULL, ".data.rel.ro", 3);
+ else
+ return mergeable_constant_section (mode, align, 0);
+ }
+}
+
+/* Implement TARGET_ASM_FUNCTION_RODATA_SECTION.
+
+ The complication here is that, with the combination TARGET_ABICALLS
+ && !TARGET_GPWORD, jump tables will use absolute addresses, and should
+ therefore not be included in the read-only part of a DSO. Handle such
+ cases by selecting a normal data section instead of a read-only one.
+ The logic apes that in default_function_rodata_section. */
+
+static section *
+mips_function_rodata_section (tree decl)
+{
+ if (!TARGET_ABICALLS || TARGET_GPWORD)
+ return default_function_rodata_section (decl);
+
+ if (decl && DECL_SECTION_NAME (decl))
+ {
+ const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
+ {
+ char *rname = ASTRDUP (name);
+ rname[14] = 'd';
+ return get_section (rname, SECTION_LINKONCE | SECTION_WRITE, decl);
+ }
+ else if (flag_function_sections && flag_data_sections
+ && strncmp (name, ".text.", 6) == 0)
+ {
+ char *rname = ASTRDUP (name);
+ memcpy (rname + 1, "data", 4);
+ return get_section (rname, SECTION_WRITE, decl);
+ }
+ }
+ return data_section;
+}
+
+/* Implement TARGET_IN_SMALL_DATA_P. This function controls whether
+ locally-defined objects go in a small data section. It also controls
+ the setting of the SYMBOL_REF_SMALL_P flag, which in turn helps
+ mips_classify_symbol decide when to use %gp_rel(...)($gp) accesses. */
+
+static bool
+mips_in_small_data_p (tree decl)
+{
+ HOST_WIDE_INT size;
+
+ if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
+ return false;
+
+ /* We don't yet generate small-data references for -mabicalls. See related
+ -G handling in override_options. */
+ if (TARGET_ABICALLS)
+ return false;
+
+ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
+ {
+ const char *name;
+
+ /* Reject anything that isn't in a known small-data section. */
+ name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
+ if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
+ return false;
+
+ /* If a symbol is defined externally, the assembler will use the
+ usual -G rules when deciding how to implement macros. */
+ if (TARGET_EXPLICIT_RELOCS || !DECL_EXTERNAL (decl))
+ return true;
+ }
+ else if (TARGET_EMBEDDED_DATA)
+ {
+ /* Don't put constants into the small data section: we want them
+ to be in ROM rather than RAM. */
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+
+ if (TREE_READONLY (decl)
+ && !TREE_SIDE_EFFECTS (decl)
+ && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
+ return false;
+ }
+
+ size = int_size_in_bytes (TREE_TYPE (decl));
+ return (size > 0 && size <= mips_section_threshold);
+}
+
+/* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P. We don't want to use
+ anchors for small data: the GP register acts as an anchor in that
+ case. We also don't want to use them for PC-relative accesses,
+ where the PC acts as an anchor. */
+
+static bool
+mips_use_anchors_for_symbol_p (rtx symbol)
+{
+ switch (mips_classify_symbol (symbol))
+ {
+ case SYMBOL_CONSTANT_POOL:
+ case SYMBOL_SMALL_DATA:
+ return false;
+
+ default:
+ return true;
+ }
+}
+
+/* See whether VALTYPE is a record whose fields should be returned in
+ floating-point registers. If so, return the number of fields and
+ list them in FIELDS (which should have two elements). Return 0
+ otherwise.
+
+ For n32 & n64, a structure with one or two fields is returned in
+ floating-point registers as long as every field has a floating-point
+ type. */
+
+static int
+mips_fpr_return_fields (tree valtype, tree *fields)
+{
+ tree field;
+ int i;
+
+ if (!TARGET_NEWABI)
+ return 0;
+
+ if (TREE_CODE (valtype) != RECORD_TYPE)
+ return 0;
+
+ i = 0;
+ for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field))
+ {
+ if (TREE_CODE (field) != FIELD_DECL)
+ continue;
+
+ if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE)
+ return 0;
+
+ if (i == 2)
+ return 0;
+
+ fields[i++] = field;
+ }
+ return i;
+}
+
+
+/* Implement TARGET_RETURN_IN_MSB. For n32 & n64, we should return
+ a value in the most significant part of $2/$3 if:
+
+ - the target is big-endian;
+
+ - the value has a structure or union type (we generalize this to
+ cover aggregates from other languages too); and
+
+ - the structure is not returned in floating-point registers. */
+
+static bool
+mips_return_in_msb (tree valtype)
+{
+ tree fields[2];
+
+ return (TARGET_NEWABI
+ && TARGET_BIG_ENDIAN
+ && AGGREGATE_TYPE_P (valtype)
+ && mips_fpr_return_fields (valtype, fields) == 0);
+}
+
+
+/* Return a composite value in a pair of floating-point registers.
+ MODE1 and OFFSET1 are the mode and byte offset for the first value,
+ likewise MODE2 and OFFSET2 for the second. MODE is the mode of the
+ complete value.
+
+ For n32 & n64, $f0 always holds the first value and $f2 the second.
+ Otherwise the values are packed together as closely as possible. */
+
+static rtx
+mips_return_fpr_pair (enum machine_mode mode,
+ enum machine_mode mode1, HOST_WIDE_INT offset1,
+ enum machine_mode mode2, HOST_WIDE_INT offset2)
+{
+ int inc;
+
+ inc = (TARGET_NEWABI ? 2 : FP_INC);
+ return gen_rtx_PARALLEL
+ (mode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode1, FP_RETURN),
+ GEN_INT (offset1)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode2, FP_RETURN + inc),
+ GEN_INT (offset2))));
+
+}
+
+
+/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls,
+ VALTYPE is the return type and MODE is VOIDmode. For libcalls,
+ VALTYPE is null and MODE is the mode of the return value. */
+
+rtx
+mips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ if (valtype)
+ {
+ tree fields[2];
+ int unsignedp;
+
+ mode = TYPE_MODE (valtype);
+ unsignedp = TYPE_UNSIGNED (valtype);
+
+ /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns
+ true, we must promote the mode just as PROMOTE_MODE does. */
+ mode = promote_mode (valtype, mode, &unsignedp, 1);
+
+ /* Handle structures whose fields are returned in $f0/$f2. */
+ switch (mips_fpr_return_fields (valtype, fields))
+ {
+ case 1:
+ return gen_rtx_REG (mode, FP_RETURN);
+
+ case 2:
+ return mips_return_fpr_pair (mode,
+ TYPE_MODE (TREE_TYPE (fields[0])),
+ int_byte_position (fields[0]),
+ TYPE_MODE (TREE_TYPE (fields[1])),
+ int_byte_position (fields[1]));
+ }
+
+ /* If a value is passed in the most significant part of a register, see
+ whether we have to round the mode up to a whole number of words. */
+ if (mips_return_in_msb (valtype))
+ {
+ HOST_WIDE_INT size = int_size_in_bytes (valtype);
+ if (size % UNITS_PER_WORD != 0)
+ {
+ size += UNITS_PER_WORD - size % UNITS_PER_WORD;
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
+ }
+ }
+
+ /* For EABI, the class of return register depends entirely on MODE.
+ For example, "struct { some_type x; }" and "union { some_type x; }"
+ are returned in the same way as a bare "some_type" would be.
+ Other ABIs only use FPRs for scalar, complex or vector types. */
+ if (mips_abi != ABI_EABI && !FLOAT_TYPE_P (valtype))
+ return gen_rtx_REG (mode, GP_RETURN);
+ }
+
+ if ((GET_MODE_CLASS (mode) == MODE_FLOAT
+ || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
+ && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE)
+ return gen_rtx_REG (mode, FP_RETURN);
+
+ /* Handle long doubles for n32 & n64. */
+ if (mode == TFmode)
+ return mips_return_fpr_pair (mode,
+ DImode, 0,
+ DImode, GET_MODE_SIZE (mode) / 2);
+
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
+ && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2)
+ return mips_return_fpr_pair (mode,
+ GET_MODE_INNER (mode), 0,
+ GET_MODE_INNER (mode),
+ GET_MODE_SIZE (mode) / 2);
+
+ return gen_rtx_REG (mode, GP_RETURN);
+}
+
+/* Return nonzero when an argument must be passed by reference. */
+
+static bool
+mips_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
+{
+ if (mips_abi == ABI_EABI)
+ {
+ int size;
+
+ /* ??? How should SCmode be handled? */
+ if (mode == DImode || mode == DFmode)
+ return 0;
+
+ size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
+ return size == -1 || size > UNITS_PER_WORD;
+ }
+ else
+ {
+ /* If we have a variable-sized parameter, we have no choice. */
+ return targetm.calls.must_pass_in_stack (mode, type);
+ }
+}
+
+static bool
+mips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ tree type ATTRIBUTE_UNUSED, bool named)
+{
+ return mips_abi == ABI_EABI && named;
+}
+
+/* Return true if registers of class CLASS cannot change from mode FROM
+ to mode TO. */
+
+bool
+mips_cannot_change_mode_class (enum machine_mode from,
+ enum machine_mode to, enum reg_class class)
+{
+ if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD
+ && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS_PER_WORD)
+ {
+ if (TARGET_BIG_ENDIAN)
+ {
+ /* When a multi-word value is stored in paired floating-point
+ registers, the first register always holds the low word.
+ We therefore can't allow FPRs to change between single-word
+ and multi-word modes. */
+ if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class))
+ return true;
+ }
+ else
+ {
+ /* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored
+ in LO and HI, the high word always comes first. We therefore
+ can't allow values stored in HI to change between single-word
+ and multi-word modes.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_classes_intersect_p (ACC_REGS, class))
+ return true;
+ }
+ }
+ /* Loading a 32-bit value into a 64-bit floating-point register
+ will not sign-extend the value, despite what LOAD_EXTEND_OP says.
+ We can't allow 64-bit float registers to change from SImode to
+ to a wider mode. */
+ if (TARGET_FLOAT64
+ && from == SImode
+ && GET_MODE_SIZE (to) >= UNITS_PER_WORD
+ && reg_classes_intersect_p (FP_REGS, class))
+ return true;
+ return false;
+}
+
+/* Return true if X should not be moved directly into register $25.
+ We need this because many versions of GAS will treat "la $25,foo" as
+ part of a call sequence and so allow a global "foo" to be lazily bound. */
+
+bool
+mips_dangerous_for_la25_p (rtx x)
+{
+ HOST_WIDE_INT offset;
+
+ if (TARGET_EXPLICIT_RELOCS)
+ return false;
+
+ mips_split_const (x, &x, &offset);
+ return global_got_operand (x, VOIDmode);
+}
+
+/* Implement PREFERRED_RELOAD_CLASS. */
+
+enum reg_class
+mips_preferred_reload_class (rtx x, enum reg_class class)
+{
+ if (mips_dangerous_for_la25_p (x) && reg_class_subset_p (LEA_REGS, class))
+ return LEA_REGS;
+
+ if (TARGET_HARD_FLOAT
+ && FLOAT_MODE_P (GET_MODE (x))
+ && reg_class_subset_p (FP_REGS, class))
+ return FP_REGS;
+
+ if (reg_class_subset_p (GR_REGS, class))
+ class = GR_REGS;
+
+ if (TARGET_MIPS16 && reg_class_subset_p (M16_REGS, class))
+ class = M16_REGS;
+
+ return class;
+}
+
+/* This function returns the register class required for a secondary
+ register when copying between one of the registers in CLASS, and X,
+ using MODE. If IN_P is nonzero, the copy is going from X to the
+ register, otherwise the register is the source. A return value of
+ NO_REGS means that no secondary register is required. */
+
+enum reg_class
+mips_secondary_reload_class (enum reg_class class,
+ enum machine_mode mode, rtx x, int in_p)
+{
+ enum reg_class gr_regs = TARGET_MIPS16 ? M16_REGS : GR_REGS;
+ int regno = -1;
+ int gp_reg_p;
+
+ if (REG_P (x)|| GET_CODE (x) == SUBREG)
+ regno = true_regnum (x);
+
+ gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno);
+
+ if (mips_dangerous_for_la25_p (x))
+ {
+ gr_regs = LEA_REGS;
+ if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], 25))
+ return gr_regs;
+ }
+
+ /* Copying from HI or LO to anywhere other than a general register
+ requires a general register.
+ This rule applies to both the original HI/LO pair and the new
+ DSP accumulators. */
+ if (reg_class_subset_p (class, ACC_REGS))
+ {
+ if (TARGET_MIPS16 && in_p)
+ {
+ /* We can't really copy to HI or LO at all in mips16 mode. */
+ return M16_REGS;
+ }
+ return gp_reg_p ? NO_REGS : gr_regs;
+ }
+ if (ACC_REG_P (regno))
+ {
+ if (TARGET_MIPS16 && ! in_p)
+ {
+ /* We can't really copy to HI or LO at all in mips16 mode. */
+ return M16_REGS;
+ }
+ return class == gr_regs ? NO_REGS : gr_regs;
+ }
+
+ /* We can only copy a value to a condition code register from a
+ floating point register, and even then we require a scratch
+ floating point register. We can only copy a value out of a
+ condition code register into a general register. */
+ if (class == ST_REGS)
+ {
+ if (in_p)
+ return FP_REGS;
+ return gp_reg_p ? NO_REGS : gr_regs;
+ }
+ if (ST_REG_P (regno))
+ {
+ if (! in_p)
+ return FP_REGS;
+ return class == gr_regs ? NO_REGS : gr_regs;
+ }
+
+ if (class == FP_REGS)
+ {
+ if (MEM_P (x))
+ {
+ /* In this case we can use lwc1, swc1, ldc1 or sdc1. */
+ return NO_REGS;
+ }
+ else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ {
+ /* We can use the l.s and l.d macros to load floating-point
+ constants. ??? For l.s, we could probably get better
+ code by returning GR_REGS here. */
+ return NO_REGS;
+ }
+ else if (gp_reg_p || x == CONST0_RTX (mode))
+ {
+ /* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */
+ return NO_REGS;
+ }
+ else if (FP_REG_P (regno))
+ {
+ /* In this case we can use mov.s or mov.d. */
+ return NO_REGS;
+ }
+ else
+ {
+ /* Otherwise, we need to reload through an integer register. */
+ return gr_regs;
+ }
+ }
+
+ /* In mips16 mode, going between memory and anything but M16_REGS
+ requires an M16_REG. */
+ if (TARGET_MIPS16)
+ {
+ if (class != M16_REGS && class != M16_NA_REGS)
+ {
+ if (gp_reg_p)
+ return NO_REGS;
+ return M16_REGS;
+ }
+ if (! gp_reg_p)
+ {
+ if (class == M16_REGS || class == M16_NA_REGS)
+ return NO_REGS;
+ return M16_REGS;
+ }
+ }
+
+ return NO_REGS;
+}
+
+/* Implement CLASS_MAX_NREGS.
+
+ Usually all registers are word-sized. The only supported exception
+ is -mgp64 -msingle-float, which has 64-bit words but 32-bit float
+ registers. A word-based calculation is correct even in that case,
+ since -msingle-float disallows multi-FPR values.
+
+ The FP status registers are an exception to this rule. They are always
+ 4 bytes wide as they only hold condition code modes, and CCmode is always
+ considered to be 4 bytes wide. */
+
+int
+mips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
+{
+ if (class == ST_REGS)
+ return (GET_MODE_SIZE (mode) + 3) / 4;
+ else
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
+static bool
+mips_valid_pointer_mode (enum machine_mode mode)
+{
+ return (mode == SImode || (TARGET_64BIT && mode == DImode));
+}
+
+/* Target hook for vector_mode_supported_p. */
+
+static bool
+mips_vector_mode_supported_p (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V2SFmode:
+ return TARGET_PAIRED_SINGLE_FLOAT;
+
+ case V2HImode:
+ case V4QImode:
+ return TARGET_DSP;
+
+ default:
+ return false;
+ }
+}
+
+/* If we can access small data directly (using gp-relative relocation
+ operators) return the small data pointer, otherwise return null.
+
+ For each mips16 function which refers to GP relative symbols, we
+ use a pseudo register, initialized at the start of the function, to
+ hold the $gp value. */
+
+static rtx
+mips16_gp_pseudo_reg (void)
+{
+ if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX)
+ {
+ rtx unspec;
+ rtx insn, scan;
+
+ cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode);
+
+ /* We want to initialize this to a value which gcc will believe
+ is constant. */
+ start_sequence ();
+ unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP);
+ emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx,
+ gen_rtx_CONST (Pmode, unspec));
+ insn = get_insns ();
+ end_sequence ();
+
+ push_topmost_sequence ();
+ /* We need to emit the initialization after the FUNCTION_BEG
+ note, so that it will be integrated. */
+ for (scan = get_insns (); scan != NULL_RTX; scan = NEXT_INSN (scan))
+ if (NOTE_P (scan)
+ && NOTE_LINE_NUMBER (scan) == NOTE_INSN_FUNCTION_BEG)
+ break;
+ if (scan == NULL_RTX)
+ scan = get_insns ();
+ insn = emit_insn_after (insn, scan);
+ pop_topmost_sequence ();
+ }
+
+ return cfun->machine->mips16_gp_pseudo_rtx;
+}
+
+/* Write out code to move floating point arguments in or out of
+ general registers. Output the instructions to FILE. FP_CODE is
+ the code describing which arguments are present (see the comment at
+ the definition of CUMULATIVE_ARGS in mips.h). FROM_FP_P is nonzero if
+ we are copying from the floating point registers. */
+
+static void
+mips16_fp_args (FILE *file, int fp_code, int from_fp_p)
+{
+ const char *s;
+ int gparg, fparg;
+ unsigned int f;
+
+ /* This code only works for the original 32 bit ABI and the O64 ABI. */
+ gcc_assert (TARGET_OLDABI);
+
+ if (from_fp_p)
+ s = "mfc1";
+ else
+ s = "mtc1";
+ gparg = GP_ARG_FIRST;
+ fparg = FP_ARG_FIRST;
+ for (f = (unsigned int) fp_code; f != 0; f >>= 2)
+ {
+ if ((f & 3) == 1)
+ {
+ if ((fparg & 1) != 0)
+ ++fparg;
+ fprintf (file, "\t%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg]);
+ }
+ else if ((f & 3) == 2)
+ {
+ if (TARGET_64BIT)
+ fprintf (file, "\td%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg]);
+ else
+ {
+ if ((fparg & 1) != 0)
+ ++fparg;
+ if (TARGET_BIG_ENDIAN)
+ fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg + 1], s,
+ reg_names[gparg + 1], reg_names[fparg]);
+ else
+ fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s,
+ reg_names[gparg], reg_names[fparg], s,
+ reg_names[gparg + 1], reg_names[fparg + 1]);
+ ++gparg;
+ ++fparg;
+ }
+ }
+ else
+ gcc_unreachable ();
+
+ ++gparg;
+ ++fparg;
+ }
+}
+
+/* Build a mips16 function stub. This is used for functions which
+ take arguments in the floating point registers. It is 32 bit code
+ that moves the floating point args into the general registers, and
+ then jumps to the 16 bit code. */
+
+static void
+build_mips16_function_stub (FILE *file)
+{
+ const char *fnname;
+ char *secname, *stubname;
+ tree stubid, stubdecl;
+ int need_comma;
+ unsigned int f;
+
+ fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0);
+ secname = (char *) alloca (strlen (fnname) + 20);
+ sprintf (secname, ".mips16.fn.%s", fnname);
+ stubname = (char *) alloca (strlen (fnname) + 20);
+ sprintf (stubname, "__fn_stub_%s", fnname);
+ stubid = get_identifier (stubname);
+ stubdecl = build_decl (FUNCTION_DECL, stubid,
+ build_function_type (void_type_node, NULL_TREE));
+ DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+
+ fprintf (file, "\t# Stub function for %s (", current_function_name ());
+ need_comma = 0;
+ for (f = (unsigned int) current_function_args_info.fp_code; f != 0; f >>= 2)
+ {
+ fprintf (file, "%s%s",
+ need_comma ? ", " : "",
+ (f & 3) == 1 ? "float" : "double");
+ need_comma = 1;
+ }
+ fprintf (file, ")\n");
+
+ fprintf (file, "\t.set\tnomips16\n");
+ switch_to_section (function_section (stubdecl));
+ ASM_OUTPUT_ALIGN (file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT));
+
+ /* ??? If FUNCTION_NAME_ALREADY_DECLARED is defined, then we are
+ within a .ent, and we cannot emit another .ent. */
+ if (!FUNCTION_NAME_ALREADY_DECLARED)
+ {
+ fputs ("\t.ent\t", file);
+ assemble_name (file, stubname);
+ fputs ("\n", file);
+ }
+
+ assemble_name (file, stubname);
+ fputs (":\n", file);
+
+ /* We don't want the assembler to insert any nops here. */
+ fprintf (file, "\t.set\tnoreorder\n");
+
+ mips16_fp_args (file, current_function_args_info.fp_code, 1);
+
+ fprintf (asm_out_file, "\t.set\tnoat\n");
+ fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]);
+ assemble_name (file, fnname);
+ fprintf (file, "\n");
+ fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
+ fprintf (asm_out_file, "\t.set\tat\n");
+
+ /* Unfortunately, we can't fill the jump delay slot. We can't fill
+ with one of the mfc1 instructions, because the result is not
+ available for one instruction, so if the very first instruction
+ in the function refers to the register, it will see the wrong
+ value. */
+ fprintf (file, "\tnop\n");
+
+ fprintf (file, "\t.set\treorder\n");
+
+ if (!FUNCTION_NAME_ALREADY_DECLARED)
+ {
+ fputs ("\t.end\t", file);
+ assemble_name (file, stubname);
+ fputs ("\n", file);
+ }
+
+ fprintf (file, "\t.set\tmips16\n");
+
+ switch_to_section (function_section (current_function_decl));
+}
+
+/* We keep a list of functions for which we have already built stubs
+ in build_mips16_call_stub. */
+
+struct mips16_stub
+{
+ struct mips16_stub *next;
+ char *name;
+ int fpret;
+};
+
+static struct mips16_stub *mips16_stubs;
+
+/* Build a call stub for a mips16 call. A stub is needed if we are
+ passing any floating point values which should go into the floating
+ point registers. If we are, and the call turns out to be to a 32
+ bit function, the stub will be used to move the values into the
+ floating point registers before calling the 32 bit function. The
+ linker will magically adjust the function call to either the 16 bit
+ function or the 32 bit stub, depending upon where the function call
+ is actually defined.
+
+ Similarly, we need a stub if the return value might come back in a
+ floating point register.
+
+ RETVAL is the location of the return value, or null if this is
+ a call rather than a call_value. FN is the address of the
+ function and ARG_SIZE is the size of the arguments. FP_CODE
+ is the code built by function_arg. This function returns a nonzero
+ value if it builds the call instruction itself. */
+
+int
+build_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code)
+{
+ int fpret;
+ const char *fnname;
+ char *secname, *stubname;
+ struct mips16_stub *l;
+ tree stubid, stubdecl;
+ int need_comma;
+ unsigned int f;
+
+ /* We don't need to do anything if we aren't in mips16 mode, or if
+ we were invoked with the -msoft-float option. */
+ if (! TARGET_MIPS16 || ! mips16_hard_float)
+ return 0;
+
+ /* Figure out whether the value might come back in a floating point
+ register. */
+ fpret = (retval != 0
+ && GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT
+ && GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE);
+
+ /* We don't need to do anything if there were no floating point
+ arguments and the value will not be returned in a floating point
+ register. */
+ if (fp_code == 0 && ! fpret)
+ return 0;
+
+ /* We don't need to do anything if this is a call to a special
+ mips16 support function. */
+ if (GET_CODE (fn) == SYMBOL_REF
+ && strncmp (XSTR (fn, 0), "__mips16_", 9) == 0)
+ return 0;
+
+ /* This code will only work for o32 and o64 abis. The other ABI's
+ require more sophisticated support. */
+ gcc_assert (TARGET_OLDABI);
+
+ /* We can only handle SFmode and DFmode floating point return
+ values. */
+ if (fpret)
+ gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode);
+
+ /* If we're calling via a function pointer, then we must always call
+ via a stub. There are magic stubs provided in libgcc.a for each
+ of the required cases. Each of them expects the function address
+ to arrive in register $2. */
+
+ if (GET_CODE (fn) != SYMBOL_REF)
+ {
+ char buf[30];
+ tree id;
+ rtx stub_fn, insn;
+
+ /* ??? If this code is modified to support other ABI's, we need
+ to handle PARALLEL return values here. */
+
+ sprintf (buf, "__mips16_call_stub_%s%d",
+ (fpret
+ ? (GET_MODE (retval) == SFmode ? "sf_" : "df_")
+ : ""),
+ fp_code);
+ id = get_identifier (buf);
+ stub_fn = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id));
+
+ emit_move_insn (gen_rtx_REG (Pmode, 2), fn);
+
+ if (retval == NULL_RTX)
+ insn = gen_call_internal (stub_fn, arg_size);
+ else
+ insn = gen_call_value_internal (retval, stub_fn, arg_size);
+ insn = emit_call_insn (insn);
+
+ /* Put the register usage information on the CALL. */
+ CALL_INSN_FUNCTION_USAGE (insn) =
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 2)),
+ CALL_INSN_FUNCTION_USAGE (insn));
+
+ /* If we are handling a floating point return value, we need to
+ save $18 in the function prologue. Putting a note on the
+ call will mean that regs_ever_live[$18] will be true if the
+ call is not eliminated, and we can check that in the prologue
+ code. */
+ if (fpret)
+ CALL_INSN_FUNCTION_USAGE (insn) =
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (word_mode, 18)),
+ CALL_INSN_FUNCTION_USAGE (insn));
+
+ /* Return 1 to tell the caller that we've generated the call
+ insn. */
+ return 1;
+ }
+
+ /* We know the function we are going to call. If we have already
+ built a stub, we don't need to do anything further. */
+
+ fnname = XSTR (fn, 0);
+ for (l = mips16_stubs; l != NULL; l = l->next)
+ if (strcmp (l->name, fnname) == 0)
+ break;
+
+ if (l == NULL)
+ {
+ /* Build a special purpose stub. When the linker sees a
+ function call in mips16 code, it will check where the target
+ is defined. If the target is a 32 bit call, the linker will
+ search for the section defined here. It can tell which
+ symbol this section is associated with by looking at the
+ relocation information (the name is unreliable, since this
+ might be a static function). If such a section is found, the
+ linker will redirect the call to the start of the magic
+ section.
+
+ If the function does not return a floating point value, the
+ special stub section is named
+ .mips16.call.FNNAME
+
+ If the function does return a floating point value, the stub
+ section is named
+ .mips16.call.fp.FNNAME
+ */
+
+ secname = (char *) alloca (strlen (fnname) + 40);
+ sprintf (secname, ".mips16.call.%s%s",
+ fpret ? "fp." : "",
+ fnname);
+ stubname = (char *) alloca (strlen (fnname) + 20);
+ sprintf (stubname, "__call_stub_%s%s",
+ fpret ? "fp_" : "",
+ fnname);
+ stubid = get_identifier (stubname);
+ stubdecl = build_decl (FUNCTION_DECL, stubid,
+ build_function_type (void_type_node, NULL_TREE));
+ DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname);
+
+ fprintf (asm_out_file, "\t# Stub function to call %s%s (",
+ (fpret
+ ? (GET_MODE (retval) == SFmode ? "float " : "double ")
+ : ""),
+ fnname);
+ need_comma = 0;
+ for (f = (unsigned int) fp_code; f != 0; f >>= 2)
+ {
+ fprintf (asm_out_file, "%s%s",
+ need_comma ? ", " : "",
+ (f & 3) == 1 ? "float" : "double");
+ need_comma = 1;
+ }
+ fprintf (asm_out_file, ")\n");
+
+ fprintf (asm_out_file, "\t.set\tnomips16\n");
+ assemble_start_function (stubdecl, stubname);
+
+ if (!FUNCTION_NAME_ALREADY_DECLARED)
+ {
+ fputs ("\t.ent\t", asm_out_file);
+ assemble_name (asm_out_file, stubname);
+ fputs ("\n", asm_out_file);
+
+ assemble_name (asm_out_file, stubname);
+ fputs (":\n", asm_out_file);
+ }
+
+ /* We build the stub code by hand. That's the only way we can
+ do it, since we can't generate 32 bit code during a 16 bit
+ compilation. */
+
+ /* We don't want the assembler to insert any nops here. */
+ fprintf (asm_out_file, "\t.set\tnoreorder\n");
+
+ mips16_fp_args (asm_out_file, fp_code, 0);
+
+ if (! fpret)
+ {
+ fprintf (asm_out_file, "\t.set\tnoat\n");
+ fprintf (asm_out_file, "\tla\t%s,%s\n", reg_names[GP_REG_FIRST + 1],
+ fnname);
+ fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]);
+ fprintf (asm_out_file, "\t.set\tat\n");
+ /* Unfortunately, we can't fill the jump delay slot. We
+ can't fill with one of the mtc1 instructions, because the
+ result is not available for one instruction, so if the
+ very first instruction in the function refers to the
+ register, it will see the wrong value. */
+ fprintf (asm_out_file, "\tnop\n");
+ }
+ else
+ {
+ fprintf (asm_out_file, "\tmove\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 18], reg_names[GP_REG_FIRST + 31]);
+ fprintf (asm_out_file, "\tjal\t%s\n", fnname);
+ /* As above, we can't fill the delay slot. */
+ fprintf (asm_out_file, "\tnop\n");
+ if (GET_MODE (retval) == SFmode)
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]);
+ else
+ {
+ if (TARGET_BIG_ENDIAN)
+ {
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 2],
+ reg_names[FP_REG_FIRST + 1]);
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 3],
+ reg_names[FP_REG_FIRST + 0]);
+ }
+ else
+ {
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 2],
+ reg_names[FP_REG_FIRST + 0]);
+ fprintf (asm_out_file, "\tmfc1\t%s,%s\n",
+ reg_names[GP_REG_FIRST + 3],
+ reg_names[FP_REG_FIRST + 1]);
+ }
+ }
+ fprintf (asm_out_file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 18]);
+ /* As above, we can't fill the delay slot. */
+ fprintf (asm_out_file, "\tnop\n");
+ }
+
+ fprintf (asm_out_file, "\t.set\treorder\n");
+
+#ifdef ASM_DECLARE_FUNCTION_SIZE
+ ASM_DECLARE_FUNCTION_SIZE (asm_out_file, stubname, stubdecl);
+#endif
+
+ if (!FUNCTION_NAME_ALREADY_DECLARED)
+ {
+ fputs ("\t.end\t", asm_out_file);
+ assemble_name (asm_out_file, stubname);
+ fputs ("\n", asm_out_file);
+ }
+
+ fprintf (asm_out_file, "\t.set\tmips16\n");
+
+ /* Record this stub. */
+ l = (struct mips16_stub *) xmalloc (sizeof *l);
+ l->name = xstrdup (fnname);
+ l->fpret = fpret;
+ l->next = mips16_stubs;
+ mips16_stubs = l;
+ }
+
+ /* If we expect a floating point return value, but we've built a
+ stub which does not expect one, then we're in trouble. We can't
+ use the existing stub, because it won't handle the floating point
+ value. We can't build a new stub, because the linker won't know
+ which stub to use for the various calls in this object file.
+ Fortunately, this case is illegal, since it means that a function
+ was declared in two different ways in a single compilation. */
+ if (fpret && ! l->fpret)
+ error ("cannot handle inconsistent calls to %qs", fnname);
+
+ /* If we are calling a stub which handles a floating point return
+ value, we need to arrange to save $18 in the prologue. We do
+ this by marking the function call as using the register. The
+ prologue will later see that it is used, and emit code to save
+ it. */
+
+ if (l->fpret)
+ {
+ rtx insn;
+
+ if (retval == NULL_RTX)
+ insn = gen_call_internal (fn, arg_size);
+ else
+ insn = gen_call_value_internal (retval, fn, arg_size);
+ insn = emit_call_insn (insn);
+
+ CALL_INSN_FUNCTION_USAGE (insn) =
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)),
+ CALL_INSN_FUNCTION_USAGE (insn));
+
+ /* Return 1 to tell the caller that we've generated the call
+ insn. */
+ return 1;
+ }
+
+ /* Return 0 to let the caller generate the call insn. */
+ return 0;
+}
+
+/* An entry in the mips16 constant pool. VALUE is the pool constant,
+ MODE is its mode, and LABEL is the CODE_LABEL associated with it. */
+
+struct mips16_constant {
+ struct mips16_constant *next;
+ rtx value;
+ rtx label;
+ enum machine_mode mode;
+};
+
+/* Information about an incomplete mips16 constant pool. FIRST is the
+ first constant, HIGHEST_ADDRESS is the highest address that the first
+ byte of the pool can have, and INSN_ADDRESS is the current instruction
+ address. */
+
+struct mips16_constant_pool {
+ struct mips16_constant *first;
+ int highest_address;
+ int insn_address;
+};
+
+/* Add constant VALUE to POOL and return its label. MODE is the
+ value's mode (used for CONST_INTs, etc.). */
+
+static rtx
+add_constant (struct mips16_constant_pool *pool,
+ rtx value, enum machine_mode mode)
+{
+ struct mips16_constant **p, *c;
+ bool first_of_size_p;
+
+ /* See whether the constant is already in the pool. If so, return the
+ existing label, otherwise leave P pointing to the place where the
+ constant should be added.
+
+ Keep the pool sorted in increasing order of mode size so that we can
+ reduce the number of alignments needed. */
+ first_of_size_p = true;
+ for (p = &pool->first; *p != 0; p = &(*p)->next)
+ {
+ if (mode == (*p)->mode && rtx_equal_p (value, (*p)->value))
+ return (*p)->label;
+ if (GET_MODE_SIZE (mode) < GET_MODE_SIZE ((*p)->mode))
+ break;
+ if (GET_MODE_SIZE (mode) == GET_MODE_SIZE ((*p)->mode))
+ first_of_size_p = false;
+ }
+
+ /* In the worst case, the constant needed by the earliest instruction
+ will end up at the end of the pool. The entire pool must then be
+ accessible from that instruction.
+
+ When adding the first constant, set the pool's highest address to
+ the address of the first out-of-range byte. Adjust this address
+ downwards each time a new constant is added. */
+ if (pool->first == 0)
+ /* For pc-relative lw, addiu and daddiu instructions, the base PC value
+ is the address of the instruction with the lowest two bits clear.
+ The base PC value for ld has the lowest three bits clear. Assume
+ the worst case here. */
+ pool->highest_address = pool->insn_address - (UNITS_PER_WORD - 2) + 0x8000;
+ pool->highest_address -= GET_MODE_SIZE (mode);
+ if (first_of_size_p)
+ /* Take into account the worst possible padding due to alignment. */
+ pool->highest_address -= GET_MODE_SIZE (mode) - 1;
+
+ /* Create a new entry. */
+ c = (struct mips16_constant *) xmalloc (sizeof *c);
+ c->value = value;
+ c->mode = mode;
+ c->label = gen_label_rtx ();
+ c->next = *p;
+ *p = c;
+
+ return c->label;
+}
+
+/* Output constant VALUE after instruction INSN and return the last
+ instruction emitted. MODE is the mode of the constant. */
+
+static rtx
+dump_constants_1 (enum machine_mode mode, rtx value, rtx insn)
+{
+ switch (GET_MODE_CLASS (mode))
+ {
+ case MODE_INT:
+ {
+ rtx size = GEN_INT (GET_MODE_SIZE (mode));
+ return emit_insn_after (gen_consttable_int (value, size), insn);
+ }
+
+ case MODE_FLOAT:
+ return emit_insn_after (gen_consttable_float (value), insn);
+
+ case MODE_VECTOR_FLOAT:
+ case MODE_VECTOR_INT:
+ {
+ int i;
+ for (i = 0; i < CONST_VECTOR_NUNITS (value); i++)
+ insn = dump_constants_1 (GET_MODE_INNER (mode),
+ CONST_VECTOR_ELT (value, i), insn);
+ return insn;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+/* Dump out the constants in CONSTANTS after INSN. */
+
+static void
+dump_constants (struct mips16_constant *constants, rtx insn)
+{
+ struct mips16_constant *c, *next;
+ int align;
+
+ align = 0;
+ for (c = constants; c != NULL; c = next)
+ {
+ /* If necessary, increase the alignment of PC. */
+ if (align < GET_MODE_SIZE (c->mode))
+ {
+ int align_log = floor_log2 (GET_MODE_SIZE (c->mode));
+ insn = emit_insn_after (gen_align (GEN_INT (align_log)), insn);
+ }
+ align = GET_MODE_SIZE (c->mode);
+
+ insn = emit_label_after (c->label, insn);
+ insn = dump_constants_1 (c->mode, c->value, insn);
+
+ next = c->next;
+ free (c);
+ }
+
+ emit_barrier_after (insn);
+}
+
+/* Return the length of instruction INSN. */
+
+static int
+mips16_insn_length (rtx insn)
+{
+ if (JUMP_P (insn))
+ {
+ rtx body = PATTERN (insn);
+ if (GET_CODE (body) == ADDR_VEC)
+ return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 0);
+ if (GET_CODE (body) == ADDR_DIFF_VEC)
+ return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 1);
+ }
+ return get_attr_length (insn);
+}
+
+/* Rewrite *X so that constant pool references refer to the constant's
+ label instead. DATA points to the constant pool structure. */
+
+static int
+mips16_rewrite_pool_refs (rtx *x, void *data)
+{
+ struct mips16_constant_pool *pool = data;
+ if (GET_CODE (*x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (*x))
+ *x = gen_rtx_LABEL_REF (Pmode, add_constant (pool,
+ get_pool_constant (*x),
+ get_pool_mode (*x)));
+ return 0;
+}
+
+/* Build MIPS16 constant pools. */
+
+static void
+mips16_lay_out_constants (void)
+{
+ struct mips16_constant_pool pool;
+ rtx insn, barrier;
+
+ barrier = 0;
+ memset (&pool, 0, sizeof (pool));
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ /* Rewrite constant pool references in INSN. */
+ if (INSN_P (insn))
+ for_each_rtx (&PATTERN (insn), mips16_rewrite_pool_refs, &pool);
+
+ pool.insn_address += mips16_insn_length (insn);
+
+ if (pool.first != NULL)
+ {
+ /* If there are no natural barriers between the first user of
+ the pool and the highest acceptable address, we'll need to
+ create a new instruction to jump around the constant pool.
+ In the worst case, this instruction will be 4 bytes long.
+
+ If it's too late to do this transformation after INSN,
+ do it immediately before INSN. */
+ if (barrier == 0 && pool.insn_address + 4 > pool.highest_address)
+ {
+ rtx label, jump;
+
+ label = gen_label_rtx ();
+
+ jump = emit_jump_insn_before (gen_jump (label), insn);
+ JUMP_LABEL (jump) = label;
+ LABEL_NUSES (label) = 1;
+ barrier = emit_barrier_after (jump);
+
+ emit_label_after (label, barrier);
+ pool.insn_address += 4;
+ }
+
+ /* See whether the constant pool is now out of range of the first
+ user. If so, output the constants after the previous barrier.
+ Note that any instructions between BARRIER and INSN (inclusive)
+ will use negative offsets to refer to the pool. */
+ if (pool.insn_address > pool.highest_address)
+ {
+ dump_constants (pool.first, barrier);
+ pool.first = NULL;
+ barrier = 0;
+ }
+ else if (BARRIER_P (insn))
+ barrier = insn;
+ }
+ }
+ dump_constants (pool.first, get_last_insn ());
+}
+
+/* A temporary variable used by for_each_rtx callbacks, etc. */
+static rtx mips_sim_insn;
+
+/* A structure representing the state of the processor pipeline.
+ Used by the mips_sim_* family of functions. */
+struct mips_sim {
+ /* The maximum number of instructions that can be issued in a cycle.
+ (Caches mips_issue_rate.) */
+ unsigned int issue_rate;
+
+ /* The current simulation time. */
+ unsigned int time;
+
+ /* How many more instructions can be issued in the current cycle. */
+ unsigned int insns_left;
+
+ /* LAST_SET[X].INSN is the last instruction to set register X.
+ LAST_SET[X].TIME is the time at which that instruction was issued.
+ INSN is null if no instruction has yet set register X. */
+ struct {
+ rtx insn;
+ unsigned int time;
+ } last_set[FIRST_PSEUDO_REGISTER];
+
+ /* The pipeline's current DFA state. */
+ state_t dfa_state;
+};
+
+/* Reset STATE to the initial simulation state. */
+
+static void
+mips_sim_reset (struct mips_sim *state)
+{
+ state->time = 0;
+ state->insns_left = state->issue_rate;
+ memset (&state->last_set, 0, sizeof (state->last_set));
+ state_reset (state->dfa_state);
+}
+
+/* Initialize STATE before its first use. DFA_STATE points to an
+ allocated but uninitialized DFA state. */
+
+static void
+mips_sim_init (struct mips_sim *state, state_t dfa_state)
+{
+ state->issue_rate = mips_issue_rate ();
+ state->dfa_state = dfa_state;
+ mips_sim_reset (state);
+}
+
+/* Advance STATE by one clock cycle. */
+
+static void
+mips_sim_next_cycle (struct mips_sim *state)
+{
+ state->time++;
+ state->insns_left = state->issue_rate;
+ state_transition (state->dfa_state, 0);
+}
+
+/* Advance simulation state STATE until instruction INSN can read
+ register REG. */
+
+static void
+mips_sim_wait_reg (struct mips_sim *state, rtx insn, rtx reg)
+{
+ unsigned int i;
+
+ for (i = 0; i < HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)); i++)
+ if (state->last_set[REGNO (reg) + i].insn != 0)
+ {
+ unsigned int t;
+
+ t = state->last_set[REGNO (reg) + i].time;
+ t += insn_latency (state->last_set[REGNO (reg) + i].insn, insn);
+ while (state->time < t)
+ mips_sim_next_cycle (state);
+ }
+}
+
+/* A for_each_rtx callback. If *X is a register, advance simulation state
+ DATA until mips_sim_insn can read the register's value. */
+
+static int
+mips_sim_wait_regs_2 (rtx *x, void *data)
+{
+ if (REG_P (*x))
+ mips_sim_wait_reg (data, mips_sim_insn, *x);
+ return 0;
+}
+
+/* Call mips_sim_wait_regs_2 (R, DATA) for each register R mentioned in *X. */
+
+static void
+mips_sim_wait_regs_1 (rtx *x, void *data)
+{
+ for_each_rtx (x, mips_sim_wait_regs_2, data);
+}
+
+/* Advance simulation state STATE until all of INSN's register
+ dependencies are satisfied. */
+
+static void
+mips_sim_wait_regs (struct mips_sim *state, rtx insn)
+{
+ mips_sim_insn = insn;
+ note_uses (&PATTERN (insn), mips_sim_wait_regs_1, state);
+}
+
+/* Advance simulation state STATE until the units required by
+ instruction INSN are available. */
+
+static void
+mips_sim_wait_units (struct mips_sim *state, rtx insn)
+{
+ state_t tmp_state;
+
+ tmp_state = alloca (state_size ());
+ while (state->insns_left == 0
+ || (memcpy (tmp_state, state->dfa_state, state_size ()),
+ state_transition (tmp_state, insn) >= 0))
+ mips_sim_next_cycle (state);
+}
+
+/* Advance simulation state STATE until INSN is ready to issue. */
+
+static void
+mips_sim_wait_insn (struct mips_sim *state, rtx insn)
+{
+ mips_sim_wait_regs (state, insn);
+ mips_sim_wait_units (state, insn);
+}
+
+/* mips_sim_insn has just set X. Update the LAST_SET array
+ in simulation state DATA. */
+
+static void
+mips_sim_record_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
+{
+ struct mips_sim *state;
+ unsigned int i;
+
+ state = data;
+ if (REG_P (x))
+ for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++)
+ {
+ state->last_set[REGNO (x) + i].insn = mips_sim_insn;
+ state->last_set[REGNO (x) + i].time = state->time;
+ }
+}
+
+/* Issue instruction INSN in scheduler state STATE. Assume that INSN
+ can issue immediately (i.e., that mips_sim_wait_insn has already
+ been called). */
+
+static void
+mips_sim_issue_insn (struct mips_sim *state, rtx insn)
+{
+ state_transition (state->dfa_state, insn);
+ state->insns_left--;
+
+ mips_sim_insn = insn;
+ note_stores (PATTERN (insn), mips_sim_record_set, state);
+}
+
+/* Simulate issuing a NOP in state STATE. */
+
+static void
+mips_sim_issue_nop (struct mips_sim *state)
+{
+ if (state->insns_left == 0)
+ mips_sim_next_cycle (state);
+ state->insns_left--;
+}
+
+/* Update simulation state STATE so that it's ready to accept the instruction
+ after INSN. INSN should be part of the main rtl chain, not a member of a
+ SEQUENCE. */
+
+static void
+mips_sim_finish_insn (struct mips_sim *state, rtx insn)
+{
+ /* If INSN is a jump with an implicit delay slot, simulate a nop. */
+ if (JUMP_P (insn))
+ mips_sim_issue_nop (state);
+
+ switch (GET_CODE (SEQ_BEGIN (insn)))
+ {
+ case CODE_LABEL:
+ case CALL_INSN:
+ /* We can't predict the processor state after a call or label. */
+ mips_sim_reset (state);
+ break;
+
+ case JUMP_INSN:
+ /* The delay slots of branch likely instructions are only executed
+ when the branch is taken. Therefore, if the caller has simulated
+ the delay slot instruction, STATE does not really reflect the state
+ of the pipeline for the instruction after the delay slot. Also,
+ branch likely instructions tend to incur a penalty when not taken,
+ so there will probably be an extra delay between the branch and
+ the instruction after the delay slot. */
+ if (INSN_ANNULLED_BRANCH_P (SEQ_BEGIN (insn)))
+ mips_sim_reset (state);
+ break;
+
+ default:
+ break;
+ }
+}
+
+/* The VR4130 pipeline issues aligned pairs of instructions together,
+ but it stalls the second instruction if it depends on the first.
+ In order to cut down the amount of logic required, this dependence
+ check is not based on a full instruction decode. Instead, any non-SPECIAL
+ instruction is assumed to modify the register specified by bits 20-16
+ (which is usually the "rt" field).
+
+ In beq, beql, bne and bnel instructions, the rt field is actually an
+ input, so we can end up with a false dependence between the branch
+ and its delay slot. If this situation occurs in instruction INSN,
+ try to avoid it by swapping rs and rt. */
+
+static void
+vr4130_avoid_branch_rt_conflict (rtx insn)
+{
+ rtx first, second;
+
+ first = SEQ_BEGIN (insn);
+ second = SEQ_END (insn);
+ if (JUMP_P (first)
+ && NONJUMP_INSN_P (second)
+ && GET_CODE (PATTERN (first)) == SET
+ && GET_CODE (SET_DEST (PATTERN (first))) == PC
+ && GET_CODE (SET_SRC (PATTERN (first))) == IF_THEN_ELSE)
+ {
+ /* Check for the right kind of condition. */
+ rtx cond = XEXP (SET_SRC (PATTERN (first)), 0);
+ if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE)
+ && REG_P (XEXP (cond, 0))
+ && REG_P (XEXP (cond, 1))
+ && reg_referenced_p (XEXP (cond, 1), PATTERN (second))
+ && !reg_referenced_p (XEXP (cond, 0), PATTERN (second)))
+ {
+ /* SECOND mentions the rt register but not the rs register. */
+ rtx tmp = XEXP (cond, 0);
+ XEXP (cond, 0) = XEXP (cond, 1);
+ XEXP (cond, 1) = tmp;
+ }
+ }
+}
+
+/* Implement -mvr4130-align. Go through each basic block and simulate the
+ processor pipeline. If we find that a pair of instructions could execute
+ in parallel, and the first of those instruction is not 8-byte aligned,
+ insert a nop to make it aligned. */
+
+static void
+vr4130_align_insns (void)
+{
+ struct mips_sim state;
+ rtx insn, subinsn, last, last2, next;
+ bool aligned_p;
+
+ dfa_start ();
+
+ /* LAST is the last instruction before INSN to have a nonzero length.
+ LAST2 is the last such instruction before LAST. */
+ last = 0;
+ last2 = 0;
+
+ /* ALIGNED_P is true if INSN is known to be at an aligned address. */
+ aligned_p = true;
+
+ mips_sim_init (&state, alloca (state_size ()));
+ for (insn = get_insns (); insn != 0; insn = next)
+ {
+ unsigned int length;
+
+ next = NEXT_INSN (insn);
+
+ /* See the comment above vr4130_avoid_branch_rt_conflict for details.
+ This isn't really related to the alignment pass, but we do it on
+ the fly to avoid a separate instruction walk. */
+ vr4130_avoid_branch_rt_conflict (insn);
+
+ if (USEFUL_INSN_P (insn))
+ FOR_EACH_SUBINSN (subinsn, insn)
+ {
+ mips_sim_wait_insn (&state, subinsn);
+
+ /* If we want this instruction to issue in parallel with the
+ previous one, make sure that the previous instruction is
+ aligned. There are several reasons why this isn't worthwhile
+ when the second instruction is a call:
+
+ - Calls are less likely to be performance critical,
+ - There's a good chance that the delay slot can execute
+ in parallel with the call.
+ - The return address would then be unaligned.
+
+ In general, if we're going to insert a nop between instructions
+ X and Y, it's better to insert it immediately after X. That
+ way, if the nop makes Y aligned, it will also align any labels
+ between X and Y. */
+ if (state.insns_left != state.issue_rate
+ && !CALL_P (subinsn))
+ {
+ if (subinsn == SEQ_BEGIN (insn) && aligned_p)
+ {
+ /* SUBINSN is the first instruction in INSN and INSN is
+ aligned. We want to align the previous instruction
+ instead, so insert a nop between LAST2 and LAST.
+
+ Note that LAST could be either a single instruction
+ or a branch with a delay slot. In the latter case,
+ LAST, like INSN, is already aligned, but the delay
+ slot must have some extra delay that stops it from
+ issuing at the same time as the branch. We therefore
+ insert a nop before the branch in order to align its
+ delay slot. */
+ emit_insn_after (gen_nop (), last2);
+ aligned_p = false;
+ }
+ else if (subinsn != SEQ_BEGIN (insn) && !aligned_p)
+ {
+ /* SUBINSN is the delay slot of INSN, but INSN is
+ currently unaligned. Insert a nop between
+ LAST and INSN to align it. */
+ emit_insn_after (gen_nop (), last);
+ aligned_p = true;
+ }
+ }
+ mips_sim_issue_insn (&state, subinsn);
+ }
+ mips_sim_finish_insn (&state, insn);
+
+ /* Update LAST, LAST2 and ALIGNED_P for the next instruction. */
+ length = get_attr_length (insn);
+ if (length > 0)
+ {
+ /* If the instruction is an asm statement or multi-instruction
+ mips.md patern, the length is only an estimate. Insert an
+ 8 byte alignment after it so that the following instructions
+ can be handled correctly. */
+ if (NONJUMP_INSN_P (SEQ_BEGIN (insn))
+ && (recog_memoized (insn) < 0 || length >= 8))
+ {
+ next = emit_insn_after (gen_align (GEN_INT (3)), insn);
+ next = NEXT_INSN (next);
+ mips_sim_next_cycle (&state);
+ aligned_p = true;
+ }
+ else if (length & 4)
+ aligned_p = !aligned_p;
+ last2 = last;
+ last = insn;
+ }
+
+ /* See whether INSN is an aligned label. */
+ if (LABEL_P (insn) && label_to_alignment (insn) >= 3)
+ aligned_p = true;
+ }
+ dfa_finish ();
+}
+
+/* Subroutine of mips_reorg. If there is a hazard between INSN
+ and a previous instruction, avoid it by inserting nops after
+ instruction AFTER.
+
+ *DELAYED_REG and *HILO_DELAY describe the hazards that apply at
+ this point. If *DELAYED_REG is non-null, INSN must wait a cycle
+ before using the value of that register. *HILO_DELAY counts the
+ number of instructions since the last hilo hazard (that is,
+ the number of instructions since the last mflo or mfhi).
+
+ After inserting nops for INSN, update *DELAYED_REG and *HILO_DELAY
+ for the next instruction.
+
+ LO_REG is an rtx for the LO register, used in dependence checking. */
+
+static void
+mips_avoid_hazard (rtx after, rtx insn, int *hilo_delay,
+ rtx *delayed_reg, rtx lo_reg)
+{
+ rtx pattern, set;
+ int nops, ninsns;
+
+ if (!INSN_P (insn))
+ return;
+
+ pattern = PATTERN (insn);
+
+ /* Do not put the whole function in .set noreorder if it contains
+ an asm statement. We don't know whether there will be hazards
+ between the asm statement and the gcc-generated code. */
+ if (GET_CODE (pattern) == ASM_INPUT || asm_noperands (pattern) >= 0)
+ cfun->machine->all_noreorder_p = false;
+
+ /* Ignore zero-length instructions (barriers and the like). */
+ ninsns = get_attr_length (insn) / 4;
+ if (ninsns == 0)
+ return;
+
+ /* Work out how many nops are needed. Note that we only care about
+ registers that are explicitly mentioned in the instruction's pattern.
+ It doesn't matter that calls use the argument registers or that they
+ clobber hi and lo. */
+ if (*hilo_delay < 2 && reg_set_p (lo_reg, pattern))
+ nops = 2 - *hilo_delay;
+ else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern))
+ nops = 1;
+ else
+ nops = 0;
+
+ /* Insert the nops between this instruction and the previous one.
+ Each new nop takes us further from the last hilo hazard. */
+ *hilo_delay += nops;
+ while (nops-- > 0)
+ emit_insn_after (gen_hazard_nop (), after);
+
+ /* Set up the state for the next instruction. */
+ *hilo_delay += ninsns;
+ *delayed_reg = 0;
+ if (INSN_CODE (insn) >= 0)
+ switch (get_attr_hazard (insn))
+ {
+ case HAZARD_NONE:
+ break;
+
+ case HAZARD_HILO:
+ *hilo_delay = 0;
+ break;
+
+ case HAZARD_DELAY:
+ set = single_set (insn);
+ gcc_assert (set != 0);
+ *delayed_reg = SET_DEST (set);
+ break;
+ }
+}
+
+
+/* Go through the instruction stream and insert nops where necessary.
+ See if the whole function can then be put into .set noreorder &
+ .set nomacro. */
+
+static void
+mips_avoid_hazards (void)
+{
+ rtx insn, last_insn, lo_reg, delayed_reg;
+ int hilo_delay, i;
+
+ /* Force all instructions to be split into their final form. */
+ split_all_insns_noflow ();
+
+ /* Recalculate instruction lengths without taking nops into account. */
+ cfun->machine->ignore_hazard_length_p = true;
+ shorten_branches (get_insns ());
+
+ cfun->machine->all_noreorder_p = true;
+
+ /* Profiled functions can't be all noreorder because the profiler
+ support uses assembler macros. */
+ if (current_function_profile)
+ cfun->machine->all_noreorder_p = false;
+
+ /* Code compiled with -mfix-vr4120 can't be all noreorder because
+ we rely on the assembler to work around some errata. */
+ if (TARGET_FIX_VR4120)
+ cfun->machine->all_noreorder_p = false;
+
+ /* The same is true for -mfix-vr4130 if we might generate mflo or
+ mfhi instructions. Note that we avoid using mflo and mfhi if
+ the VR4130 macc and dmacc instructions are available instead;
+ see the *mfhilo_{si,di}_macc patterns. */
+ if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI)
+ cfun->machine->all_noreorder_p = false;
+
+ last_insn = 0;
+ hilo_delay = 2;
+ delayed_reg = 0;
+ lo_reg = gen_rtx_REG (SImode, LO_REGNUM);
+
+ for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ {
+ if (GET_CODE (PATTERN (insn)) == SEQUENCE)
+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ mips_avoid_hazard (last_insn, XVECEXP (PATTERN (insn), 0, i),
+ &hilo_delay, &delayed_reg, lo_reg);
+ else
+ mips_avoid_hazard (last_insn, insn, &hilo_delay,
+ &delayed_reg, lo_reg);
+
+ last_insn = insn;
+ }
+}
+
+
+/* Implement TARGET_MACHINE_DEPENDENT_REORG. */
+
+static void
+mips_reorg (void)
+{
+ if (TARGET_MIPS16)
+ mips16_lay_out_constants ();
+ else if (TARGET_EXPLICIT_RELOCS)
+ {
+ if (mips_flag_delayed_branch)
+ dbr_schedule (get_insns ());
+ mips_avoid_hazards ();
+ if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN)
+ vr4130_align_insns ();
+ }
+}
+
+/* This function does three things:
+
+ - Register the special divsi3 and modsi3 functions if -mfix-vr4120.
+ - Register the mips16 hardware floating point stubs.
+ - Register the gofast functions if selected using --enable-gofast. */
+
+#include "config/gofast.h"
+
+static void
+mips_init_libfuncs (void)
+{
+ if (TARGET_FIX_VR4120)
+ {
+ set_optab_libfunc (sdiv_optab, SImode, "__vr4120_divsi3");
+ set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3");
+ }
+
+ if (TARGET_MIPS16 && mips16_hard_float)
+ {
+ set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3");
+ set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3");
+ set_optab_libfunc (smul_optab, SFmode, "__mips16_mulsf3");
+ set_optab_libfunc (sdiv_optab, SFmode, "__mips16_divsf3");
+
+ set_optab_libfunc (eq_optab, SFmode, "__mips16_eqsf2");
+ set_optab_libfunc (ne_optab, SFmode, "__mips16_nesf2");
+ set_optab_libfunc (gt_optab, SFmode, "__mips16_gtsf2");
+ set_optab_libfunc (ge_optab, SFmode, "__mips16_gesf2");
+ set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2");
+ set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2");
+
+ set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fix_truncsfsi");
+ set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf");
+
+ if (TARGET_DOUBLE_FLOAT)
+ {
+ set_optab_libfunc (add_optab, DFmode, "__mips16_adddf3");
+ set_optab_libfunc (sub_optab, DFmode, "__mips16_subdf3");
+ set_optab_libfunc (smul_optab, DFmode, "__mips16_muldf3");
+ set_optab_libfunc (sdiv_optab, DFmode, "__mips16_divdf3");
+
+ set_optab_libfunc (eq_optab, DFmode, "__mips16_eqdf2");
+ set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2");
+ set_optab_libfunc (gt_optab, DFmode, "__mips16_gtdf2");
+ set_optab_libfunc (ge_optab, DFmode, "__mips16_gedf2");
+ set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2");
+ set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2");
+
+ set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2");
+ set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2");
+
+ set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fix_truncdfsi");
+ set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf");
+ }
+ }
+ else
+ gofast_maybe_init_libfuncs ();
+}
+
+/* Return a number assessing the cost of moving a register in class
+ FROM to class TO. The classes are expressed using the enumeration
+ values such as `GENERAL_REGS'. A value of 2 is the default; other
+ values are interpreted relative to that.
+
+ It is not required that the cost always equal 2 when FROM is the
+ same as TO; on some machines it is expensive to move between
+ registers if they are not general registers.
+
+ If reload sees an insn consisting of a single `set' between two
+ hard registers, and if `REGISTER_MOVE_COST' applied to their
+ classes returns a value of 2, reload does not check to ensure that
+ the constraints of the insn are met. Setting a cost of other than
+ 2 will allow reload to verify that the constraints are met. You
+ should do this if the `movM' pattern's constraints do not allow
+ such copying.
+
+ ??? We make the cost of moving from HI/LO into general
+ registers the same as for one of moving general registers to
+ HI/LO for TARGET_MIPS16 in order to prevent allocating a
+ pseudo to HI/LO. This might hurt optimizations though, it
+ isn't clear if it is wise. And it might not work in all cases. We
+ could solve the DImode LO reg problem by using a multiply, just
+ like reload_{in,out}si. We could solve the SImode/HImode HI reg
+ problem by using divide instructions. divu puts the remainder in
+ the HI reg, so doing a divide by -1 will move the value in the HI
+ reg for all values except -1. We could handle that case by using a
+ signed divide, e.g. -1 / 2 (or maybe 1 / -2?). We'd have to emit
+ a compare/branch to test the input value to see which instruction
+ we need to use. This gets pretty messy, but it is feasible. */
+
+int
+mips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
+ enum reg_class to, enum reg_class from)
+{
+ if (from == M16_REGS && GR_REG_CLASS_P (to))
+ return 2;
+ else if (from == M16_NA_REGS && GR_REG_CLASS_P (to))
+ return 2;
+ else if (GR_REG_CLASS_P (from))
+ {
+ if (to == M16_REGS)
+ return 2;
+ else if (to == M16_NA_REGS)
+ return 2;
+ else if (GR_REG_CLASS_P (to))
+ {
+ if (TARGET_MIPS16)
+ return 4;
+ else
+ return 2;
+ }
+ else if (to == FP_REGS)
+ return 4;
+ else if (reg_class_subset_p (to, ACC_REGS))
+ {
+ if (TARGET_MIPS16)
+ return 12;
+ else
+ return 6;
+ }
+ else if (COP_REG_CLASS_P (to))
+ {
+ return 5;
+ }
+ }
+ else if (from == FP_REGS)
+ {
+ if (GR_REG_CLASS_P (to))
+ return 4;
+ else if (to == FP_REGS)
+ return 2;
+ else if (to == ST_REGS)
+ return 8;
+ }
+ else if (reg_class_subset_p (from, ACC_REGS))
+ {
+ if (GR_REG_CLASS_P (to))
+ {
+ if (TARGET_MIPS16)
+ return 12;
+ else
+ return 6;
+ }
+ }
+ else if (from == ST_REGS && GR_REG_CLASS_P (to))
+ return 4;
+ else if (COP_REG_CLASS_P (from))
+ {
+ return 5;
+ }
+
+ /* Fall through.
+ ??? What cases are these? Shouldn't we return 2 here? */
+
+ return 12;
+}
+
+/* Return the length of INSN. LENGTH is the initial length computed by
+ attributes in the machine-description file. */
+
+int
+mips_adjust_insn_length (rtx insn, int length)
+{
+ /* A unconditional jump has an unfilled delay slot if it is not part
+ of a sequence. A conditional jump normally has a delay slot, but
+ does not on MIPS16. */
+ if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn)))
+ length += 4;
+
+ /* See how many nops might be needed to avoid hardware hazards. */
+ if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0)
+ switch (get_attr_hazard (insn))
+ {
+ case HAZARD_NONE:
+ break;
+
+ case HAZARD_DELAY:
+ length += 4;
+ break;
+
+ case HAZARD_HILO:
+ length += 8;
+ break;
+ }
+
+ /* All MIPS16 instructions are a measly two bytes. */
+ if (TARGET_MIPS16)
+ length /= 2;
+
+ return length;
+}
+
+
+/* Return an asm sequence to start a noat block and load the address
+ of a label into $1. */
+
+const char *
+mips_output_load_label (void)
+{
+ if (TARGET_EXPLICIT_RELOCS)
+ switch (mips_abi)
+ {
+ case ABI_N32:
+ return "%[lw\t%@,%%got_page(%0)(%+)\n\taddiu\t%@,%@,%%got_ofst(%0)";
+
+ case ABI_64:
+ return "%[ld\t%@,%%got_page(%0)(%+)\n\tdaddiu\t%@,%@,%%got_ofst(%0)";
+
+ default:
+ if (ISA_HAS_LOAD_DELAY)
+ return "%[lw\t%@,%%got(%0)(%+)%#\n\taddiu\t%@,%@,%%lo(%0)";
+ return "%[lw\t%@,%%got(%0)(%+)\n\taddiu\t%@,%@,%%lo(%0)";
+ }
+ else
+ {
+ if (Pmode == DImode)
+ return "%[dla\t%@,%0";
+ else
+ return "%[la\t%@,%0";
+ }
+}
+
+/* Return the assembly code for INSN, which has the operands given by
+ OPERANDS, and which branches to OPERANDS[1] if some condition is true.
+ BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[1]
+ is in range of a direct branch. BRANCH_IF_FALSE is an inverted
+ version of BRANCH_IF_TRUE. */
+
+const char *
+mips_output_conditional_branch (rtx insn, rtx *operands,
+ const char *branch_if_true,
+ const char *branch_if_false)
+{
+ unsigned int length;
+ rtx taken, not_taken;
+
+ length = get_attr_length (insn);
+ if (length <= 8)
+ {
+ /* Just a simple conditional branch. */
+ mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn));
+ return branch_if_true;
+ }
+
+ /* Generate a reversed branch around a direct jump. This fallback does
+ not use branch-likely instructions. */
+ mips_branch_likely = false;
+ not_taken = gen_label_rtx ();
+ taken = operands[1];
+
+ /* Generate the reversed branch to NOT_TAKEN. */
+ operands[1] = not_taken;
+ output_asm_insn (branch_if_false, operands);
+
+ /* If INSN has a delay slot, we must provide delay slots for both the
+ branch to NOT_TAKEN and the conditional jump. We must also ensure
+ that INSN's delay slot is executed in the appropriate cases. */
+ if (final_sequence)
+ {
+ /* This first delay slot will always be executed, so use INSN's
+ delay slot if is not annulled. */
+ if (!INSN_ANNULLED_BRANCH_P (insn))
+ {
+ final_scan_insn (XVECEXP (final_sequence, 0, 1),
+ asm_out_file, optimize, 1, NULL);
+ INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
+ }
+ else
+ output_asm_insn ("nop", 0);
+ fprintf (asm_out_file, "\n");
+ }
+
+ /* Output the unconditional branch to TAKEN. */
+ if (length <= 16)
+ output_asm_insn ("j\t%0%/", &taken);
+ else
+ {
+ output_asm_insn (mips_output_load_label (), &taken);
+ output_asm_insn ("jr\t%@%]%/", 0);
+ }
+
+ /* Now deal with its delay slot; see above. */
+ if (final_sequence)
+ {
+ /* This delay slot will only be executed if the branch is taken.
+ Use INSN's delay slot if is annulled. */
+ if (INSN_ANNULLED_BRANCH_P (insn))
+ {
+ final_scan_insn (XVECEXP (final_sequence, 0, 1),
+ asm_out_file, optimize, 1, NULL);
+ INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1;
+ }
+ else
+ output_asm_insn ("nop", 0);
+ fprintf (asm_out_file, "\n");
+ }
+
+ /* Output NOT_TAKEN. */
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
+ CODE_LABEL_NUMBER (not_taken));
+ return "";
+}
+
+/* Return the assembly code for INSN, which branches to OPERANDS[1]
+ if some ordered condition is true. The condition is given by
+ OPERANDS[0] if !INVERTED_P, otherwise it is the inverse of
+ OPERANDS[0]. OPERANDS[2] is the comparison's first operand;
+ its second is always zero. */
+
+const char *
+mips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p)
+{
+ const char *branch[2];
+
+ /* Make BRANCH[1] branch to OPERANDS[1] when the condition is true.
+ Make BRANCH[0] branch on the inverse condition. */
+ switch (GET_CODE (operands[0]))
+ {
+ /* These cases are equivalent to comparisons against zero. */
+ case LEU:
+ inverted_p = !inverted_p;
+ /* Fall through. */
+ case GTU:
+ branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%1");
+ branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%1");
+ break;
+
+ /* These cases are always true or always false. */
+ case LTU:
+ inverted_p = !inverted_p;
+ /* Fall through. */
+ case GEU:
+ branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%1");
+ branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%1");
+ break;
+
+ default:
+ branch[!inverted_p] = MIPS_BRANCH ("b%C0z", "%2,%1");
+ branch[inverted_p] = MIPS_BRANCH ("b%N0z", "%2,%1");
+ break;
+ }
+ return mips_output_conditional_branch (insn, operands, branch[1], branch[0]);
+}
+
+/* Used to output div or ddiv instruction DIVISION, which has the operands
+ given by OPERANDS. Add in a divide-by-zero check if needed.
+
+ When working around R4000 and R4400 errata, we need to make sure that
+ the division is not immediately followed by a shift[1][2]. We also
+ need to stop the division from being put into a branch delay slot[3].
+ The easiest way to avoid both problems is to add a nop after the
+ division. When a divide-by-zero check is needed, this nop can be
+ used to fill the branch delay slot.
+
+ [1] If a double-word or a variable shift executes immediately
+ after starting an integer division, the shift may give an
+ incorrect result. See quotations of errata #16 and #28 from
+ "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
+ in mips.md for details.
+
+ [2] A similar bug to [1] exists for all revisions of the
+ R4000 and the R4400 when run in an MC configuration.
+ From "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0":
+
+ "19. In this following sequence:
+
+ ddiv (or ddivu or div or divu)
+ dsll32 (or dsrl32, dsra32)
+
+ if an MPT stall occurs, while the divide is slipping the cpu
+ pipeline, then the following double shift would end up with an
+ incorrect result.
+
+ Workaround: The compiler needs to avoid generating any
+ sequence with divide followed by extended double shift."
+
+ This erratum is also present in "MIPS R4400MC Errata, Processor
+ Revision 1.0" and "MIPS R4400MC Errata, Processor Revision 2.0
+ & 3.0" as errata #10 and #4, respectively.
+
+ [3] From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
+ (also valid for MIPS R4000MC processors):
+
+ "52. R4000SC: This bug does not apply for the R4000PC.
+
+ There are two flavors of this bug:
+
+ 1) If the instruction just after divide takes an RF exception
+ (tlb-refill, tlb-invalid) and gets an instruction cache
+ miss (both primary and secondary) and the line which is
+ currently in secondary cache at this index had the first
+ data word, where the bits 5..2 are set, then R4000 would
+ get a wrong result for the div.
+
+ ##1
+ nop
+ div r8, r9
+ ------------------- # end-of page. -tlb-refill
+ nop
+ ##2
+ nop
+ div r8, r9
+ ------------------- # end-of page. -tlb-invalid
+ nop
+
+ 2) If the divide is in the taken branch delay slot, where the
+ target takes RF exception and gets an I-cache miss for the
+ exception vector or where I-cache miss occurs for the
+ target address, under the above mentioned scenarios, the
+ div would get wrong results.
+
+ ##1
+ j r2 # to next page mapped or unmapped
+ div r8,r9 # this bug would be there as long
+ # as there is an ICache miss and
+ nop # the "data pattern" is present
+
+ ##2
+ beq r0, r0, NextPage # to Next page
+ div r8,r9
+ nop
+
+ This bug is present for div, divu, ddiv, and ddivu
+ instructions.
+
+ Workaround: For item 1), OS could make sure that the next page
+ after the divide instruction is also mapped. For item 2), the
+ compiler could make sure that the divide instruction is not in
+ the branch delay slot."
+
+ These processors have PRId values of 0x00004220 and 0x00004300 for
+ the R4000 and 0x00004400, 0x00004500 and 0x00004600 for the R4400. */
+
+const char *
+mips_output_division (const char *division, rtx *operands)
+{
+ const char *s;
+
+ s = division;
+ if (TARGET_FIX_R4000 || TARGET_FIX_R4400)
+ {
+ output_asm_insn (s, operands);
+ s = "nop";
+ }
+ if (TARGET_CHECK_ZERO_DIV)
+ {
+ if (TARGET_MIPS16)
+ {
+ output_asm_insn (s, operands);
+ s = "bnez\t%2,1f\n\tbreak\t7\n1:";
+ }
+ else if (GENERATE_DIVIDE_TRAPS)
+ {
+ output_asm_insn (s, operands);
+ s = "teq\t%2,%.,7";
+ }
+ else
+ {
+ output_asm_insn ("%(bne\t%2,%.,1f", operands);
+ output_asm_insn (s, operands);
+ s = "break\t7%)\n1:";
+ }
+ }
+ return s;
+}
+
+/* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL
+ with a final "000" replaced by "k". Ignore case.
+
+ Note: this function is shared between GCC and GAS. */
+
+static bool
+mips_strict_matching_cpu_name_p (const char *canonical, const char *given)
+{
+ while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical))
+ given++, canonical++;
+
+ return ((*given == 0 && *canonical == 0)
+ || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0));
+}
+
+
+/* Return true if GIVEN matches CANONICAL, where GIVEN is a user-supplied
+ CPU name. We've traditionally allowed a lot of variation here.
+
+ Note: this function is shared between GCC and GAS. */
+
+static bool
+mips_matching_cpu_name_p (const char *canonical, const char *given)
+{
+ /* First see if the name matches exactly, or with a final "000"
+ turned into "k". */
+ if (mips_strict_matching_cpu_name_p (canonical, given))
+ return true;
+
+ /* If not, try comparing based on numerical designation alone.
+ See if GIVEN is an unadorned number, or 'r' followed by a number. */
+ if (TOLOWER (*given) == 'r')
+ given++;
+ if (!ISDIGIT (*given))
+ return false;
+
+ /* Skip over some well-known prefixes in the canonical name,
+ hoping to find a number there too. */
+ if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r')
+ canonical += 2;
+ else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm')
+ canonical += 2;
+ else if (TOLOWER (canonical[0]) == 'r')
+ canonical += 1;
+
+ return mips_strict_matching_cpu_name_p (canonical, given);
+}
+
+
+/* Return the mips_cpu_info entry for the processor or ISA given
+ by CPU_STRING. Return null if the string isn't recognized.
+
+ A similar function exists in GAS. */
+
+static const struct mips_cpu_info *
+mips_parse_cpu (const char *cpu_string)
+{
+ const struct mips_cpu_info *p;
+ const char *s;
+
+ /* In the past, we allowed upper-case CPU names, but it doesn't
+ work well with the multilib machinery. */
+ for (s = cpu_string; *s != 0; s++)
+ if (ISUPPER (*s))
+ {
+ warning (0, "the cpu name must be lower case");
+ break;
+ }
+
+ /* 'from-abi' selects the most compatible architecture for the given
+ ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs. For the
+ EABIs, we have to decide whether we're using the 32-bit or 64-bit
+ version. Look first at the -mgp options, if given, otherwise base
+ the choice on MASK_64BIT in TARGET_DEFAULT. */
+ if (strcasecmp (cpu_string, "from-abi") == 0)
+ return mips_cpu_info_from_isa (ABI_NEEDS_32BIT_REGS ? 1
+ : ABI_NEEDS_64BIT_REGS ? 3
+ : (TARGET_64BIT ? 3 : 1));
+
+ /* 'default' has traditionally been a no-op. Probably not very useful. */
+ if (strcasecmp (cpu_string, "default") == 0)
+ return 0;
+
+ for (p = mips_cpu_info_table; p->name != 0; p++)
+ if (mips_matching_cpu_name_p (p->name, cpu_string))
+ return p;
+
+ return 0;
+}
+
+
+/* Return the processor associated with the given ISA level, or null
+ if the ISA isn't valid. */
+
+static const struct mips_cpu_info *
+mips_cpu_info_from_isa (int isa)
+{
+ const struct mips_cpu_info *p;
+
+ for (p = mips_cpu_info_table; p->name != 0; p++)
+ if (p->isa == isa)
+ return p;
+
+ return 0;
+}
+
+/* Implement HARD_REGNO_NREGS. The size of FP registers is controlled
+ by UNITS_PER_FPREG. The size of FP status registers is always 4, because
+ they only hold condition code modes, and CCmode is always considered to
+ be 4 bytes wide. All other registers are word sized. */
+
+unsigned int
+mips_hard_regno_nregs (int regno, enum machine_mode mode)
+{
+ if (ST_REG_P (regno))
+ return ((GET_MODE_SIZE (mode) + 3) / 4);
+ else if (! FP_REG_P (regno))
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD);
+ else
+ return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG);
+}
+
+/* Implement TARGET_RETURN_IN_MEMORY. 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. */
+
+static bool
+mips_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED)
+{
+ if (TARGET_OLDABI)
+ return (TYPE_MODE (type) == BLKmode);
+ else
+ return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
+ || (int_size_in_bytes (type) == -1));
+}
+
+static bool
+mips_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
+{
+ return !TARGET_OLDABI;
+}
+
+/* Return true if INSN is a multiply-add or multiply-subtract
+ instruction and PREV assigns to the accumulator operand. */
+
+bool
+mips_linked_madd_p (rtx prev, rtx insn)
+{
+ rtx x;
+
+ x = single_set (insn);
+ if (x == 0)
+ return false;
+
+ x = SET_SRC (x);
+
+ if (GET_CODE (x) == PLUS
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && reg_set_p (XEXP (x, 1), prev))
+ return true;
+
+ if (GET_CODE (x) == MINUS
+ && GET_CODE (XEXP (x, 1)) == MULT
+ && reg_set_p (XEXP (x, 0), prev))
+ return true;
+
+ return false;
+}
+
+/* Used by TUNE_MACC_CHAINS to record the last scheduled instruction
+ that may clobber hi or lo. */
+
+static rtx mips_macc_chains_last_hilo;
+
+/* A TUNE_MACC_CHAINS helper function. Record that instruction INSN has
+ been scheduled, updating mips_macc_chains_last_hilo appropriately. */
+
+static void
+mips_macc_chains_record (rtx insn)
+{
+ if (get_attr_may_clobber_hilo (insn))
+ mips_macc_chains_last_hilo = insn;
+}
+
+/* A TUNE_MACC_CHAINS helper function. Search ready queue READY, which
+ has NREADY elements, looking for a multiply-add or multiply-subtract
+ instruction that is cumulative with mips_macc_chains_last_hilo.
+ If there is one, promote it ahead of anything else that might
+ clobber hi or lo. */
+
+static void
+mips_macc_chains_reorder (rtx *ready, int nready)
+{
+ int i, j;
+
+ if (mips_macc_chains_last_hilo != 0)
+ for (i = nready - 1; i >= 0; i--)
+ if (mips_linked_madd_p (mips_macc_chains_last_hilo, ready[i]))
+ {
+ for (j = nready - 1; j > i; j--)
+ if (recog_memoized (ready[j]) >= 0
+ && get_attr_may_clobber_hilo (ready[j]))
+ {
+ mips_promote_ready (ready, i, j);
+ break;
+ }
+ break;
+ }
+}
+
+/* The last instruction to be scheduled. */
+
+static rtx vr4130_last_insn;
+
+/* A note_stores callback used by vr4130_true_reg_dependence_p. DATA
+ points to an rtx that is initially an instruction. Nullify the rtx
+ if the instruction uses the value of register X. */
+
+static void
+vr4130_true_reg_dependence_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data)
+{
+ rtx *insn_ptr = data;
+ if (REG_P (x)
+ && *insn_ptr != 0
+ && reg_referenced_p (x, PATTERN (*insn_ptr)))
+ *insn_ptr = 0;
+}
+
+/* Return true if there is true register dependence between vr4130_last_insn
+ and INSN. */
+
+static bool
+vr4130_true_reg_dependence_p (rtx insn)
+{
+ note_stores (PATTERN (vr4130_last_insn),
+ vr4130_true_reg_dependence_p_1, &insn);
+ return insn == 0;
+}
+
+/* A TUNE_MIPS4130 helper function. Given that INSN1 is at the head of
+ the ready queue and that INSN2 is the instruction after it, return
+ true if it is worth promoting INSN2 ahead of INSN1. Look for cases
+ in which INSN1 and INSN2 can probably issue in parallel, but for
+ which (INSN2, INSN1) should be less sensitive to instruction
+ alignment than (INSN1, INSN2). See 4130.md for more details. */
+
+static bool
+vr4130_swap_insns_p (rtx insn1, rtx insn2)
+{
+ rtx dep;
+
+ /* Check for the following case:
+
+ 1) there is some other instruction X with an anti dependence on INSN1;
+ 2) X has a higher priority than INSN2; and
+ 3) X is an arithmetic instruction (and thus has no unit restrictions).
+
+ If INSN1 is the last instruction blocking X, it would better to
+ choose (INSN1, X) over (INSN2, INSN1). */
+ for (dep = INSN_DEPEND (insn1); dep != 0; dep = XEXP (dep, 1))
+ if (REG_NOTE_KIND (dep) == REG_DEP_ANTI
+ && INSN_PRIORITY (XEXP (dep, 0)) > INSN_PRIORITY (insn2)
+ && recog_memoized (XEXP (dep, 0)) >= 0
+ && get_attr_vr4130_class (XEXP (dep, 0)) == VR4130_CLASS_ALU)
+ return false;
+
+ if (vr4130_last_insn != 0
+ && recog_memoized (insn1) >= 0
+ && recog_memoized (insn2) >= 0)
+ {
+ /* See whether INSN1 and INSN2 use different execution units,
+ or if they are both ALU-type instructions. If so, they can
+ probably execute in parallel. */
+ enum attr_vr4130_class class1 = get_attr_vr4130_class (insn1);
+ enum attr_vr4130_class class2 = get_attr_vr4130_class (insn2);
+ if (class1 != class2 || class1 == VR4130_CLASS_ALU)
+ {
+ /* If only one of the instructions has a dependence on
+ vr4130_last_insn, prefer to schedule the other one first. */
+ bool dep1 = vr4130_true_reg_dependence_p (insn1);
+ bool dep2 = vr4130_true_reg_dependence_p (insn2);
+ if (dep1 != dep2)
+ return dep1;
+
+ /* Prefer to schedule INSN2 ahead of INSN1 if vr4130_last_insn
+ is not an ALU-type instruction and if INSN1 uses the same
+ execution unit. (Note that if this condition holds, we already
+ know that INSN2 uses a different execution unit.) */
+ if (class1 != VR4130_CLASS_ALU
+ && recog_memoized (vr4130_last_insn) >= 0
+ && class1 == get_attr_vr4130_class (vr4130_last_insn))
+ return true;
+ }
+ }
+ return false;
+}
+
+/* A TUNE_MIPS4130 helper function. (READY, NREADY) describes a ready
+ queue with at least two instructions. Swap the first two if
+ vr4130_swap_insns_p says that it could be worthwhile. */
+
+static void
+vr4130_reorder (rtx *ready, int nready)
+{
+ if (vr4130_swap_insns_p (ready[nready - 1], ready[nready - 2]))
+ mips_promote_ready (ready, nready - 2, nready - 1);
+}
+
+/* Remove the instruction at index LOWER from ready queue READY and
+ reinsert it in front of the instruction at index HIGHER. LOWER must
+ be <= HIGHER. */
+
+static void
+mips_promote_ready (rtx *ready, int lower, int higher)
+{
+ rtx new_head;
+ int i;
+
+ new_head = ready[lower];
+ for (i = lower; i < higher; i++)
+ ready[i] = ready[i + 1];
+ ready[i] = new_head;
+}
+
+/* Implement TARGET_SCHED_REORDER. */
+
+static int
+mips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
+ rtx *ready, int *nreadyp, int cycle)
+{
+ if (!reload_completed && TUNE_MACC_CHAINS)
+ {
+ if (cycle == 0)
+ mips_macc_chains_last_hilo = 0;
+ if (*nreadyp > 0)
+ mips_macc_chains_reorder (ready, *nreadyp);
+ }
+ if (reload_completed && TUNE_MIPS4130 && !TARGET_VR4130_ALIGN)
+ {
+ if (cycle == 0)
+ vr4130_last_insn = 0;
+ if (*nreadyp > 1)
+ vr4130_reorder (ready, *nreadyp);
+ }
+ return mips_issue_rate ();
+}
+
+/* Implement TARGET_SCHED_VARIABLE_ISSUE. */
+
+static int
+mips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
+ rtx insn, int more)
+{
+ switch (GET_CODE (PATTERN (insn)))
+ {
+ case USE:
+ case CLOBBER:
+ /* Don't count USEs and CLOBBERs against the issue rate. */
+ break;
+
+ default:
+ more--;
+ if (!reload_completed && TUNE_MACC_CHAINS)
+ mips_macc_chains_record (insn);
+ vr4130_last_insn = insn;
+ break;
+ }
+ return more;
+}
+
+/* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output
+ dependencies have no cost. */
+
+static int
+mips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link,
+ rtx dep ATTRIBUTE_UNUSED, int cost)
+{
+ if (REG_NOTE_KIND (link) != 0)
+ return 0;
+ return cost;
+}
+
+/* Return the number of instructions that can be issued per cycle. */
+
+static int
+mips_issue_rate (void)
+{
+ switch (mips_tune)
+ {
+ case PROCESSOR_R4130:
+ case PROCESSOR_R5400:
+ case PROCESSOR_R5500:
+ case PROCESSOR_R7000:
+ case PROCESSOR_R9000:
+ return 2;
+
+ case PROCESSOR_SB1:
+ case PROCESSOR_SB1A:
+ /* This is actually 4, but we get better performance if we claim 3.
+ This is partly because of unwanted speculative code motion with the
+ larger number, and partly because in most common cases we can't
+ reach the theoretical max of 4. */
+ return 3;
+
+ default:
+ return 1;
+ }
+}
+
+/* Implements TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should
+ be as wide as the scheduling freedom in the DFA. */
+
+static int
+mips_multipass_dfa_lookahead (void)
+{
+ /* Can schedule up to 4 of the 6 function units in any one cycle. */
+ if (TUNE_SB1)
+ return 4;
+
+ return 0;
+}
+
+/* Implements a store data bypass check. We need this because the cprestore
+ pattern is type store, but defined using an UNSPEC. This UNSPEC causes the
+ default routine to abort. We just return false for that case. */
+/* ??? Should try to give a better result here than assuming false. */
+
+int
+mips_store_data_bypass_p (rtx out_insn, rtx in_insn)
+{
+ if (GET_CODE (PATTERN (in_insn)) == UNSPEC_VOLATILE)
+ return false;
+
+ return ! store_data_bypass_p (out_insn, in_insn);
+}
+
+/* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY),
+ return the first operand of the associated "pref" or "prefx" insn. */
+
+rtx
+mips_prefetch_cookie (rtx write, rtx locality)
+{
+ /* store_streamed / load_streamed. */
+ if (INTVAL (locality) <= 0)
+ return GEN_INT (INTVAL (write) + 4);
+
+ /* store / load. */
+ if (INTVAL (locality) <= 2)
+ return write;
+
+ /* store_retained / load_retained. */
+ return GEN_INT (INTVAL (write) + 6);
+}
+
+/* MIPS builtin function support. */
+
+struct builtin_description
+{
+ /* The code of the main .md file instruction. See mips_builtin_type
+ for more information. */
+ enum insn_code icode;
+
+ /* The floating-point comparison code to use with ICODE, if any. */
+ enum mips_fp_condition cond;
+
+ /* The name of the builtin function. */
+ const char *name;
+
+ /* Specifies how the function should be expanded. */
+ enum mips_builtin_type builtin_type;
+
+ /* The function's prototype. */
+ enum mips_function_type function_type;
+
+ /* The target flags required for this function. */
+ int target_flags;
+};
+
+/* Define a MIPS_BUILTIN_DIRECT function for instruction CODE_FOR_mips_<INSN>.
+ FUNCTION_TYPE and TARGET_FLAGS are builtin_description fields. */
+#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
+ MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, TARGET_FLAGS }
+
+/* Define __builtin_mips_<INSN>_<COND>_{s,d}, both of which require
+ TARGET_FLAGS. */
+#define CMP_SCALAR_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_" #INSN "_" #COND "_s", \
+ MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_SF_SF, TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_d, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_" #INSN "_" #COND "_d", \
+ MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_DF_DF, TARGET_FLAGS }
+
+/* Define __builtin_mips_{any,all,upper,lower}_<INSN>_<COND>_ps.
+ The lower and upper forms require TARGET_FLAGS while the any and all
+ forms require MASK_MIPS3D. */
+#define CMP_PS_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_any_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_all_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_lower_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_LOWER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_upper_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_CMP_UPPER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }
+
+/* Define __builtin_mips_{any,all}_<INSN>_<COND>_4s. The functions
+ require MASK_MIPS3D. */
+#define CMP_4S_BUILTINS(INSN, COND) \
+ { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_any_" #INSN "_" #COND "_4s", \
+ MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ MASK_MIPS3D }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_all_" #INSN "_" #COND "_4s", \
+ MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ MASK_MIPS3D }
+
+/* Define __builtin_mips_mov{t,f}_<INSN>_<COND>_ps. The comparison
+ instruction requires TARGET_FLAGS. */
+#define MOVTF_BUILTINS(INSN, COND, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_movt_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_MOVT, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ TARGET_FLAGS }, \
+ { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \
+ "__builtin_mips_movf_" #INSN "_" #COND "_ps", \
+ MIPS_BUILTIN_MOVF, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \
+ TARGET_FLAGS }
+
+/* Define all the builtins related to c.cond.fmt condition COND. */
+#define CMP_BUILTINS(COND) \
+ MOVTF_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
+ MOVTF_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_SCALAR_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_PS_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \
+ CMP_PS_BUILTINS (cabs, COND, MASK_MIPS3D), \
+ CMP_4S_BUILTINS (c, COND), \
+ CMP_4S_BUILTINS (cabs, COND)
+
+static const struct builtin_description mips_bdesc[] =
+{
+ DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (puu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_ps_s, MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_s_pl, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (cvt_s_pu, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (abs_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT),
+
+ DIRECT_BUILTIN (alnv_ps, MIPS_V2SF_FTYPE_V2SF_V2SF_INT,
+ MASK_PAIRED_SINGLE_FLOAT),
+ DIRECT_BUILTIN (addr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (mulr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (cvt_pw_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (cvt_ps_pw, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+
+ DIRECT_BUILTIN (recip1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (recip2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+
+ DIRECT_BUILTIN (rsqrt1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D),
+ DIRECT_BUILTIN (rsqrt2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D),
+
+ MIPS_FP_CONDITIONS (CMP_BUILTINS)
+};
+
+/* Builtin functions for the SB-1 processor. */
+
+#define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2
+
+static const struct builtin_description sb1_bdesc[] =
+{
+ DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT)
+};
+
+/* Builtin functions for DSP ASE. */
+
+#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3
+#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3
+#define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3
+#define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3
+
+/* Define a MIPS_BUILTIN_DIRECT_NO_TARGET function for instruction
+ CODE_FOR_mips_<INSN>. FUNCTION_TYPE and TARGET_FLAGS are
+ builtin_description fields. */
+#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \
+ { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \
+ MIPS_BUILTIN_DIRECT_NO_TARGET, FUNCTION_TYPE, TARGET_FLAGS }
+
+/* Define __builtin_mips_bposge<VALUE>. <VALUE> is 32 for the MIPS32 DSP
+ branch instruction. TARGET_FLAGS is a builtin_description field. */
+#define BPOSGE_BUILTIN(VALUE, TARGET_FLAGS) \
+ { CODE_FOR_mips_bposge, 0, "__builtin_mips_bposge" #VALUE, \
+ MIPS_BUILTIN_BPOSGE ## VALUE, MIPS_SI_FTYPE_VOID, TARGET_FLAGS }
+
+static const struct builtin_description dsp_bdesc[] =
+{
+ DIRECT_BUILTIN (addq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (addq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (subq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (subu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (subu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (addsc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (addwc, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (modsub, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (raddu_w_qb, MIPS_SI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_ph, MIPS_V2HI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (absq_s_w, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrq_rs_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (precrqu_s_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phl, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (preceq_w_phr, MIPS_SI_FTYPE_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (precequ_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (preceu_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (shll_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shll_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shrl_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shra_r_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbl, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleu_s_ph_qbr, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulq_rs_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phl, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (muleq_s_w_phr, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpau_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpsu_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (mulsaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (dpaq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (dpsq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_s_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (maq_sa_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (bitrev, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (insv, MIPS_SI_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_qb, MIPS_V4QI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (repl_ph, MIPS_V2HI_FTYPE_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_eq_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_lt_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmpu_le_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_eq_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_lt_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (cmpgu_le_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_eq_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_lt_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (cmp_le_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (pick_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP),
+ DIRECT_BUILTIN (pick_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (packrl_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP),
+ DIRECT_BUILTIN (extr_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_r_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_rs_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extr_s_h, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, MASK_DSP),
+ DIRECT_NO_TARGET_BUILTIN (wrdsp, MIPS_VOID_FTYPE_SI_SI, MASK_DSP),
+ DIRECT_BUILTIN (rddsp, MIPS_SI_FTYPE_SI, MASK_DSP),
+ DIRECT_BUILTIN (lbux, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lhx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ DIRECT_BUILTIN (lwx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP),
+ BPOSGE_BUILTIN (32, MASK_DSP)
+};
+
+/* This helps provide a mapping from builtin function codes to bdesc
+ arrays. */
+
+struct bdesc_map
+{
+ /* The builtin function table that this entry describes. */
+ const struct builtin_description *bdesc;
+
+ /* The number of entries in the builtin function table. */
+ unsigned int size;
+
+ /* The target processor that supports these builtin functions.
+ PROCESSOR_MAX means we enable them for all processors. */
+ enum processor_type proc;
+};
+
+static const struct bdesc_map bdesc_arrays[] =
+{
+ { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_MAX },
+ { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 },
+ { dsp_bdesc, ARRAY_SIZE (dsp_bdesc), PROCESSOR_MAX }
+};
+
+/* Take the head of argument list *ARGLIST and convert it into a form
+ suitable for input operand OP of instruction ICODE. Return the value
+ and point *ARGLIST at the next element of the list. */
+
+static rtx
+mips_prepare_builtin_arg (enum insn_code icode,
+ unsigned int op, tree *arglist)
+{
+ rtx value;
+ enum machine_mode mode;
+
+ value = expand_normal (TREE_VALUE (*arglist));
+ mode = insn_data[icode].operand[op].mode;
+ if (!insn_data[icode].operand[op].predicate (value, mode))
+ {
+ value = copy_to_mode_reg (mode, value);
+ /* Check the predicate again. */
+ if (!insn_data[icode].operand[op].predicate (value, mode))
+ {
+ error ("invalid argument to builtin function");
+ return const0_rtx;
+ }
+ }
+
+ *arglist = TREE_CHAIN (*arglist);
+ return value;
+}
+
+/* Return an rtx suitable for output operand OP of instruction ICODE.
+ If TARGET is non-null, try to use it where possible. */
+
+static rtx
+mips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target)
+{
+ enum machine_mode mode;
+
+ mode = insn_data[icode].operand[op].mode;
+ if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode))
+ target = gen_reg_rtx (mode);
+
+ return target;
+}
+
+/* Expand builtin functions. This is called from TARGET_EXPAND_BUILTIN. */
+
+rtx
+mips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
+{
+ enum insn_code icode;
+ enum mips_builtin_type type;
+ tree fndecl, arglist;
+ unsigned int fcode;
+ const struct builtin_description *bdesc;
+ const struct bdesc_map *m;
+
+ fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ arglist = TREE_OPERAND (exp, 1);
+ fcode = DECL_FUNCTION_CODE (fndecl);
+
+ bdesc = NULL;
+ for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
+ {
+ if (fcode < m->size)
+ {
+ bdesc = m->bdesc;
+ icode = bdesc[fcode].icode;
+ type = bdesc[fcode].builtin_type;
+ break;
+ }
+ fcode -= m->size;
+ }
+ if (bdesc == NULL)
+ return 0;
+
+ switch (type)
+ {
+ case MIPS_BUILTIN_DIRECT:
+ return mips_expand_builtin_direct (icode, target, arglist, true);
+
+ case MIPS_BUILTIN_DIRECT_NO_TARGET:
+ return mips_expand_builtin_direct (icode, target, arglist, false);
+
+ case MIPS_BUILTIN_MOVT:
+ case MIPS_BUILTIN_MOVF:
+ return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond,
+ target, arglist);
+
+ case MIPS_BUILTIN_CMP_ANY:
+ case MIPS_BUILTIN_CMP_ALL:
+ case MIPS_BUILTIN_CMP_UPPER:
+ case MIPS_BUILTIN_CMP_LOWER:
+ case MIPS_BUILTIN_CMP_SINGLE:
+ return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond,
+ target, arglist);
+
+ case MIPS_BUILTIN_BPOSGE32:
+ return mips_expand_builtin_bposge (type, target);
+
+ default:
+ return 0;
+ }
+}
+
+/* Init builtin functions. This is called from TARGET_INIT_BUILTIN. */
+
+void
+mips_init_builtins (void)
+{
+ const struct builtin_description *d;
+ const struct bdesc_map *m;
+ tree types[(int) MIPS_MAX_FTYPE_MAX];
+ tree V2SF_type_node;
+ tree V2HI_type_node;
+ tree V4QI_type_node;
+ unsigned int offset;
+
+ /* We have only builtins for -mpaired-single, -mips3d and -mdsp. */
+ if (!TARGET_PAIRED_SINGLE_FLOAT && !TARGET_DSP)
+ return;
+
+ if (TARGET_PAIRED_SINGLE_FLOAT)
+ {
+ V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode);
+
+ types[MIPS_V2SF_FTYPE_V2SF]
+ = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ integer_type_node, NULL_TREE);
+
+ types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (V2SF_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_V2SF_FTYPE_SF_SF]
+ = build_function_type_list (V2SF_type_node,
+ float_type_node, float_type_node, NULL_TREE);
+
+ types[MIPS_INT_FTYPE_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF]
+ = build_function_type_list (integer_type_node,
+ V2SF_type_node, V2SF_type_node,
+ V2SF_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_INT_FTYPE_SF_SF]
+ = build_function_type_list (integer_type_node,
+ float_type_node, float_type_node, NULL_TREE);
+
+ types[MIPS_INT_FTYPE_DF_DF]
+ = build_function_type_list (integer_type_node,
+ double_type_node, double_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_V2SF]
+ = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, NULL_TREE);
+
+ types[MIPS_SF_FTYPE_SF_SF]
+ = build_function_type_list (float_type_node,
+ float_type_node, float_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, NULL_TREE);
+
+ types[MIPS_DF_FTYPE_DF_DF]
+ = build_function_type_list (double_type_node,
+ double_type_node, double_type_node, NULL_TREE);
+ }
+
+ if (TARGET_DSP)
+ {
+ V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
+ V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode);
+
+ types[MIPS_V2HI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_SI]
+ = build_function_type_list (intSI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (V4QI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_V4QI_SI]
+ = build_function_type_list (V4QI_type_node,
+ V4QI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V2HI_SI]
+ = build_function_type_list (V2HI_type_node,
+ V2HI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_V4QI_V2HI]
+ = build_function_type_list (V2HI_type_node,
+ V4QI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V2HI_V2HI]
+ = build_function_type_list (intSI_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V4QI_V4QI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_V2HI_V2HI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V4QI_FTYPE_SI]
+ = build_function_type_list (V4QI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_V2HI_FTYPE_SI]
+ = build_function_type_list (V2HI_type_node,
+ intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V4QI_V4QI]
+ = build_function_type_list (void_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_V4QI_V4QI]
+ = build_function_type_list (intSI_type_node,
+ V4QI_type_node, V4QI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_V2HI_V2HI]
+ = build_function_type_list (void_type_node,
+ V2HI_type_node, V2HI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_DI_SI]
+ = build_function_type_list (intSI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_DI_FTYPE_DI_SI]
+ = build_function_type_list (intDI_type_node,
+ intDI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_VOID_FTYPE_SI_SI]
+ = build_function_type_list (void_type_node,
+ intSI_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_PTR_SI]
+ = build_function_type_list (intSI_type_node,
+ ptr_type_node, intSI_type_node,
+ NULL_TREE);
+
+ types[MIPS_SI_FTYPE_VOID]
+ = build_function_type (intSI_type_node, void_list_node);
+ }
+
+ /* Iterate through all of the bdesc arrays, initializing all of the
+ builtin functions. */
+
+ offset = 0;
+ for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++)
+ {
+ if (m->proc == PROCESSOR_MAX || (m->proc == mips_arch))
+ for (d = m->bdesc; d < &m->bdesc[m->size]; d++)
+ if ((d->target_flags & target_flags) == d->target_flags)
+ lang_hooks.builtin_function (d->name, types[d->function_type],
+ d - m->bdesc + offset,
+ BUILT_IN_MD, NULL, NULL);
+ offset += m->size;
+ }
+}
+
+/* Expand a MIPS_BUILTIN_DIRECT function. ICODE is the code of the
+ .md pattern and ARGLIST is the list of function arguments. TARGET,
+ if nonnull, suggests a good place to put the result.
+ HAS_TARGET indicates the function must return something. */
+
+static rtx
+mips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist,
+ bool has_target)
+{
+ rtx ops[MAX_RECOG_OPERANDS];
+ int i = 0;
+
+ if (has_target)
+ {
+ /* We save target to ops[0]. */
+ ops[0] = mips_prepare_builtin_target (icode, 0, target);
+ i = 1;
+ }
+
+ /* We need to test if arglist is not zero. Some instructions have extra
+ clobber registers. */
+ for (; i < insn_data[icode].n_operands && arglist != 0; i++)
+ ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
+
+ switch (i)
+ {
+ case 2:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1]));
+ break;
+
+ case 3:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2]));
+ break;
+
+ case 4:
+ emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ return target;
+}
+
+/* Expand a __builtin_mips_movt_*_ps() or __builtin_mips_movf_*_ps()
+ function (TYPE says which). ARGLIST is the list of arguments to the
+ function, ICODE is the instruction that should be used to compare
+ the first two arguments, and COND is the condition it should test.
+ TARGET, if nonnull, suggests a good place to put the result. */
+
+static rtx
+mips_expand_builtin_movtf (enum mips_builtin_type type,
+ enum insn_code icode, enum mips_fp_condition cond,
+ rtx target, tree arglist)
+{
+ rtx cmp_result, op0, op1;
+
+ cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond)));
+
+ icode = CODE_FOR_mips_cond_move_tf_ps;
+ target = mips_prepare_builtin_target (icode, 0, target);
+ if (type == MIPS_BUILTIN_MOVT)
+ {
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ }
+ else
+ {
+ op0 = mips_prepare_builtin_arg (icode, 1, &arglist);
+ op1 = mips_prepare_builtin_arg (icode, 2, &arglist);
+ }
+ emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result));
+ return target;
+}
+
+/* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE
+ into TARGET otherwise. Return TARGET. */
+
+static rtx
+mips_builtin_branch_and_move (rtx condition, rtx target,
+ rtx value_if_true, rtx value_if_false)
+{
+ rtx true_label, done_label;
+
+ true_label = gen_label_rtx ();
+ done_label = gen_label_rtx ();
+
+ /* First assume that CONDITION is false. */
+ emit_move_insn (target, value_if_false);
+
+ /* Branch to TRUE_LABEL if CONDITION is true and DONE_LABEL otherwise. */
+ emit_jump_insn (gen_condjump (condition, true_label));
+ emit_jump_insn (gen_jump (done_label));
+ emit_barrier ();
+
+ /* Fix TARGET if CONDITION is true. */
+ emit_label (true_label);
+ emit_move_insn (target, value_if_true);
+
+ emit_label (done_label);
+ return target;
+}
+
+/* Expand a comparison builtin of type BUILTIN_TYPE. ICODE is the code
+ of the comparison instruction and COND is the condition it should test.
+ ARGLIST is the list of function arguments and TARGET, if nonnull,
+ suggests a good place to put the boolean result. */
+
+static rtx
+mips_expand_builtin_compare (enum mips_builtin_type builtin_type,
+ enum insn_code icode, enum mips_fp_condition cond,
+ rtx target, tree arglist)
+{
+ rtx offset, condition, cmp_result, ops[MAX_RECOG_OPERANDS];
+ int i;
+
+ if (target == 0 || GET_MODE (target) != SImode)
+ target = gen_reg_rtx (SImode);
+
+ /* Prepare the operands to the comparison. */
+ cmp_result = mips_prepare_builtin_target (icode, 0, 0);
+ for (i = 1; i < insn_data[icode].n_operands - 1; i++)
+ ops[i] = mips_prepare_builtin_arg (icode, i, &arglist);
+
+ switch (insn_data[icode].n_operands)
+ {
+ case 4:
+ emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond)));
+ break;
+
+ case 6:
+ emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2],
+ ops[3], ops[4], GEN_INT (cond)));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ /* If the comparison sets more than one register, we define the result
+ to be 0 if all registers are false and -1 if all registers are true.
+ The value of the complete result is indeterminate otherwise. */
+ switch (builtin_type)
+ {
+ case MIPS_BUILTIN_CMP_ALL:
+ condition = gen_rtx_NE (VOIDmode, cmp_result, constm1_rtx);
+ return mips_builtin_branch_and_move (condition, target,
+ const0_rtx, const1_rtx);
+
+ case MIPS_BUILTIN_CMP_UPPER:
+ case MIPS_BUILTIN_CMP_LOWER:
+ offset = GEN_INT (builtin_type == MIPS_BUILTIN_CMP_UPPER);
+ condition = gen_single_cc (cmp_result, offset);
+ return mips_builtin_branch_and_move (condition, target,
+ const1_rtx, const0_rtx);
+
+ default:
+ condition = gen_rtx_NE (VOIDmode, cmp_result, const0_rtx);
+ return mips_builtin_branch_and_move (condition, target,
+ const1_rtx, const0_rtx);
+ }
+}
+
+/* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull,
+ suggests a good place to put the boolean result. */
+
+static rtx
+mips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target)
+{
+ rtx condition, cmp_result;
+ int cmp_value;
+
+ if (target == 0 || GET_MODE (target) != SImode)
+ target = gen_reg_rtx (SImode);
+
+ cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM);
+
+ if (builtin_type == MIPS_BUILTIN_BPOSGE32)
+ cmp_value = 32;
+ else
+ gcc_assert (0);
+
+ condition = gen_rtx_GE (VOIDmode, cmp_result, GEN_INT (cmp_value));
+ return mips_builtin_branch_and_move (condition, target,
+ const1_rtx, const0_rtx);
+}
+
+/* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL.
+ FIRST is true if this is the first time handling this decl. */
+
+static void
+mips_encode_section_info (tree decl, rtx rtl, int first)
+{
+ default_encode_section_info (decl, rtl, first);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
+ {
+ rtx symbol = XEXP (rtl, 0);
+ SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL;
+ }
+}
+
+/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. PIC_FUNCTION_ADDR_REGNUM is live
+ on entry to a function when generating -mshared abicalls code. */
+
+static void
+mips_extra_live_on_entry (bitmap regs)
+{
+ if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS)
+ bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM);
+}
+
+/* SImode values are represented as sign-extended to DImode. */
+
+int
+mips_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep)
+{
+ if (TARGET_64BIT && mode == SImode && mode_rep == DImode)
+ return SIGN_EXTEND;
+
+ return UNKNOWN;
+}
+
+#include "gt-mips.h"
diff --git a/contrib/gcc/config/mips/mips.h b/contrib/gcc/config/mips/mips.h
new file mode 100644
index 0000000..ba77d86
--- /dev/null
+++ b/contrib/gcc/config/mips/mips.h
@@ -0,0 +1,2711 @@
+/* Definitions of target machine for GNU compiler. MIPS version.
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Contributed by A. Lichnewsky (lich@inria.inria.fr).
+ Changed by Michael Meissner (meissner@osf.org).
+ 64 bit r4000 support by Ian Lance Taylor (ian@cygnus.com) and
+ Brendan Eich (brendan@microunity.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+
+/* MIPS external variables defined in mips.c. */
+
+/* Which processor to schedule for. Since there is no difference between
+ a R2000 and R3000 in terms of the scheduler, we collapse them into
+ just an R3000. The elements of the enumeration must match exactly
+ the cpu attribute in the mips.md machine description. */
+
+enum processor_type {
+ PROCESSOR_R3000,
+ PROCESSOR_4KC,
+ PROCESSOR_4KP,
+ PROCESSOR_5KC,
+ PROCESSOR_5KF,
+ PROCESSOR_20KC,
+ PROCESSOR_24K,
+ PROCESSOR_24KX,
+ PROCESSOR_M4K,
+ PROCESSOR_R3900,
+ PROCESSOR_R6000,
+ PROCESSOR_R4000,
+ PROCESSOR_R4100,
+ PROCESSOR_R4111,
+ PROCESSOR_R4120,
+ PROCESSOR_R4130,
+ PROCESSOR_R4300,
+ PROCESSOR_R4600,
+ PROCESSOR_R4650,
+ PROCESSOR_R5000,
+ PROCESSOR_R5400,
+ PROCESSOR_R5500,
+ PROCESSOR_R7000,
+ PROCESSOR_R8000,
+ PROCESSOR_R9000,
+ PROCESSOR_SB1,
+ PROCESSOR_SB1A,
+ PROCESSOR_SR71000,
+ PROCESSOR_MAX
+};
+
+/* Costs of various operations on the different architectures. */
+
+struct mips_rtx_cost_data
+{
+ unsigned short fp_add;
+ unsigned short fp_mult_sf;
+ unsigned short fp_mult_df;
+ unsigned short fp_div_sf;
+ unsigned short fp_div_df;
+ unsigned short int_mult_si;
+ unsigned short int_mult_di;
+ unsigned short int_div_si;
+ unsigned short int_div_di;
+ unsigned short branch_cost;
+ unsigned short memory_latency;
+};
+
+/* Which ABI to use. ABI_32 (original 32, or o32), ABI_N32 (n32),
+ ABI_64 (n64) are all defined by SGI. ABI_O64 is o32 extended
+ to work on a 64 bit machine. */
+
+#define ABI_32 0
+#define ABI_N32 1
+#define ABI_64 2
+#define ABI_EABI 3
+#define ABI_O64 4
+
+/* Information about one recognized processor. Defined here for the
+ benefit of TARGET_CPU_CPP_BUILTINS. */
+struct mips_cpu_info {
+ /* The 'canonical' name of the processor as far as GCC is concerned.
+ It's typically a manufacturer's prefix followed by a numerical
+ designation. It should be lower case. */
+ const char *name;
+
+ /* The internal processor number that most closely matches this
+ entry. Several processors can have the same value, if there's no
+ difference between them from GCC's point of view. */
+ enum processor_type cpu;
+
+ /* The ISA level that the processor implements. */
+ int isa;
+};
+
+#ifndef USED_FOR_TARGET
+extern char mips_print_operand_punct[256]; /* print_operand punctuation chars */
+extern const char *current_function_file; /* filename current function is in */
+extern int num_source_filenames; /* current .file # */
+extern int mips_section_threshold; /* # bytes of data/sdata cutoff */
+extern int sym_lineno; /* sgi next label # for each stmt */
+extern int set_noreorder; /* # of nested .set noreorder's */
+extern int set_nomacro; /* # of nested .set nomacro's */
+extern int set_noat; /* # of nested .set noat's */
+extern int set_volatile; /* # of nested .set volatile's */
+extern int mips_branch_likely; /* emit 'l' after br (branch likely) */
+extern int mips_dbx_regno[]; /* Map register # to debug register # */
+extern bool mips_split_p[];
+extern GTY(()) rtx cmp_operands[2];
+extern enum processor_type mips_arch; /* which cpu to codegen for */
+extern enum processor_type mips_tune; /* which cpu to schedule for */
+extern int mips_isa; /* architectural level */
+extern int mips_abi; /* which ABI to use */
+extern int mips16_hard_float; /* mips16 without -msoft-float */
+extern const struct mips_cpu_info mips_cpu_info_table[];
+extern const struct mips_cpu_info *mips_arch_info;
+extern const struct mips_cpu_info *mips_tune_info;
+extern const struct mips_rtx_cost_data *mips_cost;
+#endif
+
+/* Macros to silence warnings about numbers being signed in traditional
+ C and unsigned in ISO C when compiled on 32-bit hosts. */
+
+#define BITMASK_HIGH (((unsigned long)1) << 31) /* 0x80000000 */
+#define BITMASK_UPPER16 ((unsigned long)0xffff << 16) /* 0xffff0000 */
+#define BITMASK_LOWER16 ((unsigned long)0xffff) /* 0x0000ffff */
+
+
+/* Run-time compilation parameters selecting different hardware subsets. */
+
+/* True if the call patterns should be split into a jalr followed by
+ an instruction to restore $gp. This is only ever true for SVR4 PIC,
+ in which $gp is call-clobbered. It is only safe to split the load
+ from the call when every use of $gp is explicit. */
+
+#define TARGET_SPLIT_CALLS \
+ (TARGET_EXPLICIT_RELOCS && TARGET_ABICALLS && !TARGET_NEWABI)
+
+/* True if we're generating a form of -mabicalls in which we can use
+ operators like %hi and %lo to refer to locally-binding symbols.
+ We can only do this for -mno-shared, and only then if we can use
+ relocation operations instead of assembly macros. It isn't really
+ worth using absolute sequences for 64-bit symbols because GOT
+ accesses are so much shorter. */
+
+#define TARGET_ABSOLUTE_ABICALLS \
+ (TARGET_ABICALLS \
+ && !TARGET_SHARED \
+ && TARGET_EXPLICIT_RELOCS \
+ && !ABI_HAS_64BIT_SYMBOLS)
+
+/* True if we can optimize sibling calls. For simplicity, we only
+ handle cases in which call_insn_operand will reject invalid
+ sibcall addresses. There are two cases in which this isn't true:
+
+ - TARGET_MIPS16. call_insn_operand accepts constant addresses
+ but there is no direct jump instruction. It isn't worth
+ using sibling calls in this case anyway; they would usually
+ be longer than normal calls.
+
+ - TARGET_ABICALLS && !TARGET_EXPLICIT_RELOCS. call_insn_operand
+ accepts global constants, but "jr $25" is the only allowed
+ sibcall. */
+
+#define TARGET_SIBCALLS \
+ (!TARGET_MIPS16 && (!TARGET_ABICALLS || TARGET_EXPLICIT_RELOCS))
+
+/* True if .gpword or .gpdword should be used for switch tables.
+
+ Although GAS does understand .gpdword, the SGI linker mishandles
+ the relocations GAS generates (R_MIPS_GPREL32 followed by R_MIPS_64).
+ We therefore disable GP-relative switch tables for n64 on IRIX targets. */
+#define TARGET_GPWORD (TARGET_ABICALLS && !(mips_abi == ABI_64 && TARGET_IRIX))
+
+/* Generate mips16 code */
+#define TARGET_MIPS16 ((target_flags & MASK_MIPS16) != 0)
+/* Generate mips16e code. Default 16bit ASE for mips32/mips32r2/mips64 */
+#define GENERATE_MIPS16E (TARGET_MIPS16 && mips_isa >= 32)
+
+/* Generic ISA defines. */
+#define ISA_MIPS1 (mips_isa == 1)
+#define ISA_MIPS2 (mips_isa == 2)
+#define ISA_MIPS3 (mips_isa == 3)
+#define ISA_MIPS4 (mips_isa == 4)
+#define ISA_MIPS32 (mips_isa == 32)
+#define ISA_MIPS32R2 (mips_isa == 33)
+#define ISA_MIPS64 (mips_isa == 64)
+
+/* Architecture target defines. */
+#define TARGET_MIPS3900 (mips_arch == PROCESSOR_R3900)
+#define TARGET_MIPS4000 (mips_arch == PROCESSOR_R4000)
+#define TARGET_MIPS4120 (mips_arch == PROCESSOR_R4120)
+#define TARGET_MIPS4130 (mips_arch == PROCESSOR_R4130)
+#define TARGET_MIPS5400 (mips_arch == PROCESSOR_R5400)
+#define TARGET_MIPS5500 (mips_arch == PROCESSOR_R5500)
+#define TARGET_MIPS7000 (mips_arch == PROCESSOR_R7000)
+#define TARGET_MIPS9000 (mips_arch == PROCESSOR_R9000)
+#define TARGET_SB1 (mips_arch == PROCESSOR_SB1 \
+ || mips_arch == PROCESSOR_SB1A)
+#define TARGET_SR71K (mips_arch == PROCESSOR_SR71000)
+
+/* Scheduling target defines. */
+#define TUNE_MIPS3000 (mips_tune == PROCESSOR_R3000)
+#define TUNE_MIPS3900 (mips_tune == PROCESSOR_R3900)
+#define TUNE_MIPS4000 (mips_tune == PROCESSOR_R4000)
+#define TUNE_MIPS4120 (mips_tune == PROCESSOR_R4120)
+#define TUNE_MIPS4130 (mips_tune == PROCESSOR_R4130)
+#define TUNE_MIPS5000 (mips_tune == PROCESSOR_R5000)
+#define TUNE_MIPS5400 (mips_tune == PROCESSOR_R5400)
+#define TUNE_MIPS5500 (mips_tune == PROCESSOR_R5500)
+#define TUNE_MIPS6000 (mips_tune == PROCESSOR_R6000)
+#define TUNE_MIPS7000 (mips_tune == PROCESSOR_R7000)
+#define TUNE_MIPS9000 (mips_tune == PROCESSOR_R9000)
+#define TUNE_SB1 (mips_tune == PROCESSOR_SB1 \
+ || mips_tune == PROCESSOR_SB1A)
+
+/* True if the pre-reload scheduler should try to create chains of
+ multiply-add or multiply-subtract instructions. For example,
+ suppose we have:
+
+ t1 = a * b
+ t2 = t1 + c * d
+ t3 = e * f
+ t4 = t3 - g * h
+
+ t1 will have a higher priority than t2 and t3 will have a higher
+ priority than t4. However, before reload, there is no dependence
+ between t1 and t3, and they can often have similar priorities.
+ The scheduler will then tend to prefer:
+
+ t1 = a * b
+ t3 = e * f
+ t2 = t1 + c * d
+ t4 = t3 - g * h
+
+ which stops us from making full use of macc/madd-style instructions.
+ This sort of situation occurs frequently in Fourier transforms and
+ in unrolled loops.
+
+ To counter this, the TUNE_MACC_CHAINS code will reorder the ready
+ queue so that chained multiply-add and multiply-subtract instructions
+ appear ahead of any other instruction that is likely to clobber lo.
+ In the example above, if t2 and t3 become ready at the same time,
+ the code ensures that t2 is scheduled first.
+
+ Multiply-accumulate instructions are a bigger win for some targets
+ than others, so this macro is defined on an opt-in basis. */
+#define TUNE_MACC_CHAINS (TUNE_MIPS5500 \
+ || TUNE_MIPS4120 \
+ || TUNE_MIPS4130)
+
+#define TARGET_OLDABI (mips_abi == ABI_32 || mips_abi == ABI_O64)
+#define TARGET_NEWABI (mips_abi == ABI_N32 || mips_abi == ABI_64)
+
+/* IRIX specific stuff. */
+#define TARGET_IRIX 0
+#define TARGET_IRIX6 0
+
+/* Define preprocessor macros for the -march and -mtune options.
+ PREFIX is either _MIPS_ARCH or _MIPS_TUNE, INFO is the selected
+ processor. If INFO's canonical name is "foo", define PREFIX to
+ be "foo", and define an additional macro PREFIX_FOO. */
+#define MIPS_CPP_SET_PROCESSOR(PREFIX, INFO) \
+ do \
+ { \
+ char *macro, *p; \
+ \
+ macro = concat ((PREFIX), "_", (INFO)->name, NULL); \
+ for (p = macro; *p != 0; p++) \
+ *p = TOUPPER (*p); \
+ \
+ builtin_define (macro); \
+ builtin_define_with_value ((PREFIX), (INFO)->name, 1); \
+ free (macro); \
+ } \
+ while (0)
+
+/* Target CPU builtins. */
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ /* Everyone but IRIX defines this to mips. */ \
+ if (!TARGET_IRIX) \
+ builtin_assert ("machine=mips"); \
+ \
+ builtin_assert ("cpu=mips"); \
+ builtin_define ("__mips__"); \
+ builtin_define ("_mips"); \
+ \
+ /* We do this here because __mips is defined below \
+ and so we can't use builtin_define_std. */ \
+ if (!flag_iso) \
+ builtin_define ("mips"); \
+ \
+ if (TARGET_64BIT) \
+ builtin_define ("__mips64"); \
+ \
+ if (!TARGET_IRIX) \
+ { \
+ /* Treat _R3000 and _R4000 like register-size \
+ defines, which is how they've historically \
+ been used. */ \
+ if (TARGET_64BIT) \
+ { \
+ builtin_define_std ("R4000"); \
+ builtin_define ("_R4000"); \
+ } \
+ else \
+ { \
+ builtin_define_std ("R3000"); \
+ builtin_define ("_R3000"); \
+ } \
+ } \
+ if (TARGET_FLOAT64) \
+ builtin_define ("__mips_fpr=64"); \
+ else \
+ builtin_define ("__mips_fpr=32"); \
+ \
+ if (TARGET_MIPS16) \
+ builtin_define ("__mips16"); \
+ \
+ if (TARGET_MIPS3D) \
+ builtin_define ("__mips3d"); \
+ \
+ if (TARGET_DSP) \
+ builtin_define ("__mips_dsp"); \
+ \
+ MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info); \
+ MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info); \
+ \
+ if (ISA_MIPS1) \
+ { \
+ builtin_define ("__mips=1"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS1"); \
+ } \
+ else if (ISA_MIPS2) \
+ { \
+ builtin_define ("__mips=2"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS2"); \
+ } \
+ else if (ISA_MIPS3) \
+ { \
+ builtin_define ("__mips=3"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS3"); \
+ } \
+ else if (ISA_MIPS4) \
+ { \
+ builtin_define ("__mips=4"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS4"); \
+ } \
+ else if (ISA_MIPS32) \
+ { \
+ builtin_define ("__mips=32"); \
+ builtin_define ("__mips_isa_rev=1"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32"); \
+ } \
+ else if (ISA_MIPS32R2) \
+ { \
+ builtin_define ("__mips=32"); \
+ builtin_define ("__mips_isa_rev=2"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS32"); \
+ } \
+ else if (ISA_MIPS64) \
+ { \
+ builtin_define ("__mips=64"); \
+ builtin_define ("__mips_isa_rev=1"); \
+ builtin_define ("_MIPS_ISA=_MIPS_ISA_MIPS64"); \
+ } \
+ \
+ if (TARGET_HARD_FLOAT) \
+ builtin_define ("__mips_hard_float"); \
+ else if (TARGET_SOFT_FLOAT) \
+ builtin_define ("__mips_soft_float"); \
+ \
+ if (TARGET_SINGLE_FLOAT) \
+ builtin_define ("__mips_single_float"); \
+ \
+ if (TARGET_PAIRED_SINGLE_FLOAT) \
+ builtin_define ("__mips_paired_single_float"); \
+ \
+ if (TARGET_BIG_ENDIAN) \
+ { \
+ builtin_define_std ("MIPSEB"); \
+ builtin_define ("_MIPSEB"); \
+ } \
+ else \
+ { \
+ builtin_define_std ("MIPSEL"); \
+ builtin_define ("_MIPSEL"); \
+ } \
+ \
+ /* Macros dependent on the C dialect. */ \
+ if (preprocessing_asm_p ()) \
+ { \
+ builtin_define_std ("LANGUAGE_ASSEMBLY"); \
+ builtin_define ("_LANGUAGE_ASSEMBLY"); \
+ } \
+ else if (c_dialect_cxx ()) \
+ { \
+ builtin_define ("_LANGUAGE_C_PLUS_PLUS"); \
+ builtin_define ("__LANGUAGE_C_PLUS_PLUS"); \
+ builtin_define ("__LANGUAGE_C_PLUS_PLUS__"); \
+ } \
+ else \
+ { \
+ builtin_define_std ("LANGUAGE_C"); \
+ builtin_define ("_LANGUAGE_C"); \
+ } \
+ if (c_dialect_objc ()) \
+ { \
+ builtin_define ("_LANGUAGE_OBJECTIVE_C"); \
+ builtin_define ("__LANGUAGE_OBJECTIVE_C"); \
+ /* Bizarre, but needed at least for Irix. */ \
+ builtin_define_std ("LANGUAGE_C"); \
+ builtin_define ("_LANGUAGE_C"); \
+ } \
+ \
+ if (mips_abi == ABI_EABI) \
+ builtin_define ("__mips_eabi"); \
+ \
+} while (0)
+
+/* Default target_flags if no switches are specified */
+
+#ifndef TARGET_DEFAULT
+#define TARGET_DEFAULT 0
+#endif
+
+#ifndef TARGET_CPU_DEFAULT
+#define TARGET_CPU_DEFAULT 0
+#endif
+
+#ifndef TARGET_ENDIAN_DEFAULT
+#define TARGET_ENDIAN_DEFAULT MASK_BIG_ENDIAN
+#endif
+
+#ifndef TARGET_FP_EXCEPTIONS_DEFAULT
+#define TARGET_FP_EXCEPTIONS_DEFAULT MASK_FP_EXCEPTIONS
+#endif
+
+/* 'from-abi' makes a good default: you get whatever the ABI requires. */
+#ifndef MIPS_ISA_DEFAULT
+#ifndef MIPS_CPU_STRING_DEFAULT
+#define MIPS_CPU_STRING_DEFAULT "from-abi"
+#endif
+#endif
+
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+/* Make this compile time constant for libgcc2 */
+#ifdef __mips64
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif /* IN_LIBGCC2 */
+
+#define TARGET_LIBGCC_SDATA_SECTION ".sdata"
+
+#ifndef MULTILIB_ENDIAN_DEFAULT
+#if TARGET_ENDIAN_DEFAULT == 0
+#define MULTILIB_ENDIAN_DEFAULT "EL"
+#else
+#define MULTILIB_ENDIAN_DEFAULT "EB"
+#endif
+#endif
+
+#ifndef MULTILIB_ISA_DEFAULT
+# if MIPS_ISA_DEFAULT == 1
+# define MULTILIB_ISA_DEFAULT "mips1"
+# else
+# if MIPS_ISA_DEFAULT == 2
+# define MULTILIB_ISA_DEFAULT "mips2"
+# else
+# if MIPS_ISA_DEFAULT == 3
+# define MULTILIB_ISA_DEFAULT "mips3"
+# else
+# if MIPS_ISA_DEFAULT == 4
+# define MULTILIB_ISA_DEFAULT "mips4"
+# else
+# if MIPS_ISA_DEFAULT == 32
+# define MULTILIB_ISA_DEFAULT "mips32"
+# else
+# if MIPS_ISA_DEFAULT == 33
+# define MULTILIB_ISA_DEFAULT "mips32r2"
+# else
+# if MIPS_ISA_DEFAULT == 64
+# define MULTILIB_ISA_DEFAULT "mips64"
+# else
+# define MULTILIB_ISA_DEFAULT "mips1"
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+# endif
+#endif
+
+#ifndef MULTILIB_DEFAULTS
+#define MULTILIB_DEFAULTS \
+ { MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT, MULTILIB_ABI_DEFAULT }
+#endif
+
+/* We must pass -EL to the linker by default for little endian embedded
+ targets using linker scripts with a OUTPUT_FORMAT line. Otherwise, the
+ linker will default to using big-endian output files. The OUTPUT_FORMAT
+ line must be in the linker script, otherwise -EB/-EL will not work. */
+
+#ifndef ENDIAN_SPEC
+#if TARGET_ENDIAN_DEFAULT == 0
+#define ENDIAN_SPEC "%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
+#else
+#define ENDIAN_SPEC "%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
+#endif
+#endif
+
+/* Support for a compile-time default CPU, et cetera. The rules are:
+ --with-arch is ignored if -march is specified or a -mips is specified
+ (other than -mips16).
+ --with-tune is ignored if -mtune is specified.
+ --with-abi is ignored if -mabi is specified.
+ --with-float is ignored if -mhard-float or -msoft-float are
+ specified.
+ --with-divide is ignored if -mdivide-traps or -mdivide-breaks are
+ specified. */
+#define OPTION_DEFAULT_SPECS \
+ {"arch", "%{!march=*:%{mips16:-march=%(VALUE)}%{!mips*:-march=%(VALUE)}}" }, \
+ {"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
+ {"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
+ {"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }
+
+
+#define GENERATE_DIVIDE_TRAPS (TARGET_DIVIDE_TRAPS \
+ && ISA_HAS_COND_TRAP)
+
+#define GENERATE_BRANCHLIKELY (TARGET_BRANCHLIKELY \
+ && !TARGET_SR71K \
+ && !TARGET_MIPS16)
+
+/* Generate three-operand multiply instructions for SImode. */
+#define GENERATE_MULT3_SI ((TARGET_MIPS3900 \
+ || TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_MIPS7000 \
+ || TARGET_MIPS9000 \
+ || TARGET_MAD \
+ || ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64) \
+ && !TARGET_MIPS16)
+
+/* Generate three-operand multiply instructions for DImode. */
+#define GENERATE_MULT3_DI ((TARGET_MIPS3900) \
+ && !TARGET_MIPS16)
+
+/* True if the ABI can only work with 64-bit integer registers. We
+ generally allow ad-hoc variations for TARGET_SINGLE_FLOAT, but
+ otherwise floating-point registers must also be 64-bit. */
+#define ABI_NEEDS_64BIT_REGS (TARGET_NEWABI || mips_abi == ABI_O64)
+
+/* Likewise for 32-bit regs. */
+#define ABI_NEEDS_32BIT_REGS (mips_abi == ABI_32)
+
+/* True if symbols are 64 bits wide. At present, n64 is the only
+ ABI for which this is true. */
+#define ABI_HAS_64BIT_SYMBOLS (mips_abi == ABI_64 && !TARGET_SYM32)
+
+/* ISA has instructions for managing 64 bit fp and gp regs (e.g. mips3). */
+#define ISA_HAS_64BIT_REGS (ISA_MIPS3 \
+ || ISA_MIPS4 \
+ || ISA_MIPS64)
+
+/* ISA has branch likely instructions (e.g. mips2). */
+/* Disable branchlikely for tx39 until compare rewrite. They haven't
+ been generated up to this point. */
+#define ISA_HAS_BRANCHLIKELY (!ISA_MIPS1)
+
+/* ISA has the conditional move instructions introduced in mips4. */
+#define ISA_HAS_CONDMOVE ((ISA_MIPS4 \
+ || ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64) \
+ && !TARGET_MIPS5500 \
+ && !TARGET_MIPS16)
+
+/* ISA has the mips4 FP condition code instructions: FP-compare to CC,
+ branch on CC, and move (both FP and non-FP) on CC. */
+#define ISA_HAS_8CC (ISA_MIPS4 \
+ || ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64)
+
+/* This is a catch all for other mips4 instructions: indexed load, the
+ FP madd and msub instructions, and the FP recip and recip sqrt
+ instructions. */
+#define ISA_HAS_FP4 ((ISA_MIPS4 \
+ || ISA_MIPS64) \
+ && !TARGET_MIPS16)
+
+/* ISA has conditional trap instructions. */
+#define ISA_HAS_COND_TRAP (!ISA_MIPS1 \
+ && !TARGET_MIPS16)
+
+/* ISA has integer multiply-accumulate instructions, madd and msub. */
+#define ISA_HAS_MADD_MSUB ((ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64 \
+ ) && !TARGET_MIPS16)
+
+/* ISA has floating-point nmadd and nmsub instructions. */
+#define ISA_HAS_NMADD_NMSUB ((ISA_MIPS4 \
+ || ISA_MIPS64) \
+ && (!TARGET_MIPS5400 || TARGET_MAD) \
+ && ! TARGET_MIPS16)
+
+/* ISA has count leading zeroes/ones instruction (not implemented). */
+#define ISA_HAS_CLZ_CLO ((ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64 \
+ ) && !TARGET_MIPS16)
+
+/* ISA has double-word count leading zeroes/ones instruction (not
+ implemented). */
+#define ISA_HAS_DCLZ_DCLO (ISA_MIPS64 \
+ && !TARGET_MIPS16)
+
+/* ISA has three operand multiply instructions that put
+ the high part in an accumulator: mulhi or mulhiu. */
+#define ISA_HAS_MULHI (TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ )
+
+/* ISA has three operand multiply instructions that
+ negates the result and puts the result in an accumulator. */
+#define ISA_HAS_MULS (TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ )
+
+/* ISA has three operand multiply instructions that subtracts the
+ result from a 4th operand and puts the result in an accumulator. */
+#define ISA_HAS_MSAC (TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ )
+/* ISA has three operand multiply instructions that the result
+ from a 4th operand and puts the result in an accumulator. */
+#define ISA_HAS_MACC ((TARGET_MIPS4120 && !TARGET_MIPS16) \
+ || (TARGET_MIPS4130 && !TARGET_MIPS16) \
+ || TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ )
+
+/* ISA has NEC VR-style MACC, MACCHI, DMACC and DMACCHI instructions. */
+#define ISA_HAS_MACCHI (!TARGET_MIPS16 \
+ && (TARGET_MIPS4120 \
+ || TARGET_MIPS4130))
+
+/* ISA has 32-bit rotate right instruction. */
+#define ISA_HAS_ROTR_SI (!TARGET_MIPS16 \
+ && (ISA_MIPS32R2 \
+ || TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ ))
+
+/* ISA has 64-bit rotate right instruction. */
+#define ISA_HAS_ROTR_DI (TARGET_64BIT \
+ && !TARGET_MIPS16 \
+ && (TARGET_MIPS5400 \
+ || TARGET_MIPS5500 \
+ || TARGET_SR71K \
+ ))
+
+/* ISA has data prefetch instructions. This controls use of 'pref'. */
+#define ISA_HAS_PREFETCH ((ISA_MIPS4 \
+ || ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64) \
+ && !TARGET_MIPS16)
+
+/* ISA has data indexed prefetch instructions. This controls use of
+ 'prefx', along with TARGET_HARD_FLOAT and TARGET_DOUBLE_FLOAT.
+ (prefx is a cop1x instruction, so can only be used if FP is
+ enabled.) */
+#define ISA_HAS_PREFETCHX ((ISA_MIPS4 \
+ || ISA_MIPS64) \
+ && !TARGET_MIPS16)
+
+/* True if trunc.w.s and trunc.w.d are real (not synthetic)
+ instructions. Both require TARGET_HARD_FLOAT, and trunc.w.d
+ also requires TARGET_DOUBLE_FLOAT. */
+#define ISA_HAS_TRUNC_W (!ISA_MIPS1)
+
+/* ISA includes the MIPS32r2 seb and seh instructions. */
+#define ISA_HAS_SEB_SEH (!TARGET_MIPS16 \
+ && (ISA_MIPS32R2 \
+ ))
+
+/* ISA includes the MIPS32/64 rev 2 ext and ins instructions. */
+#define ISA_HAS_EXT_INS (!TARGET_MIPS16 \
+ && (ISA_MIPS32R2 \
+ ))
+
+/* True if the result of a load is not available to the next instruction.
+ A nop will then be needed between instructions like "lw $4,..."
+ and "addiu $4,$4,1". */
+#define ISA_HAS_LOAD_DELAY (mips_isa == 1 \
+ && !TARGET_MIPS3900 \
+ && !TARGET_MIPS16)
+
+/* Likewise mtc1 and mfc1. */
+#define ISA_HAS_XFER_DELAY (mips_isa <= 3)
+
+/* Likewise floating-point comparisons. */
+#define ISA_HAS_FCMP_DELAY (mips_isa <= 3)
+
+/* True if mflo and mfhi can be immediately followed by instructions
+ which write to the HI and LO registers.
+
+ According to MIPS specifications, MIPS ISAs I, II, and III need
+ (at least) two instructions between the reads of HI/LO and
+ instructions which write them, and later ISAs do not. Contradicting
+ the MIPS specifications, some MIPS IV processor user manuals (e.g.
+ the UM for the NEC Vr5000) document needing the instructions between
+ HI/LO reads and writes, as well. Therefore, we declare only MIPS32,
+ MIPS64 and later ISAs to have the interlocks, plus any specific
+ earlier-ISA CPUs for which CPU documentation declares that the
+ instructions are really interlocked. */
+#define ISA_HAS_HILO_INTERLOCKS (ISA_MIPS32 \
+ || ISA_MIPS32R2 \
+ || ISA_MIPS64 \
+ || TARGET_MIPS5500)
+
+/* Add -G xx support. */
+
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
+
+#define OVERRIDE_OPTIONS override_options ()
+
+#define CONDITIONAL_REGISTER_USAGE mips_conditional_register_usage ()
+
+/* Show we can debug even without a frame pointer. */
+#define CAN_DEBUG_WITHOUT_FP
+
+/* Tell collect what flags to pass to nm. */
+#ifndef NM_FLAGS
+#define NM_FLAGS "-Bn"
+#endif
+
+
+#ifndef MIPS_ABI_DEFAULT
+#define MIPS_ABI_DEFAULT ABI_32
+#endif
+
+/* Use the most portable ABI flag for the ASM specs. */
+
+#if MIPS_ABI_DEFAULT == ABI_32
+#define MULTILIB_ABI_DEFAULT "mabi=32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_O64
+#define MULTILIB_ABI_DEFAULT "mabi=o64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_N32
+#define MULTILIB_ABI_DEFAULT "mabi=n32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_64
+#define MULTILIB_ABI_DEFAULT "mabi=64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_EABI
+#define MULTILIB_ABI_DEFAULT "mabi=eabi"
+#endif
+
+/* SUBTARGET_ASM_OPTIMIZING_SPEC handles passing optimization options
+ to the assembler. It may be overridden by subtargets. */
+#ifndef SUBTARGET_ASM_OPTIMIZING_SPEC
+#define SUBTARGET_ASM_OPTIMIZING_SPEC "\
+%{noasmopt:-O0} \
+%{!noasmopt:%{O:-O2} %{O1:-O2} %{O2:-O2} %{O3:-O3}}"
+#endif
+
+/* SUBTARGET_ASM_DEBUGGING_SPEC handles passing debugging options to
+ the assembler. It may be overridden by subtargets.
+
+ Beginning with gas 2.13, -mdebug must be passed to correctly handle
+ COFF debugging info. */
+
+#ifndef SUBTARGET_ASM_DEBUGGING_SPEC
+#define SUBTARGET_ASM_DEBUGGING_SPEC "\
+%{g} %{g0} %{g1} %{g2} %{g3} \
+%{ggdb:-g} %{ggdb0:-g0} %{ggdb1:-g1} %{ggdb2:-g2} %{ggdb3:-g3} \
+%{gstabs:-g} %{gstabs0:-g0} %{gstabs1:-g1} %{gstabs2:-g2} %{gstabs3:-g3} \
+%{gstabs+:-g} %{gstabs+0:-g0} %{gstabs+1:-g1} %{gstabs+2:-g2} %{gstabs+3:-g3} \
+%{gcoff:-g} %{gcoff0:-g0} %{gcoff1:-g1} %{gcoff2:-g2} %{gcoff3:-g3} \
+%{gcoff*:-mdebug} %{!gcoff*:-no-mdebug}"
+#endif
+
+/* SUBTARGET_ASM_SPEC is always passed to the assembler. It may be
+ overridden by subtargets. */
+
+#ifndef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC ""
+#endif
+
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
+%{mips32} %{mips32r2} %{mips64} \
+%{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
+%{mips3d:-mips3d} \
+%{mdsp} \
+%{mfix-vr4120} %{mfix-vr4130} \
+%(subtarget_asm_optimizing_spec) \
+%(subtarget_asm_debugging_spec) \
+%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
+%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
+%{mshared} %{mno-shared} \
+%{msym32} %{mno-sym32} \
+%{mtune=*} %{v} \
+%(subtarget_asm_spec)"
+
+/* Extra switches sometimes passed to the linker. */
+/* ??? The bestGnum will never be passed to the linker, because the gcc driver
+ will interpret it as a -b option. */
+
+#ifndef LINK_SPEC
+#define LINK_SPEC "\
+%(endian_spec) \
+%{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \
+%{bestGnum} %{shared} %{non_shared}"
+#endif /* LINK_SPEC defined */
+
+
+/* Specs for the compiler proper */
+
+/* SUBTARGET_CC1_SPEC is passed to the compiler proper. It may be
+ overridden by subtargets. */
+#ifndef SUBTARGET_CC1_SPEC
+#define SUBTARGET_CC1_SPEC ""
+#endif
+
+/* CC1_SPEC is the set of arguments to pass to the compiler proper. */
+
+#undef CC1_SPEC
+#define CC1_SPEC "\
+%{gline:%{!g:%{!g0:%{!g1:%{!g2: -g1}}}}} \
+%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}} \
+%{save-temps: } \
+%(subtarget_cc1_spec)"
+
+/* Preprocessor specs. */
+
+/* SUBTARGET_CPP_SPEC is passed to the preprocessor. It may be
+ overridden by subtargets. */
+#ifndef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC ""
+#endif
+
+#define CPP_SPEC "%(subtarget_cpp_spec)"
+
+/* This macro defines names of additional specifications to put in the specs
+ that can be used in various specifications like CC1_SPEC. Its definition
+ is an initializer with a subgrouping for each command option.
+
+ Each subgrouping contains a string constant, that defines the
+ specification name, and a string constant that used by the GCC driver
+ program.
+
+ Do not define this macro if it does not need to do anything. */
+
+#define EXTRA_SPECS \
+ { "subtarget_cc1_spec", SUBTARGET_CC1_SPEC }, \
+ { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC }, \
+ { "subtarget_asm_optimizing_spec", SUBTARGET_ASM_OPTIMIZING_SPEC }, \
+ { "subtarget_asm_debugging_spec", SUBTARGET_ASM_DEBUGGING_SPEC }, \
+ { "subtarget_asm_spec", SUBTARGET_ASM_SPEC }, \
+ { "asm_abi_default_spec", "-" MULTILIB_ABI_DEFAULT }, \
+ { "endian_spec", ENDIAN_SPEC }, \
+ SUBTARGET_EXTRA_SPECS
+
+#ifndef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS
+#endif
+
+#define DBX_DEBUGGING_INFO 1 /* generate stabs (OSF/rose) */
+#define MIPS_DEBUGGING_INFO 1 /* MIPS specific debugging info */
+#define DWARF2_DEBUGGING_INFO 1 /* dwarf2 debugging info */
+
+#ifndef PREFERRED_DEBUGGING_TYPE
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#endif
+
+#define DWARF2_ADDR_SIZE (ABI_HAS_64BIT_SYMBOLS ? 8 : 4)
+
+/* By default, turn on GDB extensions. */
+#define DEFAULT_GDB_EXTENSIONS 1
+
+/* Local compiler-generated symbols must have a prefix that the assembler
+ understands. By default, this is $, although some targets (e.g.,
+ NetBSD-ELF) need to override this. */
+
+#ifndef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "$"
+#endif
+
+/* By default on the mips, external symbols do not have an underscore
+ prepended, but some targets (e.g., NetBSD) require this. */
+
+#ifndef USER_LABEL_PREFIX
+#define USER_LABEL_PREFIX ""
+#endif
+
+/* 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. */
+#define DBX_REGISTER_NUMBER(REGNO) mips_dbx_regno[ (REGNO) ]
+
+/* The mapping from gcc register number to DWARF 2 CFA column number. */
+#define DWARF_FRAME_REGNUM(REG) (REG)
+
+/* The DWARF 2 CFA column which tracks the return address. */
+#define DWARF_FRAME_RETURN_COLUMN (GP_REG_FIRST + 31)
+
+/* The DWARF 2 CFA column which tracks the return address from a
+ signal handler context. */
+#define SIGNAL_UNWIND_RETURN_COLUMN (FP_REG_LAST + 1)
+
+/* 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) < (TARGET_MIPS16 ? 2 : 4) ? (N) + GP_ARG_FIRST : INVALID_REGNUM)
+
+#define EH_RETURN_STACKADJ_RTX gen_rtx_REG (Pmode, GP_REG_FIRST + 3)
+
+/* Offsets recorded in opcodes are a multiple of this alignment factor.
+ The default for this in 64-bit mode is 8, which causes problems with
+ SFmode register saves. */
+#define DWARF_CIE_DATA_ALIGNMENT -4
+
+/* Correct the offset of automatic variables and arguments. Note that
+ the MIPS debug format wants all automatic variables and arguments
+ to be in terms of the virtual frame pointer (stack pointer before
+ any adjustment in the function), while the MIPS 3.0 linker wants
+ the frame pointer to be the stack pointer after the initial
+ adjustment. */
+
+#define DEBUGGER_AUTO_OFFSET(X) \
+ mips_debugger_offset (X, (HOST_WIDE_INT) 0)
+#define DEBUGGER_ARG_OFFSET(OFFSET, X) \
+ mips_debugger_offset (X, (HOST_WIDE_INT) OFFSET)
+
+/* Target machine storage layout */
+
+#define BITS_BIG_ENDIAN 0
+#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
+
+/* Define this to set the endianness to use in libgcc2.c, which can
+ not depend on target_flags. */
+#if !defined(MIPSEL) && !defined(__MIPSEL__)
+#define LIBGCC2_WORDS_BIG_ENDIAN 1
+#else
+#define LIBGCC2_WORDS_BIG_ENDIAN 0
+#endif
+
+#define MAX_BITS_PER_WORD 64
+
+/* Width of a word, in units (bytes). */
+#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
+#ifndef IN_LIBGCC2
+#define MIN_UNITS_PER_WORD 4
+#endif
+
+/* For MIPS, width of a floating point register. */
+#define UNITS_PER_FPREG (TARGET_FLOAT64 ? 8 : 4)
+
+/* If register $f0 holds a floating-point value, $f(0 + FP_INC) is
+ the next available register. */
+#define FP_INC (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT ? 1 : 2)
+
+/* The largest size of value that can be held in floating-point
+ registers and moved with a single instruction. */
+#define UNITS_PER_HWFPVALUE (TARGET_SOFT_FLOAT ? 0 : FP_INC * UNITS_PER_FPREG)
+
+/* The largest size of value that can be held in floating-point
+ registers. */
+#define UNITS_PER_FPVALUE \
+ (TARGET_SOFT_FLOAT ? 0 \
+ : TARGET_SINGLE_FLOAT ? UNITS_PER_FPREG \
+ : LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)
+
+/* The number of bytes in a double. */
+#define UNITS_PER_DOUBLE (TYPE_PRECISION (double_type_node) / BITS_PER_UNIT)
+
+#define UNITS_PER_SIMD_WORD (TARGET_PAIRED_SINGLE_FLOAT ? 8 : UNITS_PER_WORD)
+
+/* Set the sizes of the core types. */
+#define SHORT_TYPE_SIZE 16
+#define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE (TARGET_LONG64 ? 64 : 32)
+#define LONG_LONG_TYPE_SIZE 64
+
+#define FLOAT_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE 64
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_NEWABI ? 128 : 64)
+
+/* long double is not a fixed mode, but the idea is that, if we
+ support long double, we also want a 128-bit integer type. */
+#define MAX_FIXED_MODE_SIZE LONG_DOUBLE_TYPE_SIZE
+
+#ifdef IN_LIBGCC2
+#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
+ || (defined _ABI64 && _MIPS_SIM == _ABI64)
+# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+# else
+# define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+# endif
+#endif
+
+/* Width in bits of a pointer. */
+#ifndef POINTER_SIZE
+#define POINTER_SIZE ((TARGET_LONG64 && TARGET_64BIT) ? 64 : 32)
+#endif
+
+/* Allocation boundary (in *bits*) for storing arguments in argument list. */
+#define PARM_BOUNDARY BITS_PER_WORD
+
+/* Allocation boundary (in *bits*) for the code of a function. */
+#define FUNCTION_BOUNDARY 32
+
+/* Alignment of field after `int : 0' in a structure. */
+#define EMPTY_FIELD_BOUNDARY 32
+
+/* Every structure's size must be a multiple of this. */
+/* 8 is observed right on a DECstation and on riscos 4.02. */
+#define STRUCTURE_SIZE_BOUNDARY 8
+
+/* There is no point aligning anything to a rounder boundary than this. */
+#define BIGGEST_ALIGNMENT LONG_DOUBLE_TYPE_SIZE
+
+/* All accesses must be aligned. */
+#define STRICT_ALIGNMENT 1
+
+/* Define this if you wish to imitate the way many other C compilers
+ handle alignment of bitfields and the structures that contain
+ them.
+
+ The behavior is that the type written for a bit-field (`int',
+ `short', or other integer type) imposes an alignment for the
+ entire structure, as if the structure really did contain an
+ ordinary field of that type. In addition, the bit-field is placed
+ within the structure so that it would fit within such a field,
+ not crossing a boundary for it.
+
+ Thus, on most machines, a bit-field whose type is written as `int'
+ would not cross a four-byte boundary, and would force four-byte
+ alignment for the whole structure. (The alignment used may not
+ be four bytes; it is controlled by the other alignment
+ parameters.)
+
+ If the macro is defined, its definition should be a C expression;
+ a nonzero value for the expression enables this behavior. */
+
+#define PCC_BITFIELD_TYPE_MATTERS 1
+
+/* If defined, a C expression to compute the alignment given to a
+ constant that is being placed in memory. CONSTANT is the constant
+ and ALIGN is the alignment that the object would ordinarily have.
+ The value of this macro is used instead of that alignment to align
+ the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ The typical use of this macro is to increase alignment for string
+ constants to be word aligned so that `strcpy' calls that copy
+ constants can be done inline. */
+
+#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
+ ((TREE_CODE (EXP) == STRING_CST || TREE_CODE (EXP) == CONSTRUCTOR) \
+ && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
+
+/* If defined, a C expression to compute the alignment for a static
+ variable. TYPE is the data type, and ALIGN is the alignment that
+ the object would ordinarily have. The value of this macro is used
+ instead of that alignment to align the object.
+
+ If this macro is not defined, then ALIGN is used.
+
+ One use of this macro is to increase alignment of medium-size
+ data to make it all fit in fewer cache lines. Another is to
+ cause character arrays to be word-aligned so that `strcpy' calls
+ that copy constants to character arrays can be done inline. */
+
+#undef DATA_ALIGNMENT
+#define DATA_ALIGNMENT(TYPE, ALIGN) \
+ ((((ALIGN) < BITS_PER_WORD) \
+ && (TREE_CODE (TYPE) == ARRAY_TYPE \
+ || TREE_CODE (TYPE) == UNION_TYPE \
+ || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
+
+
+#define PAD_VARARGS_DOWN \
+ (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
+
+/* Define if operations between registers always perform the operation
+ on the full register even if a narrower mode is specified. */
+#define WORD_REGISTER_OPERATIONS
+
+/* When in 64 bit mode, move insns will sign extend SImode and CCmode
+ moves. All other references are zero extended. */
+#define LOAD_EXTEND_OP(MODE) \
+ (TARGET_64BIT && ((MODE) == SImode || (MODE) == CCmode) \
+ ? SIGN_EXTEND : ZERO_EXTEND)
+
+/* Define this macro if it is advisable to hold scalars in registers
+ in a wider mode than that declared by the program. In such cases,
+ the value is constrained to be within the bounds of the declared
+ type, but kept valid in the wider mode. The signedness of the
+ extension may differ from that of the type. */
+
+#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+ if (GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
+ { \
+ if ((MODE) == SImode) \
+ (UNSIGNEDP) = 0; \
+ (MODE) = Pmode; \
+ }
+
+/* Define if loading short immediate values into registers sign extends. */
+#define SHORT_IMMEDIATES_SIGN_EXTEND
+
+/* The [d]clz instructions have the natural values at 0. */
+
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
+ ((VALUE) = GET_MODE_BITSIZE (MODE), true)
+
+/* Standard register usage. */
+
+/* Number of hardware registers. We have:
+
+ - 32 integer registers
+ - 32 floating point registers
+ - 8 condition code registers
+ - 2 accumulator registers (hi and lo)
+ - 32 registers each for coprocessors 0, 2 and 3
+ - 3 fake registers:
+ - ARG_POINTER_REGNUM
+ - FRAME_POINTER_REGNUM
+ - FAKE_CALL_REGNO (see the comment above load_callsi for details)
+ - 3 dummy entries that were used at various times in the past.
+ - 6 DSP accumulator registers (3 hi-lo pairs) for MIPS DSP ASE
+ - 6 DSP control registers */
+
+#define FIRST_PSEUDO_REGISTER 188
+
+/* By default, fix the kernel registers ($26 and $27), the global
+ pointer ($28) and the stack pointer ($29). This can change
+ depending on the command-line options.
+
+ Regarding coprocessor registers: without evidence to the contrary,
+ it's best to assume that each coprocessor register has a unique
+ use. This can be overridden, in, e.g., override_options() or
+ CONDITIONAL_REGISTER_USAGE should the assumption be inappropriate
+ for a particular target. */
+
+#define FIXED_REGISTERS \
+{ \
+ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, \
+ /* COP0 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP2 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP3 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1 \
+}
+
+
+/* Set up this array for o32 by default.
+
+ Note that we don't mark $31 as a call-clobbered register. The idea is
+ that it's really the call instructions themselves which clobber $31.
+ We don't care what the called function does with it afterwards.
+
+ This approach makes it easier to implement sibcalls. Unlike normal
+ calls, sibcalls don't clobber $31, so the register reaches the
+ called function in tact. EPILOGUE_USES says that $31 is useful
+ to the called function. */
+
+#define CALL_USED_REGISTERS \
+{ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP0 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP2 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP3 registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 \
+}
+
+
+/* Define this since $28, though fixed, is call-saved in many ABIs. */
+
+#define CALL_REALLY_USED_REGISTERS \
+{ /* General registers. */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, \
+ /* Floating-point registers. */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* Others. */ \
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
+ /* COP0 registers */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* COP2 registers */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* COP3 registers */ \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
+ /* 6 DSP accumulator registers & 6 control registers */ \
+ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 \
+}
+
+/* Internal macros to classify a register number as to whether it's a
+ general purpose register, a floating point register, a
+ multiply/divide register, or a status register. */
+
+#define GP_REG_FIRST 0
+#define GP_REG_LAST 31
+#define GP_REG_NUM (GP_REG_LAST - GP_REG_FIRST + 1)
+#define GP_DBX_FIRST 0
+
+#define FP_REG_FIRST 32
+#define FP_REG_LAST 63
+#define FP_REG_NUM (FP_REG_LAST - FP_REG_FIRST + 1)
+#define FP_DBX_FIRST ((write_symbols == DBX_DEBUG) ? 38 : 32)
+
+#define MD_REG_FIRST 64
+#define MD_REG_LAST 65
+#define MD_REG_NUM (MD_REG_LAST - MD_REG_FIRST + 1)
+#define MD_DBX_FIRST (FP_DBX_FIRST + FP_REG_NUM)
+
+#define ST_REG_FIRST 67
+#define ST_REG_LAST 74
+#define ST_REG_NUM (ST_REG_LAST - ST_REG_FIRST + 1)
+
+
+/* FIXME: renumber. */
+#define COP0_REG_FIRST 80
+#define COP0_REG_LAST 111
+#define COP0_REG_NUM (COP0_REG_LAST - COP0_REG_FIRST + 1)
+
+#define COP2_REG_FIRST 112
+#define COP2_REG_LAST 143
+#define COP2_REG_NUM (COP2_REG_LAST - COP2_REG_FIRST + 1)
+
+#define COP3_REG_FIRST 144
+#define COP3_REG_LAST 175
+#define COP3_REG_NUM (COP3_REG_LAST - COP3_REG_FIRST + 1)
+/* ALL_COP_REG_NUM assumes that COP0,2,and 3 are numbered consecutively. */
+#define ALL_COP_REG_NUM (COP3_REG_LAST - COP0_REG_FIRST + 1)
+
+#define DSP_ACC_REG_FIRST 176
+#define DSP_ACC_REG_LAST 181
+#define DSP_ACC_REG_NUM (DSP_ACC_REG_LAST - DSP_ACC_REG_FIRST + 1)
+
+#define AT_REGNUM (GP_REG_FIRST + 1)
+#define HI_REGNUM (MD_REG_FIRST + 0)
+#define LO_REGNUM (MD_REG_FIRST + 1)
+#define AC1HI_REGNUM (DSP_ACC_REG_FIRST + 0)
+#define AC1LO_REGNUM (DSP_ACC_REG_FIRST + 1)
+#define AC2HI_REGNUM (DSP_ACC_REG_FIRST + 2)
+#define AC2LO_REGNUM (DSP_ACC_REG_FIRST + 3)
+#define AC3HI_REGNUM (DSP_ACC_REG_FIRST + 4)
+#define AC3LO_REGNUM (DSP_ACC_REG_FIRST + 5)
+
+/* FPSW_REGNUM is the single condition code used if !ISA_HAS_8CC.
+ If ISA_HAS_8CC, it should not be used, and an arbitrary ST_REG
+ should be used instead. */
+#define FPSW_REGNUM ST_REG_FIRST
+
+#define GP_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - GP_REG_FIRST) < GP_REG_NUM)
+#define M16_REG_P(REGNO) \
+ (((REGNO) >= 2 && (REGNO) <= 7) || (REGNO) == 16 || (REGNO) == 17)
+#define FP_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - FP_REG_FIRST) < FP_REG_NUM)
+#define MD_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - MD_REG_FIRST) < MD_REG_NUM)
+#define ST_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - ST_REG_FIRST) < ST_REG_NUM)
+#define COP0_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - COP0_REG_FIRST) < COP0_REG_NUM)
+#define COP2_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - COP2_REG_FIRST) < COP2_REG_NUM)
+#define COP3_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - COP3_REG_FIRST) < COP3_REG_NUM)
+#define ALL_COP_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - COP0_REG_FIRST) < ALL_COP_REG_NUM)
+/* Test if REGNO is one of the 6 new DSP accumulators. */
+#define DSP_ACC_REG_P(REGNO) \
+ ((unsigned int) ((int) (REGNO) - DSP_ACC_REG_FIRST) < DSP_ACC_REG_NUM)
+/* Test if REGNO is hi, lo, or one of the 6 new DSP accumulators. */
+#define ACC_REG_P(REGNO) \
+ (MD_REG_P (REGNO) || DSP_ACC_REG_P (REGNO))
+/* Test if REGNO is HI or the first register of 3 new DSP accumulator pairs. */
+#define ACC_HI_REG_P(REGNO) \
+ ((REGNO) == HI_REGNUM || (REGNO) == AC1HI_REGNUM || (REGNO) == AC2HI_REGNUM \
+ || (REGNO) == AC3HI_REGNUM)
+
+#define FP_REG_RTX_P(X) (REG_P (X) && FP_REG_P (REGNO (X)))
+
+/* True if X is (const (unspec [(const_int 0)] UNSPEC_GP)). This is used
+ to initialize the mips16 gp pseudo register. */
+#define CONST_GP_P(X) \
+ (GET_CODE (X) == CONST \
+ && GET_CODE (XEXP (X, 0)) == UNSPEC \
+ && XINT (XEXP (X, 0), 1) == UNSPEC_GP)
+
+/* Return coprocessor number from register number. */
+
+#define COPNUM_AS_CHAR_FROM_REGNUM(REGNO) \
+ (COP0_REG_P (REGNO) ? '0' : COP2_REG_P (REGNO) ? '2' \
+ : COP3_REG_P (REGNO) ? '3' : '?')
+
+
+#define HARD_REGNO_NREGS(REGNO, MODE) mips_hard_regno_nregs (REGNO, MODE)
+
+/* To make the code simpler, HARD_REGNO_MODE_OK just references an
+ array built in override_options. Because machmodes.h is not yet
+ included before this file is processed, the MODE bound can't be
+ expressed here. */
+
+extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER];
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ mips_hard_regno_mode_ok[ (int)(MODE) ][ (REGNO) ]
+
+/* 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) \
+ ((GET_MODE_CLASS (MODE1) == MODE_FLOAT || \
+ GET_MODE_CLASS (MODE1) == MODE_COMPLEX_FLOAT) \
+ == (GET_MODE_CLASS (MODE2) == MODE_FLOAT || \
+ GET_MODE_CLASS (MODE2) == MODE_COMPLEX_FLOAT))
+
+/* Register to use for pushing function arguments. */
+#define STACK_POINTER_REGNUM (GP_REG_FIRST + 29)
+
+/* These two registers don't really exist: they get eliminated to either
+ the stack or hard frame pointer. */
+#define ARG_POINTER_REGNUM 77
+#define FRAME_POINTER_REGNUM 78
+
+/* $30 is not available on the mips16, so we use $17 as the frame
+ pointer. */
+#define HARD_FRAME_POINTER_REGNUM \
+ (TARGET_MIPS16 ? GP_REG_FIRST + 17 : GP_REG_FIRST + 30)
+
+/* 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 (current_function_calls_alloca)
+
+/* Register in which static-chain is passed to a function. */
+#define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2)
+
+/* Registers used as temporaries in prologue/epilogue code. If we're
+ generating mips16 code, these registers must come from the core set
+ of 8. The prologue register mustn't conflict with any incoming
+ arguments, the static chain pointer, or the frame pointer. The
+ epilogue temporary mustn't conflict with the return registers, the
+ frame pointer, the EH stack adjustment, or the EH data registers. */
+
+#define MIPS_PROLOGUE_TEMP_REGNUM (GP_REG_FIRST + 3)
+#define MIPS_EPILOGUE_TEMP_REGNUM (GP_REG_FIRST + (TARGET_MIPS16 ? 6 : 8))
+
+#define MIPS_PROLOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_PROLOGUE_TEMP_REGNUM)
+#define MIPS_EPILOGUE_TEMP(MODE) gen_rtx_REG (MODE, MIPS_EPILOGUE_TEMP_REGNUM)
+
+/* Define this macro if it is as good or better to call a constant
+ function address than to call an address kept in a register. */
+#define NO_FUNCTION_CSE 1
+
+/* The ABI-defined global pointer. Sometimes we use a different
+ register in leaf functions: see PIC_OFFSET_TABLE_REGNUM. */
+#define GLOBAL_POINTER_REGNUM (GP_REG_FIRST + 28)
+
+/* We normally use $28 as the global pointer. However, when generating
+ n32/64 PIC, it is better for leaf functions to use a call-clobbered
+ register instead. They can then avoid saving and restoring $28
+ and perhaps avoid using a frame at all.
+
+ When a leaf function uses something other than $28, mips_expand_prologue
+ will modify pic_offset_table_rtx in place. Take the register number
+ from there after reload. */
+#define PIC_OFFSET_TABLE_REGNUM \
+ (reload_completed ? REGNO (pic_offset_table_rtx) : GLOBAL_POINTER_REGNUM)
+
+#define PIC_FUNCTION_ADDR_REGNUM (GP_REG_FIRST + 25)
+
+/* Define the classes of registers for register constraints in the
+ machine description. Also define ranges of constants.
+
+ One of the classes must always be named ALL_REGS and include all hard regs.
+ If there is more than one class, another class must be named NO_REGS
+ and contain no registers.
+
+ The name GENERAL_REGS must be the name of a class (or an alias for
+ another name such as ALL_REGS). This is the class of registers
+ that is allowed by "g" or "r" in a register constraint.
+ Also, registers outside this class are allocated only when
+ instructions express preferences for them.
+
+ The classes must be numbered in nondecreasing order; that is,
+ a larger-numbered class must never be contained completely
+ in a smaller-numbered class.
+
+ For any two classes, it is very desirable that there be another
+ class that represents their union. */
+
+enum reg_class
+{
+ NO_REGS, /* no registers in set */
+ M16_NA_REGS, /* mips16 regs not used to pass args */
+ M16_REGS, /* mips16 directly accessible registers */
+ T_REG, /* mips16 T register ($24) */
+ M16_T_REGS, /* mips16 registers plus T register */
+ PIC_FN_ADDR_REG, /* SVR4 PIC function address register */
+ V1_REG, /* Register $v1 ($3) used for TLS access. */
+ LEA_REGS, /* Every GPR except $25 */
+ GR_REGS, /* integer registers */
+ FP_REGS, /* floating point registers */
+ HI_REG, /* hi register */
+ LO_REG, /* lo register */
+ MD_REGS, /* multiply/divide registers (hi/lo) */
+ COP0_REGS, /* generic coprocessor classes */
+ COP2_REGS,
+ COP3_REGS,
+ HI_AND_GR_REGS, /* union classes */
+ LO_AND_GR_REGS,
+ HI_AND_FP_REGS,
+ COP0_AND_GR_REGS,
+ COP2_AND_GR_REGS,
+ COP3_AND_GR_REGS,
+ ALL_COP_REGS,
+ ALL_COP_AND_GR_REGS,
+ ST_REGS, /* status registers (fp status) */
+ DSP_ACC_REGS, /* DSP accumulator registers */
+ ACC_REGS, /* Hi/Lo and DSP accumulator registers */
+ ALL_REGS, /* all registers */
+ LIM_REG_CLASSES /* max value + 1 */
+};
+
+#define N_REG_CLASSES (int) LIM_REG_CLASSES
+
+#define GENERAL_REGS GR_REGS
+
+/* An initializer containing the names of the register classes as C
+ string constants. These names are used in writing some of the
+ debugging dumps. */
+
+#define REG_CLASS_NAMES \
+{ \
+ "NO_REGS", \
+ "M16_NA_REGS", \
+ "M16_REGS", \
+ "T_REG", \
+ "M16_T_REGS", \
+ "PIC_FN_ADDR_REG", \
+ "V1_REG", \
+ "LEA_REGS", \
+ "GR_REGS", \
+ "FP_REGS", \
+ "HI_REG", \
+ "LO_REG", \
+ "MD_REGS", \
+ /* coprocessor registers */ \
+ "COP0_REGS", \
+ "COP2_REGS", \
+ "COP3_REGS", \
+ "HI_AND_GR_REGS", \
+ "LO_AND_GR_REGS", \
+ "HI_AND_FP_REGS", \
+ "COP0_AND_GR_REGS", \
+ "COP2_AND_GR_REGS", \
+ "COP3_AND_GR_REGS", \
+ "ALL_COP_REGS", \
+ "ALL_COP_AND_GR_REGS", \
+ "ST_REGS", \
+ "DSP_ACC_REGS", \
+ "ACC_REGS", \
+ "ALL_REGS" \
+}
+
+/* An initializer containing the contents of the register classes,
+ as integers which are bit masks. The Nth integer specifies the
+ contents of class N. The way the integer MASK is interpreted is
+ that register R is in the class if `MASK & (1 << R)' is 1.
+
+ When the machine has more than 32 registers, an integer does not
+ suffice. Then the integers are replaced by sub-initializers,
+ braced groupings containing several integers. Each
+ sub-initializer must be suitable as an initializer for the type
+ `HARD_REG_SET' which is defined in `hard-reg-set.h'. */
+
+#define REG_CLASS_CONTENTS \
+{ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* no registers */ \
+ { 0x0003000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 nonarg regs */\
+ { 0x000300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 registers */ \
+ { 0x01000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 T register */ \
+ { 0x010300fc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* mips16 and T regs */ \
+ { 0x02000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* SVR4 PIC function address register */ \
+ { 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* only $v1 */ \
+ { 0xfdffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* Every other GPR except $25 */ \
+ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* integer registers */ \
+ { 0x00000000, 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* floating registers*/ \
+ { 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* hi register */ \
+ { 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, /* lo register */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000000 }, /* mul/div registers */ \
+ { 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, /* cop0 registers */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, /* cop2 registers */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, /* cop3 registers */ \
+ { 0xffffffff, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, /* union classes */ \
+ { 0xffffffff, 0x00000000, 0x00000002, 0x00000000, 0x00000000, 0x00000000 }, \
+ { 0x00000000, 0xffffffff, 0x00000001, 0x00000000, 0x00000000, 0x00000000 }, \
+ { 0xffffffff, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000, 0x00000000 }, \
+ { 0xffffffff, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff, 0x00000000 }, \
+ { 0xffffffff, 0x00000000, 0x00000000, 0x00000000, 0xffff0000, 0x0000ffff }, \
+ { 0x00000000, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
+ { 0xffffffff, 0x00000000, 0xffff0000, 0xffffffff, 0xffffffff, 0x0000ffff }, \
+ { 0x00000000, 0x00000000, 0x000007f8, 0x00000000, 0x00000000, 0x00000000 }, /* status registers */ \
+ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003f0000 }, /* dsp accumulator registers */ \
+ { 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x003f0000 }, /* hi/lo and dsp accumulator registers */ \
+ { 0xffffffff, 0xffffffff, 0xffff07ff, 0xffffffff, 0xffffffff, 0x0fffffff } /* all registers */ \
+}
+
+
+/* A C expression whose value is a register class containing hard
+ register REGNO. In general there is more that one such class;
+ choose a class which is "minimal", meaning that no smaller class
+ also contains the register. */
+
+extern const enum reg_class mips_regno_to_class[];
+
+#define REGNO_REG_CLASS(REGNO) mips_regno_to_class[ (REGNO) ]
+
+/* A macro whose definition is the name of the class to which a
+ valid base register must belong. A base register is one used in
+ an address which is the register value plus a displacement. */
+
+#define BASE_REG_CLASS (TARGET_MIPS16 ? M16_REGS : GR_REGS)
+
+/* A macro whose definition is the name of the class to which a
+ valid index register must belong. An index register is one used
+ in an address where its value is either multiplied by a scale
+ factor or added to another register (as well as added to a
+ displacement). */
+
+#define INDEX_REG_CLASS NO_REGS
+
+/* When SMALL_REGISTER_CLASSES is nonzero, the compiler allows
+ registers explicitly used in the rtl to be used as spill registers
+ but prevents the compiler from extending the lifetime of these
+ registers. */
+
+#define SMALL_REGISTER_CLASSES (TARGET_MIPS16)
+
+/* This macro is used later on in the file. */
+#define GR_REG_CLASS_P(CLASS) \
+ ((CLASS) == GR_REGS || (CLASS) == M16_REGS || (CLASS) == T_REG \
+ || (CLASS) == M16_T_REGS || (CLASS) == M16_NA_REGS \
+ || (CLASS) == V1_REG \
+ || (CLASS) == PIC_FN_ADDR_REG || (CLASS) == LEA_REGS)
+
+/* This macro is also used later on in the file. */
+#define COP_REG_CLASS_P(CLASS) \
+ ((CLASS) == COP0_REGS || (CLASS) == COP2_REGS || (CLASS) == COP3_REGS)
+
+/* REG_ALLOC_ORDER is to order in which to allocate registers. This
+ is the default value (allocate the registers in numeric order). We
+ define it just so that we can override it for the mips16 target in
+ ORDER_REGS_FOR_LOCAL_ALLOC. */
+
+#define REG_ALLOC_ORDER \
+{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, \
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, \
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, \
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, \
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, \
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, \
+ 96, 97, 98, 99, 100,101,102,103,104,105,106,107,108,109,110,111, \
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, \
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, \
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, \
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, \
+ 176,177,178,179,180,181,182,183,184,185,186,187 \
+}
+
+/* ORDER_REGS_FOR_LOCAL_ALLOC is a macro which permits reg_alloc_order
+ to be rearranged based on a particular function. On the mips16, we
+ want to allocate $24 (T_REG) before other registers for
+ instructions for which it is possible. */
+
+#define ORDER_REGS_FOR_LOCAL_ALLOC mips_order_regs_for_local_alloc ()
+
+/* True if VALUE is an unsigned 6-bit number. */
+
+#define UIMM6_OPERAND(VALUE) \
+ (((VALUE) & ~(unsigned HOST_WIDE_INT) 0x3f) == 0)
+
+/* True if VALUE is a signed 10-bit number. */
+
+#define IMM10_OPERAND(VALUE) \
+ ((unsigned HOST_WIDE_INT) (VALUE) + 0x200 < 0x400)
+
+/* True if VALUE is a signed 16-bit number. */
+
+#define SMALL_OPERAND(VALUE) \
+ ((unsigned HOST_WIDE_INT) (VALUE) + 0x8000 < 0x10000)
+
+/* True if VALUE is an unsigned 16-bit number. */
+
+#define SMALL_OPERAND_UNSIGNED(VALUE) \
+ (((VALUE) & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
+
+/* True if VALUE can be loaded into a register using LUI. */
+
+#define LUI_OPERAND(VALUE) \
+ (((VALUE) | 0x7fff0000) == 0x7fff0000 \
+ || ((VALUE) | 0x7fff0000) + 0x10000 == 0)
+
+/* Return a value X with the low 16 bits clear, and such that
+ VALUE - X is a signed 16-bit value. */
+
+#define CONST_HIGH_PART(VALUE) \
+ (((VALUE) + 0x8000) & ~(unsigned HOST_WIDE_INT) 0xffff)
+
+#define CONST_LOW_PART(VALUE) \
+ ((VALUE) - CONST_HIGH_PART (VALUE))
+
+#define SMALL_INT(X) SMALL_OPERAND (INTVAL (X))
+#define SMALL_INT_UNSIGNED(X) SMALL_OPERAND_UNSIGNED (INTVAL (X))
+#define LUI_INT(X) LUI_OPERAND (INTVAL (X))
+
+#define PREFERRED_RELOAD_CLASS(X,CLASS) \
+ mips_preferred_reload_class (X, CLASS)
+
+/* Certain machines have the property that some registers cannot be
+ copied to some other registers without using memory. Define this
+ macro on those machines to be a C expression that is nonzero if
+ objects of mode MODE in registers of CLASS1 can only be copied to
+ registers of class CLASS2 by storing a register of CLASS1 into
+ memory and loading that memory location into a register of CLASS2.
+
+ Do not define this macro if its value would always be zero. */
+#if 0
+#define SECONDARY_MEMORY_NEEDED(CLASS1, CLASS2, MODE) \
+ ((!TARGET_DEBUG_H_MODE \
+ && GET_MODE_CLASS (MODE) == MODE_INT \
+ && ((CLASS1 == FP_REGS && GR_REG_CLASS_P (CLASS2)) \
+ || (GR_REG_CLASS_P (CLASS1) && CLASS2 == FP_REGS))) \
+ || (TARGET_FLOAT64 && !TARGET_64BIT && (MODE) == DFmode \
+ && ((GR_REG_CLASS_P (CLASS1) && CLASS2 == FP_REGS) \
+ || (GR_REG_CLASS_P (CLASS2) && CLASS1 == FP_REGS))))
+#endif
+/* The HI and LO registers can only be reloaded via the general
+ registers. Condition code registers can only be loaded to the
+ general registers, and from the floating point registers. */
+
+#define SECONDARY_INPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ mips_secondary_reload_class (CLASS, MODE, X, 1)
+#define SECONDARY_OUTPUT_RELOAD_CLASS(CLASS, MODE, X) \
+ mips_secondary_reload_class (CLASS, MODE, X, 0)
+
+/* Return the maximum number of consecutive registers
+ needed to represent mode MODE in a register of class CLASS. */
+
+#define CLASS_MAX_NREGS(CLASS, MODE) mips_class_max_nregs (CLASS, MODE)
+
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ mips_cannot_change_mode_class (FROM, TO, CLASS)
+
+/* Stack layout; function entry, exit and calling. */
+
+#define STACK_GROWS_DOWNWARD
+
+/* The offset of the first local variable from the beginning of the frame.
+ See compute_frame_size for details about the frame layout.
+
+ ??? If flag_profile_values is true, and we are generating 32-bit code, then
+ we assume that we will need 16 bytes of argument space. This is because
+ the value profiling code may emit calls to cmpdi2 in leaf functions.
+ Without this hack, the local variables will start at sp+8 and the gp save
+ area will be at sp+16, and thus they will overlap. compute_frame_size is
+ OK because it uses STARTING_FRAME_OFFSET to compute cprestore_size, which
+ will end up as 24 instead of 8. This won't be needed if profiling code is
+ inserted before virtual register instantiation. */
+
+#define STARTING_FRAME_OFFSET \
+ ((flag_profile_values && ! TARGET_64BIT \
+ ? MAX (REG_PARM_STACK_SPACE(NULL), current_function_outgoing_args_size) \
+ : current_function_outgoing_args_size) \
+ + (TARGET_ABICALLS && !TARGET_NEWABI \
+ ? MIPS_STACK_ALIGN (UNITS_PER_WORD) : 0))
+
+#define RETURN_ADDR_RTX mips_return_addr
+
+/* Since the mips16 ISA mode is encoded in the least-significant bit
+ of the address, mask it off return addresses for purposes of
+ finding exception handling regions. */
+
+#define MASK_RETURN_ADDR GEN_INT (-2)
+
+
+/* Similarly, don't use the least-significant bit to tell pointers to
+ code from vtable index. */
+
+#define TARGET_PTRMEMFUNC_VBIT_LOCATION ptrmemfunc_vbit_in_delta
+
+/* The eliminations to $17 are only used for mips16 code. See the
+ definition of HARD_FRAME_POINTER_REGNUM. */
+
+#define ELIMINABLE_REGS \
+{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, GP_REG_FIRST + 30}, \
+ { ARG_POINTER_REGNUM, GP_REG_FIRST + 17}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, GP_REG_FIRST + 30}, \
+ { FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
+
+/* We can always eliminate to the hard frame pointer. We can eliminate
+ to the stack pointer unless a frame pointer is needed.
+
+ In mips16 mode, we need a frame pointer for a large frame; otherwise,
+ reload may be unable to compute the address of a local variable,
+ since there is no way to add a large constant to the stack pointer
+ without using a temporary register. */
+#define CAN_ELIMINATE(FROM, TO) \
+ ((TO) == HARD_FRAME_POINTER_REGNUM \
+ || ((TO) == STACK_POINTER_REGNUM && !frame_pointer_needed \
+ && (!TARGET_MIPS16 \
+ || compute_frame_size (get_frame_size ()) < 32768)))
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = mips_initial_elimination_offset ((FROM), (TO))
+
+/* Allocate stack space for arguments at the beginning of each function. */
+#define ACCUMULATE_OUTGOING_ARGS 1
+
+/* The argument pointer always points to the first argument. */
+#define FIRST_PARM_OFFSET(FNDECL) 0
+
+/* o32 and o64 reserve stack space for all argument registers. */
+#define REG_PARM_STACK_SPACE(FNDECL) \
+ (TARGET_OLDABI \
+ ? (MAX_ARGS_IN_REGISTERS * UNITS_PER_WORD) \
+ : 0)
+
+/* Define this if it is the responsibility of the caller to
+ allocate the area reserved for arguments passed in registers.
+ If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
+ of this macro is to determine whether the space is included in
+ `current_function_outgoing_args_size'. */
+#define OUTGOING_REG_PARM_STACK_SPACE
+
+#define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64)
+
+#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
+
+/* Symbolic macros for the registers used to return integer and floating
+ point values. */
+
+#define GP_RETURN (GP_REG_FIRST + 2)
+#define FP_RETURN ((TARGET_SOFT_FLOAT) ? GP_RETURN : (FP_REG_FIRST + 0))
+
+#define MAX_ARGS_IN_REGISTERS (TARGET_OLDABI ? 4 : 8)
+
+/* Symbolic macros for the first/last argument registers. */
+
+#define GP_ARG_FIRST (GP_REG_FIRST + 4)
+#define GP_ARG_LAST (GP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
+#define FP_ARG_FIRST (FP_REG_FIRST + 12)
+#define FP_ARG_LAST (FP_ARG_FIRST + MAX_ARGS_IN_REGISTERS - 1)
+
+#define LIBCALL_VALUE(MODE) \
+ mips_function_value (NULL_TREE, NULL, (MODE))
+
+#define FUNCTION_VALUE(VALTYPE, FUNC) \
+ mips_function_value ((VALTYPE), (FUNC), VOIDmode)
+
+/* 1 if N is a possible register number for a function value.
+ On the MIPS, R2 R3 and F0 F2 are the only register thus used.
+ Currently, R2 and F0 are only implemented here (C has no complex type) */
+
+#define FUNCTION_VALUE_REGNO_P(N) ((N) == GP_RETURN || (N) == FP_RETURN \
+ || (LONG_DOUBLE_TYPE_SIZE == 128 && FP_RETURN != GP_RETURN \
+ && (N) == FP_RETURN + 2))
+
+/* 1 if N is a possible register number for function argument passing.
+ We have no FP argument registers when soft-float. When FP registers
+ are 32 bits, we can't directly reference the odd numbered ones. */
+
+#define FUNCTION_ARG_REGNO_P(N) \
+ ((IN_RANGE((N), GP_ARG_FIRST, GP_ARG_LAST) \
+ || (IN_RANGE((N), FP_ARG_FIRST, FP_ARG_LAST))) \
+ && !fixed_regs[N])
+
+/* This structure has to cope with two different argument allocation
+ schemes. Most MIPS ABIs view the arguments as a structure, of which
+ the first N words go in registers and the rest go on the stack. If I
+ < N, the Ith word might go in Ith integer argument register or in a
+ floating-point register. For these ABIs, we only need to remember
+ the offset of the current argument into the structure.
+
+ The EABI instead allocates the integer and floating-point arguments
+ separately. The first N words of FP arguments go in FP registers,
+ the rest go on the stack. Likewise, the first N words of the other
+ arguments go in integer registers, and the rest go on the stack. We
+ need to maintain three counts: the number of integer registers used,
+ the number of floating-point registers used, and the number of words
+ passed on the stack.
+
+ We could keep separate information for the two ABIs (a word count for
+ the standard ABIs, and three separate counts for the EABI). But it
+ seems simpler to view the standard ABIs as forms of EABI that do not
+ allocate floating-point registers.
+
+ So for the standard ABIs, the first N words are allocated to integer
+ registers, and function_arg decides on an argument-by-argument basis
+ whether that argument should really go in an integer register, or in
+ a floating-point one. */
+
+typedef struct mips_args {
+ /* Always true for varargs functions. Otherwise true if at least
+ one argument has been passed in an integer register. */
+ int gp_reg_found;
+
+ /* The number of arguments seen so far. */
+ unsigned int arg_number;
+
+ /* The number of integer registers used so far. For all ABIs except
+ EABI, this is the number of words that have been added to the
+ argument structure, limited to MAX_ARGS_IN_REGISTERS. */
+ unsigned int num_gprs;
+
+ /* For EABI, the number of floating-point registers used so far. */
+ unsigned int num_fprs;
+
+ /* The number of words passed on the stack. */
+ unsigned int stack_words;
+
+ /* On the mips16, we need to keep track of which floating point
+ arguments were passed in general registers, but would have been
+ passed in the FP regs if this were a 32 bit function, so that we
+ can move them to the FP regs if we wind up calling a 32 bit
+ function. We record this information in fp_code, encoded in base
+ four. A zero digit means no floating point argument, a one digit
+ means an SFmode argument, and a two digit means a DFmode argument,
+ and a three digit is not used. The low order digit is the first
+ argument. Thus 6 == 1 * 4 + 2 means a DFmode argument followed by
+ an SFmode argument. ??? A more sophisticated approach will be
+ needed if MIPS_ABI != ABI_32. */
+ int fp_code;
+
+ /* True if the function has a prototype. */
+ int prototype;
+} 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, INDIRECT, N_NAMED_ARGS) \
+ init_cumulative_args (&CUM, FNTYPE, LIBNAME) \
+
+/* 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) \
+ function_arg_advance (&CUM, MODE, TYPE, NAMED)
+
+/* Determine where to put an argument to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis). */
+
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ function_arg( &CUM, MODE, TYPE, NAMED)
+
+#define FUNCTION_ARG_BOUNDARY function_arg_boundary
+
+#define FUNCTION_ARG_PADDING(MODE, TYPE) \
+ (mips_pad_arg_upward (MODE, TYPE) ? upward : downward)
+
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+ (mips_pad_reg_upward (MODE, TYPE) ? upward : downward)
+
+/* True if using EABI and varargs can be passed in floating-point
+ registers. Under these conditions, we need a more complex form
+ of va_list, which tracks GPR, FPR and stack arguments separately. */
+#define EABI_FLOAT_VARARGS_P \
+ (mips_abi == ABI_EABI && UNITS_PER_FPVALUE >= UNITS_PER_DOUBLE)
+
+
+/* Say that the epilogue uses the return address register. Note that
+ in the case of sibcalls, the values "used by the epilogue" are
+ considered live at the start of the called function. */
+#define EPILOGUE_USES(REGNO) ((REGNO) == 31)
+
+/* Treat LOC as a byte offset from the stack pointer and round it up
+ to the next fully-aligned offset. */
+#define MIPS_STACK_ALIGN(LOC) \
+ (TARGET_NEWABI ? ((LOC) + 15) & -16 : ((LOC) + 7) & -8)
+
+
+/* Implement `va_start' for varargs and stdarg. */
+#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
+ mips_va_start (valist, nextarg)
+
+/* Output assembler code to FILE to increment profiler label # LABELNO
+ for profiling a function entry. */
+
+#define FUNCTION_PROFILER(FILE, LABELNO) \
+{ \
+ if (TARGET_MIPS16) \
+ sorry ("mips16 function profiling"); \
+ fprintf (FILE, "\t.set\tnoat\n"); \
+ fprintf (FILE, "\tmove\t%s,%s\t\t# save current return address\n", \
+ reg_names[GP_REG_FIRST + 1], reg_names[GP_REG_FIRST + 31]); \
+ if (!TARGET_NEWABI) \
+ { \
+ fprintf (FILE, \
+ "\t%s\t%s,%s,%d\t\t# _mcount pops 2 words from stack\n", \
+ TARGET_64BIT ? "dsubu" : "subu", \
+ reg_names[STACK_POINTER_REGNUM], \
+ reg_names[STACK_POINTER_REGNUM], \
+ Pmode == DImode ? 16 : 8); \
+ } \
+ fprintf (FILE, "\tjal\t_mcount\n"); \
+ fprintf (FILE, "\t.set\tat\n"); \
+}
+
+/* No mips port has ever used the profiler counter word, so don't emit it
+ or the label for it. */
+
+#define NO_PROFILE_COUNTERS 1
+
+/* Define this macro if the code for function profiling should come
+ before the function prologue. Normally, the profiling code comes
+ after. */
+
+/* #define PROFILE_BEFORE_PROLOGUE */
+
+/* EXIT_IGNORE_STACK should be nonzero if, when returning from a function,
+ the stack pointer does not matter. The value is tested only in
+ functions that have frame pointers.
+ No definition is equivalent to always zero. */
+
+#define EXIT_IGNORE_STACK 1
+
+
+/* A C statement to output, on the stream FILE, assembler code for a
+ block of data that contains the constant parts of a trampoline.
+ This code should not include a label--the label is taken care of
+ automatically. */
+
+#define TRAMPOLINE_TEMPLATE(STREAM) \
+{ \
+ if (ptr_mode == DImode) \
+ fprintf (STREAM, "\t.word\t0x03e0082d\t\t# dmove $1,$31\n"); \
+ else \
+ fprintf (STREAM, "\t.word\t0x03e00821\t\t# move $1,$31\n"); \
+ fprintf (STREAM, "\t.word\t0x04110001\t\t# bgezal $0,.+8\n"); \
+ fprintf (STREAM, "\t.word\t0x00000000\t\t# nop\n"); \
+ if (ptr_mode == DImode) \
+ { \
+ fprintf (STREAM, "\t.word\t0xdfe30014\t\t# ld $3,20($31)\n"); \
+ fprintf (STREAM, "\t.word\t0xdfe2001c\t\t# ld $2,28($31)\n"); \
+ fprintf (STREAM, "\t.word\t0x0060c82d\t\t# dmove $25,$3\n"); \
+ } \
+ else \
+ { \
+ fprintf (STREAM, "\t.word\t0x8fe30014\t\t# lw $3,20($31)\n"); \
+ fprintf (STREAM, "\t.word\t0x8fe20018\t\t# lw $2,24($31)\n"); \
+ fprintf (STREAM, "\t.word\t0x0060c821\t\t# move $25,$3\n"); \
+ } \
+ fprintf (STREAM, "\t.word\t0x00600008\t\t# jr $3\n"); \
+ if (ptr_mode == DImode) \
+ { \
+ fprintf (STREAM, "\t.word\t0x0020f82d\t\t# dmove $31,$1\n"); \
+ fprintf (STREAM, "\t.dword\t0x00000000\t\t# <function address>\n"); \
+ fprintf (STREAM, "\t.dword\t0x00000000\t\t# <static chain value>\n"); \
+ } \
+ else \
+ { \
+ fprintf (STREAM, "\t.word\t0x0020f821\t\t# move $31,$1\n"); \
+ fprintf (STREAM, "\t.word\t0x00000000\t\t# <function address>\n"); \
+ fprintf (STREAM, "\t.word\t0x00000000\t\t# <static chain value>\n"); \
+ } \
+}
+
+/* A C expression for the size in bytes of the trampoline, as an
+ integer. */
+
+#define TRAMPOLINE_SIZE (32 + GET_MODE_SIZE (ptr_mode) * 2)
+
+/* Alignment required for trampolines, in bits. */
+
+#define TRAMPOLINE_ALIGNMENT GET_MODE_BITSIZE (ptr_mode)
+
+/* INITIALIZE_TRAMPOLINE calls this library function to flush
+ program and data caches. */
+
+#ifndef CACHE_FLUSH_FUNC
+#define CACHE_FLUSH_FUNC "_flush_cache"
+#endif
+
+/* A C statement to initialize the variable parts of a trampoline.
+ ADDR is an RTX for the address of the trampoline; FNADDR is an
+ RTX for the address of the nested function; STATIC_CHAIN is an
+ RTX for the static chain value that should be passed to the
+ function when it is called. */
+
+#define INITIALIZE_TRAMPOLINE(ADDR, FUNC, CHAIN) \
+{ \
+ rtx func_addr, chain_addr; \
+ \
+ func_addr = plus_constant (ADDR, 32); \
+ chain_addr = plus_constant (func_addr, GET_MODE_SIZE (ptr_mode)); \
+ emit_move_insn (gen_rtx_MEM (ptr_mode, func_addr), FUNC); \
+ emit_move_insn (gen_rtx_MEM (ptr_mode, chain_addr), CHAIN); \
+ \
+ /* Flush both caches. We need to flush the data cache in case \
+ the system has a write-back cache. */ \
+ /* ??? Should check the return value for errors. */ \
+ if (mips_cache_flush_func && mips_cache_flush_func[0]) \
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mips_cache_flush_func), \
+ 0, VOIDmode, 3, ADDR, Pmode, \
+ GEN_INT (TRAMPOLINE_SIZE), TYPE_MODE (integer_type_node),\
+ GEN_INT (3), TYPE_MODE (integer_type_node)); \
+}
+
+/* Addressing modes, and classification of registers for them. */
+
+#define REGNO_OK_FOR_INDEX_P(REGNO) 0
+#define REGNO_MODE_OK_FOR_BASE_P(REGNO, MODE) \
+ mips_regno_mode_ok_for_base_p (REGNO, MODE, 1)
+
+/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
+ and check its validity for a certain class.
+ We have two alternate definitions for each of them.
+ The usual definition accepts all pseudo regs; the other rejects them all.
+ The symbol REG_OK_STRICT causes the latter definition to be used.
+
+ Most source files want to accept pseudo regs in the hope that
+ they will get allocated to the class that the insn wants them to be in.
+ Some source files that are used after register allocation
+ need to be strict. */
+
+#ifndef REG_OK_STRICT
+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
+ mips_regno_mode_ok_for_base_p (REGNO (X), MODE, 0)
+#else
+#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
+ mips_regno_mode_ok_for_base_p (REGNO (X), MODE, 1)
+#endif
+
+#define REG_OK_FOR_INDEX_P(X) 0
+
+
+/* Maximum number of registers that can appear in a valid memory address. */
+
+#define MAX_REGS_PER_ADDRESS 1
+
+#ifdef REG_OK_STRICT
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (mips_legitimate_address_p (MODE, X, 1)) \
+ goto ADDR; \
+}
+#else
+#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
+{ \
+ if (mips_legitimate_address_p (MODE, X, 0)) \
+ goto ADDR; \
+}
+#endif
+
+/* Check for constness inline but use mips_legitimate_address_p
+ to check whether a constant really is an address. */
+
+#define CONSTANT_ADDRESS_P(X) \
+ (CONSTANT_P (X) && mips_legitimate_address_p (SImode, X, 0))
+
+#define LEGITIMATE_CONSTANT_P(X) (mips_const_insns (X) > 0)
+
+#define LEGITIMIZE_ADDRESS(X,OLDX,MODE,WIN) \
+ do { \
+ if (mips_legitimize_address (&(X), MODE)) \
+ goto WIN; \
+ } while (0)
+
+
+/* A C statement or compound statement with a conditional `goto
+ LABEL;' executed if memory address X (an RTX) can have different
+ meanings depending on the machine mode of the memory reference it
+ is used for.
+
+ Autoincrement and autodecrement addresses typically have
+ mode-dependent effects because the amount of the increment or
+ decrement is the size of the operand being addressed. Some
+ machines have other mode-dependent addresses. Many RISC machines
+ have no mode-dependent addresses.
+
+ You may assume that ADDR is a valid address for the machine. */
+
+#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR,LABEL) {}
+
+/* This handles the magic '..CURRENT_FUNCTION' symbol, which means
+ 'the start of the function that this code is output in'. */
+
+#define ASM_OUTPUT_LABELREF(FILE,NAME) \
+ if (strcmp (NAME, "..CURRENT_FUNCTION") == 0) \
+ asm_fprintf ((FILE), "%U%s", \
+ XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0)); \
+ else \
+ asm_fprintf ((FILE), "%U%s", (NAME))
+
+/* Flag to mark a function decl symbol that requires a long call. */
+#define SYMBOL_FLAG_LONG_CALL (SYMBOL_FLAG_MACH_DEP << 0)
+#define SYMBOL_REF_LONG_CALL_P(X) \
+ ((SYMBOL_REF_FLAGS (X) & SYMBOL_FLAG_LONG_CALL) != 0)
+
+/* Specify the machine mode that this machine uses
+ for the index in the tablejump instruction.
+ ??? Using HImode in mips16 mode can cause overflow. */
+#define CASE_VECTOR_MODE \
+ (TARGET_MIPS16 ? HImode : ptr_mode)
+
+/* Define as C expression which evaluates to nonzero if the tablejump
+ instruction expects the table to contain offsets from the address of the
+ table.
+ Do not define this if the table should contain absolute addresses. */
+#define CASE_VECTOR_PC_RELATIVE (TARGET_MIPS16)
+
+/* Define this as 1 if `char' should by default be signed; else as 0. */
+#ifndef DEFAULT_SIGNED_CHAR
+#define DEFAULT_SIGNED_CHAR 1
+#endif
+
+/* Max number of bytes we can move from memory to memory
+ in one reasonably fast instruction. */
+#define MOVE_MAX (TARGET_64BIT ? 8 : 4)
+#define MAX_MOVE_MAX 8
+
+/* Define this macro as a C expression which is nonzero if
+ accessing less than a word of memory (i.e. a `char' or a
+ `short') is no faster than accessing a word of memory, i.e., if
+ such access require more than one instruction or if there is no
+ difference in cost between byte and (aligned) word loads.
+
+ On RISC machines, it tends to generate better code to define
+ this as 1, since it avoids making a QI or HI mode register. */
+#define SLOW_BYTE_ACCESS 1
+
+/* Define this to be nonzero if shift instructions ignore all but the low-order
+ few bits. */
+#define SHIFT_COUNT_TRUNCATED 1
+
+/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
+ is done just by pretending it is already truncated. */
+#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) \
+ (TARGET_64BIT ? ((INPREC) <= 32 || (OUTPREC) > 32) : 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. */
+
+#ifndef Pmode
+#define Pmode (TARGET_64BIT && TARGET_LONG64 ? DImode : SImode)
+#endif
+
+/* Give call MEMs SImode since it is the "most permissive" mode
+ for both 32-bit and 64-bit targets. */
+
+#define FUNCTION_MODE SImode
+
+
+/* The cost of loading values from the constant pool. It should be
+ larger than the cost of any constant we want to synthesize in-line. */
+
+#define CONSTANT_POOL_COST COSTS_N_INSNS (8)
+
+/* A C expression for the cost of moving data from a register in
+ class FROM to one in class TO. The classes are expressed using
+ the enumeration values such as `GENERAL_REGS'. A value of 2 is
+ the default; other values are interpreted relative to that.
+
+ It is not required that the cost always equal 2 when FROM is the
+ same as TO; on some machines it is expensive to move between
+ registers if they are not general registers.
+
+ If reload sees an insn consisting of a single `set' between two
+ hard registers, and if `REGISTER_MOVE_COST' applied to their
+ classes returns a value of 2, reload does not check to ensure
+ that the constraints of the insn are met. Setting a cost of
+ other than 2 will allow reload to verify that the constraints are
+ met. You should do this if the `movM' pattern's constraints do
+ not allow such copying. */
+
+#define REGISTER_MOVE_COST(MODE, FROM, TO) \
+ mips_register_move_cost (MODE, FROM, TO)
+
+#define MEMORY_MOVE_COST(MODE,CLASS,TO_P) \
+ (mips_cost->memory_latency \
+ + memory_move_secondary_cost ((MODE), (CLASS), (TO_P)))
+
+/* Define if copies to/from condition code registers should be avoided.
+
+ This is needed for the MIPS because reload_outcc is not complete;
+ it needs to handle cases where the source is a general or another
+ condition code register. */
+#define AVOID_CCMODE_COPIES
+
+/* 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 mips_cost->branch_cost
+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
+
+/* If defined, modifies the length assigned to instruction INSN as a
+ function of the context in which it is used. LENGTH is an lvalue
+ that contains the initially computed length of the insn and should
+ be updated with the correct length of the insn. */
+#define ADJUST_INSN_LENGTH(INSN, LENGTH) \
+ ((LENGTH) = mips_adjust_insn_length ((INSN), (LENGTH)))
+
+/* Return the asm template for a non-MIPS16 conditional branch instruction.
+ OPCODE is the opcode's mnemonic and OPERANDS is the asm template for
+ its operands. */
+#define MIPS_BRANCH(OPCODE, OPERANDS) \
+ "%*" OPCODE "%?\t" OPERANDS "%/"
+
+/* Return the asm template for a call. INSN is the instruction's mnemonic
+ ("j" or "jal"), OPERANDS are its operands, and OPNO is the operand number
+ of the target.
+
+ When generating -mabicalls without explicit relocation operators,
+ all calls should use assembly macros. Otherwise, all indirect
+ calls should use "jr" or "jalr"; we will arrange to restore $gp
+ afterwards if necessary. Finally, we can only generate direct
+ calls for -mabicalls by temporarily switching to non-PIC mode. */
+#define MIPS_CALL(INSN, OPERANDS, OPNO) \
+ (TARGET_ABICALLS && !TARGET_EXPLICIT_RELOCS \
+ ? "%*" INSN "\t%" #OPNO "%/" \
+ : REG_P (OPERANDS[OPNO]) \
+ ? "%*" INSN "r\t%" #OPNO "%/" \
+ : TARGET_ABICALLS \
+ ? (".option\tpic0\n\t" \
+ "%*" INSN "\t%" #OPNO "%/\n\t" \
+ ".option\tpic2") \
+ : "%*" INSN "\t%" #OPNO "%/")
+
+/* Control the assembler format that we output. */
+
+/* Output to assembler file text saying following lines
+ may contain character constants, extra white space, comments, etc. */
+
+#ifndef ASM_APP_ON
+#define ASM_APP_ON " #APP\n"
+#endif
+
+/* Output to assembler file text saying following lines
+ no longer contain unusual constructs. */
+
+#ifndef ASM_APP_OFF
+#define ASM_APP_OFF " #NO_APP\n"
+#endif
+
+#define REGISTER_NAMES \
+{ "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", \
+ "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15", \
+ "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23", \
+ "$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31", \
+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", \
+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23", \
+ "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31", \
+ "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4", \
+ "$fcc5","$fcc6","$fcc7","", "", "$arg", "$frame", "$fakec", \
+ "$c0r0", "$c0r1", "$c0r2", "$c0r3", "$c0r4", "$c0r5", "$c0r6", "$c0r7", \
+ "$c0r8", "$c0r9", "$c0r10","$c0r11","$c0r12","$c0r13","$c0r14","$c0r15", \
+ "$c0r16","$c0r17","$c0r18","$c0r19","$c0r20","$c0r21","$c0r22","$c0r23", \
+ "$c0r24","$c0r25","$c0r26","$c0r27","$c0r28","$c0r29","$c0r30","$c0r31", \
+ "$c2r0", "$c2r1", "$c2r2", "$c2r3", "$c2r4", "$c2r5", "$c2r6", "$c2r7", \
+ "$c2r8", "$c2r9", "$c2r10","$c2r11","$c2r12","$c2r13","$c2r14","$c2r15", \
+ "$c2r16","$c2r17","$c2r18","$c2r19","$c2r20","$c2r21","$c2r22","$c2r23", \
+ "$c2r24","$c2r25","$c2r26","$c2r27","$c2r28","$c2r29","$c2r30","$c2r31", \
+ "$c3r0", "$c3r1", "$c3r2", "$c3r3", "$c3r4", "$c3r5", "$c3r6", "$c3r7", \
+ "$c3r8", "$c3r9", "$c3r10","$c3r11","$c3r12","$c3r13","$c3r14","$c3r15", \
+ "$c3r16","$c3r17","$c3r18","$c3r19","$c3r20","$c3r21","$c3r22","$c3r23", \
+ "$c3r24","$c3r25","$c3r26","$c3r27","$c3r28","$c3r29","$c3r30","$c3r31", \
+ "$ac1hi","$ac1lo","$ac2hi","$ac2lo","$ac3hi","$ac3lo","$dsp_po","$dsp_sc", \
+ "$dsp_ca","$dsp_ou","$dsp_cc","$dsp_ef" }
+
+/* List the "software" names for each register. Also list the numerical
+ names for $fp and $sp. */
+
+#define ADDITIONAL_REGISTER_NAMES \
+{ \
+ { "$29", 29 + GP_REG_FIRST }, \
+ { "$30", 30 + GP_REG_FIRST }, \
+ { "at", 1 + GP_REG_FIRST }, \
+ { "v0", 2 + GP_REG_FIRST }, \
+ { "v1", 3 + GP_REG_FIRST }, \
+ { "a0", 4 + GP_REG_FIRST }, \
+ { "a1", 5 + GP_REG_FIRST }, \
+ { "a2", 6 + GP_REG_FIRST }, \
+ { "a3", 7 + GP_REG_FIRST }, \
+ { "t0", 8 + GP_REG_FIRST }, \
+ { "t1", 9 + GP_REG_FIRST }, \
+ { "t2", 10 + GP_REG_FIRST }, \
+ { "t3", 11 + GP_REG_FIRST }, \
+ { "t4", 12 + GP_REG_FIRST }, \
+ { "t5", 13 + GP_REG_FIRST }, \
+ { "t6", 14 + GP_REG_FIRST }, \
+ { "t7", 15 + GP_REG_FIRST }, \
+ { "s0", 16 + GP_REG_FIRST }, \
+ { "s1", 17 + GP_REG_FIRST }, \
+ { "s2", 18 + GP_REG_FIRST }, \
+ { "s3", 19 + GP_REG_FIRST }, \
+ { "s4", 20 + GP_REG_FIRST }, \
+ { "s5", 21 + GP_REG_FIRST }, \
+ { "s6", 22 + GP_REG_FIRST }, \
+ { "s7", 23 + GP_REG_FIRST }, \
+ { "t8", 24 + GP_REG_FIRST }, \
+ { "t9", 25 + GP_REG_FIRST }, \
+ { "k0", 26 + GP_REG_FIRST }, \
+ { "k1", 27 + GP_REG_FIRST }, \
+ { "gp", 28 + GP_REG_FIRST }, \
+ { "sp", 29 + GP_REG_FIRST }, \
+ { "fp", 30 + GP_REG_FIRST }, \
+ { "ra", 31 + GP_REG_FIRST }, \
+ ALL_COP_ADDITIONAL_REGISTER_NAMES \
+}
+
+/* This is meant to be redefined in the host dependent files. It is a
+ set of alternative names and regnums for mips coprocessors. */
+
+#define ALL_COP_ADDITIONAL_REGISTER_NAMES
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand X. X is an RTL
+ expression.
+
+ CODE is a value that can be used to specify one of several ways
+ of printing the operand. It is used when identical operands
+ must be printed differently depending on the context. CODE
+ comes from the `%' specification that was used to request
+ printing of the operand. If the specification was just `%DIGIT'
+ then CODE is 0; if the specification was `%LTR DIGIT' then CODE
+ is the ASCII code for LTR.
+
+ If X is a register, this macro should print the register's name.
+ The names can be found in an array `reg_names' whose type is
+ `char *[]'. `reg_names' is initialized from `REGISTER_NAMES'.
+
+ When the machine description has a specification `%PUNCT' (a `%'
+ followed by a punctuation character), this macro is called with
+ a null pointer for X and the punctuation character for CODE.
+
+ See mips.c for the MIPS specific codes. */
+
+#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
+
+/* A C expression which evaluates to true if CODE is a valid
+ punctuation character for use in the `PRINT_OPERAND' macro. If
+ `PRINT_OPERAND_PUNCT_VALID_P' is not defined, it means that no
+ punctuation characters (except for the standard one, `%') are
+ used in this way. */
+
+#define PRINT_OPERAND_PUNCT_VALID_P(CODE) mips_print_operand_punct[CODE]
+
+/* A C compound statement to output to stdio stream STREAM the
+ assembler syntax for an instruction operand that is a memory
+ reference whose address is ADDR. ADDR is an RTL expression. */
+
+#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+
+
+/* A C statement, to be executed after all slot-filler instructions
+ have been output. If necessary, call `dbr_sequence_length' to
+ determine the number of slots filled in a sequence (zero if not
+ currently outputting a sequence), to decide how many no-ops to
+ output, or whatever.
+
+ Don't define this macro if it has nothing to do, but it is
+ helpful in reading assembly output if the extent of the delay
+ sequence is made explicit (e.g. with white space).
+
+ Note that output routines for instructions with delay slots must
+ be prepared to deal with not being output as part of a sequence
+ (i.e. when the scheduling pass is not run, or when no slot
+ fillers could be found.) The variable `final_sequence' is null
+ when not processing a sequence, otherwise it contains the
+ `sequence' rtx being output. */
+
+#define DBR_OUTPUT_SEQEND(STREAM) \
+do \
+ { \
+ if (set_nomacro > 0 && --set_nomacro == 0) \
+ fputs ("\t.set\tmacro\n", STREAM); \
+ \
+ if (set_noreorder > 0 && --set_noreorder == 0) \
+ fputs ("\t.set\treorder\n", STREAM); \
+ \
+ fputs ("\n", STREAM); \
+ } \
+while (0)
+
+
+/* How to tell the debugger about changes of source files. */
+#define ASM_OUTPUT_SOURCE_FILENAME(STREAM, NAME) \
+ mips_output_filename (STREAM, NAME)
+
+/* mips-tfile does not understand .stabd directives. */
+#define DBX_OUTPUT_SOURCE_LINE(STREAM, LINE, COUNTER) do { \
+ dbxout_begin_stabn_sline (LINE); \
+ dbxout_stab_value_internal_label ("LM", &COUNTER); \
+} while (0)
+
+/* Use .loc directives for SDB line numbers. */
+#define SDB_OUTPUT_SOURCE_LINE(STREAM, LINE) \
+ fprintf (STREAM, "\t.loc\t%d %d\n", num_source_filenames, LINE)
+
+/* The MIPS implementation uses some labels for its own purpose. The
+ following lists what labels are created, and are all formed by the
+ pattern $L[a-z].*. The machine independent portion of GCC creates
+ labels matching: $L[A-Z][0-9]+ and $L[0-9]+.
+
+ LM[0-9]+ Silicon Graphics/ECOFF stabs label before each stmt.
+ $Lb[0-9]+ Begin blocks for MIPS debug support
+ $Lc[0-9]+ Label for use in s<xx> operation.
+ $Le[0-9]+ End blocks for MIPS debug support */
+
+#undef ASM_DECLARE_OBJECT_NAME
+#define ASM_DECLARE_OBJECT_NAME(STREAM, NAME, DECL) \
+ mips_declare_object (STREAM, NAME, "", ":\n", 0)
+
+/* Globalizing directive for a label. */
+#define GLOBAL_ASM_OP "\t.globl\t"
+
+/* This says how to define a global common symbol. */
+
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON mips_output_aligned_decl_common
+
+/* This says how to define a local common symbol (i.e., not visible to
+ linker). */
+
+#ifndef ASM_OUTPUT_ALIGNED_LOCAL
+#define ASM_OUTPUT_ALIGNED_LOCAL(STREAM, NAME, SIZE, ALIGN) \
+ mips_declare_common_object (STREAM, NAME, "\n\t.lcomm\t", SIZE, ALIGN, false)
+#endif
+
+/* This says how to output an external. It would be possible not to
+ output anything and let undefined symbol become external. However
+ the assembler uses length information on externals to allocate in
+ data/sdata bss/sbss, thereby saving exec time. */
+
+#define ASM_OUTPUT_EXTERNAL(STREAM,DECL,NAME) \
+ mips_output_external(STREAM,DECL,NAME)
+
+/* This is how to declare a function name. The actual work of
+ emitting the label is moved to function_prologue, so that we can
+ get the line number correctly emitted before the .ent directive,
+ and after any .file directives. Define as empty so that the function
+ is not declared before the .ent directive elsewhere. */
+
+#undef ASM_DECLARE_FUNCTION_NAME
+#define ASM_DECLARE_FUNCTION_NAME(STREAM,NAME,DECL)
+
+#ifndef FUNCTION_NAME_ALREADY_DECLARED
+#define FUNCTION_NAME_ALREADY_DECLARED 0
+#endif
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf ((LABEL), "*%s%s%ld", (LOCAL_LABEL_PREFIX), (PREFIX), (long)(NUM))
+
+/* This is how to output an element of a case-vector that is absolute. */
+
+#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
+ fprintf (STREAM, "\t%s\t%sL%d\n", \
+ ptr_mode == DImode ? ".dword" : ".word", \
+ LOCAL_LABEL_PREFIX, \
+ VALUE)
+
+/* This is how to output an element of a case-vector. We can make the
+ entries PC-relative in MIPS16 code and GP-relative when .gp(d)word
+ is supported. */
+
+#define ASM_OUTPUT_ADDR_DIFF_ELT(STREAM, BODY, VALUE, REL) \
+do { \
+ if (TARGET_MIPS16) \
+ fprintf (STREAM, "\t.half\t%sL%d-%sL%d\n", \
+ LOCAL_LABEL_PREFIX, VALUE, LOCAL_LABEL_PREFIX, REL); \
+ else if (TARGET_GPWORD) \
+ fprintf (STREAM, "\t%s\t%sL%d\n", \
+ ptr_mode == DImode ? ".gpdword" : ".gpword", \
+ LOCAL_LABEL_PREFIX, VALUE); \
+ else \
+ fprintf (STREAM, "\t%s\t%sL%d\n", \
+ ptr_mode == DImode ? ".dword" : ".word", \
+ LOCAL_LABEL_PREFIX, VALUE); \
+} while (0)
+
+/* When generating MIPS16 code, we want the jump table to be in the text
+ section so that we can load its address using a PC-relative addition. */
+#define JUMP_TABLES_IN_TEXT_SECTION TARGET_MIPS16
+
+/* 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(STREAM,LOG) \
+ fprintf (STREAM, "\t.align\t%d\n", (LOG))
+
+/* 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"HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE))
+
+/* This is how to output a string. */
+#undef ASM_OUTPUT_ASCII
+#define ASM_OUTPUT_ASCII(STREAM, STRING, LEN) \
+ mips_output_ascii (STREAM, STRING, LEN, "\t.ascii\t")
+
+/* Output #ident as a in the read-only data section. */
+#undef ASM_OUTPUT_IDENT
+#define ASM_OUTPUT_IDENT(FILE, STRING) \
+{ \
+ const char *p = STRING; \
+ int size = strlen (p) + 1; \
+ switch_to_section (readonly_data_section); \
+ assemble_string (p, size); \
+}
+
+/* Default to -G 8 */
+#ifndef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 8
+#endif
+
+/* Define the strings to put out for each section in the object file. */
+#define TEXT_SECTION_ASM_OP "\t.text" /* instructions */
+#define DATA_SECTION_ASM_OP "\t.data" /* large data */
+
+#undef READONLY_DATA_SECTION_ASM_OP
+#define READONLY_DATA_SECTION_ASM_OP "\t.rdata" /* read-only data */
+
+#define ASM_OUTPUT_REG_PUSH(STREAM,REGNO) \
+do \
+ { \
+ fprintf (STREAM, "\t%s\t%s,%s,8\n\t%s\t%s,0(%s)\n", \
+ TARGET_64BIT ? "dsubu" : "subu", \
+ reg_names[STACK_POINTER_REGNUM], \
+ reg_names[STACK_POINTER_REGNUM], \
+ TARGET_64BIT ? "sd" : "sw", \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM]); \
+ } \
+while (0)
+
+#define ASM_OUTPUT_REG_POP(STREAM,REGNO) \
+do \
+ { \
+ if (! set_noreorder) \
+ fprintf (STREAM, "\t.set\tnoreorder\n"); \
+ \
+ fprintf (STREAM, "\t%s\t%s,0(%s)\n\t%s\t%s,%s,8\n", \
+ TARGET_64BIT ? "ld" : "lw", \
+ reg_names[REGNO], \
+ reg_names[STACK_POINTER_REGNUM], \
+ TARGET_64BIT ? "daddu" : "addu", \
+ reg_names[STACK_POINTER_REGNUM], \
+ reg_names[STACK_POINTER_REGNUM]); \
+ \
+ if (! set_noreorder) \
+ fprintf (STREAM, "\t.set\treorder\n"); \
+ } \
+while (0)
+
+/* How to start an assembler comment.
+ The leading space is important (the mips native assembler requires it). */
+#ifndef ASM_COMMENT_START
+#define ASM_COMMENT_START " #"
+#endif
+
+/* Default definitions for size_t and ptrdiff_t. We must override the
+ definitions from ../svr4.h on mips-*-linux-gnu. */
+
+#undef SIZE_TYPE
+#define SIZE_TYPE (POINTER_SIZE == 64 ? "long unsigned int" : "unsigned int")
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (POINTER_SIZE == 64 ? "long int" : "int")
+
+#ifndef __mips16
+/* Since the bits of the _init and _fini function is spread across
+ many object files, each potentially with its own GP, we must assume
+ we need to load our GP. We don't preserve $gp or $ra, since each
+ init/fini chunk is supposed to initialize $gp, and crti/crtn
+ already take care of preserving $ra and, when appropriate, $gp. */
+#if (defined _ABIO32 && _MIPS_SIM == _ABIO32)
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n\
+ .set noreorder\n\
+ bal 1f\n\
+ nop\n\
+1: .cpload $31\n\
+ .set reorder\n\
+ jal " USER_LABEL_PREFIX #FUNC "\n\
+ " TEXT_SECTION_ASM_OP);
+#endif /* Switch to #elif when we're no longer limited by K&R C. */
+#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
+ || (defined _ABI64 && _MIPS_SIM == _ABI64)
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n\
+ .set noreorder\n\
+ bal 1f\n\
+ nop\n\
+1: .set reorder\n\
+ .cpsetup $31, $2, 1b\n\
+ jal " USER_LABEL_PREFIX #FUNC "\n\
+ " TEXT_SECTION_ASM_OP);
+#endif
+#endif
+
+#ifndef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+#endif
diff --git a/contrib/gcc/config/mips/mips.md b/contrib/gcc/config/mips/mips.md
new file mode 100644
index 0000000..969d22f
--- /dev/null
+++ b/contrib/gcc/config/mips/mips.md
@@ -0,0 +1,5485 @@
+;; Mips.md Machine Description for MIPS based processors
+;; Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; Contributed by A. Lichnewsky, lich@inria.inria.fr
+;; Changes by Michael Meissner, meissner@osf.org
+;; 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and
+;; Brendan Eich, brendan@microunity.com.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_constants
+ [(UNSPEC_LOAD_DF_LOW 0)
+ (UNSPEC_LOAD_DF_HIGH 1)
+ (UNSPEC_STORE_DF_HIGH 2)
+ (UNSPEC_GET_FNADDR 3)
+ (UNSPEC_BLOCKAGE 4)
+ (UNSPEC_CPRESTORE 5)
+ (UNSPEC_EH_RECEIVER 6)
+ (UNSPEC_EH_RETURN 7)
+ (UNSPEC_CONSTTABLE_INT 8)
+ (UNSPEC_CONSTTABLE_FLOAT 9)
+ (UNSPEC_ALIGN 14)
+ (UNSPEC_HIGH 17)
+ (UNSPEC_LOAD_LEFT 18)
+ (UNSPEC_LOAD_RIGHT 19)
+ (UNSPEC_STORE_LEFT 20)
+ (UNSPEC_STORE_RIGHT 21)
+ (UNSPEC_LOADGP 22)
+ (UNSPEC_LOAD_CALL 23)
+ (UNSPEC_LOAD_GOT 24)
+ (UNSPEC_GP 25)
+ (UNSPEC_MFHILO 26)
+ (UNSPEC_TLS_LDM 27)
+ (UNSPEC_TLS_GET_TP 28)
+
+ (UNSPEC_ADDRESS_FIRST 100)
+
+ (FAKE_CALL_REGNO 79)
+
+ ;; For MIPS Paired-Singled Floating Point Instructions.
+
+ (UNSPEC_MOVE_TF_PS 200)
+ (UNSPEC_C 201)
+
+ ;; MIPS64/MIPS32R2 alnv.ps
+ (UNSPEC_ALNV_PS 202)
+
+ ;; MIPS-3D instructions
+ (UNSPEC_CABS 203)
+
+ (UNSPEC_ADDR_PS 204)
+ (UNSPEC_CVT_PW_PS 205)
+ (UNSPEC_CVT_PS_PW 206)
+ (UNSPEC_MULR_PS 207)
+ (UNSPEC_ABS_PS 208)
+
+ (UNSPEC_RSQRT1 209)
+ (UNSPEC_RSQRT2 210)
+ (UNSPEC_RECIP1 211)
+ (UNSPEC_RECIP2 212)
+ (UNSPEC_SINGLE_CC 213)
+ (UNSPEC_SCC 214)
+
+ ;; MIPS DSP ASE Revision 0.98 3/24/2005
+ (UNSPEC_ADDQ 300)
+ (UNSPEC_ADDQ_S 301)
+ (UNSPEC_SUBQ 302)
+ (UNSPEC_SUBQ_S 303)
+ (UNSPEC_ADDSC 304)
+ (UNSPEC_ADDWC 305)
+ (UNSPEC_MODSUB 306)
+ (UNSPEC_RADDU_W_QB 307)
+ (UNSPEC_ABSQ_S 308)
+ (UNSPEC_PRECRQ_QB_PH 309)
+ (UNSPEC_PRECRQ_PH_W 310)
+ (UNSPEC_PRECRQ_RS_PH_W 311)
+ (UNSPEC_PRECRQU_S_QB_PH 312)
+ (UNSPEC_PRECEQ_W_PHL 313)
+ (UNSPEC_PRECEQ_W_PHR 314)
+ (UNSPEC_PRECEQU_PH_QBL 315)
+ (UNSPEC_PRECEQU_PH_QBR 316)
+ (UNSPEC_PRECEQU_PH_QBLA 317)
+ (UNSPEC_PRECEQU_PH_QBRA 318)
+ (UNSPEC_PRECEU_PH_QBL 319)
+ (UNSPEC_PRECEU_PH_QBR 320)
+ (UNSPEC_PRECEU_PH_QBLA 321)
+ (UNSPEC_PRECEU_PH_QBRA 322)
+ (UNSPEC_SHLL 323)
+ (UNSPEC_SHLL_S 324)
+ (UNSPEC_SHRL_QB 325)
+ (UNSPEC_SHRA_PH 326)
+ (UNSPEC_SHRA_R 327)
+ (UNSPEC_MULEU_S_PH_QBL 328)
+ (UNSPEC_MULEU_S_PH_QBR 329)
+ (UNSPEC_MULQ_RS_PH 330)
+ (UNSPEC_MULEQ_S_W_PHL 331)
+ (UNSPEC_MULEQ_S_W_PHR 332)
+ (UNSPEC_DPAU_H_QBL 333)
+ (UNSPEC_DPAU_H_QBR 334)
+ (UNSPEC_DPSU_H_QBL 335)
+ (UNSPEC_DPSU_H_QBR 336)
+ (UNSPEC_DPAQ_S_W_PH 337)
+ (UNSPEC_DPSQ_S_W_PH 338)
+ (UNSPEC_MULSAQ_S_W_PH 339)
+ (UNSPEC_DPAQ_SA_L_W 340)
+ (UNSPEC_DPSQ_SA_L_W 341)
+ (UNSPEC_MAQ_S_W_PHL 342)
+ (UNSPEC_MAQ_S_W_PHR 343)
+ (UNSPEC_MAQ_SA_W_PHL 344)
+ (UNSPEC_MAQ_SA_W_PHR 345)
+ (UNSPEC_BITREV 346)
+ (UNSPEC_INSV 347)
+ (UNSPEC_REPL_QB 348)
+ (UNSPEC_REPL_PH 349)
+ (UNSPEC_CMP_EQ 350)
+ (UNSPEC_CMP_LT 351)
+ (UNSPEC_CMP_LE 352)
+ (UNSPEC_CMPGU_EQ_QB 353)
+ (UNSPEC_CMPGU_LT_QB 354)
+ (UNSPEC_CMPGU_LE_QB 355)
+ (UNSPEC_PICK 356)
+ (UNSPEC_PACKRL_PH 357)
+ (UNSPEC_EXTR_W 358)
+ (UNSPEC_EXTR_R_W 359)
+ (UNSPEC_EXTR_RS_W 360)
+ (UNSPEC_EXTR_S_H 361)
+ (UNSPEC_EXTP 362)
+ (UNSPEC_EXTPDP 363)
+ (UNSPEC_SHILO 364)
+ (UNSPEC_MTHLIP 365)
+ (UNSPEC_WRDSP 366)
+ (UNSPEC_RDDSP 367)
+ ]
+)
+
+(include "predicates.md")
+(include "constraints.md")
+
+;; ....................
+;;
+;; Attributes
+;;
+;; ....................
+
+(define_attr "got" "unset,xgot_high,load"
+ (const_string "unset"))
+
+;; For jal instructions, this attribute is DIRECT when the target address
+;; is symbolic and INDIRECT when it is a register.
+(define_attr "jal" "unset,direct,indirect"
+ (const_string "unset"))
+
+;; This attribute is YES if the instruction is a jal macro (not a
+;; real jal instruction).
+;;
+;; jal is always a macro for o32 and o64 abicalls because it includes an
+;; instruction to restore $gp. Direct jals are also macros for -mshared
+;; abicalls because they first load the target address into $25.
+(define_attr "jal_macro" "no,yes"
+ (cond [(eq_attr "jal" "direct")
+ (symbol_ref "TARGET_ABICALLS
+ && (TARGET_OLDABI || !TARGET_ABSOLUTE_ABICALLS)")
+ (eq_attr "jal" "indirect")
+ (symbol_ref "TARGET_ABICALLS && TARGET_OLDABI")]
+ (const_string "no")))
+
+;; Classification of each insn.
+;; branch conditional branch
+;; jump unconditional jump
+;; call unconditional call
+;; load load instruction(s)
+;; fpload floating point load
+;; fpidxload floating point indexed load
+;; store store instruction(s)
+;; fpstore floating point store
+;; fpidxstore floating point indexed store
+;; prefetch memory prefetch (register + offset)
+;; prefetchx memory indexed prefetch (register + register)
+;; condmove conditional moves
+;; xfer transfer to/from coprocessor
+;; mthilo transfer to hi/lo registers
+;; mfhilo transfer from hi/lo registers
+;; const load constant
+;; arith integer arithmetic and logical instructions
+;; shift integer shift instructions
+;; slt set less than instructions
+;; clz the clz and clo instructions
+;; trap trap if instructions
+;; imul integer multiply 2 operands
+;; imul3 integer multiply 3 operands
+;; imadd integer multiply-add
+;; idiv integer divide
+;; fmove floating point register move
+;; fadd floating point add/subtract
+;; fmul floating point multiply
+;; fmadd floating point multiply-add
+;; fdiv floating point divide
+;; frdiv floating point reciprocal divide
+;; frdiv1 floating point reciprocal divide step 1
+;; frdiv2 floating point reciprocal divide step 2
+;; fabs floating point absolute value
+;; fneg floating point negation
+;; fcmp floating point compare
+;; fcvt floating point convert
+;; fsqrt floating point square root
+;; frsqrt floating point reciprocal square root
+;; frsqrt1 floating point reciprocal square root step1
+;; frsqrt2 floating point reciprocal square root step2
+;; multi multiword sequence (or user asm statements)
+;; nop no operation
+(define_attr "type"
+ "unknown,branch,jump,call,load,fpload,fpidxload,store,fpstore,fpidxstore,prefetch,prefetchx,condmove,xfer,mthilo,mfhilo,const,arith,shift,slt,clz,trap,imul,imul3,imadd,idiv,fmove,fadd,fmul,fmadd,fdiv,frdiv,frdiv1,frdiv2,fabs,fneg,fcmp,fcvt,fsqrt,frsqrt,frsqrt1,frsqrt2,multi,nop"
+ (cond [(eq_attr "jal" "!unset") (const_string "call")
+ (eq_attr "got" "load") (const_string "load")]
+ (const_string "unknown")))
+
+;; Main data type used by the insn
+(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW"
+ (const_string "unknown"))
+
+;; Mode for conversion types (fcvt)
+;; I2S integer to float single (SI/DI to SF)
+;; I2D integer to float double (SI/DI to DF)
+;; S2I float to integer (SF to SI/DI)
+;; D2I float to integer (DF to SI/DI)
+;; D2S double to float single
+;; S2D float single to double
+
+(define_attr "cnv_mode" "unknown,I2S,I2D,S2I,D2I,D2S,S2D"
+ (const_string "unknown"))
+
+;; Is this an extended instruction in mips16 mode?
+(define_attr "extended_mips16" "no,yes"
+ (const_string "no"))
+
+;; Length of instruction in bytes.
+(define_attr "length" ""
+ (cond [;; Direct branch instructions have a range of [-0x40000,0x3fffc].
+ ;; If a branch is outside this range, we have a choice of two
+ ;; sequences. For PIC, an out-of-range branch like:
+ ;;
+ ;; bne r1,r2,target
+ ;; dslot
+ ;;
+ ;; becomes the equivalent of:
+ ;;
+ ;; beq r1,r2,1f
+ ;; dslot
+ ;; la $at,target
+ ;; jr $at
+ ;; nop
+ ;; 1:
+ ;;
+ ;; where the load address can be up to three instructions long
+ ;; (lw, nop, addiu).
+ ;;
+ ;; The non-PIC case is similar except that we use a direct
+ ;; jump instead of an la/jr pair. Since the target of this
+ ;; jump is an absolute 28-bit bit address (the other bits
+ ;; coming from the address of the delay slot) this form cannot
+ ;; cross a 256MB boundary. We could provide the option of
+ ;; using la/jr in this case too, but we do not do so at
+ ;; present.
+ ;;
+ ;; Note that this value does not account for the delay slot
+ ;; instruction, whose length is added separately. If the RTL
+ ;; pattern has no explicit delay slot, mips_adjust_insn_length
+ ;; will add the length of the implicit nop. The values for
+ ;; forward and backward branches will be different as well.
+ (eq_attr "type" "branch")
+ (cond [(and (le (minus (match_dup 1) (pc)) (const_int 131064))
+ (le (minus (pc) (match_dup 1)) (const_int 131068)))
+ (const_int 4)
+ (ne (symbol_ref "flag_pic") (const_int 0))
+ (const_int 24)
+ ] (const_int 12))
+
+ (eq_attr "got" "load")
+ (const_int 4)
+ (eq_attr "got" "xgot_high")
+ (const_int 8)
+
+ (eq_attr "type" "const")
+ (symbol_ref "mips_const_insns (operands[1]) * 4")
+ (eq_attr "type" "load,fpload")
+ (symbol_ref "mips_fetch_insns (operands[1]) * 4")
+ (eq_attr "type" "store,fpstore")
+ (symbol_ref "mips_fetch_insns (operands[0]) * 4")
+
+ ;; In the worst case, a call macro will take 8 instructions:
+ ;;
+ ;; lui $25,%call_hi(FOO)
+ ;; addu $25,$25,$28
+ ;; lw $25,%call_lo(FOO)($25)
+ ;; nop
+ ;; jalr $25
+ ;; nop
+ ;; lw $gp,X($sp)
+ ;; nop
+ (eq_attr "jal_macro" "yes")
+ (const_int 32)
+
+ (and (eq_attr "extended_mips16" "yes")
+ (ne (symbol_ref "TARGET_MIPS16") (const_int 0)))
+ (const_int 8)
+
+ ;; Various VR4120 errata require a nop to be inserted after a macc
+ ;; instruction. The assembler does this for us, so account for
+ ;; the worst-case length here.
+ (and (eq_attr "type" "imadd")
+ (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0)))
+ (const_int 8)
+
+ ;; VR4120 errata MD(4): if there are consecutive dmult instructions,
+ ;; the result of the second one is missed. The assembler should work
+ ;; around this by inserting a nop after the first dmult.
+ (and (eq_attr "type" "imul,imul3")
+ (and (eq_attr "mode" "DI")
+ (ne (symbol_ref "TARGET_FIX_VR4120") (const_int 0))))
+ (const_int 8)
+
+ (eq_attr "type" "idiv")
+ (symbol_ref "mips_idiv_insns () * 4")
+ ] (const_int 4)))
+
+;; Attribute describing the processor. This attribute must match exactly
+;; with the processor_type enumeration in mips.h.
+(define_attr "cpu"
+ "r3000,4kc,4kp,5kc,5kf,20kc,24k,24kx,m4k,r3900,r6000,r4000,r4100,r4111,r4120,r4130,r4300,r4600,r4650,r5000,r5400,r5500,r7000,r8000,r9000,sb1,sb1a,sr71000"
+ (const (symbol_ref "mips_tune")))
+
+;; The type of hardware hazard associated with this instruction.
+;; DELAY means that the next instruction cannot read the result
+;; of this one. HILO means that the next two instructions cannot
+;; write to HI or LO.
+(define_attr "hazard" "none,delay,hilo"
+ (cond [(and (eq_attr "type" "load,fpload,fpidxload")
+ (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0)))
+ (const_string "delay")
+
+ (and (eq_attr "type" "xfer")
+ (ne (symbol_ref "ISA_HAS_XFER_DELAY") (const_int 0)))
+ (const_string "delay")
+
+ (and (eq_attr "type" "fcmp")
+ (ne (symbol_ref "ISA_HAS_FCMP_DELAY") (const_int 0)))
+ (const_string "delay")
+
+ ;; The r4000 multiplication patterns include an mflo instruction.
+ (and (eq_attr "type" "imul")
+ (ne (symbol_ref "TARGET_FIX_R4000") (const_int 0)))
+ (const_string "hilo")
+
+ (and (eq_attr "type" "mfhilo")
+ (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0)))
+ (const_string "hilo")]
+ (const_string "none")))
+
+;; Is it a single instruction?
+(define_attr "single_insn" "no,yes"
+ (symbol_ref "get_attr_length (insn) == (TARGET_MIPS16 ? 2 : 4)"))
+
+;; Can the instruction be put into a delay slot?
+(define_attr "can_delay" "no,yes"
+ (if_then_else (and (eq_attr "type" "!branch,call,jump")
+ (and (eq_attr "hazard" "none")
+ (eq_attr "single_insn" "yes")))
+ (const_string "yes")
+ (const_string "no")))
+
+;; Attribute defining whether or not we can use the branch-likely instructions
+(define_attr "branch_likely" "no,yes"
+ (const
+ (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
+ (const_string "yes")
+ (const_string "no"))))
+
+;; True if an instruction might assign to hi or lo when reloaded.
+;; This is used by the TUNE_MACC_CHAINS code.
+(define_attr "may_clobber_hilo" "no,yes"
+ (if_then_else (eq_attr "type" "imul,imul3,imadd,idiv,mthilo")
+ (const_string "yes")
+ (const_string "no")))
+
+;; Describe a user's asm statement.
+(define_asm_attributes
+ [(set_attr "type" "multi")
+ (set_attr "can_delay" "no")])
+
+;; This mode macro allows 32-bit and 64-bit GPR patterns to be generated
+;; from the same template.
+(define_mode_macro GPR [SI (DI "TARGET_64BIT")])
+
+;; This mode macro allows :P to be used for patterns that operate on
+;; pointer-sized quantities. Exactly one of the two alternatives will match.
+(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
+
+;; This mode macro allows :MOVECC to be used anywhere that a
+;; conditional-move-type condition is needed.
+(define_mode_macro MOVECC [SI (DI "TARGET_64BIT") (CC "TARGET_HARD_FLOAT")])
+
+;; This mode macro allows the QI and HI extension patterns to be defined from
+;; the same template.
+(define_mode_macro SHORT [QI HI])
+
+;; This mode macro allows :ANYF to be used wherever a scalar or vector
+;; floating-point mode is allowed.
+(define_mode_macro ANYF [(SF "TARGET_HARD_FLOAT")
+ (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")
+ (V2SF "TARGET_PAIRED_SINGLE_FLOAT")])
+
+;; Like ANYF, but only applies to scalar modes.
+(define_mode_macro SCALARF [(SF "TARGET_HARD_FLOAT")
+ (DF "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT")])
+
+;; In GPR templates, a string like "<d>subu" will expand to "subu" in the
+;; 32-bit version and "dsubu" in the 64-bit version.
+(define_mode_attr d [(SI "") (DI "d")])
+
+;; This attribute gives the length suffix for a sign- or zero-extension
+;; instruction.
+(define_mode_attr size [(QI "b") (HI "h")])
+
+;; This attributes gives the mode mask of a SHORT.
+(define_mode_attr mask [(QI "0x00ff") (HI "0xffff")])
+
+;; Mode attributes for GPR loads and stores.
+(define_mode_attr load [(SI "lw") (DI "ld")])
+(define_mode_attr store [(SI "sw") (DI "sd")])
+
+;; Similarly for MIPS IV indexed FPR loads and stores.
+(define_mode_attr loadx [(SF "lwxc1") (DF "ldxc1") (V2SF "ldxc1")])
+(define_mode_attr storex [(SF "swxc1") (DF "sdxc1") (V2SF "sdxc1")])
+
+;; The unextended ranges of the MIPS16 addiu and daddiu instructions
+;; are different. Some forms of unextended addiu have an 8-bit immediate
+;; field but the equivalent daddiu has only a 5-bit field.
+(define_mode_attr si8_di5 [(SI "8") (DI "5")])
+
+;; This attribute gives the best constraint to use for registers of
+;; a given mode.
+(define_mode_attr reg [(SI "d") (DI "d") (CC "z")])
+
+;; This attribute gives the format suffix for floating-point operations.
+(define_mode_attr fmt [(SF "s") (DF "d") (V2SF "ps")])
+
+;; This attribute gives the upper-case mode name for one unit of a
+;; floating-point mode.
+(define_mode_attr UNITMODE [(SF "SF") (DF "DF") (V2SF "SF")])
+
+;; This attribute works around the early SB-1 rev2 core "F2" erratum:
+;;
+;; In certain cases, div.s and div.ps may have a rounding error
+;; and/or wrong inexact flag.
+;;
+;; Therefore, we only allow div.s if not working around SB-1 rev2
+;; errata or if a slight loss of precision is OK.
+(define_mode_attr divide_condition
+ [DF (SF "!TARGET_FIX_SB1 || flag_unsafe_math_optimizations")
+ (V2SF "TARGET_SB1 && (!TARGET_FIX_SB1 || flag_unsafe_math_optimizations)")])
+
+; This attribute gives the condition for which sqrt instructions exist.
+(define_mode_attr sqrt_condition
+ [(SF "!ISA_MIPS1") (DF "!ISA_MIPS1") (V2SF "TARGET_SB1")])
+
+; This attribute gives the condition for which recip and rsqrt instructions
+; exist.
+(define_mode_attr recip_condition
+ [(SF "ISA_HAS_FP4") (DF "ISA_HAS_FP4") (V2SF "TARGET_SB1")])
+
+;; This code macro allows all branch instructions to be generated from
+;; a single define_expand template.
+(define_code_macro any_cond [unordered ordered unlt unge uneq ltgt unle ungt
+ eq ne gt ge lt le gtu geu ltu leu])
+
+;; This code macro allows signed and unsigned widening multiplications
+;; to use the same template.
+(define_code_macro any_extend [sign_extend zero_extend])
+
+;; This code macro allows the three shift instructions to be generated
+;; from the same template.
+(define_code_macro any_shift [ashift ashiftrt lshiftrt])
+
+;; This code macro allows all native floating-point comparisons to be
+;; generated from the same template.
+(define_code_macro fcond [unordered uneq unlt unle eq lt le])
+
+;; This code macro is used for comparisons that can be implemented
+;; by swapping the operands.
+(define_code_macro swapped_fcond [ge gt unge ungt])
+
+;; <u> expands to an empty string when doing a signed operation and
+;; "u" when doing an unsigned operation.
+(define_code_attr u [(sign_extend "") (zero_extend "u")])
+
+;; <su> is like <u>, but the signed form expands to "s" rather than "".
+(define_code_attr su [(sign_extend "s") (zero_extend "u")])
+
+;; <optab> expands to the name of the optab for a particular code.
+(define_code_attr optab [(ashift "ashl")
+ (ashiftrt "ashr")
+ (lshiftrt "lshr")])
+
+;; <insn> expands to the name of the insn that implements a particular code.
+(define_code_attr insn [(ashift "sll")
+ (ashiftrt "sra")
+ (lshiftrt "srl")])
+
+;; <fcond> is the c.cond.fmt condition associated with a particular code.
+(define_code_attr fcond [(unordered "un")
+ (uneq "ueq")
+ (unlt "ult")
+ (unle "ule")
+ (eq "eq")
+ (lt "lt")
+ (le "le")])
+
+;; Similar, but for swapped conditions.
+(define_code_attr swapped_fcond [(ge "le")
+ (gt "lt")
+ (unge "ule")
+ (ungt "ult")])
+
+;; .........................
+;;
+;; Branch, call and jump delay slots
+;;
+;; .........................
+
+(define_delay (and (eq_attr "type" "branch")
+ (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))
+ [(eq_attr "can_delay" "yes")
+ (nil)
+ (and (eq_attr "branch_likely" "yes")
+ (eq_attr "can_delay" "yes"))])
+
+(define_delay (eq_attr "type" "jump")
+ [(eq_attr "can_delay" "yes")
+ (nil)
+ (nil)])
+
+(define_delay (and (eq_attr "type" "call")
+ (eq_attr "jal_macro" "no"))
+ [(eq_attr "can_delay" "yes")
+ (nil)
+ (nil)])
+
+;; Pipeline descriptions.
+;;
+;; generic.md provides a fallback for processors without a specific
+;; pipeline description. It is derived from the old define_function_unit
+;; version and uses the "alu" and "imuldiv" units declared below.
+;;
+;; Some of the processor-specific files are also derived from old
+;; define_function_unit descriptions and simply override the parts of
+;; generic.md that don't apply. The other processor-specific files
+;; are self-contained.
+(define_automaton "alu,imuldiv")
+
+(define_cpu_unit "alu" "alu")
+(define_cpu_unit "imuldiv" "imuldiv")
+
+(include "4k.md")
+(include "5k.md")
+(include "24k.md")
+(include "3000.md")
+(include "4000.md")
+(include "4100.md")
+(include "4130.md")
+(include "4300.md")
+(include "4600.md")
+(include "5000.md")
+(include "5400.md")
+(include "5500.md")
+(include "6000.md")
+(include "7000.md")
+(include "9000.md")
+(include "sb1.md")
+(include "sr71k.md")
+(include "generic.md")
+
+;;
+;; ....................
+;;
+;; CONDITIONAL TRAPS
+;;
+;; ....................
+;;
+
+(define_insn "trap"
+ [(trap_if (const_int 1) (const_int 0))]
+ ""
+{
+ if (ISA_HAS_COND_TRAP)
+ return "teq\t$0,$0";
+ else if (TARGET_MIPS16)
+ return "break 0";
+ else
+ return "break";
+}
+ [(set_attr "type" "trap")])
+
+(define_expand "conditional_trap"
+ [(trap_if (match_operator 0 "comparison_operator"
+ [(match_dup 2) (match_dup 3)])
+ (match_operand 1 "const_int_operand"))]
+ "ISA_HAS_COND_TRAP"
+{
+ if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT
+ && operands[1] == const0_rtx)
+ {
+ mips_gen_conditional_trap (operands);
+ DONE;
+ }
+ else
+ FAIL;
+})
+
+(define_insn "*conditional_trap<mode>"
+ [(trap_if (match_operator:GPR 0 "trap_comparison_operator"
+ [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+ (match_operand:GPR 2 "arith_operand" "dI")])
+ (const_int 0))]
+ "ISA_HAS_COND_TRAP"
+ "t%C0\t%z1,%2"
+ [(set_attr "type" "trap")])
+
+;;
+;; ....................
+;;
+;; ADDITION
+;;
+;; ....................
+;;
+
+(define_insn "add<mode>3"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (plus:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f")))]
+ ""
+ "add.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_expand "add<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (plus:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "arith_operand")))]
+ "")
+
+(define_insn "*add<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (plus:GPR (match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "arith_operand" "d,Q")))]
+ "!TARGET_MIPS16"
+ "@
+ <d>addu\t%0,%1,%2
+ <d>addiu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+;; We need to recognize MIPS16 stack pointer additions explicitly, since
+;; we don't have a constraint for $sp. These insns will be generated by
+;; the save_restore_insns functions.
+
+(define_insn "*add<mode>3_sp1"
+ [(set (reg:GPR 29)
+ (plus:GPR (reg:GPR 29)
+ (match_operand:GPR 0 "const_arith_operand" "")))]
+ "TARGET_MIPS16"
+ "<d>addiu\t%$,%$,%0"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length") (if_then_else (match_operand 0 "m16_simm8_8")
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn "*add<mode>3_sp2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (plus:GPR (reg:GPR 29)
+ (match_operand:GPR 1 "const_arith_operand" "")))]
+ "TARGET_MIPS16"
+ "<d>addiu\t%0,%$,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length") (if_then_else (match_operand 1 "m16_uimm<si8_di5>_4")
+ (const_int 4)
+ (const_int 8)))])
+
+(define_insn "*add<mode>3_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (plus:GPR (match_operand:GPR 1 "register_operand" "0,d,d")
+ (match_operand:GPR 2 "arith_operand" "Q,O,d")))]
+ "TARGET_MIPS16"
+ "@
+ <d>addiu\t%0,%2
+ <d>addiu\t%0,%1,%2
+ <d>addu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")
+ (set_attr_alternative "length"
+ [(if_then_else (match_operand 2 "m16_simm<si8_di5>_1")
+ (const_int 4)
+ (const_int 8))
+ (if_then_else (match_operand 2 "m16_simm4_1")
+ (const_int 4)
+ (const_int 8))
+ (const_int 4)])])
+
+
+;; On the mips16, we can sometimes split an add of a constant which is
+;; a 4 byte instruction into two adds which are both 2 byte
+;; instructions. There are two cases: one where we are adding a
+;; constant plus a register to another register, and one where we are
+;; simply adding a constant to a register.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (plus:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand")))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) > 0x7f
+ && INTVAL (operands[1]) <= 0x7f + 0x7f)
+ || (INTVAL (operands[1]) < - 0x80
+ && INTVAL (operands[1]) >= - 0x80 - 0x80))"
+ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val >= 0)
+ {
+ operands[1] = GEN_INT (0x7f);
+ operands[2] = GEN_INT (val - 0x7f);
+ }
+ else
+ {
+ operands[1] = GEN_INT (- 0x80);
+ operands[2] = GEN_INT (val + 0x80);
+ }
+})
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (plus:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "const_int_operand")))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && REG_P (operands[1])
+ && M16_REG_P (REGNO (operands[1]))
+ && REGNO (operands[0]) != REGNO (operands[1])
+ && GET_CODE (operands[2]) == CONST_INT
+ && ((INTVAL (operands[2]) > 0x7
+ && INTVAL (operands[2]) <= 0x7 + 0x7f)
+ || (INTVAL (operands[2]) < - 0x8
+ && INTVAL (operands[2]) >= - 0x8 - 0x80))"
+ [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val >= 0)
+ {
+ operands[2] = GEN_INT (0x7);
+ operands[3] = GEN_INT (val - 0x7);
+ }
+ else
+ {
+ operands[2] = GEN_INT (- 0x8);
+ operands[3] = GEN_INT (val + 0x8);
+ }
+})
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (plus:DI (match_dup 0)
+ (match_operand:DI 1 "const_int_operand")))]
+ "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) > 0xf
+ && INTVAL (operands[1]) <= 0xf + 0xf)
+ || (INTVAL (operands[1]) < - 0x10
+ && INTVAL (operands[1]) >= - 0x10 - 0x10))"
+ [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val >= 0)
+ {
+ operands[1] = GEN_INT (0xf);
+ operands[2] = GEN_INT (val - 0xf);
+ }
+ else
+ {
+ operands[1] = GEN_INT (- 0x10);
+ operands[2] = GEN_INT (val + 0x10);
+ }
+})
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (plus:DI (match_operand:DI 1 "register_operand")
+ (match_operand:DI 2 "const_int_operand")))]
+ "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && REG_P (operands[1])
+ && M16_REG_P (REGNO (operands[1]))
+ && REGNO (operands[0]) != REGNO (operands[1])
+ && GET_CODE (operands[2]) == CONST_INT
+ && ((INTVAL (operands[2]) > 0x7
+ && INTVAL (operands[2]) <= 0x7 + 0xf)
+ || (INTVAL (operands[2]) < - 0x8
+ && INTVAL (operands[2]) >= - 0x8 - 0x10))"
+ [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[2]);
+
+ if (val >= 0)
+ {
+ operands[2] = GEN_INT (0x7);
+ operands[3] = GEN_INT (val - 0x7);
+ }
+ else
+ {
+ operands[2] = GEN_INT (- 0x8);
+ operands[3] = GEN_INT (val + 0x8);
+ }
+})
+
+(define_insn "*addsi3_extended"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI
+ (plus:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "arith_operand" "d,Q"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "@
+ addu\t%0,%1,%2
+ addiu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+;; Split this insn so that the addiu splitters can have a crack at it.
+;; Use a conservative length estimate until the split.
+(define_insn_and_split "*addsi3_extended_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=d,d,d")
+ (sign_extend:DI
+ (plus:SI (match_operand:SI 1 "register_operand" "0,d,d")
+ (match_operand:SI 2 "arith_operand" "Q,O,d"))))]
+ "TARGET_64BIT && TARGET_MIPS16"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))]
+ { operands[3] = gen_lowpart (SImode, operands[0]); }
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")
+ (set_attr "extended_mips16" "yes")])
+
+;;
+;; ....................
+;;
+;; SUBTRACTION
+;;
+;; ....................
+;;
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (minus:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f")))]
+ ""
+ "sub.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "sub<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (minus:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ ""
+ "<d>subu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*subsi3_extended"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI
+ (minus:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))]
+ "TARGET_64BIT"
+ "subu\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+;;
+;; ....................
+;;
+;; MULTIPLICATION
+;;
+;; ....................
+;;
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:SCALARF 0 "register_operand")
+ (mult:SCALARF (match_operand:SCALARF 1 "register_operand")
+ (match_operand:SCALARF 2 "register_operand")))]
+ ""
+ "")
+
+(define_insn "*mul<mode>3"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
+ "!TARGET_4300_MUL_FIX"
+ "mul.<fmt>\t%0,%1,%2"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "<MODE>")])
+
+;; Early VR4300 silicon has a CPU bug where multiplies with certain
+;; operands may corrupt immediately following multiplies. This is a
+;; simple fix to insert NOPs.
+
+(define_insn "*mul<mode>3_r4300"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f")
+ (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
+ "TARGET_4300_MUL_FIX"
+ "mul.<fmt>\t%0,%1,%2\;nop"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "8")])
+
+(define_insn "mulv2sf3"
+ [(set (match_operand:V2SF 0 "register_operand" "=f")
+ (mult:V2SF (match_operand:V2SF 1 "register_operand" "f")
+ (match_operand:V2SF 2 "register_operand" "f")))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+ "mul.ps\t%0,%1,%2"
+ [(set_attr "type" "fmul")
+ (set_attr "mode" "SF")])
+
+;; The original R4000 has a cpu bug. If a double-word or a variable
+;; shift executes while an integer multiplication is in progress, the
+;; shift may give an incorrect result. Avoid this by keeping the mflo
+;; with the mult on the R4000.
+;;
+;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0"
+;; (also valid for MIPS R4000MC processors):
+;;
+;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to
+;; this errata description.
+;; The following code sequence causes the R4000 to incorrectly
+;; execute the Double Shift Right Arithmetic 32 (dsra32)
+;; instruction. If the dsra32 instruction is executed during an
+;; integer multiply, the dsra32 will only shift by the amount in
+;; specified in the instruction rather than the amount plus 32
+;; bits.
+;; instruction 1: mult rs,rt integer multiply
+;; instruction 2-12: dsra32 rd,rt,rs doubleword shift
+;; right arithmetic + 32
+;; Workaround: A dsra32 instruction placed after an integer
+;; multiply should not be one of the 11 instructions after the
+;; multiply instruction."
+;;
+;; and:
+;;
+;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by
+;; the following description.
+;; All extended shifts (shift by n+32) and variable shifts (32 and
+;; 64-bit versions) may produce incorrect results under the
+;; following conditions:
+;; 1) An integer multiply is currently executing
+;; 2) These types of shift instructions are executed immediately
+;; following an integer divide instruction.
+;; Workaround:
+;; 1) Make sure no integer multiply is running wihen these
+;; instruction are executed. If this cannot be predicted at
+;; compile time, then insert a "mfhi" to R0 instruction
+;; immediately after the integer multiply instruction. This
+;; will cause the integer multiply to complete before the shift
+;; is executed.
+;; 2) Separate integer divide and these two classes of shift
+;; instructions by another instruction or a noop."
+;;
+;; These processors have PRId values of 0x00004220 and 0x00004300,
+;; respectively.
+
+(define_expand "mul<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (mult:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")))]
+ ""
+{
+ if (GENERATE_MULT3_<MODE>)
+ emit_insn (gen_mul<mode>3_mult3 (operands[0], operands[1], operands[2]));
+ else if (!TARGET_FIX_R4000)
+ emit_insn (gen_mul<mode>3_internal (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2]));
+ DONE;
+})
+
+(define_insn "mulsi3_mult3"
+ [(set (match_operand:SI 0 "register_operand" "=d,l")
+ (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "register_operand" "d,d")))
+ (clobber (match_scratch:SI 3 "=h,h"))
+ (clobber (match_scratch:SI 4 "=l,X"))]
+ "GENERATE_MULT3_SI"
+{
+ if (which_alternative == 1)
+ return "mult\t%1,%2";
+ if (TARGET_MAD
+ || TARGET_MIPS5400
+ || TARGET_MIPS5500
+ || TARGET_MIPS7000
+ || TARGET_MIPS9000
+ || ISA_MIPS32
+ || ISA_MIPS32R2
+ || ISA_MIPS64)
+ return "mul\t%0,%1,%2";
+ return "mult\t%0,%1,%2";
+}
+ [(set_attr "type" "imul3,imul")
+ (set_attr "mode" "SI")])
+
+(define_insn "muldi3_mult3"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "register_operand" "d")))
+ (clobber (match_scratch:DI 3 "=h"))
+ (clobber (match_scratch:DI 4 "=l"))]
+ "TARGET_64BIT && GENERATE_MULT3_DI"
+ "dmult\t%0,%1,%2"
+ [(set_attr "type" "imul3")
+ (set_attr "mode" "DI")])
+
+;; If a register gets allocated to LO, and we spill to memory, the reload
+;; will include a move from LO to a GPR. Merge it into the multiplication
+;; if it can set the GPR directly.
+;;
+;; Operand 0: LO
+;; Operand 1: GPR (1st multiplication operand)
+;; Operand 2: GPR (2nd multiplication operand)
+;; Operand 3: HI
+;; Operand 4: GPR (destination)
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (mult:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand")))
+ (clobber (match_operand:SI 3 "register_operand"))
+ (clobber (scratch:SI))])
+ (set (match_operand:SI 4 "register_operand")
+ (unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
+ "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])"
+ [(parallel
+ [(set (match_dup 4)
+ (mult:SI (match_dup 1)
+ (match_dup 2)))
+ (clobber (match_dup 3))
+ (clobber (match_dup 0))])])
+
+(define_insn "mul<mode>3_internal"
+ [(set (match_operand:GPR 0 "register_operand" "=l")
+ (mult:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))
+ (clobber (match_scratch:GPR 3 "=h"))]
+ "!TARGET_FIX_R4000"
+ "<d>mult\t%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "mul<mode>3_r4000"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (mult:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))
+ (clobber (match_scratch:GPR 3 "=h"))
+ (clobber (match_scratch:GPR 4 "=l"))]
+ "TARGET_FIX_R4000"
+ "<d>mult\t%1,%2\;mflo\t%0"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "8")])
+
+;; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead
+;; of "mult; mflo". They have the same latency, but the first form gives
+;; us an extra cycle to compute the operands.
+
+;; Operand 0: LO
+;; Operand 1: GPR (1st multiplication operand)
+;; Operand 2: GPR (2nd multiplication operand)
+;; Operand 3: HI
+;; Operand 4: GPR (destination)
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (mult:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand")))
+ (clobber (match_operand:SI 3 "register_operand"))])
+ (set (match_operand:SI 4 "register_operand")
+ (unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))]
+ "ISA_HAS_MACC && !GENERATE_MULT3_SI"
+ [(set (match_dup 0)
+ (const_int 0))
+ (parallel
+ [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (set (match_dup 4)
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (clobber (match_dup 3))])])
+
+;; Multiply-accumulate patterns
+
+;; For processors that can copy the output to a general register:
+;;
+;; The all-d alternative is needed because the combiner will find this
+;; pattern and then register alloc/reload will move registers around to
+;; make them fit, and we don't want to trigger unnecessary loads to LO.
+;;
+;; The last alternative should be made slightly less desirable, but adding
+;; "?" to the constraint is too strong, and causes values to be loaded into
+;; LO even when that's more costly. For now, using "*d" mostly does the
+;; trick.
+(define_insn "*mul_acc_si"
+ [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d")
+ (match_operand:SI 2 "register_operand" "d,d,d"))
+ (match_operand:SI 3 "register_operand" "0,l,*d")))
+ (clobber (match_scratch:SI 4 "=h,h,h"))
+ (clobber (match_scratch:SI 5 "=X,3,l"))
+ (clobber (match_scratch:SI 6 "=X,X,&d"))]
+ "(TARGET_MIPS3900
+ || ISA_HAS_MADD_MSUB)
+ && !TARGET_MIPS16"
+{
+ static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" };
+ if (which_alternative == 2)
+ return "#";
+ if (ISA_HAS_MADD_MSUB && which_alternative != 0)
+ return "#";
+ return madd[which_alternative];
+}
+ [(set_attr "type" "imadd,imadd,multi")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4,4,8")])
+
+;; Split the above insn if we failed to get LO allocated.
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand"))
+ (match_operand:SI 3 "register_operand")))
+ (clobber (match_scratch:SI 4))
+ (clobber (match_scratch:SI 5))
+ (clobber (match_scratch:SI 6))]
+ "reload_completed && !TARGET_DEBUG_D_MODE
+ && GP_REG_P (true_regnum (operands[0]))
+ && GP_REG_P (true_regnum (operands[3]))"
+ [(parallel [(set (match_dup 6)
+ (mult:SI (match_dup 1) (match_dup 2)))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))])
+ (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))]
+ "")
+
+;; Splitter to copy result of MADD to a general register
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand"))
+ (match_operand:SI 3 "register_operand")))
+ (clobber (match_scratch:SI 4))
+ (clobber (match_scratch:SI 5))
+ (clobber (match_scratch:SI 6))]
+ "reload_completed && !TARGET_DEBUG_D_MODE
+ && GP_REG_P (true_regnum (operands[0]))
+ && true_regnum (operands[3]) == LO_REGNUM"
+ [(parallel [(set (match_dup 3)
+ (plus:SI (mult:SI (match_dup 1) (match_dup 2))
+ (match_dup 3)))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))
+ (clobber (match_dup 6))])
+ (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
+ "")
+
+(define_insn "*macc"
+ [(set (match_operand:SI 0 "register_operand" "=l,d")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "register_operand" "d,d"))
+ (match_operand:SI 3 "register_operand" "0,l")))
+ (clobber (match_scratch:SI 4 "=h,h"))
+ (clobber (match_scratch:SI 5 "=X,3"))]
+ "ISA_HAS_MACC"
+{
+ if (which_alternative == 1)
+ return "macc\t%0,%1,%2";
+ else if (TARGET_MIPS5500)
+ return "madd\t%1,%2";
+ else
+ /* The VR4130 assumes that there is a two-cycle latency between a macc
+ that "writes" to $0 and an instruction that reads from it. We avoid
+ this by assigning to $1 instead. */
+ return "%[macc\t%@,%1,%2%]";
+}
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "*msac"
+ [(set (match_operand:SI 0 "register_operand" "=l,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,l")
+ (mult:SI (match_operand:SI 2 "register_operand" "d,d")
+ (match_operand:SI 3 "register_operand" "d,d"))))
+ (clobber (match_scratch:SI 4 "=h,h"))
+ (clobber (match_scratch:SI 5 "=X,1"))]
+ "ISA_HAS_MSAC"
+{
+ if (which_alternative == 1)
+ return "msac\t%0,%2,%3";
+ else if (TARGET_MIPS5500)
+ return "msub\t%2,%3";
+ else
+ return "msac\t$0,%2,%3";
+}
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; An msac-like instruction implemented using negation and a macc.
+(define_insn_and_split "*msac_using_macc"
+ [(set (match_operand:SI 0 "register_operand" "=l,d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,l")
+ (mult:SI (match_operand:SI 2 "register_operand" "d,d")
+ (match_operand:SI 3 "register_operand" "d,d"))))
+ (clobber (match_scratch:SI 4 "=h,h"))
+ (clobber (match_scratch:SI 5 "=X,1"))
+ (clobber (match_scratch:SI 6 "=d,d"))]
+ "ISA_HAS_MACC && !ISA_HAS_MSAC"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 6)
+ (neg:SI (match_dup 3)))
+ (parallel
+ [(set (match_dup 0)
+ (plus:SI (mult:SI (match_dup 2)
+ (match_dup 6))
+ (match_dup 1)))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))])]
+ ""
+ [(set_attr "type" "imadd")
+ (set_attr "length" "8")])
+
+;; Patterns generated by the define_peephole2 below.
+
+(define_insn "*macc2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (match_dup 0)))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (plus:SI (mult:SI (match_dup 1)
+ (match_dup 2))
+ (match_dup 0)))
+ (clobber (match_scratch:SI 4 "=h"))]
+ "ISA_HAS_MACC && reload_completed"
+ "macc\t%3,%1,%2"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "*msac2"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (minus:SI (match_dup 0)
+ (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))))
+ (set (match_operand:SI 3 "register_operand" "=d")
+ (minus:SI (match_dup 0)
+ (mult:SI (match_dup 1)
+ (match_dup 2))))
+ (clobber (match_scratch:SI 4 "=h"))]
+ "ISA_HAS_MSAC && reload_completed"
+ "msac\t%3,%1,%2"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
+;; Similarly msac.
+;;
+;; Operand 0: LO
+;; Operand 1: macc/msac
+;; Operand 2: HI
+;; Operand 3: GPR (destination)
+(define_peephole2
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "macc_msac_operand"))
+ (clobber (match_operand:SI 2 "register_operand"))
+ (clobber (scratch:SI))])
+ (set (match_operand:SI 3 "register_operand")
+ (unspec:SI [(match_dup 0) (match_dup 2)] UNSPEC_MFHILO))]
+ ""
+ [(parallel [(set (match_dup 0)
+ (match_dup 1))
+ (set (match_dup 3)
+ (match_dup 1))
+ (clobber (match_dup 2))])]
+ "")
+
+;; When we have a three-address multiplication instruction, it should
+;; be faster to do a separate multiply and add, rather than moving
+;; something into LO in order to use a macc instruction.
+;;
+;; This peephole needs a scratch register to cater for the case when one
+;; of the multiplication operands is the same as the destination.
+;;
+;; Operand 0: GPR (scratch)
+;; Operand 1: LO
+;; Operand 2: GPR (addend)
+;; Operand 3: GPR (destination)
+;; Operand 4: macc/msac
+;; Operand 5: HI
+;; Operand 6: new multiplication
+;; Operand 7: new addition/subtraction
+(define_peephole2
+ [(match_scratch:SI 0 "d")
+ (set (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand"))
+ (match_dup 0)
+ (parallel
+ [(set (match_operand:SI 3 "register_operand")
+ (match_operand:SI 4 "macc_msac_operand"))
+ (clobber (match_operand:SI 5 "register_operand"))
+ (clobber (match_dup 1))])]
+ "GENERATE_MULT3_SI
+ && true_regnum (operands[1]) == LO_REGNUM
+ && peep2_reg_dead_p (2, operands[1])
+ && GP_REG_P (true_regnum (operands[3]))"
+ [(parallel [(set (match_dup 0)
+ (match_dup 6))
+ (clobber (match_dup 5))
+ (clobber (match_dup 1))])
+ (set (match_dup 3)
+ (match_dup 7))]
+{
+ operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
+ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
+ operands[2], operands[0]);
+})
+
+;; Same as above, except LO is the initial target of the macc.
+;;
+;; Operand 0: GPR (scratch)
+;; Operand 1: LO
+;; Operand 2: GPR (addend)
+;; Operand 3: macc/msac
+;; Operand 4: HI
+;; Operand 5: GPR (destination)
+;; Operand 6: new multiplication
+;; Operand 7: new addition/subtraction
+(define_peephole2
+ [(match_scratch:SI 0 "d")
+ (set (match_operand:SI 1 "register_operand")
+ (match_operand:SI 2 "register_operand"))
+ (match_dup 0)
+ (parallel
+ [(set (match_dup 1)
+ (match_operand:SI 3 "macc_msac_operand"))
+ (clobber (match_operand:SI 4 "register_operand"))
+ (clobber (scratch:SI))])
+ (match_dup 0)
+ (set (match_operand:SI 5 "register_operand")
+ (unspec:SI [(match_dup 1) (match_dup 4)] UNSPEC_MFHILO))]
+ "GENERATE_MULT3_SI && peep2_reg_dead_p (3, operands[1])"
+ [(parallel [(set (match_dup 0)
+ (match_dup 6))
+ (clobber (match_dup 4))
+ (clobber (match_dup 1))])
+ (set (match_dup 5)
+ (match_dup 7))]
+{
+ operands[6] = XEXP (operands[4], GET_CODE (operands[4]) == PLUS ? 0 : 1);
+ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[4]), SImode,
+ operands[2], operands[0]);
+})
+
+(define_insn "*mul_sub_si"
+ [(set (match_operand:SI 0 "register_operand" "=l,*d,*d")
+ (minus:SI (match_operand:SI 1 "register_operand" "0,l,*d")
+ (mult:SI (match_operand:SI 2 "register_operand" "d,d,d")
+ (match_operand:SI 3 "register_operand" "d,d,d"))))
+ (clobber (match_scratch:SI 4 "=h,h,h"))
+ (clobber (match_scratch:SI 5 "=X,1,l"))
+ (clobber (match_scratch:SI 6 "=X,X,&d"))]
+ "ISA_HAS_MADD_MSUB"
+ "@
+ msub\t%2,%3
+ #
+ #"
+ [(set_attr "type" "imadd,multi,multi")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4,8,8")])
+
+;; Split the above insn if we failed to get LO allocated.
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (minus:SI (match_operand:SI 1 "register_operand")
+ (mult:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "register_operand"))))
+ (clobber (match_scratch:SI 4))
+ (clobber (match_scratch:SI 5))
+ (clobber (match_scratch:SI 6))]
+ "reload_completed && !TARGET_DEBUG_D_MODE
+ && GP_REG_P (true_regnum (operands[0]))
+ && GP_REG_P (true_regnum (operands[1]))"
+ [(parallel [(set (match_dup 6)
+ (mult:SI (match_dup 2) (match_dup 3)))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))])
+ (set (match_dup 0) (minus:SI (match_dup 1) (match_dup 6)))]
+ "")
+
+;; Splitter to copy result of MSUB to a general register
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (minus:SI (match_operand:SI 1 "register_operand")
+ (mult:SI (match_operand:SI 2 "register_operand")
+ (match_operand:SI 3 "register_operand"))))
+ (clobber (match_scratch:SI 4))
+ (clobber (match_scratch:SI 5))
+ (clobber (match_scratch:SI 6))]
+ "reload_completed && !TARGET_DEBUG_D_MODE
+ && GP_REG_P (true_regnum (operands[0]))
+ && true_regnum (operands[1]) == LO_REGNUM"
+ [(parallel [(set (match_dup 1)
+ (minus:SI (match_dup 1)
+ (mult:SI (match_dup 2) (match_dup 3))))
+ (clobber (match_dup 4))
+ (clobber (match_dup 5))
+ (clobber (match_dup 6))])
+ (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))]
+ "")
+
+(define_insn "*muls"
+ [(set (match_operand:SI 0 "register_operand" "=l,d")
+ (neg:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d")
+ (match_operand:SI 2 "register_operand" "d,d"))))
+ (clobber (match_scratch:SI 3 "=h,h"))
+ (clobber (match_scratch:SI 4 "=X,l"))]
+ "ISA_HAS_MULS"
+ "@
+ muls\t$0,%1,%2
+ muls\t%0,%1,%2"
+ [(set_attr "type" "imul,imul3")
+ (set_attr "mode" "SI")])
+
+;; ??? We could define a mulditi3 pattern when TARGET_64BIT.
+
+(define_expand "<u>mulsidi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand"))))
+ (clobber (scratch:DI))
+ (clobber (scratch:DI))
+ (clobber (scratch:DI))])]
+ "!TARGET_64BIT || !TARGET_FIX_R4000"
+{
+ if (!TARGET_64BIT)
+ {
+ if (!TARGET_FIX_R4000)
+ emit_insn (gen_<u>mulsidi3_32bit_internal (operands[0], operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_<u>mulsidi3_32bit_r4000 (operands[0], operands[1],
+ operands[2]));
+ DONE;
+ }
+})
+
+(define_insn "<u>mulsidi3_32bit_internal"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))]
+ "!TARGET_64BIT && !TARGET_FIX_R4000"
+ "mult<u>\t%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")])
+
+(define_insn "<u>mulsidi3_32bit_r4000"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
+ (clobber (match_scratch:DI 3 "=x"))]
+ "!TARGET_64BIT && TARGET_FIX_R4000"
+ "mult<u>\t%1,%2\;mflo\t%L0;mfhi\t%M0"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set_attr "length" "12")])
+
+(define_insn_and_split "*<u>mulsidi3_64bit"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d"))))
+ (clobber (match_scratch:DI 3 "=l"))
+ (clobber (match_scratch:DI 4 "=h"))
+ (clobber (match_scratch:DI 5 "=d"))]
+ "TARGET_64BIT && !TARGET_FIX_R4000"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 3)
+ (sign_extend:DI
+ (mult:SI (match_dup 1)
+ (match_dup 2))))
+ (set (match_dup 4)
+ (ashiftrt:DI
+ (mult:DI (any_extend:DI (match_dup 1))
+ (any_extend:DI (match_dup 2)))
+ (const_int 32)))])
+
+ ;; OP5 <- LO, OP0 <- HI
+ (set (match_dup 5) (unspec:DI [(match_dup 3) (match_dup 4)] UNSPEC_MFHILO))
+ (set (match_dup 0) (unspec:DI [(match_dup 4) (match_dup 3)] UNSPEC_MFHILO))
+
+ ;; Zero-extend OP5.
+ (set (match_dup 5)
+ (ashift:DI (match_dup 5)
+ (const_int 32)))
+ (set (match_dup 5)
+ (lshiftrt:DI (match_dup 5)
+ (const_int 32)))
+
+ ;; Shift OP0 into place.
+ (set (match_dup 0)
+ (ashift:DI (match_dup 0)
+ (const_int 32)))
+
+ ;; OR the two halves together
+ (set (match_dup 0)
+ (ior:DI (match_dup 0)
+ (match_dup 5)))]
+ ""
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")
+ (set_attr "length" "24")])
+
+(define_insn "*<u>mulsidi3_64bit_parts"
+ [(set (match_operand:DI 0 "register_operand" "=l")
+ (sign_extend:DI
+ (mult:SI (match_operand:SI 2 "register_operand" "d")
+ (match_operand:SI 3 "register_operand" "d"))))
+ (set (match_operand:DI 1 "register_operand" "=h")
+ (ashiftrt:DI
+ (mult:DI (any_extend:DI (match_dup 2))
+ (any_extend:DI (match_dup 3)))
+ (const_int 32)))]
+ "TARGET_64BIT && !TARGET_FIX_R4000"
+ "mult<u>\t%2,%3"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")])
+
+;; Widening multiply with negation.
+(define_insn "*muls<u>_di"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (neg:DI
+ (mult:DI
+ (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
+ "!TARGET_64BIT && ISA_HAS_MULS"
+ "muls<u>\t$0,%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")])
+
+(define_insn "*msac<u>_di"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (minus:DI
+ (match_operand:DI 3 "register_operand" "0")
+ (mult:DI
+ (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d")))))]
+ "!TARGET_64BIT && ISA_HAS_MSAC"
+{
+ if (TARGET_MIPS5500)
+ return "msub<u>\t%1,%2";
+ else
+ return "msac<u>\t$0,%1,%2";
+}
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; _highpart patterns
+
+(define_expand "<su>mulsi3_highpart"
+ [(set (match_operand:SI 0 "register_operand")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand"))
+ (any_extend:DI (match_operand:SI 2 "register_operand")))
+ (const_int 32))))]
+ "ISA_HAS_MULHI || !TARGET_FIX_R4000"
+{
+ if (ISA_HAS_MULHI)
+ emit_insn (gen_<su>mulsi3_highpart_mulhi_internal (operands[0],
+ operands[1],
+ operands[2]));
+ else
+ emit_insn (gen_<su>mulsi3_highpart_internal (operands[0], operands[1],
+ operands[2]));
+ DONE;
+})
+
+(define_insn "<su>mulsi3_highpart_internal"
+ [(set (match_operand:SI 0 "register_operand" "=h")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=l"))]
+ "!ISA_HAS_MULHI && !TARGET_FIX_R4000"
+ "mult<u>\t%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "SI")])
+
+(define_insn "<su>mulsi3_highpart_mulhi_internal"
+ [(set (match_operand:SI 0 "register_operand" "=h,d")
+ (truncate:SI
+ (lshiftrt:DI
+ (mult:DI
+ (any_extend:DI (match_operand:SI 1 "register_operand" "d,d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d,d")))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=l,l"))
+ (clobber (match_scratch:SI 4 "=X,h"))]
+ "ISA_HAS_MULHI"
+ "@
+ mult<u>\t%1,%2
+ mulhi<u>\t%0,%1,%2"
+ [(set_attr "type" "imul,imul3")
+ (set_attr "mode" "SI")])
+
+(define_insn "*<su>mulsi3_highpart_neg_mulhi_internal"
+ [(set (match_operand:SI 0 "register_operand" "=h,d")
+ (truncate:SI
+ (lshiftrt:DI
+ (neg:DI
+ (mult:DI
+ (any_extend:DI (match_operand:SI 1 "register_operand" "d,d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d,d"))))
+ (const_int 32))))
+ (clobber (match_scratch:SI 3 "=l,l"))
+ (clobber (match_scratch:SI 4 "=X,h"))]
+ "ISA_HAS_MULHI"
+ "@
+ mulshi<u>\t%.,%1,%2
+ mulshi<u>\t%0,%1,%2"
+ [(set_attr "type" "imul,imul3")
+ (set_attr "mode" "SI")])
+
+;; Disable unsigned multiplication for -mfix-vr4120. This is for VR4120
+;; errata MD(0), which says that dmultu does not always produce the
+;; correct result.
+(define_insn "<su>muldi3_highpart"
+ [(set (match_operand:DI 0 "register_operand" "=h")
+ (truncate:DI
+ (lshiftrt:TI
+ (mult:TI
+ (any_extend:TI (match_operand:DI 1 "register_operand" "d"))
+ (any_extend:TI (match_operand:DI 2 "register_operand" "d")))
+ (const_int 64))))
+ (clobber (match_scratch:DI 3 "=l"))]
+ "TARGET_64BIT && !TARGET_FIX_R4000
+ && !(<CODE> == ZERO_EXTEND && TARGET_FIX_VR4120)"
+ "dmult<u>\t%1,%2"
+ [(set_attr "type" "imul")
+ (set_attr "mode" "DI")])
+
+;; The R4650 supports a 32 bit multiply/ 64 bit accumulate
+;; instruction. The HI/LO registers are used as a 64 bit accumulator.
+
+(define_insn "madsi"
+ [(set (match_operand:SI 0 "register_operand" "+l")
+ (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "register_operand" "d"))
+ (match_dup 0)))
+ (clobber (match_scratch:SI 3 "=h"))]
+ "TARGET_MAD"
+ "mad\t%1,%2"
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+(define_insn "*<su>mul_acc_di"
+ [(set (match_operand:DI 0 "register_operand" "=x")
+ (plus:DI
+ (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d"))
+ (any_extend:DI (match_operand:SI 2 "register_operand" "d")))
+ (match_operand:DI 3 "register_operand" "0")))]
+ "(TARGET_MAD || ISA_HAS_MACC)
+ && !TARGET_64BIT"
+{
+ if (TARGET_MAD)
+ return "mad<u>\t%1,%2";
+ else if (TARGET_MIPS5500)
+ return "madd<u>\t%1,%2";
+ else
+ /* See comment in *macc. */
+ return "%[macc<u>\t%@,%1,%2%]";
+}
+ [(set_attr "type" "imadd")
+ (set_attr "mode" "SI")])
+
+;; Floating point multiply accumulate instructions.
+
+(define_insn "*madd<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f"))
+ (match_operand:ANYF 3 "register_operand" "f")))]
+ "ISA_HAS_FP4 && TARGET_FUSED_MADD"
+ "madd.<fmt>\t%0,%3,%1,%2"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*msub<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f"))
+ (match_operand:ANYF 3 "register_operand" "f")))]
+ "ISA_HAS_FP4 && TARGET_FUSED_MADD"
+ "msub.<fmt>\t%0,%3,%1,%2"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*nmadd<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (neg:ANYF (plus:ANYF
+ (mult:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f"))
+ (match_operand:ANYF 3 "register_operand" "f"))))]
+ "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
+ "nmadd.<fmt>\t%0,%3,%1,%2"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*nmadd<mode>_fastmath"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (minus:ANYF
+ (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f"))
+ (match_operand:ANYF 2 "register_operand" "f"))
+ (match_operand:ANYF 3 "register_operand" "f")))]
+ "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
+ && !HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
+ "nmadd.<fmt>\t%0,%3,%1,%2"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*nmsub<mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (neg:ANYF (minus:ANYF
+ (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+ (match_operand:ANYF 3 "register_operand" "f"))
+ (match_operand:ANYF 1 "register_operand" "f"))))]
+ "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
+ && HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
+ "nmsub.<fmt>\t%0,%1,%2,%3"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "*nmsub<mode>_fastmath"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (minus:ANYF
+ (match_operand:ANYF 1 "register_operand" "f")
+ (mult:ANYF (match_operand:ANYF 2 "register_operand" "f")
+ (match_operand:ANYF 3 "register_operand" "f"))))]
+ "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD
+ && !HONOR_SIGNED_ZEROS (<MODE>mode)
+ && !HONOR_NANS (<MODE>mode)"
+ "nmsub.<fmt>\t%0,%1,%2,%3"
+ [(set_attr "type" "fmadd")
+ (set_attr "mode" "<UNITMODE>")])
+
+;;
+;; ....................
+;;
+;; DIVISION and REMAINDER
+;;
+;; ....................
+;;
+
+(define_expand "div<mode>3"
+ [(set (match_operand:ANYF 0 "register_operand")
+ (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand")
+ (match_operand:ANYF 2 "register_operand")))]
+ "<divide_condition>"
+{
+ if (const_1_operand (operands[1], <MODE>mode))
+ if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations))
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+})
+
+;; These patterns work around the early SB-1 rev2 core "F1" erratum:
+;;
+;; If an mfc1 or dmfc1 happens to access the floating point register
+;; file at the same time a long latency operation (div, sqrt, recip,
+;; sqrt) iterates an intermediate result back through the floating
+;; point register file bypass, then instead returning the correct
+;; register value the mfc1 or dmfc1 operation returns the intermediate
+;; result of the long latency operation.
+;;
+;; The workaround is to insert an unconditional 'mov' from/to the
+;; long latency op destination register.
+
+(define_insn "*div<mode>3"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (div:ANYF (match_operand:ANYF 1 "register_operand" "f")
+ (match_operand:ANYF 2 "register_operand" "f")))]
+ "<divide_condition>"
+{
+ if (TARGET_FIX_SB1)
+ return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0";
+ else
+ return "div.<fmt>\t%0,%1,%2";
+}
+ [(set_attr "type" "fdiv")
+ (set_attr "mode" "<UNITMODE>")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*recip<mode>3"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+ (match_operand:ANYF 2 "register_operand" "f")))]
+ "<recip_condition> && flag_unsafe_math_optimizations"
+{
+ if (TARGET_FIX_SB1)
+ return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
+ else
+ return "recip.<fmt>\t%0,%2";
+}
+ [(set_attr "type" "frdiv")
+ (set_attr "mode" "<UNITMODE>")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+;; VR4120 errata MD(A1): signed division instructions do not work correctly
+;; with negative operands. We use special libgcc functions instead.
+(define_insn "divmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=l")
+ (div:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))
+ (set (match_operand:GPR 3 "register_operand" "=h")
+ (mod:GPR (match_dup 1)
+ (match_dup 2)))]
+ "!TARGET_FIX_VR4120"
+ { return mips_output_division ("<d>div\t$0,%1,%2", operands); }
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "udivmod<mode>4"
+ [(set (match_operand:GPR 0 "register_operand" "=l")
+ (udiv:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))
+ (set (match_operand:GPR 3 "register_operand" "=h")
+ (umod:GPR (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { return mips_output_division ("<d>divu\t$0,%1,%2", operands); }
+ [(set_attr "type" "idiv")
+ (set_attr "mode" "<MODE>")])
+
+;;
+;; ....................
+;;
+;; SQUARE ROOT
+;;
+;; ....................
+
+;; These patterns work around the early SB-1 rev2 core "F1" erratum (see
+;; "*div[sd]f3" comment for details).
+
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
+ "<sqrt_condition>"
+{
+ if (TARGET_FIX_SB1)
+ return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0";
+ else
+ return "sqrt.<fmt>\t%0,%1";
+}
+ [(set_attr "type" "fsqrt")
+ (set_attr "mode" "<UNITMODE>")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*rsqrt<mode>a"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+ (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))]
+ "<recip_condition> && flag_unsafe_math_optimizations"
+{
+ if (TARGET_FIX_SB1)
+ return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
+ else
+ return "rsqrt.<fmt>\t%0,%2";
+}
+ [(set_attr "type" "frsqrt")
+ (set_attr "mode" "<UNITMODE>")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+(define_insn "*rsqrt<mode>b"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "")
+ (match_operand:ANYF 2 "register_operand" "f"))))]
+ "<recip_condition> && flag_unsafe_math_optimizations"
+{
+ if (TARGET_FIX_SB1)
+ return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0";
+ else
+ return "rsqrt.<fmt>\t%0,%2";
+}
+ [(set_attr "type" "frsqrt")
+ (set_attr "mode" "<UNITMODE>")
+ (set (attr "length")
+ (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0))
+ (const_int 8)
+ (const_int 4)))])
+
+;;
+;; ....................
+;;
+;; ABSOLUTE VALUE
+;;
+;; ....................
+
+;; Do not use the integer abs macro instruction, since that signals an
+;; exception on -2147483648 (sigh).
+
+;; abs.fmt is an arithmetic instruction and treats all NaN inputs as
+;; invalid; it does not clear their sign bits. We therefore can't use
+;; abs.fmt if the signs of NaNs matter.
+
+(define_insn "abs<mode>2"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
+ "!HONOR_NANS (<MODE>mode)"
+ "abs.<fmt>\t%0,%1"
+ [(set_attr "type" "fabs")
+ (set_attr "mode" "<UNITMODE>")])
+
+;;
+;; ...................
+;;
+;; Count leading zeroes.
+;;
+;; ...................
+;;
+
+(define_insn "clz<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (clz:GPR (match_operand:GPR 1 "register_operand" "d")))]
+ "ISA_HAS_CLZ_CLO"
+ "<d>clz\t%0,%1"
+ [(set_attr "type" "clz")
+ (set_attr "mode" "<MODE>")])
+
+;;
+;; ....................
+;;
+;; NEGATION and ONE'S COMPLEMENT
+;;
+;; ....................
+
+(define_insn "negsi2"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (neg:SI (match_operand:SI 1 "register_operand" "d")))]
+ ""
+{
+ if (TARGET_MIPS16)
+ return "neg\t%0,%1";
+ else
+ return "subu\t%0,%.,%1";
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn "negdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "dsubu\t%0,%.,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+;; neg.fmt is an arithmetic instruction and treats all NaN inputs as
+;; invalid; it does not flip their sign bit. We therefore can't use
+;; neg.fmt if the signs of NaNs matter.
+
+(define_insn "neg<mode>2"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))]
+ "!HONOR_NANS (<MODE>mode)"
+ "neg.<fmt>\t%0,%1"
+ [(set_attr "type" "fneg")
+ (set_attr "mode" "<UNITMODE>")])
+
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (not:GPR (match_operand:GPR 1 "register_operand" "d")))]
+ ""
+{
+ if (TARGET_MIPS16)
+ return "not\t%0,%1";
+ else
+ return "nor\t%0,%.,%1";
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+;;
+;; ....................
+;;
+;; LOGICAL
+;;
+;; ....................
+;;
+
+;; Many of these instructions use trivial define_expands, because we
+;; want to use a different set of constraints when TARGET_MIPS16.
+
+(define_expand "and<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (and:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "uns_arith_operand")))]
+ ""
+{
+ if (TARGET_MIPS16)
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+})
+
+(define_insn "*and<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (and:GPR (match_operand:GPR 1 "register_operand" "%d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
+ "!TARGET_MIPS16"
+ "@
+ and\t%0,%1,%2
+ andi\t%0,%1,%x2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*and<mode>3_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (and:GPR (match_operand:GPR 1 "register_operand" "%0")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_MIPS16"
+ "and\t%0,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "ior<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (ior:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "uns_arith_operand")))]
+ ""
+{
+ if (TARGET_MIPS16)
+ operands[2] = force_reg (<MODE>mode, operands[2]);
+})
+
+(define_insn "*ior<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (ior:GPR (match_operand:GPR 1 "register_operand" "%d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
+ "!TARGET_MIPS16"
+ "@
+ or\t%0,%1,%2
+ ori\t%0,%1,%x2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*ior<mode>3_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ior:GPR (match_operand:GPR 1 "register_operand" "%0")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_MIPS16"
+ "or\t%0,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "xor<mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (xor:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "uns_arith_operand")))]
+ ""
+ "")
+
+(define_insn ""
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (xor:GPR (match_operand:GPR 1 "register_operand" "%d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "d,K")))]
+ "!TARGET_MIPS16"
+ "@
+ xor\t%0,%1,%2
+ xori\t%0,%1,%x2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn ""
+ [(set (match_operand:GPR 0 "register_operand" "=d,t,t")
+ (xor:GPR (match_operand:GPR 1 "register_operand" "%0,d,d")
+ (match_operand:GPR 2 "uns_arith_operand" "d,K,d")))]
+ "TARGET_MIPS16"
+ "@
+ xor\t%0,%2
+ cmpi\t%1,%2
+ cmp\t%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand:VOID 2 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))
+ (const_int 4)])])
+
+(define_insn "*nor<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (and:GPR (not:GPR (match_operand:GPR 1 "register_operand" "d"))
+ (not:GPR (match_operand:GPR 2 "register_operand" "d"))))]
+ "!TARGET_MIPS16"
+ "nor\t%0,%1,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+;;
+;; ....................
+;;
+;; TRUNCATION
+;;
+;; ....................
+
+
+
+(define_insn "truncdfsf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "cvt.s.d\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "cnv_mode" "D2S")
+ (set_attr "mode" "SF")])
+
+;; Integer truncation patterns. Truncating SImode values to smaller
+;; modes is a no-op, as it is for most other GCC ports. Truncating
+;; DImode values to SImode is not a no-op for TARGET_64BIT since we
+;; need to make sure that the lower 32 bits are properly sign-extended
+;; (see TRULY_NOOP_TRUNCATION). Truncating DImode values into modes
+;; smaller than SImode is equivalent to two separate truncations:
+;;
+;; A B
+;; DI ---> HI == DI ---> SI ---> HI
+;; DI ---> QI == DI ---> SI ---> QI
+;;
+;; Step A needs a real instruction but step B does not.
+
+(define_insn "truncdisi2"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
+ (truncate:SI (match_operand:DI 1 "register_operand" "d,d")))]
+ "TARGET_64BIT"
+ "@
+ sll\t%0,%1,0
+ sw\t%1,%0"
+ [(set_attr "type" "shift,store")
+ (set_attr "mode" "SI")
+ (set_attr "extended_mips16" "yes,*")])
+
+(define_insn "truncdihi2"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,m")
+ (truncate:HI (match_operand:DI 1 "register_operand" "d,d")))]
+ "TARGET_64BIT"
+ "@
+ sll\t%0,%1,0
+ sh\t%1,%0"
+ [(set_attr "type" "shift,store")
+ (set_attr "mode" "SI")
+ (set_attr "extended_mips16" "yes,*")])
+
+(define_insn "truncdiqi2"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,m")
+ (truncate:QI (match_operand:DI 1 "register_operand" "d,d")))]
+ "TARGET_64BIT"
+ "@
+ sll\t%0,%1,0
+ sb\t%1,%0"
+ [(set_attr "type" "shift,store")
+ (set_attr "mode" "SI")
+ (set_attr "extended_mips16" "yes,*")])
+
+;; Combiner patterns to optimize shift/truncate combinations.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (match_operand:DI 2 "const_arith_operand" ""))))]
+ "TARGET_64BIT && !TARGET_MIPS16 && INTVAL (operands[2]) >= 32"
+ "dsra\t%0,%1,%2"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
+ (const_int 32))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "dsra\t%0,%1,32"
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+
+;; Combiner patterns for truncate/sign_extend combinations. They use
+;; the shift/truncate patterns above.
+
+(define_insn_and_split ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI
+ (truncate:HI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (const_int 48)))
+ (set (match_dup 0)
+ (truncate:SI (ashiftrt:DI (match_dup 2)
+ (const_int 48))))]
+ { operands[2] = gen_lowpart (DImode, operands[0]); })
+
+(define_insn_and_split ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (const_int 56)))
+ (set (match_dup 0)
+ (truncate:SI (ashiftrt:DI (match_dup 2)
+ (const_int 56))))]
+ { operands[2] = gen_lowpart (DImode, operands[0]); })
+
+
+;; Combiner patterns to optimize truncate/zero_extend combinations.
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (truncate:HI
+ (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "andi\t%0,%1,0xffff"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (zero_extend:SI (truncate:QI
+ (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "andi\t%0,%1,0xff"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn ""
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (zero_extend:HI (truncate:QI
+ (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "andi\t%0,%1,0xff"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "HI")])
+
+;;
+;; ....................
+;;
+;; ZERO EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+
+(define_insn_and_split "zero_extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,W")))]
+ "TARGET_64BIT"
+ "@
+ #
+ lwu\t%0,%1"
+ "&& reload_completed && REG_P (operands[1])"
+ [(set (match_dup 0)
+ (ashift:DI (match_dup 1) (const_int 32)))
+ (set (match_dup 0)
+ (lshiftrt:DI (match_dup 0) (const_int 32)))]
+ { operands[1] = gen_lowpart (DImode, operands[1]); }
+ [(set_attr "type" "multi,load")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8,*")])
+
+;; Combine is not allowed to convert this insn into a zero_extendsidi2
+;; because of TRULY_NOOP_TRUNCATION.
+
+(define_insn_and_split "*clear_upper32"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
+ (const_int 4294967295)))]
+ "TARGET_64BIT"
+{
+ if (which_alternative == 0)
+ return "#";
+
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ return "lwu\t%0,%1";
+}
+ "&& reload_completed && REG_P (operands[1])"
+ [(set (match_dup 0)
+ (ashift:DI (match_dup 1) (const_int 32)))
+ (set (match_dup 0)
+ (lshiftrt:DI (match_dup 0) (const_int 32)))]
+ ""
+ [(set_attr "type" "multi,load")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8,*")])
+
+(define_expand "zero_extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand")
+ (zero_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
+ ""
+{
+ if (TARGET_MIPS16 && !GENERATE_MIPS16E
+ && !memory_operand (operands[1], <SHORT:MODE>mode))
+ {
+ emit_insn (gen_and<GPR:mode>3 (operands[0],
+ gen_lowpart (<GPR:MODE>mode, operands[1]),
+ force_reg (<GPR:MODE>mode,
+ GEN_INT (<SHORT:mask>))));
+ DONE;
+ }
+})
+
+(define_insn "*zero_extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (zero_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
+ "!TARGET_MIPS16"
+ "@
+ andi\t%0,%1,<SHORT:mask>
+ l<SHORT:size>u\t%0,%1"
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16e"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extend:GPR (match_operand:SHORT 1 "register_operand" "0")))]
+ "GENERATE_MIPS16E"
+ "ze<SHORT:size>\t%0"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*zero_extend<SHORT:mode><GPR:mode>2_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extend:GPR (match_operand:SHORT 1 "memory_operand" "m")))]
+ "TARGET_MIPS16"
+ "l<SHORT:size>u\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_expand "zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand")))]
+ ""
+{
+ if (TARGET_MIPS16 && !memory_operand (operands[1], QImode))
+ {
+ emit_insn (gen_zero_extendqisi2 (gen_lowpart (SImode, operands[0]),
+ operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "*zero_extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "!TARGET_MIPS16"
+ "@
+ andi\t%0,%1,0x00ff
+ lbu\t%0,%1"
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "HI")])
+
+(define_insn "*zero_extendqihi2_mips16"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
+ "TARGET_MIPS16"
+ "lbu\t%0,%1"
+ [(set_attr "type" "load")
+ (set_attr "mode" "HI")])
+
+;;
+;; ....................
+;;
+;; SIGN EXTENSION
+;;
+;; ....................
+
+;; Extension insns.
+;; Those for integer source operand are ordered widest source type first.
+
+;; When TARGET_64BIT, all SImode integer registers should already be in
+;; sign-extended form (see TRULY_NOOP_TRUNCATION and truncdisi2). We can
+;; therefore get rid of register->register instructions if we constrain
+;; the source to be in the same register as the destination.
+;;
+;; The register alternative has type "arith" so that the pre-reload
+;; scheduler will treat it as a move. This reflects what happens if
+;; the register alternative needs a reload.
+(define_insn_and_split "extendsidi2"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "0,m")))]
+ "TARGET_64BIT"
+ "@
+ #
+ lw\t%0,%1"
+ "&& reload_completed && register_operand (operands[1], VOIDmode)"
+ [(const_int 0)]
+{
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+}
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "DI")])
+
+(define_expand "extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand")
+ (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand")))]
+ "")
+
+(define_insn "*extend<SHORT:mode><GPR:mode>2_mips16e"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR (match_operand:SHORT 1 "nonimmediate_operand" "0,m")))]
+ "GENERATE_MIPS16E"
+ "@
+ se<SHORT:size>\t%0
+ l<SHORT:size>\t%0,%1"
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn_and_split "*extend<SHORT:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
+ "!ISA_HAS_SEB_SEH && !GENERATE_MIPS16E"
+ "@
+ #
+ l<SHORT:size>\t%0,%1"
+ "&& reload_completed && REG_P (operands[1])"
+ [(set (match_dup 0) (ashift:GPR (match_dup 1) (match_dup 2)))
+ (set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))]
+{
+ operands[1] = gen_lowpart (<GPR:MODE>mode, operands[1]);
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<GPR:MODE>mode)
+ - GET_MODE_BITSIZE (<SHORT:MODE>mode));
+}
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")
+ (set_attr "length" "8,*")])
+
+(define_insn "*extend<SHORT:mode><GPR:mode>2_se<SHORT:size>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR
+ (match_operand:SHORT 1 "nonimmediate_operand" "d,m")))]
+ "ISA_HAS_SEB_SEH"
+ "@
+ se<SHORT:size>\t%0,%1
+ l<SHORT:size>\t%0,%1"
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "<GPR:MODE>")])
+
+;; This pattern generates the same code as extendqisi2; split it into
+;; that form after reload.
+(define_insn_and_split "extendqihi2"
+ [(set (match_operand:HI 0 "register_operand" "=d,d")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (sign_extend:SI (match_dup 1)))]
+ { operands[0] = gen_lowpart (SImode, operands[0]); }
+ [(set_attr "type" "arith,load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "8,*")])
+
+(define_insn "extendsfdf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "cvt.d.s\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "cnv_mode" "S2D")
+ (set_attr "mode" "DF")])
+
+;;
+;; ....................
+;;
+;; CONVERSIONS
+;;
+;; ....................
+
+(define_expand "fix_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand")
+ (fix:SI (match_operand:DF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+{
+ if (!ISA_HAS_TRUNC_W)
+ {
+ emit_insn (gen_fix_truncdfsi2_macro (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "fix_truncdfsi2_insn"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && ISA_HAS_TRUNC_W"
+ "trunc.w.d %0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "DF")
+ (set_attr "cnv_mode" "D2I")
+ (set_attr "length" "4")])
+
+(define_insn "fix_truncdfsi2_macro"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:DF 1 "register_operand" "f")))
+ (clobber (match_scratch:DF 2 "=d"))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !ISA_HAS_TRUNC_W"
+{
+ if (set_nomacro)
+ return ".set\tmacro\;trunc.w.d %0,%1,%2\;.set\tnomacro";
+ else
+ return "trunc.w.d %0,%1,%2";
+}
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "DF")
+ (set_attr "cnv_mode" "D2I")
+ (set_attr "length" "36")])
+
+(define_expand "fix_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand")
+ (fix:SI (match_operand:SF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT"
+{
+ if (!ISA_HAS_TRUNC_W)
+ {
+ emit_insn (gen_fix_truncsfsi2_macro (operands[0], operands[1]));
+ DONE;
+ }
+})
+
+(define_insn "fix_truncsfsi2_insn"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:SF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && ISA_HAS_TRUNC_W"
+ "trunc.w.s %0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")
+ (set_attr "cnv_mode" "S2I")
+ (set_attr "length" "4")])
+
+(define_insn "fix_truncsfsi2_macro"
+ [(set (match_operand:SI 0 "register_operand" "=f")
+ (fix:SI (match_operand:SF 1 "register_operand" "f")))
+ (clobber (match_scratch:SF 2 "=d"))]
+ "TARGET_HARD_FLOAT && !ISA_HAS_TRUNC_W"
+{
+ if (set_nomacro)
+ return ".set\tmacro\;trunc.w.s %0,%1,%2\;.set\tnomacro";
+ else
+ return "trunc.w.s %0,%1,%2";
+}
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")
+ (set_attr "cnv_mode" "S2I")
+ (set_attr "length" "36")])
+
+
+(define_insn "fix_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (fix:DI (match_operand:DF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
+ "trunc.l.d %0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "DF")
+ (set_attr "cnv_mode" "D2I")
+ (set_attr "length" "4")])
+
+
+(define_insn "fix_truncsfdi2"
+ [(set (match_operand:DI 0 "register_operand" "=f")
+ (fix:DI (match_operand:SF 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
+ "trunc.l.s %0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")
+ (set_attr "cnv_mode" "S2I")
+ (set_attr "length" "4")])
+
+
+(define_insn "floatsidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:SI 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+ "cvt.d.w\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "DF")
+ (set_attr "cnv_mode" "I2D")
+ (set_attr "length" "4")])
+
+
+(define_insn "floatdidf2"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float:DF (match_operand:DI 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
+ "cvt.d.l\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "DF")
+ (set_attr "cnv_mode" "I2D")
+ (set_attr "length" "4")])
+
+
+(define_insn "floatsisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:SI 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT"
+ "cvt.s.w\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")
+ (set_attr "cnv_mode" "I2S")
+ (set_attr "length" "4")])
+
+
+(define_insn "floatdisf2"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float:SF (match_operand:DI 1 "register_operand" "f")))]
+ "TARGET_HARD_FLOAT && TARGET_FLOAT64 && TARGET_DOUBLE_FLOAT"
+ "cvt.s.l\t%0,%1"
+ [(set_attr "type" "fcvt")
+ (set_attr "mode" "SF")
+ (set_attr "cnv_mode" "I2S")
+ (set_attr "length" "4")])
+
+
+(define_expand "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "register_operand")
+ (unsigned_fix:SI (match_operand:DF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+{
+ rtx reg1 = gen_reg_rtx (DFmode);
+ rtx reg2 = gen_reg_rtx (DFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset;
+
+ real_2expN (&offset, 31);
+
+ if (reg1) /* Turn off complaints about unreached code. */
+ {
+ emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
+ do_pending_stack_adjust ();
+
+ emit_insn (gen_cmpdf (operands[1], reg1));
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1));
+ emit_move_insn (reg3, GEN_INT (trunc_int_for_mode
+ (BITMASK_HIGH, SImode)));
+
+ emit_insn (gen_fix_truncdfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* Allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ DONE;
+ }
+})
+
+
+(define_expand "fixuns_truncdfdi2"
+ [(set (match_operand:DI 0 "register_operand")
+ (unsigned_fix:DI (match_operand:DF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
+{
+ rtx reg1 = gen_reg_rtx (DFmode);
+ rtx reg2 = gen_reg_rtx (DFmode);
+ rtx reg3 = gen_reg_rtx (DImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset;
+
+ real_2expN (&offset, 63);
+
+ emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, DFmode));
+ do_pending_stack_adjust ();
+
+ emit_insn (gen_cmpdf (operands[1], reg1));
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncdfdi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx_MINUS (DFmode, operands[1], reg1));
+ emit_move_insn (reg3, GEN_INT (BITMASK_HIGH));
+ emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32)));
+
+ emit_insn (gen_fix_truncdfdi2 (operands[0], reg2));
+ emit_insn (gen_iordi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* Allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ DONE;
+})
+
+
+(define_expand "fixuns_truncsfsi2"
+ [(set (match_operand:SI 0 "register_operand")
+ (unsigned_fix:SI (match_operand:SF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT"
+{
+ rtx reg1 = gen_reg_rtx (SFmode);
+ rtx reg2 = gen_reg_rtx (SFmode);
+ rtx reg3 = gen_reg_rtx (SImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset;
+
+ real_2expN (&offset, 31);
+
+ emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
+ do_pending_stack_adjust ();
+
+ emit_insn (gen_cmpsf (operands[1], reg1));
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1));
+ emit_move_insn (reg3, GEN_INT (trunc_int_for_mode
+ (BITMASK_HIGH, SImode)));
+
+ emit_insn (gen_fix_truncsfsi2 (operands[0], reg2));
+ emit_insn (gen_iorsi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* Allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ DONE;
+})
+
+
+(define_expand "fixuns_truncsfdi2"
+ [(set (match_operand:DI 0 "register_operand")
+ (unsigned_fix:DI (match_operand:SF 1 "register_operand")))]
+ "TARGET_HARD_FLOAT && TARGET_64BIT && TARGET_DOUBLE_FLOAT"
+{
+ rtx reg1 = gen_reg_rtx (SFmode);
+ rtx reg2 = gen_reg_rtx (SFmode);
+ rtx reg3 = gen_reg_rtx (DImode);
+ rtx label1 = gen_label_rtx ();
+ rtx label2 = gen_label_rtx ();
+ REAL_VALUE_TYPE offset;
+
+ real_2expN (&offset, 63);
+
+ emit_move_insn (reg1, CONST_DOUBLE_FROM_REAL_VALUE (offset, SFmode));
+ do_pending_stack_adjust ();
+
+ emit_insn (gen_cmpsf (operands[1], reg1));
+ emit_jump_insn (gen_bge (label1));
+
+ emit_insn (gen_fix_truncsfdi2 (operands[0], operands[1]));
+ emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, label2)));
+ emit_barrier ();
+
+ emit_label (label1);
+ emit_move_insn (reg2, gen_rtx_MINUS (SFmode, operands[1], reg1));
+ emit_move_insn (reg3, GEN_INT (BITMASK_HIGH));
+ emit_insn (gen_ashldi3 (reg3, reg3, GEN_INT (32)));
+
+ emit_insn (gen_fix_truncsfdi2 (operands[0], reg2));
+ emit_insn (gen_iordi3 (operands[0], operands[0], reg3));
+
+ emit_label (label2);
+
+ /* Allow REG_NOTES to be set on last insn (labels don't have enough
+ fields, and can't be used for REG_NOTES anyway). */
+ emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
+ DONE;
+})
+
+;;
+;; ....................
+;;
+;; DATA MOVEMENT
+;;
+;; ....................
+
+;; Bit field extract patterns which use lwl/lwr or ldl/ldr.
+
+(define_expand "extv"
+ [(set (match_operand 0 "register_operand")
+ (sign_extract (match_operand:QI 1 "memory_operand")
+ (match_operand 2 "immediate_operand")
+ (match_operand 3 "immediate_operand")))]
+ "!TARGET_MIPS16"
+{
+ if (mips_expand_unaligned_load (operands[0], operands[1],
+ INTVAL (operands[2]),
+ INTVAL (operands[3])))
+ DONE;
+ else
+ FAIL;
+})
+
+(define_expand "extzv"
+ [(set (match_operand 0 "register_operand")
+ (zero_extract (match_operand 1 "nonimmediate_operand")
+ (match_operand 2 "immediate_operand")
+ (match_operand 3 "immediate_operand")))]
+ "!TARGET_MIPS16"
+{
+ if (mips_expand_unaligned_load (operands[0], operands[1],
+ INTVAL (operands[2]),
+ INTVAL (operands[3])))
+ DONE;
+ else if (mips_use_ins_ext_p (operands[1], operands[2], operands[3]))
+ {
+ if (GET_MODE (operands[0]) == DImode)
+ emit_insn (gen_extzvdi (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_extzvsi (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+ else
+ FAIL;
+})
+
+(define_insn "extzv<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extract:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:SI 2 "immediate_operand" "I")
+ (match_operand:SI 3 "immediate_operand" "I")))]
+ "mips_use_ins_ext_p (operands[1], operands[2], operands[3])"
+ "<d>ext\t%0,%1,%3,%2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+
+(define_expand "insv"
+ [(set (zero_extract (match_operand 0 "nonimmediate_operand")
+ (match_operand 1 "immediate_operand")
+ (match_operand 2 "immediate_operand"))
+ (match_operand 3 "reg_or_0_operand"))]
+ "!TARGET_MIPS16"
+{
+ if (mips_expand_unaligned_store (operands[0], operands[3],
+ INTVAL (operands[1]),
+ INTVAL (operands[2])))
+ DONE;
+ else if (mips_use_ins_ext_p (operands[0], operands[1], operands[2]))
+ {
+ if (GET_MODE (operands[0]) == DImode)
+ emit_insn (gen_insvdi (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_insvsi (operands[0], operands[1], operands[2],
+ operands[3]));
+ DONE;
+ }
+ else
+ FAIL;
+})
+
+(define_insn "insv<mode>"
+ [(set (zero_extract:GPR (match_operand:GPR 0 "register_operand" "+d")
+ (match_operand:SI 1 "immediate_operand" "I")
+ (match_operand:SI 2 "immediate_operand" "I"))
+ (match_operand:GPR 3 "reg_or_0_operand" "dJ"))]
+ "mips_use_ins_ext_p (operands[0], operands[1], operands[2])"
+ "<d>ins\t%0,%z3,%2,%1"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+;; Unaligned word moves generated by the bit field patterns.
+;;
+;; As far as the rtl is concerned, both the left-part and right-part
+;; instructions can access the whole field. However, the real operand
+;; refers to just the first or the last byte (depending on endianness).
+;; We therefore use two memory operands to each instruction, one to
+;; describe the rtl effect and one to use in the assembly output.
+;;
+;; Operands 0 and 1 are the rtl-level target and source respectively.
+;; This allows us to use the standard length calculations for the "load"
+;; and "store" type attributes.
+
+(define_insn "mov_<load>l"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
+ (match_operand:QI 2 "memory_operand" "m")]
+ UNSPEC_LOAD_LEFT))]
+ "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
+ "<load>l\t%0,%2"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "mov_<load>r"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (unspec:GPR [(match_operand:BLK 1 "memory_operand" "m")
+ (match_operand:QI 2 "memory_operand" "m")
+ (match_operand:GPR 3 "register_operand" "0")]
+ UNSPEC_LOAD_RIGHT))]
+ "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[1])"
+ "<load>r\t%0,%2"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "mov_<store>l"
+ [(set (match_operand:BLK 0 "memory_operand" "=m")
+ (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+ (match_operand:QI 2 "memory_operand" "m")]
+ UNSPEC_STORE_LEFT))]
+ "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
+ "<store>l\t%z1,%2"
+ [(set_attr "type" "store")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "mov_<store>r"
+ [(set (match_operand:BLK 0 "memory_operand" "+m")
+ (unspec:BLK [(match_operand:GPR 1 "reg_or_0_operand" "dJ")
+ (match_operand:QI 2 "memory_operand" "m")
+ (match_dup 0)]
+ UNSPEC_STORE_RIGHT))]
+ "!TARGET_MIPS16 && mips_mem_fits_mode_p (<MODE>mode, operands[0])"
+ "<store>r\t%z1,%2"
+ [(set_attr "type" "store")
+ (set_attr "mode" "<MODE>")])
+
+;; An instruction to calculate the high part of a 64-bit SYMBOL_GENERAL.
+;; The required value is:
+;;
+;; (%highest(op1) << 48) + (%higher(op1) << 32) + (%hi(op1) << 16)
+;;
+;; which translates to:
+;;
+;; lui op0,%highest(op1)
+;; daddiu op0,op0,%higher(op1)
+;; dsll op0,op0,16
+;; daddiu op0,op0,%hi(op1)
+;; dsll op0,op0,16
+;;
+;; The split is deferred until after flow2 to allow the peephole2 below
+;; to take effect.
+(define_insn_and_split "*lea_high64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (high:DI (match_operand:DI 1 "general_symbolic_operand" "")))]
+ "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
+ "#"
+ "&& flow2_completed"
+ [(set (match_dup 0) (high:DI (match_dup 2)))
+ (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 2)))
+ (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))
+ (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
+ (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 16)))]
+{
+ operands[2] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
+ operands[3] = mips_unspec_address (operands[1], SYMBOL_64_MID);
+}
+ [(set_attr "length" "20")])
+
+;; Use a scratch register to reduce the latency of the above pattern
+;; on superscalar machines. The optimized sequence is:
+;;
+;; lui op1,%highest(op2)
+;; lui op0,%hi(op2)
+;; daddiu op1,op1,%higher(op2)
+;; dsll32 op1,op1,0
+;; daddu op1,op1,op0
+(define_peephole2
+ [(set (match_operand:DI 1 "register_operand")
+ (high:DI (match_operand:DI 2 "general_symbolic_operand")))
+ (match_scratch:DI 0 "d")]
+ "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS"
+ [(set (match_dup 1) (high:DI (match_dup 3)))
+ (set (match_dup 0) (high:DI (match_dup 4)))
+ (set (match_dup 1) (lo_sum:DI (match_dup 1) (match_dup 3)))
+ (set (match_dup 1) (ashift:DI (match_dup 1) (const_int 32)))
+ (set (match_dup 1) (plus:DI (match_dup 1) (match_dup 0)))]
+{
+ operands[3] = mips_unspec_address (operands[2], SYMBOL_64_HIGH);
+ operands[4] = mips_unspec_address (operands[2], SYMBOL_64_LOW);
+})
+
+;; On most targets, the expansion of (lo_sum (high X) X) for a 64-bit
+;; SYMBOL_GENERAL X will take 6 cycles. This next pattern allows combine
+;; to merge the HIGH and LO_SUM parts of a move if the HIGH part is only
+;; used once. We can then use the sequence:
+;;
+;; lui op0,%highest(op1)
+;; lui op2,%hi(op1)
+;; daddiu op0,op0,%higher(op1)
+;; daddiu op2,op2,%lo(op1)
+;; dsll32 op0,op0,0
+;; daddu op0,op0,op2
+;;
+;; which takes 4 cycles on most superscalar targets.
+(define_insn_and_split "*lea64"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (match_operand:DI 1 "general_symbolic_operand" ""))
+ (clobber (match_scratch:DI 2 "=&d"))]
+ "TARGET_EXPLICIT_RELOCS && ABI_HAS_64BIT_SYMBOLS && cse_not_expected"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (high:DI (match_dup 3)))
+ (set (match_dup 2) (high:DI (match_dup 4)))
+ (set (match_dup 0) (lo_sum:DI (match_dup 0) (match_dup 3)))
+ (set (match_dup 2) (lo_sum:DI (match_dup 2) (match_dup 4)))
+ (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
+ (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]
+{
+ operands[3] = mips_unspec_address (operands[1], SYMBOL_64_HIGH);
+ operands[4] = mips_unspec_address (operands[1], SYMBOL_64_LOW);
+}
+ [(set_attr "length" "24")])
+
+;; Insns to fetch a global symbol from a big GOT.
+
+(define_insn_and_split "*xgot_hi<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (high:P (match_operand:P 1 "global_got_operand" "")))]
+ "TARGET_EXPLICIT_RELOCS && TARGET_XGOT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (high:P (match_dup 2)))
+ (set (match_dup 0) (plus:P (match_dup 0) (match_dup 3)))]
+{
+ operands[2] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
+ operands[3] = pic_offset_table_rtx;
+}
+ [(set_attr "got" "xgot_high")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn_and_split "*xgot_lo<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (lo_sum:P (match_operand:P 1 "register_operand" "d")
+ (match_operand:P 2 "global_got_operand" "")))]
+ "TARGET_EXPLICIT_RELOCS && TARGET_XGOT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:P [(match_dup 1) (match_dup 3)] UNSPEC_LOAD_GOT))]
+ { operands[3] = mips_unspec_address (operands[2], SYMBOL_GOTOFF_GLOBAL); }
+ [(set_attr "got" "load")
+ (set_attr "mode" "<MODE>")])
+
+;; Insns to fetch a global symbol from a normal GOT.
+
+(define_insn_and_split "*got_disp<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (match_operand:P 1 "global_got_operand" ""))]
+ "TARGET_EXPLICIT_RELOCS && !TARGET_XGOT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_GLOBAL);
+}
+ [(set_attr "got" "load")
+ (set_attr "mode" "<MODE>")])
+
+;; Insns for loading the high part of a local symbol.
+
+(define_insn_and_split "*got_page<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (high:P (match_operand:P 1 "local_got_operand" "")))]
+ "TARGET_EXPLICIT_RELOCS"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (unspec:P [(match_dup 2) (match_dup 3)] UNSPEC_LOAD_GOT))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = mips_unspec_address (operands[1], SYMBOL_GOTOFF_PAGE);
+}
+ [(set_attr "got" "load")
+ (set_attr "mode" "<MODE>")])
+
+;; Lower-level instructions for loading an address from the GOT.
+;; We could use MEMs, but an unspec gives more optimization
+;; opportunities.
+
+(define_insn "load_got<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (unspec:P [(match_operand:P 1 "register_operand" "d")
+ (match_operand:P 2 "immediate_operand" "")]
+ UNSPEC_LOAD_GOT))]
+ ""
+ "<load>\t%0,%R2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "4")])
+
+;; Instructions for adding the low 16 bits of an address to a register.
+;; Operand 2 is the address: print_operand works out which relocation
+;; should be applied.
+
+(define_insn "*low<mode>"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (lo_sum:P (match_operand:P 1 "register_operand" "d")
+ (match_operand:P 2 "immediate_operand" "")))]
+ "!TARGET_MIPS16"
+ "<d>addiu\t%0,%1,%R2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*low<mode>_mips16"
+ [(set (match_operand:P 0 "register_operand" "=d")
+ (lo_sum:P (match_operand:P 1 "register_operand" "0")
+ (match_operand:P 2 "immediate_operand" "")))]
+ "TARGET_MIPS16"
+ "<d>addiu\t%0,%R2"
+ [(set_attr "type" "arith")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "8")])
+
+;; Allow combine to split complex const_int load sequences, using operand 2
+;; to store the intermediate results. See move_operand for details.
+(define_split
+ [(set (match_operand:GPR 0 "register_operand")
+ (match_operand:GPR 1 "splittable_const_int_operand"))
+ (clobber (match_operand:GPR 2 "register_operand"))]
+ ""
+ [(const_int 0)]
+{
+ mips_move_integer (operands[0], operands[2], INTVAL (operands[1]));
+ DONE;
+})
+
+;; Likewise, for symbolic operands.
+(define_split
+ [(set (match_operand:P 0 "register_operand")
+ (match_operand:P 1 "splittable_symbolic_operand"))
+ (clobber (match_operand:P 2 "register_operand"))]
+ ""
+ [(set (match_dup 0) (match_dup 1))]
+ { operands[1] = mips_split_symbol (operands[2], operands[1]); })
+
+;; 64-bit integer moves
+
+;; Unlike most other insns, the move insns can't be split with
+;; different predicates, because register spilling and other parts of
+;; the compiler, have memoized the insn number already.
+
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "")
+ (match_operand:DI 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (DImode, operands[0], operands[1]))
+ DONE;
+})
+
+;; For mips16, we need a special case to handle storing $31 into
+;; memory, since we don't have a constraint to match $31. This
+;; instruction can be generated by save_restore_insns.
+
+(define_insn "*mov<mode>_ra"
+ [(set (match_operand:GPR 0 "stack_operand" "=m")
+ (reg:GPR 31))]
+ "TARGET_MIPS16"
+ "<store>\t$31,%0"
+ [(set_attr "type" "store")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*movdi_32bit"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,m,*a,*d,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,i,m,d,*J*d,*a,*d,*m,*B*C*D,*B*C*D"))]
+ "!TARGET_64BIT && !TARGET_MIPS16
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,load,store,mthilo,mfhilo,xfer,load,xfer,store")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8,16,*,*,8,8,8,*,8,*")])
+
+(define_insn "*movdi_32bit_mips16"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m,*d")
+ (match_operand:DI 1 "move_operand" "d,d,y,K,N,m,d,*x"))]
+ "!TARGET_64BIT && TARGET_MIPS16
+ && (register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,arith,arith,arith,load,store,mfhilo")
+ (set_attr "mode" "DI")
+ (set_attr "length" "8,8,8,8,12,*,*,8")])
+
+(define_insn "*movdi_64bit"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*x,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:DI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*J*d,*d,*m,*B*C*D,*B*C*D"))]
+ "TARGET_64BIT && !TARGET_MIPS16
+ && (register_operand (operands[0], DImode)
+ || reg_or_0_operand (operands[1], DImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,mthilo,xfer,load,xfer,store")
+ (set_attr "mode" "DI")
+ (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,8,*,8,*")])
+
+(define_insn "*movdi_64bit_mips16"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m")
+ (match_operand:DI 1 "move_operand" "d,d,y,K,N,U,m,d"))]
+ "TARGET_64BIT && TARGET_MIPS16
+ && (register_operand (operands[0], DImode)
+ || register_operand (operands[1], DImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store")
+ (set_attr "mode" "DI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (const_int 4)
+ (const_int 4)
+ (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))
+ (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
+ (const_int 8)
+ (const_int 12))
+ (const_string "*")
+ (const_string "*")
+ (const_string "*")])])
+
+
+;; On the mips16, we can split ld $r,N($r) into an add and a load,
+;; when the original load is a 4 byte instruction but the add and the
+;; load are 2 2 byte instructions.
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand")
+ (mem:DI (plus:DI (match_dup 0)
+ (match_operand:DI 1 "const_int_operand"))))]
+ "TARGET_64BIT && TARGET_MIPS16 && reload_completed
+ && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -0x10)
+ || (INTVAL (operands[1]) >= 32 * 8
+ && INTVAL (operands[1]) <= 31 * 8 + 0x8)
+ || (INTVAL (operands[1]) >= 0
+ && INTVAL (operands[1]) < 32 * 8
+ && (INTVAL (operands[1]) & 7) != 0))"
+ [(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (mem:DI (plus:DI (match_dup 0) (match_dup 2))))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val < 0)
+ operands[2] = const0_rtx;
+ else if (val >= 32 * 8)
+ {
+ int off = val & 7;
+
+ operands[1] = GEN_INT (0x8 + off);
+ operands[2] = GEN_INT (val - off - 0x8);
+ }
+ else
+ {
+ int off = val & 7;
+
+ operands[1] = GEN_INT (off);
+ operands[2] = GEN_INT (val - off);
+ }
+})
+
+;; 32-bit Integer moves
+
+;; Unlike most other insns, the move insns can't be split with
+;; different predicates, because register spilling and other parts of
+;; the compiler, have memoized the insn number already.
+
+(define_expand "movsi"
+ [(set (match_operand:SI 0 "")
+ (match_operand:SI 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (SImode, operands[0], operands[1]))
+ DONE;
+})
+
+;; The difference between these two is whether or not ints are allowed
+;; in FP registers (off by default, use -mdebugh to enable).
+
+(define_insn "*movsi_internal"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,e,d,m,*f,*f,*f,*d,*m,*d,*z,*a,*d,*B*C*D,*B*C*D,*d,*m")
+ (match_operand:SI 1 "move_operand" "d,U,T,m,dJ,*f,*d*J,*m,*f,*f,*z,*d,*J*d,*A,*d,*m,*B*C*D,*B*C*D"))]
+ "!TARGET_MIPS16
+ && (register_operand (operands[0], SImode)
+ || reg_or_0_operand (operands[1], SImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,const,const,load,store,fmove,xfer,fpload,xfer,fpstore,xfer,xfer,mthilo,mfhilo,xfer,load,xfer,store")
+ (set_attr "mode" "SI")
+ (set_attr "length" "4,*,*,*,*,4,4,*,4,*,4,4,4,4,4,*,4,*")])
+
+(define_insn "*movsi_mips16"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,y,d,d,d,d,d,m")
+ (match_operand:SI 1 "move_operand" "d,d,y,K,N,U,m,d"))]
+ "TARGET_MIPS16
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,arith,arith,arith,const,load,store")
+ (set_attr "mode" "SI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (const_int 4)
+ (const_int 4)
+ (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))
+ (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
+ (const_int 8)
+ (const_int 12))
+ (const_string "*")
+ (const_string "*")
+ (const_string "*")])])
+
+;; On the mips16, we can split lw $r,N($r) into an add and a load,
+;; when the original load is a 4 byte instruction but the add and the
+;; load are 2 2 byte instructions.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (mem:SI (plus:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand"))))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -0x80)
+ || (INTVAL (operands[1]) >= 32 * 4
+ && INTVAL (operands[1]) <= 31 * 4 + 0x7c)
+ || (INTVAL (operands[1]) >= 0
+ && INTVAL (operands[1]) < 32 * 4
+ && (INTVAL (operands[1]) & 3) != 0))"
+ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (mem:SI (plus:SI (match_dup 0) (match_dup 2))))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val < 0)
+ operands[2] = const0_rtx;
+ else if (val >= 32 * 4)
+ {
+ int off = val & 3;
+
+ operands[1] = GEN_INT (0x7c + off);
+ operands[2] = GEN_INT (val - off - 0x7c);
+ }
+ else
+ {
+ int off = val & 3;
+
+ operands[1] = GEN_INT (off);
+ operands[2] = GEN_INT (val - off);
+ }
+})
+
+;; On the mips16, we can split a load of certain constants into a load
+;; and an add. This turns a 4 byte instruction into 2 2 byte
+;; instructions.
+
+(define_split
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "const_int_operand"))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && INTVAL (operands[1]) >= 0x100
+ && INTVAL (operands[1]) <= 0xff + 0x7f"
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 2)))]
+{
+ int val = INTVAL (operands[1]);
+
+ operands[1] = GEN_INT (0xff);
+ operands[2] = GEN_INT (val - 0xff);
+})
+
+;; This insn handles moving CCmode values. It's really just a
+;; slightly simplified copy of movsi_internal2, with additional cases
+;; to move a condition register to a general register and to move
+;; between the general registers and the floating point registers.
+
+(define_insn "movcc"
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=d,*d,*d,*m,*d,*f,*f,*f,*m")
+ (match_operand:CC 1 "general_operand" "z,*d,*m,*d,*f,*d,*f,*m,*f"))]
+ "ISA_HAS_8CC && TARGET_HARD_FLOAT"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "xfer,arith,load,store,xfer,xfer,fmove,fpload,fpstore")
+ (set_attr "mode" "SI")
+ (set_attr "length" "8,4,*,*,4,4,4,*,*")])
+
+;; Reload condition code registers. reload_incc and reload_outcc
+;; both handle moves from arbitrary operands into condition code
+;; registers. reload_incc handles the more common case in which
+;; a source operand is constrained to be in a condition-code
+;; register, but has not been allocated to one.
+;;
+;; Sometimes, such as in movcc, we have a CCmode destination whose
+;; constraints do not include 'z'. reload_outcc handles the case
+;; when such an operand is allocated to a condition-code register.
+;;
+;; Note that reloads from a condition code register to some
+;; other location can be done using ordinary moves. Moving
+;; into a GPR takes a single movcc, moving elsewhere takes
+;; two. We can leave these cases to the generic reload code.
+(define_expand "reload_incc"
+ [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
+ (match_operand:CC 1 "general_operand" ""))
+ (clobber (match_operand:TF 2 "register_operand" "=&f"))]
+ "ISA_HAS_8CC && TARGET_HARD_FLOAT"
+{
+ mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
+ DONE;
+})
+
+(define_expand "reload_outcc"
+ [(set (match_operand:CC 0 "fcc_reload_operand" "=z")
+ (match_operand:CC 1 "register_operand" ""))
+ (clobber (match_operand:TF 2 "register_operand" "=&f"))]
+ "ISA_HAS_8CC && TARGET_HARD_FLOAT"
+{
+ mips_emit_fcc_reload (operands[0], operands[1], operands[2]);
+ DONE;
+})
+
+;; MIPS4 supports loading and storing a floating point register from
+;; the sum of two general registers. We use two versions for each of
+;; these four instructions: one where the two general registers are
+;; SImode, and one where they are DImode. This is because general
+;; registers will be in SImode when they hold 32 bit values, but,
+;; since the 32 bit values are always sign extended, the [ls][wd]xc1
+;; instructions will still work correctly.
+
+;; ??? Perhaps it would be better to support these instructions by
+;; modifying GO_IF_LEGITIMATE_ADDRESS and friends. However, since
+;; these instructions can only be used to load and store floating
+;; point registers, that would probably cause trouble in reload.
+
+(define_insn "*<ANYF:loadx>_<P:mode>"
+ [(set (match_operand:ANYF 0 "register_operand" "=f")
+ (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
+ (match_operand:P 2 "register_operand" "d"))))]
+ "ISA_HAS_FP4"
+ "<ANYF:loadx>\t%0,%1(%2)"
+ [(set_attr "type" "fpidxload")
+ (set_attr "mode" "<ANYF:UNITMODE>")])
+
+(define_insn "*<ANYF:storex>_<P:mode>"
+ [(set (mem:ANYF (plus:P (match_operand:P 1 "register_operand" "d")
+ (match_operand:P 2 "register_operand" "d")))
+ (match_operand:ANYF 0 "register_operand" "f"))]
+ "ISA_HAS_FP4"
+ "<ANYF:storex>\t%0,%1(%2)"
+ [(set_attr "type" "fpidxstore")
+ (set_attr "mode" "<ANYF:UNITMODE>")])
+
+;; 16-bit Integer moves
+
+;; Unlike most other insns, the move insns can't be split with
+;; different predicates, because register spilling and other parts of
+;; the compiler, have memoized the insn number already.
+;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
+
+(define_expand "movhi"
+ [(set (match_operand:HI 0 "")
+ (match_operand:HI 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (HImode, operands[0], operands[1]))
+ DONE;
+})
+
+(define_insn "*movhi_internal"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
+ (match_operand:HI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))]
+ "!TARGET_MIPS16
+ && (register_operand (operands[0], HImode)
+ || reg_or_0_operand (operands[1], HImode))"
+ "@
+ move\t%0,%1
+ li\t%0,%1
+ lhu\t%0,%1
+ sh\t%z1,%0
+ mfc1\t%0,%1
+ mtc1\t%1,%0
+ mov.s\t%0,%1
+ mt%0\t%1"
+ [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo")
+ (set_attr "mode" "HI")
+ (set_attr "length" "4,4,*,*,4,4,4,4")])
+
+(define_insn "*movhi_mips16"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")
+ (match_operand:HI 1 "move_operand" "d,d,y,K,N,m,d"))]
+ "TARGET_MIPS16
+ && (register_operand (operands[0], HImode)
+ || register_operand (operands[1], HImode))"
+ "@
+ move\t%0,%1
+ move\t%0,%1
+ move\t%0,%1
+ li\t%0,%1
+ #
+ lhu\t%0,%1
+ sh\t%1,%0"
+ [(set_attr "type" "arith,arith,arith,arith,arith,load,store")
+ (set_attr "mode" "HI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (const_int 4)
+ (const_int 4)
+ (if_then_else (match_operand:VOID 1 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))
+ (if_then_else (match_operand:VOID 1 "m16_nuimm8_1")
+ (const_int 8)
+ (const_int 12))
+ (const_string "*")
+ (const_string "*")])])
+
+
+;; On the mips16, we can split lh $r,N($r) into an add and a load,
+;; when the original load is a 4 byte instruction but the add and the
+;; load are 2 2 byte instructions.
+
+(define_split
+ [(set (match_operand:HI 0 "register_operand")
+ (mem:HI (plus:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand"))))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -0x80)
+ || (INTVAL (operands[1]) >= 32 * 2
+ && INTVAL (operands[1]) <= 31 * 2 + 0x7e)
+ || (INTVAL (operands[1]) >= 0
+ && INTVAL (operands[1]) < 32 * 2
+ && (INTVAL (operands[1]) & 1) != 0))"
+ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (mem:HI (plus:SI (match_dup 0) (match_dup 2))))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val < 0)
+ operands[2] = const0_rtx;
+ else if (val >= 32 * 2)
+ {
+ int off = val & 1;
+
+ operands[1] = GEN_INT (0x7e + off);
+ operands[2] = GEN_INT (val - off - 0x7e);
+ }
+ else
+ {
+ int off = val & 1;
+
+ operands[1] = GEN_INT (off);
+ operands[2] = GEN_INT (val - off);
+ }
+})
+
+;; 8-bit Integer moves
+
+;; Unlike most other insns, the move insns can't be split with
+;; different predicates, because register spilling and other parts of
+;; the compiler, have memoized the insn number already.
+;; Unsigned loads are used because LOAD_EXTEND_OP returns ZERO_EXTEND.
+
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "")
+ (match_operand:QI 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (QImode, operands[0], operands[1]))
+ DONE;
+})
+
+(define_insn "*movqi_internal"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,m,*d,*f,*f,*x")
+ (match_operand:QI 1 "move_operand" "d,I,m,dJ,*f,*d,*f,*d"))]
+ "!TARGET_MIPS16
+ && (register_operand (operands[0], QImode)
+ || reg_or_0_operand (operands[1], QImode))"
+ "@
+ move\t%0,%1
+ li\t%0,%1
+ lbu\t%0,%1
+ sb\t%z1,%0
+ mfc1\t%0,%1
+ mtc1\t%1,%0
+ mov.s\t%0,%1
+ mt%0\t%1"
+ [(set_attr "type" "arith,arith,load,store,xfer,xfer,fmove,mthilo")
+ (set_attr "mode" "QI")
+ (set_attr "length" "4,4,*,*,4,4,4,4")])
+
+(define_insn "*movqi_mips16"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,y,d,d,d,d,m")
+ (match_operand:QI 1 "move_operand" "d,d,y,K,N,m,d"))]
+ "TARGET_MIPS16
+ && (register_operand (operands[0], QImode)
+ || register_operand (operands[1], QImode))"
+ "@
+ move\t%0,%1
+ move\t%0,%1
+ move\t%0,%1
+ li\t%0,%1
+ #
+ lbu\t%0,%1
+ sb\t%1,%0"
+ [(set_attr "type" "arith,arith,arith,arith,arith,load,store")
+ (set_attr "mode" "QI")
+ (set_attr "length" "4,4,4,4,8,*,*")])
+
+;; On the mips16, we can split lb $r,N($r) into an add and a load,
+;; when the original load is a 4 byte instruction but the add and the
+;; load are 2 2 byte instructions.
+
+(define_split
+ [(set (match_operand:QI 0 "register_operand")
+ (mem:QI (plus:SI (match_dup 0)
+ (match_operand:SI 1 "const_int_operand"))))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && REG_P (operands[0])
+ && M16_REG_P (REGNO (operands[0]))
+ && GET_CODE (operands[1]) == CONST_INT
+ && ((INTVAL (operands[1]) < 0
+ && INTVAL (operands[1]) >= -0x80)
+ || (INTVAL (operands[1]) >= 32
+ && INTVAL (operands[1]) <= 31 + 0x7f))"
+ [(set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))
+ (set (match_dup 0) (mem:QI (plus:SI (match_dup 0) (match_dup 2))))]
+{
+ HOST_WIDE_INT val = INTVAL (operands[1]);
+
+ if (val < 0)
+ operands[2] = const0_rtx;
+ else
+ {
+ operands[1] = GEN_INT (0x7f);
+ operands[2] = GEN_INT (val - 0x7f);
+ }
+})
+
+;; 32-bit floating point moves
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "")
+ (match_operand:SF 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (SFmode, operands[0], operands[1]))
+ DONE;
+})
+
+(define_insn "*movsf_hardfloat"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
+ (match_operand:SF 1 "move_operand" "f,G,m,f,G,*d,*f,*G*d,*m,*d"))]
+ "TARGET_HARD_FLOAT
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
+
+(define_insn "*movsf_softfloat"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,m")
+ (match_operand:SF 1 "move_operand" "Gd,m,d"))]
+ "TARGET_SOFT_FLOAT && !TARGET_MIPS16
+ && (register_operand (operands[0], SFmode)
+ || reg_or_0_operand (operands[1], SFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,load,store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "4,*,*")])
+
+(define_insn "*movsf_mips16"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=d,y,d,d,m")
+ (match_operand:SF 1 "move_operand" "d,d,y,m,d"))]
+ "TARGET_MIPS16
+ && (register_operand (operands[0], SFmode)
+ || register_operand (operands[1], SFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,arith,load,store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "4,4,4,*,*")])
+
+
+;; 64-bit floating point moves
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "")
+ (match_operand:DF 1 ""))]
+ ""
+{
+ if (mips_legitimize_move (DFmode, operands[0], operands[1]))
+ DONE;
+})
+
+(define_insn "*movdf_hardfloat_64bit"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && TARGET_64BIT
+ && (register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
+
+(define_insn "*movdf_hardfloat_32bit"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
+ (match_operand:DF 1 "move_operand" "f,G,m,f,G,*d,*f,*d*G,*m,*d"))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT
+ && (register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "4,8,*,*,*,8,8,8,*,*")])
+
+(define_insn "*movdf_softfloat"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,m,d,f,f")
+ (match_operand:DF 1 "move_operand" "dG,m,dG,f,d,f"))]
+ "(TARGET_SOFT_FLOAT || TARGET_SINGLE_FLOAT) && !TARGET_MIPS16
+ && (register_operand (operands[0], DFmode)
+ || reg_or_0_operand (operands[1], DFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,load,store,xfer,xfer,fmove")
+ (set_attr "mode" "DF")
+ (set_attr "length" "8,*,*,4,4,4")])
+
+(define_insn "*movdf_mips16"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=d,y,d,d,m")
+ (match_operand:DF 1 "move_operand" "d,d,y,m,d"))]
+ "TARGET_MIPS16
+ && (register_operand (operands[0], DFmode)
+ || register_operand (operands[1], DFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "arith,arith,arith,load,store")
+ (set_attr "mode" "DF")
+ (set_attr "length" "8,8,8,*,*")])
+
+(define_split
+ [(set (match_operand:DI 0 "nonimmediate_operand")
+ (match_operand:DI 1 "move_operand"))]
+ "reload_completed && !TARGET_64BIT
+ && mips_split_64bit_move_p (operands[0], operands[1])"
+ [(const_int 0)]
+{
+ mips_split_64bit_move (operands[0], operands[1]);
+ DONE;
+})
+
+(define_split
+ [(set (match_operand:DF 0 "nonimmediate_operand")
+ (match_operand:DF 1 "move_operand"))]
+ "reload_completed && !TARGET_64BIT
+ && mips_split_64bit_move_p (operands[0], operands[1])"
+ [(const_int 0)]
+{
+ mips_split_64bit_move (operands[0], operands[1]);
+ DONE;
+})
+
+;; When generating mips16 code, split moves of negative constants into
+;; a positive "li" followed by a negation.
+(define_split
+ [(set (match_operand 0 "register_operand")
+ (match_operand 1 "const_int_operand"))]
+ "TARGET_MIPS16 && reload_completed && INTVAL (operands[1]) < 0"
+ [(set (match_dup 2)
+ (match_dup 3))
+ (set (match_dup 2)
+ (neg:SI (match_dup 2)))]
+{
+ operands[2] = gen_lowpart (SImode, operands[0]);
+ operands[3] = GEN_INT (-INTVAL (operands[1]));
+})
+
+;; 64-bit paired-single floating point moves
+
+(define_expand "movv2sf"
+ [(set (match_operand:V2SF 0)
+ (match_operand:V2SF 1))]
+ "TARGET_PAIRED_SINGLE_FLOAT"
+{
+ if (mips_legitimize_move (V2SFmode, operands[0], operands[1]))
+ DONE;
+})
+
+(define_insn "movv2sf_hardfloat_64bit"
+ [(set (match_operand:V2SF 0 "nonimmediate_operand" "=f,f,f,m,m,*f,*d,*d,*d,*m")
+ (match_operand:V2SF 1 "move_operand" "f,YG,m,f,YG,*d,*f,*d*YG,*m,*d"))]
+ "TARGET_PAIRED_SINGLE_FLOAT
+ && TARGET_64BIT
+ && (register_operand (operands[0], V2SFmode)
+ || reg_or_0_operand (operands[1], V2SFmode))"
+ { return mips_output_move (operands[0], operands[1]); }
+ [(set_attr "type" "fmove,xfer,fpload,fpstore,store,xfer,xfer,arith,load,store")
+ (set_attr "mode" "SF")
+ (set_attr "length" "4,4,*,*,*,4,4,4,*,*")])
+
+;; The HI and LO registers are not truly independent. If we move an mthi
+;; instruction before an mflo instruction, it will make the result of the
+;; mflo unpredictable. The same goes for mtlo and mfhi.
+;;
+;; We cope with this by making the mflo and mfhi patterns use both HI and LO.
+;; Operand 1 is the register we want, operand 2 is the other one.
+;;
+;; When generating VR4120 or VR4130 code, we use macc{,hi} and
+;; dmacc{,hi} instead of mfhi and mflo. This avoids both the normal
+;; MIPS III hi/lo hazards and the errata related to -mfix-vr4130.
+
+(define_expand "mfhilo_<mode>"
+ [(set (match_operand:GPR 0 "register_operand")
+ (unspec:GPR [(match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "register_operand")]
+ UNSPEC_MFHILO))])
+
+(define_insn "*mfhilo_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l")
+ (match_operand:GPR 2 "register_operand" "l,h")]
+ UNSPEC_MFHILO))]
+ "!ISA_HAS_MACCHI"
+ "mf%1\t%0"
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*mfhilo_<mode>_macc"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (unspec:GPR [(match_operand:GPR 1 "register_operand" "h,l")
+ (match_operand:GPR 2 "register_operand" "l,h")]
+ UNSPEC_MFHILO))]
+ "ISA_HAS_MACCHI"
+{
+ if (REGNO (operands[1]) == HI_REGNUM)
+ return "<d>macchi\t%0,%.,%.";
+ else
+ return "<d>macc\t%0,%.,%.";
+}
+ [(set_attr "type" "mfhilo")
+ (set_attr "mode" "<MODE>")])
+
+;; Patterns for loading or storing part of a paired floating point
+;; register. We need them because odd-numbered floating-point registers
+;; are not fully independent: see mips_split_64bit_move.
+
+;; Load the low word of operand 0 with operand 1.
+(define_insn "load_df_low"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")]
+ UNSPEC_LOAD_DF_LOW))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
+{
+ operands[0] = mips_subword (operands[0], 0);
+ return mips_output_move (operands[0], operands[1]);
+}
+ [(set_attr "type" "xfer,fpload")
+ (set_attr "mode" "SF")])
+
+;; Load the high word of operand 0 from operand 1, preserving the value
+;; in the low word.
+(define_insn "load_df_high"
+ [(set (match_operand:DF 0 "register_operand" "=f,f")
+ (unspec:DF [(match_operand:SI 1 "general_operand" "dJ,m")
+ (match_operand:DF 2 "register_operand" "0,0")]
+ UNSPEC_LOAD_DF_HIGH))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
+{
+ operands[0] = mips_subword (operands[0], 1);
+ return mips_output_move (operands[0], operands[1]);
+}
+ [(set_attr "type" "xfer,fpload")
+ (set_attr "mode" "SF")])
+
+;; Store the high word of operand 1 in operand 0. The corresponding
+;; low-word move is done in the normal way.
+(define_insn "store_df_high"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,m")
+ (unspec:SI [(match_operand:DF 1 "register_operand" "f,f")]
+ UNSPEC_STORE_DF_HIGH))]
+ "TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT && !TARGET_64BIT"
+{
+ operands[1] = mips_subword (operands[1], 1);
+ return mips_output_move (operands[0], operands[1]);
+}
+ [(set_attr "type" "xfer,fpstore")
+ (set_attr "mode" "SF")])
+
+;; Insn to initialize $gp for n32/n64 abicalls. Operand 0 is the offset
+;; of _gp from the start of this function. Operand 1 is the incoming
+;; function address.
+(define_insn_and_split "loadgp"
+ [(unspec_volatile [(match_operand 0 "" "")
+ (match_operand 1 "register_operand" "")] UNSPEC_LOADGP)]
+ "mips_current_loadgp_style () == LOADGP_NEWABI"
+ "#"
+ ""
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 2) (match_dup 4))
+ (set (match_dup 2) (match_dup 5))]
+{
+ operands[2] = pic_offset_table_rtx;
+ operands[3] = gen_rtx_HIGH (Pmode, operands[0]);
+ operands[4] = gen_rtx_PLUS (Pmode, operands[2], operands[1]);
+ operands[5] = gen_rtx_LO_SUM (Pmode, operands[2], operands[0]);
+}
+ [(set_attr "length" "12")])
+
+;; Likewise, for -mno-shared code. Operand 0 is the __gnu_local_gp symbol.
+(define_insn_and_split "loadgp_noshared"
+ [(unspec_volatile [(match_operand 0 "" "")] UNSPEC_LOADGP)]
+ "mips_current_loadgp_style () == LOADGP_ABSOLUTE"
+ "#"
+ ""
+ [(const_int 0)]
+{
+ emit_move_insn (pic_offset_table_rtx, operands[0]);
+ DONE;
+}
+ [(set_attr "length" "8")])
+
+;; The use of gp is hidden when not using explicit relocations.
+;; This blockage instruction prevents the gp load from being
+;; scheduled after an implicit use of gp. It also prevents
+;; the load from being deleted as dead.
+(define_insn "loadgp_blockage"
+ [(unspec_volatile [(reg:DI 28)] UNSPEC_BLOCKAGE)]
+ ""
+ ""
+ [(set_attr "type" "unknown")
+ (set_attr "mode" "none")
+ (set_attr "length" "0")])
+
+;; Emit a .cprestore directive, which normally expands to a single store
+;; instruction. Note that we continue to use .cprestore for explicit reloc
+;; code so that jals inside inline asms will work correctly.
+(define_insn "cprestore"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "I,i")]
+ UNSPEC_CPRESTORE)]
+ ""
+{
+ if (set_nomacro && which_alternative == 1)
+ return ".set\tmacro\;.cprestore\t%0\;.set\tnomacro";
+ else
+ return ".cprestore\t%0";
+}
+ [(set_attr "type" "store")
+ (set_attr "length" "4,12")])
+
+;; Block moves, see mips.c for more details.
+;; Argument 0 is the destination
+;; Argument 1 is the source
+;; Argument 2 is the length
+;; Argument 3 is the alignment
+
+(define_expand "movmemsi"
+ [(parallel [(set (match_operand:BLK 0 "general_operand")
+ (match_operand:BLK 1 "general_operand"))
+ (use (match_operand:SI 2 ""))
+ (use (match_operand:SI 3 "const_int_operand"))])]
+ "!TARGET_MIPS16 && !TARGET_MEMCPY"
+{
+ if (mips_expand_block_move (operands[0], operands[1], operands[2]))
+ DONE;
+ else
+ FAIL;
+})
+
+;;
+;; ....................
+;;
+;; SHIFTS
+;;
+;; ....................
+
+(define_expand "<optab><mode>3"
+ [(set (match_operand:GPR 0 "register_operand")
+ (any_shift:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:SI 2 "arith_operand")))]
+ ""
+{
+ /* On the mips16, a shift of more than 8 is a four byte instruction,
+ so, for a shift between 8 and 16, it is just as fast to do two
+ shifts of 8 or less. If there is a lot of shifting going on, we
+ may win in CSE. Otherwise combine will put the shifts back
+ together again. This can be called by function_arg, so we must
+ be careful not to allocate a new register if we've reached the
+ reload pass. */
+ if (TARGET_MIPS16
+ && optimize
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16
+ && !reload_in_progress
+ && !reload_completed)
+ {
+ rtx temp = gen_reg_rtx (<MODE>mode);
+
+ emit_insn (gen_<optab><mode>3 (temp, operands[1], GEN_INT (8)));
+ emit_insn (gen_<optab><mode>3 (operands[0], temp,
+ GEN_INT (INTVAL (operands[2]) - 8)));
+ DONE;
+ }
+})
+
+(define_insn "*<optab><mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (any_shift:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:SI 2 "arith_operand" "dI")))]
+ "!TARGET_MIPS16"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2])
+ & (GET_MODE_BITSIZE (<MODE>mode) - 1));
+
+ return "<d><insn>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*<optab>si3_extend"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI
+ (any_shift:SI (match_operand:SI 1 "register_operand" "d")
+ (match_operand:SI 2 "arith_operand" "dI"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+
+ return "<insn>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")])
+
+(define_insn "*<optab>si3_mips16"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (any_shift:SI (match_operand:SI 1 "register_operand" "0,d")
+ (match_operand:SI 2 "arith_operand" "d,I")))]
+ "TARGET_MIPS16"
+{
+ if (which_alternative == 0)
+ return "<insn>\t%0,%2";
+
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
+ return "<insn>\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "SI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm3_b")
+ (const_int 4)
+ (const_int 8))])])
+
+;; We need separate DImode MIPS16 patterns because of the irregularity
+;; of right shifts.
+(define_insn "*ashldi3_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashift:DI (match_operand:DI 1 "register_operand" "0,d")
+ (match_operand:SI 2 "arith_operand" "d,I")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+{
+ if (which_alternative == 0)
+ return "dsll\t%0,%2";
+
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
+ return "dsll\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "DI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm3_b")
+ (const_int 4)
+ (const_int 8))])])
+
+(define_insn "*ashrdi3_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "arith_operand" "d,I")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
+
+ return "dsra\t%0,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "DI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm3_b")
+ (const_int 4)
+ (const_int 8))])])
+
+(define_insn "*lshrdi3_mips16"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (lshiftrt:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:SI 2 "arith_operand" "d,I")))]
+ "TARGET_64BIT && TARGET_MIPS16"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
+
+ return "dsrl\t%0,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "DI")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm3_b")
+ (const_int 4)
+ (const_int 8))])])
+
+;; On the mips16, we can split a 4 byte shift into 2 2 byte shifts.
+
+(define_split
+ [(set (match_operand:GPR 0 "register_operand")
+ (any_shift:GPR (match_operand:GPR 1 "register_operand")
+ (match_operand:GPR 2 "const_int_operand")))]
+ "TARGET_MIPS16 && reload_completed && !TARGET_DEBUG_D_MODE
+ && GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) > 8
+ && INTVAL (operands[2]) <= 16"
+ [(set (match_dup 0) (any_shift:GPR (match_dup 1) (const_int 8)))
+ (set (match_dup 0) (any_shift:GPR (match_dup 0) (match_dup 2)))]
+ { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); })
+
+;; If we load a byte on the mips16 as a bitfield, the resulting
+;; sequence of instructions is too complicated for combine, because it
+;; involves four instructions: a load, a shift, a constant load into a
+;; register, and an and (the key problem here is that the mips16 does
+;; not have and immediate). We recognize a shift of a load in order
+;; to make it simple enough for combine to understand.
+;;
+;; The length here is the worst case: the length of the split version
+;; will be more accurate.
+(define_insn_and_split ""
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (lshiftrt:SI (match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "immediate_operand" "I")))]
+ "TARGET_MIPS16"
+ "#"
+ ""
+ [(set (match_dup 0) (match_dup 1))
+ (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+ ""
+ [(set_attr "type" "load")
+ (set_attr "mode" "SI")
+ (set_attr "length" "16")])
+
+(define_insn "rotr<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (rotatert:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:SI 2 "arith_operand" "dI")))]
+ "ISA_HAS_ROTR_<MODE>"
+{
+ if (GET_CODE (operands[2]) == CONST_INT)
+ gcc_assert (INTVAL (operands[2]) >= 0
+ && INTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode));
+
+ return "<d>ror\t%0,%1,%2";
+}
+ [(set_attr "type" "shift")
+ (set_attr "mode" "<MODE>")])
+
+;;
+;; ....................
+;;
+;; COMPARISONS
+;;
+;; ....................
+
+;; Flow here is rather complex:
+;;
+;; 1) The cmp{si,di,sf,df} routine is called. It deposits the arguments
+;; into cmp_operands[] but generates no RTL.
+;;
+;; 2) The appropriate branch define_expand is called, which then
+;; creates the appropriate RTL for the comparison and branch.
+;; Different CC modes are used, based on what type of branch is
+;; done, so that we can constrain things appropriately. There
+;; are assumptions in the rest of GCC that break if we fold the
+;; operands into the branches for integer operations, and use cc0
+;; for floating point, so we use the fp status register instead.
+;; If needed, an appropriate temporary is created to hold the
+;; of the integer compare.
+
+(define_expand "cmp<mode>"
+ [(set (cc0)
+ (compare:CC (match_operand:GPR 0 "register_operand")
+ (match_operand:GPR 1 "nonmemory_operand")))]
+ ""
+{
+ cmp_operands[0] = operands[0];
+ cmp_operands[1] = operands[1];
+ DONE;
+})
+
+(define_expand "cmp<mode>"
+ [(set (cc0)
+ (compare:CC (match_operand:SCALARF 0 "register_operand")
+ (match_operand:SCALARF 1 "register_operand")))]
+ ""
+{
+ cmp_operands[0] = operands[0];
+ cmp_operands[1] = operands[1];
+ DONE;
+})
+
+;;
+;; ....................
+;;
+;; CONDITIONAL BRANCHES
+;;
+;; ....................
+
+;; Conditional branches on floating-point equality tests.
+
+(define_insn "*branch_fp"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:CC 2 "register_operand" "z")
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "TARGET_HARD_FLOAT"
+{
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%F0", "%Z2%1"),
+ MIPS_BRANCH ("b%W0", "%Z2%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+(define_insn "*branch_fp_inverted"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:CC 2 "register_operand" "z")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "TARGET_HARD_FLOAT"
+{
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%W0", "%Z2%1"),
+ MIPS_BRANCH ("b%F0", "%Z2%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+;; Conditional branches on ordered comparisons with zero.
+
+(define_insn "*branch_order<mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "order_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (const_int 0)])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "!TARGET_MIPS16"
+ { return mips_output_order_conditional_branch (insn, operands, false); }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+(define_insn "*branch_order<mode>_inverted"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "order_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (const_int 0)])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "!TARGET_MIPS16"
+ { return mips_output_order_conditional_branch (insn, operands, true); }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+;; Conditional branch on equality comparison.
+
+(define_insn "*branch_equality<mode>"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
+ (label_ref (match_operand 1 "" ""))
+ (pc)))]
+ "!TARGET_MIPS16"
+{
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%C0", "%2,%z3,%1"),
+ MIPS_BRANCH ("b%N0", "%2,%z3,%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+(define_insn "*branch_equality<mode>_inverted"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 2 "register_operand" "d")
+ (match_operand:GPR 3 "reg_or_0_operand" "dJ")])
+ (pc)
+ (label_ref (match_operand 1 "" ""))))]
+ "!TARGET_MIPS16"
+{
+ return mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("b%N0", "%2,%z3,%1"),
+ MIPS_BRANCH ("b%C0", "%2,%z3,%1"));
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")])
+
+;; MIPS16 branches
+
+(define_insn "*branch_equality<mode>_mips16"
+ [(set (pc)
+ (if_then_else
+ (match_operator 0 "equality_operator"
+ [(match_operand:GPR 1 "register_operand" "d,t")
+ (const_int 0)])
+ (match_operand 2 "pc_or_label_operand" "")
+ (match_operand 3 "pc_or_label_operand" "")))]
+ "TARGET_MIPS16"
+{
+ if (operands[2] != pc_rtx)
+ {
+ if (which_alternative == 0)
+ return "b%C0z\t%1,%2";
+ else
+ return "bt%C0z\t%2";
+ }
+ else
+ {
+ if (which_alternative == 0)
+ return "b%N0z\t%1,%3";
+ else
+ return "bt%N0z\t%3";
+ }
+}
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "length" "8")])
+
+(define_expand "b<code>"
+ [(set (pc)
+ (if_then_else (any_cond:CC (cc0)
+ (const_int 0))
+ (label_ref (match_operand 0 ""))
+ (pc)))]
+ ""
+{
+ gen_conditional_branch (operands, <CODE>);
+ DONE;
+})
+
+;; Used to implement built-in functions.
+(define_expand "condjump"
+ [(set (pc)
+ (if_then_else (match_operand 0)
+ (label_ref (match_operand 1))
+ (pc)))])
+
+;;
+;; ....................
+;;
+;; SETTING A REGISTER FROM A COMPARISON
+;;
+;; ....................
+
+(define_expand "seq"
+ [(set (match_operand:SI 0 "register_operand")
+ (eq:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (EQ, operands[0])) DONE; else FAIL; })
+
+(define_insn "*seq_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (eq:GPR (match_operand:GPR 1 "register_operand" "d")
+ (const_int 0)))]
+ "!TARGET_MIPS16"
+ "sltu\t%0,%1,1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*seq_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t")
+ (eq:GPR (match_operand:GPR 1 "register_operand" "d")
+ (const_int 0)))]
+ "TARGET_MIPS16"
+ "sltu\t%1,1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+;; "sne" uses sltu instructions in which the first operand is $0.
+;; This isn't possible in mips16 code.
+
+(define_expand "sne"
+ [(set (match_operand:SI 0 "register_operand")
+ (ne:SI (match_dup 1)
+ (match_dup 2)))]
+ "!TARGET_MIPS16"
+ { if (mips_emit_scc (NE, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sne_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ne:GPR (match_operand:GPR 1 "register_operand" "d")
+ (const_int 0)))]
+ "!TARGET_MIPS16"
+ "sltu\t%0,%.,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "sgt"
+ [(set (match_operand:SI 0 "register_operand")
+ (gt:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (GT, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sgt_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (gt:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "reg_or_0_operand" "dJ")))]
+ "!TARGET_MIPS16"
+ "slt\t%0,%z2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sgt_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t")
+ (gt:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_MIPS16"
+ "slt\t%2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "sge"
+ [(set (match_operand:SI 0 "register_operand")
+ (ge:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (GE, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sge_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ge:GPR (match_operand:GPR 1 "register_operand" "d")
+ (const_int 1)))]
+ "!TARGET_MIPS16"
+ "slt\t%0,%.,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "slt"
+ [(set (match_operand:SI 0 "register_operand")
+ (lt:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (LT, operands[0])) DONE; else FAIL; })
+
+(define_insn "*slt_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (lt:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "arith_operand" "dI")))]
+ "!TARGET_MIPS16"
+ "slt\t%0,%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*slt_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t,t")
+ (lt:GPR (match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "arith_operand" "d,I")))]
+ "TARGET_MIPS16"
+ "slt\t%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))])])
+
+(define_expand "sle"
+ [(set (match_operand:SI 0 "register_operand")
+ (le:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (LE, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sle_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (le:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "sle_operand" "")))]
+ "!TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "slt\t%0,%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sle_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t")
+ (le:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "sle_operand" "")))]
+ "TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "slt\t%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
+ (const_int 4)
+ (const_int 8)))])
+
+(define_expand "sgtu"
+ [(set (match_operand:SI 0 "register_operand")
+ (gtu:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (GTU, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sgtu_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (gtu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "reg_or_0_operand" "dJ")))]
+ "!TARGET_MIPS16"
+ "sltu\t%0,%z2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sgtu_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t")
+ (gtu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "register_operand" "d")))]
+ "TARGET_MIPS16"
+ "sltu\t%2,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "sgeu"
+ [(set (match_operand:SI 0 "register_operand")
+ (geu:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (GEU, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sge_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (geu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (const_int 1)))]
+ "!TARGET_MIPS16"
+ "sltu\t%0,%.,%1"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_expand "sltu"
+ [(set (match_operand:SI 0 "register_operand")
+ (ltu:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (LTU, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sltu_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ltu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "arith_operand" "dI")))]
+ "!TARGET_MIPS16"
+ "sltu\t%0,%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sltu_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t,t")
+ (ltu:GPR (match_operand:GPR 1 "register_operand" "d,d")
+ (match_operand:GPR 2 "arith_operand" "d,I")))]
+ "TARGET_MIPS16"
+ "sltu\t%1,%2"
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")
+ (set_attr_alternative "length"
+ [(const_int 4)
+ (if_then_else (match_operand 2 "m16_uimm8_1")
+ (const_int 4)
+ (const_int 8))])])
+
+(define_expand "sleu"
+ [(set (match_operand:SI 0 "register_operand")
+ (leu:SI (match_dup 1)
+ (match_dup 2)))]
+ ""
+ { if (mips_emit_scc (LEU, operands[0])) DONE; else FAIL; })
+
+(define_insn "*sleu_<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (leu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "sleu_operand" "")))]
+ "!TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "sltu\t%0,%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")])
+
+(define_insn "*sleu_<mode>_mips16"
+ [(set (match_operand:GPR 0 "register_operand" "=t")
+ (leu:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:GPR 2 "sleu_operand" "")))]
+ "TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) + 1);
+ return "sltu\t%1,%2";
+}
+ [(set_attr "type" "slt")
+ (set_attr "mode" "<MODE>")
+ (set (attr "length") (if_then_else (match_operand 2 "m16_uimm8_m1_1")
+ (const_int 4)
+ (const_int 8)))])
+
+;;
+;; ....................
+;;
+;; FLOATING POINT COMPARISONS
+;;
+;; ....................
+
+(define_insn "s<code>_<mode>"
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
+ ""
+ "c.<fcond>.<fmt>\t%Z0%1,%2"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+(define_insn "s<code>_<mode>"
+ [(set (match_operand:CC 0 "register_operand" "=z")
+ (swapped_fcond:CC (match_operand:SCALARF 1 "register_operand" "f")
+ (match_operand:SCALARF 2 "register_operand" "f")))]
+ ""
+ "c.<swapped_fcond>.<fmt>\t%Z0%2,%1"
+ [(set_attr "type" "fcmp")
+ (set_attr "mode" "FPSW")])
+
+;;
+;; ....................
+;;
+;; UNCONDITIONAL BRANCHES
+;;
+;; ....................
+
+;; Unconditional branches.
+
+(define_insn "jump"
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ "!TARGET_MIPS16"
+{
+ if (flag_pic)
+ {
+ if (get_attr_length (insn) <= 8)
+ return "%*b\t%l0%/";
+ else
+ {
+ output_asm_insn (mips_output_load_label (), operands);
+ return "%*jr\t%@%/%]";
+ }
+ }
+ else
+ return "%*j\t%l0%/";
+}
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")
+ (set (attr "length")
+ ;; We can't use `j' when emitting PIC. Emit a branch if it's
+ ;; in range, otherwise load the address of the branch target into
+ ;; $at and then jump to it.
+ (if_then_else
+ (ior (eq (symbol_ref "flag_pic") (const_int 0))
+ (lt (abs (minus (match_dup 0)
+ (plus (pc) (const_int 4))))
+ (const_int 131072)))
+ (const_int 4) (const_int 16)))])
+
+;; We need a different insn for the mips16, because a mips16 branch
+;; does not have a delay slot.
+
+(define_insn ""
+ [(set (pc)
+ (label_ref (match_operand 0 "" "")))]
+ "TARGET_MIPS16"
+ "b\t%l0"
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "length" "8")])
+
+(define_expand "indirect_jump"
+ [(set (pc) (match_operand 0 "register_operand"))]
+ ""
+{
+ operands[0] = force_reg (Pmode, operands[0]);
+ if (Pmode == SImode)
+ emit_jump_insn (gen_indirect_jumpsi (operands[0]));
+ else
+ emit_jump_insn (gen_indirect_jumpdi (operands[0]));
+ DONE;
+})
+
+(define_insn "indirect_jump<mode>"
+ [(set (pc) (match_operand:P 0 "register_operand" "d"))]
+ ""
+ "%*j\t%0%/"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")])
+
+(define_expand "tablejump"
+ [(set (pc)
+ (match_operand 0 "register_operand"))
+ (use (label_ref (match_operand 1 "")))]
+ ""
+{
+ if (TARGET_MIPS16)
+ operands[0] = expand_binop (Pmode, add_optab,
+ convert_to_mode (Pmode, operands[0], false),
+ gen_rtx_LABEL_REF (Pmode, operands[1]),
+ 0, 0, OPTAB_WIDEN);
+ else if (TARGET_GPWORD)
+ operands[0] = expand_binop (Pmode, add_optab, operands[0],
+ pic_offset_table_rtx, 0, 0, OPTAB_WIDEN);
+
+ if (Pmode == SImode)
+ emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "tablejump<mode>"
+ [(set (pc)
+ (match_operand:P 0 "register_operand" "d"))
+ (use (label_ref (match_operand 1 "" "")))]
+ ""
+ "%*j\t%0%/"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")])
+
+;; For TARGET_ABICALLS, we save the gp in the jmp_buf as well.
+;; While it is possible to either pull it off the stack (in the
+;; o32 case) or recalculate it given t9 and our target label,
+;; it takes 3 or 4 insns to do so.
+
+(define_expand "builtin_setjmp_setup"
+ [(use (match_operand 0 "register_operand"))]
+ "TARGET_ABICALLS"
+{
+ rtx addr;
+
+ addr = plus_constant (operands[0], GET_MODE_SIZE (Pmode) * 3);
+ emit_move_insn (gen_rtx_MEM (Pmode, addr), pic_offset_table_rtx);
+ DONE;
+})
+
+;; Restore the gp that we saved above. Despite the earlier comment, it seems
+;; that older code did recalculate the gp from $25. Continue to jump through
+;; $25 for compatibility (we lose nothing by doing so).
+
+(define_expand "builtin_longjmp"
+ [(use (match_operand 0 "register_operand"))]
+ "TARGET_ABICALLS"
+{
+ /* The elements of the buffer are, in order: */
+ int W = GET_MODE_SIZE (Pmode);
+ rtx fp = gen_rtx_MEM (Pmode, operands[0]);
+ rtx lab = gen_rtx_MEM (Pmode, plus_constant (operands[0], 1*W));
+ rtx stack = gen_rtx_MEM (Pmode, plus_constant (operands[0], 2*W));
+ rtx gpv = gen_rtx_MEM (Pmode, plus_constant (operands[0], 3*W));
+ rtx pv = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM);
+ /* Use gen_raw_REG to avoid being given pic_offset_table_rtx.
+ The target is bound to be using $28 as the global pointer
+ but the current function might not be. */
+ rtx gp = gen_raw_REG (Pmode, GLOBAL_POINTER_REGNUM);
+
+ /* This bit is similar to expand_builtin_longjmp except that it
+ restores $gp as well. */
+ emit_move_insn (hard_frame_pointer_rtx, fp);
+ emit_move_insn (pv, lab);
+ emit_stack_restore (SAVE_NONLOCAL, stack, NULL_RTX);
+ emit_move_insn (gp, gpv);
+ 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, gp));
+ emit_indirect_jump (pv);
+ DONE;
+})
+
+;;
+;; ....................
+;;
+;; Function prologue/epilogue
+;;
+;; ....................
+;;
+
+(define_expand "prologue"
+ [(const_int 1)]
+ ""
+{
+ mips_expand_prologue ();
+ DONE;
+})
+
+;; Block any insns from being moved before this point, since the
+;; profiling call to mcount can use various registers that aren't
+;; saved or used to pass arguments.
+
+(define_insn "blockage"
+ [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
+ ""
+ ""
+ [(set_attr "type" "unknown")
+ (set_attr "mode" "none")
+ (set_attr "length" "0")])
+
+(define_expand "epilogue"
+ [(const_int 2)]
+ ""
+{
+ mips_expand_epilogue (false);
+ DONE;
+})
+
+(define_expand "sibcall_epilogue"
+ [(const_int 2)]
+ ""
+{
+ mips_expand_epilogue (true);
+ DONE;
+})
+
+;; Trivial return. Make it look like a normal return insn as that
+;; allows jump optimizations to work better.
+
+(define_insn "return"
+ [(return)]
+ "mips_can_use_return_insn ()"
+ "%*j\t$31%/"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")])
+
+;; Normal return.
+
+(define_insn "return_internal"
+ [(return)
+ (use (match_operand 0 "pmode_register_operand" ""))]
+ ""
+ "%*j\t%0%/"
+ [(set_attr "type" "jump")
+ (set_attr "mode" "none")])
+
+;; This is used in compiling the unwind routines.
+(define_expand "eh_return"
+ [(use (match_operand 0 "general_operand"))]
+ ""
+{
+ enum machine_mode gpr_mode = TARGET_64BIT ? DImode : SImode;
+
+ if (GET_MODE (operands[0]) != gpr_mode)
+ operands[0] = convert_to_mode (gpr_mode, operands[0], 0);
+ if (TARGET_64BIT)
+ emit_insn (gen_eh_set_lr_di (operands[0]));
+ else
+ emit_insn (gen_eh_set_lr_si (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" "d")] UNSPEC_EH_RETURN)
+ (clobber (match_scratch:SI 1 "=&d"))]
+ "! TARGET_64BIT"
+ "#")
+
+(define_insn "eh_set_lr_di"
+ [(unspec [(match_operand:DI 0 "register_operand" "d")] UNSPEC_EH_RETURN)
+ (clobber (match_scratch:DI 1 "=&d"))]
+ "TARGET_64BIT"
+ "#")
+
+(define_split
+ [(unspec [(match_operand 0 "register_operand")] UNSPEC_EH_RETURN)
+ (clobber (match_scratch 1))]
+ "reload_completed && !TARGET_DEBUG_D_MODE"
+ [(const_int 0)]
+{
+ mips_set_return_address (operands[0], operands[1]);
+ DONE;
+})
+
+(define_insn_and_split "exception_receiver"
+ [(set (reg:SI 28)
+ (unspec_volatile:SI [(const_int 0)] UNSPEC_EH_RECEIVER))]
+ "TARGET_ABICALLS && TARGET_OLDABI"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ mips_restore_gp ();
+ DONE;
+}
+ [(set_attr "type" "load")
+ (set_attr "length" "12")])
+
+;;
+;; ....................
+;;
+;; FUNCTION CALLS
+;;
+;; ....................
+
+;; Instructions to load a call address from the GOT. The address might
+;; point to a function or to a lazy binding stub. In the latter case,
+;; the stub will use the dynamic linker to resolve the function, which
+;; in turn will change the GOT entry to point to the function's real
+;; address.
+;;
+;; This means that every call, even pure and constant ones, can
+;; potentially modify the GOT entry. And once a stub has been called,
+;; we must not call it again.
+;;
+;; We represent this restriction using an imaginary fixed register that
+;; acts like a GOT version number. By making the register call-clobbered,
+;; we tell the target-independent code that the address could be changed
+;; by any call insn.
+(define_insn "load_call<mode>"
+ [(set (match_operand:P 0 "register_operand" "=c")
+ (unspec:P [(match_operand:P 1 "register_operand" "r")
+ (match_operand:P 2 "immediate_operand" "")
+ (reg:P FAKE_CALL_REGNO)]
+ UNSPEC_LOAD_CALL))]
+ "TARGET_ABICALLS"
+ "<load>\t%0,%R2(%1)"
+ [(set_attr "type" "load")
+ (set_attr "mode" "<MODE>")
+ (set_attr "length" "4")])
+
+;; Sibling calls. All these patterns use jump instructions.
+
+;; If TARGET_SIBCALLS, call_insn_operand will only accept constant
+;; addresses if a direct jump is acceptable. Since the 'S' constraint
+;; is defined in terms of call_insn_operand, the same is true of the
+;; constraints.
+
+;; When we use an indirect jump, we need a register that will be
+;; preserved by the epilogue. Since TARGET_ABICALLS forces us to
+;; use $25 for this purpose -- and $25 is never clobbered by the
+;; epilogue -- we might as well use it for !TARGET_ABICALLS as well.
+
+(define_expand "sibcall"
+ [(parallel [(call (match_operand 0 "")
+ (match_operand 1 ""))
+ (use (match_operand 2 "")) ;; next_arg_reg
+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx
+ "TARGET_SIBCALLS"
+{
+ mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], true);
+ DONE;
+})
+
+(define_insn "sibcall_internal"
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "j,S"))
+ (match_operand 1 "" ""))]
+ "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
+ { return MIPS_CALL ("j", operands, 0); }
+ [(set_attr "type" "call")])
+
+(define_expand "sibcall_value"
+ [(parallel [(set (match_operand 0 "")
+ (call (match_operand 1 "")
+ (match_operand 2 "")))
+ (use (match_operand 3 ""))])] ;; next_arg_reg
+ "TARGET_SIBCALLS"
+{
+ mips_expand_call (operands[0], XEXP (operands[1], 0),
+ operands[2], operands[3], true);
+ DONE;
+})
+
+(define_insn "sibcall_value_internal"
+ [(set (match_operand 0 "register_operand" "=df,df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
+ (match_operand 2 "" "")))]
+ "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
+ { return MIPS_CALL ("j", operands, 1); }
+ [(set_attr "type" "call")])
+
+(define_insn "sibcall_value_multiple_internal"
+ [(set (match_operand 0 "register_operand" "=df,df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "j,S"))
+ (match_operand 2 "" "")))
+ (set (match_operand 3 "register_operand" "=df,df")
+ (call (mem:SI (match_dup 1))
+ (match_dup 2)))]
+ "TARGET_SIBCALLS && SIBLING_CALL_P (insn)"
+ { return MIPS_CALL ("j", operands, 1); }
+ [(set_attr "type" "call")])
+
+(define_expand "call"
+ [(parallel [(call (match_operand 0 "")
+ (match_operand 1 ""))
+ (use (match_operand 2 "")) ;; next_arg_reg
+ (use (match_operand 3 ""))])] ;; struct_value_size_rtx
+ ""
+{
+ mips_expand_call (0, XEXP (operands[0], 0), operands[1], operands[2], false);
+ DONE;
+})
+
+;; This instruction directly corresponds to an assembly-language "jal".
+;; There are four cases:
+;;
+;; - -mno-abicalls:
+;; Both symbolic and register destinations are OK. The pattern
+;; always expands to a single mips instruction.
+;;
+;; - -mabicalls/-mno-explicit-relocs:
+;; Again, both symbolic and register destinations are OK.
+;; The call is treated as a multi-instruction black box.
+;;
+;; - -mabicalls/-mexplicit-relocs with n32 or n64:
+;; Only "jal $25" is allowed. This expands to a single "jalr $25"
+;; instruction.
+;;
+;; - -mabicalls/-mexplicit-relocs with o32 or o64:
+;; Only "jal $25" is allowed. The call is actually two instructions:
+;; "jalr $25" followed by an insn to reload $gp.
+;;
+;; In the last case, we can generate the individual instructions with
+;; a define_split. There are several things to be wary of:
+;;
+;; - We can't expose the load of $gp before reload. If we did,
+;; it might get removed as dead, but reload can introduce new
+;; uses of $gp by rematerializing constants.
+;;
+;; - We shouldn't restore $gp after calls that never return.
+;; It isn't valid to insert instructions between a noreturn
+;; call and the following barrier.
+;;
+;; - The splitter deliberately changes the liveness of $gp. The unsplit
+;; instruction preserves $gp and so have no effect on its liveness.
+;; But once we generate the separate insns, it becomes obvious that
+;; $gp is not live on entry to the call.
+;;
+;; ??? The operands[2] = insn check is a hack to make the original insn
+;; available to the splitter.
+(define_insn_and_split "call_internal"
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "c,S"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI 31))]
+ ""
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 0); }
+ "reload_completed && TARGET_SPLIT_CALLS && (operands[2] = insn)"
+ [(const_int 0)]
+{
+ emit_call_insn (gen_call_split (operands[0], operands[1]));
+ if (!find_reg_note (operands[2], REG_NORETURN, 0))
+ mips_restore_gp ();
+ DONE;
+}
+ [(set_attr "jal" "indirect,direct")
+ (set_attr "extended_mips16" "no,yes")])
+
+(define_insn "call_split"
+ [(call (mem:SI (match_operand 0 "call_insn_operand" "cS"))
+ (match_operand 1 "" ""))
+ (clobber (reg:SI 31))
+ (clobber (reg:SI 28))]
+ "TARGET_SPLIT_CALLS"
+ { return MIPS_CALL ("jal", operands, 0); }
+ [(set_attr "type" "call")])
+
+(define_expand "call_value"
+ [(parallel [(set (match_operand 0 "")
+ (call (match_operand 1 "")
+ (match_operand 2 "")))
+ (use (match_operand 3 ""))])] ;; next_arg_reg
+ ""
+{
+ mips_expand_call (operands[0], XEXP (operands[1], 0),
+ operands[2], operands[3], false);
+ DONE;
+})
+
+;; See comment for call_internal.
+(define_insn_and_split "call_value_internal"
+ [(set (match_operand 0 "register_operand" "=df,df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 31))]
+ ""
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
+ "reload_completed && TARGET_SPLIT_CALLS && (operands[3] = insn)"
+ [(const_int 0)]
+{
+ emit_call_insn (gen_call_value_split (operands[0], operands[1],
+ operands[2]));
+ if (!find_reg_note (operands[3], REG_NORETURN, 0))
+ mips_restore_gp ();
+ DONE;
+}
+ [(set_attr "jal" "indirect,direct")
+ (set_attr "extended_mips16" "no,yes")])
+
+(define_insn "call_value_split"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "cS"))
+ (match_operand 2 "" "")))
+ (clobber (reg:SI 31))
+ (clobber (reg:SI 28))]
+ "TARGET_SPLIT_CALLS"
+ { return MIPS_CALL ("jal", operands, 1); }
+ [(set_attr "type" "call")])
+
+;; See comment for call_internal.
+(define_insn_and_split "call_value_multiple_internal"
+ [(set (match_operand 0 "register_operand" "=df,df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "c,S"))
+ (match_operand 2 "" "")))
+ (set (match_operand 3 "register_operand" "=df,df")
+ (call (mem:SI (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:SI 31))]
+ ""
+ { return TARGET_SPLIT_CALLS ? "#" : MIPS_CALL ("jal", operands, 1); }
+ "reload_completed && TARGET_SPLIT_CALLS && (operands[4] = insn)"
+ [(const_int 0)]
+{
+ emit_call_insn (gen_call_value_multiple_split (operands[0], operands[1],
+ operands[2], operands[3]));
+ if (!find_reg_note (operands[4], REG_NORETURN, 0))
+ mips_restore_gp ();
+ DONE;
+}
+ [(set_attr "jal" "indirect,direct")
+ (set_attr "extended_mips16" "no,yes")])
+
+(define_insn "call_value_multiple_split"
+ [(set (match_operand 0 "register_operand" "=df")
+ (call (mem:SI (match_operand 1 "call_insn_operand" "cS"))
+ (match_operand 2 "" "")))
+ (set (match_operand 3 "register_operand" "=df")
+ (call (mem:SI (match_dup 1))
+ (match_dup 2)))
+ (clobber (reg:SI 31))
+ (clobber (reg:SI 28))]
+ "TARGET_SPLIT_CALLS"
+ { return MIPS_CALL ("jal", operands, 1); }
+ [(set_attr "type" "call")])
+
+;; 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, NULL, const0_rtx));
+
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+ rtx set = XVECEXP (operands[2], 0, i);
+ emit_move_insn (SET_DEST (set), SET_SRC (set));
+ }
+
+ emit_insn (gen_blockage ());
+ DONE;
+})
+
+;;
+;; ....................
+;;
+;; MISC.
+;;
+;; ....................
+;;
+
+
+(define_insn "prefetch"
+ [(prefetch (match_operand:QI 0 "address_operand" "p")
+ (match_operand 1 "const_int_operand" "n")
+ (match_operand 2 "const_int_operand" "n"))]
+ "ISA_HAS_PREFETCH && TARGET_EXPLICIT_RELOCS"
+{
+ operands[1] = mips_prefetch_cookie (operands[1], operands[2]);
+ return "pref\t%1,%a0";
+}
+ [(set_attr "type" "prefetch")])
+
+(define_insn "*prefetch_indexed_<mode>"
+ [(prefetch (plus:P (match_operand:P 0 "register_operand" "d")
+ (match_operand:P 1 "register_operand" "d"))
+ (match_operand 2 "const_int_operand" "n")
+ (match_operand 3 "const_int_operand" "n"))]
+ "ISA_HAS_PREFETCHX && TARGET_HARD_FLOAT && TARGET_DOUBLE_FLOAT"
+{
+ operands[2] = mips_prefetch_cookie (operands[2], operands[3]);
+ return "prefx\t%2,%1(%0)";
+}
+ [(set_attr "type" "prefetchx")])
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "%(nop%)"
+ [(set_attr "type" "nop")
+ (set_attr "mode" "none")])
+
+;; Like nop, but commented out when outside a .set noreorder block.
+(define_insn "hazard_nop"
+ [(const_int 1)]
+ ""
+ {
+ if (set_noreorder)
+ return "nop";
+ else
+ return "#nop";
+ }
+ [(set_attr "type" "nop")])
+
+;; MIPS4 Conditional move instructions.
+
+(define_insn "*mov<GPR:mode>_on_<MOVECC:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (if_then_else:GPR
+ (match_operator:MOVECC 4 "equality_operator"
+ [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
+ (const_int 0)])
+ (match_operand:GPR 2 "reg_or_0_operand" "dJ,0")
+ (match_operand:GPR 3 "reg_or_0_operand" "0,dJ")))]
+ "ISA_HAS_CONDMOVE"
+ "@
+ mov%T4\t%0,%z2,%1
+ mov%t4\t%0,%z3,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*mov<SCALARF:mode>_on_<MOVECC:mode>"
+ [(set (match_operand:SCALARF 0 "register_operand" "=f,f")
+ (if_then_else:SCALARF
+ (match_operator:MOVECC 4 "equality_operator"
+ [(match_operand:MOVECC 1 "register_operand" "<MOVECC:reg>,<MOVECC:reg>")
+ (const_int 0)])
+ (match_operand:SCALARF 2 "register_operand" "f,0")
+ (match_operand:SCALARF 3 "register_operand" "0,f")))]
+ "ISA_HAS_CONDMOVE"
+ "@
+ mov%T4.<fmt>\t%0,%2,%1
+ mov%t4.<fmt>\t%0,%3,%1"
+ [(set_attr "type" "condmove")
+ (set_attr "mode" "<SCALARF:MODE>")])
+
+;; These are the main define_expand's used to make conditional moves.
+
+(define_expand "mov<mode>cc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator"))
+ (set (match_operand:GPR 0 "register_operand")
+ (if_then_else:GPR (match_dup 5)
+ (match_operand:GPR 2 "reg_or_0_operand")
+ (match_operand:GPR 3 "reg_or_0_operand")))]
+ "ISA_HAS_CONDMOVE"
+{
+ gen_conditional_move (operands);
+ DONE;
+})
+
+(define_expand "mov<mode>cc"
+ [(set (match_dup 4) (match_operand 1 "comparison_operator"))
+ (set (match_operand:SCALARF 0 "register_operand")
+ (if_then_else:SCALARF (match_dup 5)
+ (match_operand:SCALARF 2 "register_operand")
+ (match_operand:SCALARF 3 "register_operand")))]
+ "ISA_HAS_CONDMOVE"
+{
+ gen_conditional_move (operands);
+ DONE;
+})
+
+;;
+;; ....................
+;;
+;; mips16 inline constant tables
+;;
+;; ....................
+;;
+
+(define_insn "consttable_int"
+ [(unspec_volatile [(match_operand 0 "consttable_operand" "")
+ (match_operand 1 "const_int_operand" "")]
+ UNSPEC_CONSTTABLE_INT)]
+ "TARGET_MIPS16"
+{
+ assemble_integer (operands[0], INTVAL (operands[1]),
+ BITS_PER_UNIT * INTVAL (operands[1]), 1);
+ return "";
+}
+ [(set (attr "length") (symbol_ref "INTVAL (operands[1])"))])
+
+(define_insn "consttable_float"
+ [(unspec_volatile [(match_operand 0 "consttable_operand" "")]
+ UNSPEC_CONSTTABLE_FLOAT)]
+ "TARGET_MIPS16"
+{
+ REAL_VALUE_TYPE d;
+
+ gcc_assert (GET_CODE (operands[0]) == CONST_DOUBLE);
+ REAL_VALUE_FROM_CONST_DOUBLE (d, operands[0]);
+ assemble_real (d, GET_MODE (operands[0]),
+ GET_MODE_BITSIZE (GET_MODE (operands[0])));
+ return "";
+}
+ [(set (attr "length")
+ (symbol_ref "GET_MODE_SIZE (GET_MODE (operands[0]))"))])
+
+(define_insn "align"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "")] UNSPEC_ALIGN)]
+ ""
+ ".align\t%0"
+ [(set (attr "length") (symbol_ref "(1 << INTVAL (operands[0])) - 1"))])
+
+(define_split
+ [(match_operand 0 "small_data_pattern")]
+ "reload_completed"
+ [(match_dup 0)]
+ { operands[0] = mips_rewrite_small_data (operands[0]); })
+
+; Thread-Local Storage
+
+; The TLS base pointer is accessed via "rdhwr $v1, $29". No current
+; MIPS architecture defines this register, and no current
+; implementation provides it; instead, any OS which supports TLS is
+; expected to trap and emulate this instruction. rdhwr is part of the
+; MIPS 32r2 specification, but we use it on any architecture because
+; we expect it to be emulated. Use .set to force the assembler to
+; accept it.
+
+(define_insn "tls_get_tp_<mode>"
+ [(set (match_operand:P 0 "register_operand" "=v")
+ (unspec:P [(const_int 0)]
+ UNSPEC_TLS_GET_TP))]
+ "HAVE_AS_TLS && !TARGET_MIPS16"
+ ".set\tpush\;.set\tmips32r2\t\;rdhwr\t%0,$29\;.set\tpop"
+ [(set_attr "type" "unknown")
+ ; Since rdhwr always generates a trap for now, putting it in a delay
+ ; slot would make the kernel's emulation of it much slower.
+ (set_attr "can_delay" "no")
+ (set_attr "mode" "<MODE>")])
+
+; The MIPS Paired-Single Floating Point and MIPS-3D Instructions.
+
+(include "mips-ps-3d.md")
+
+; The MIPS DSP Instructions.
+
+(include "mips-dsp.md")
diff --git a/contrib/gcc/config/mips/mips.opt b/contrib/gcc/config/mips/mips.opt
new file mode 100644
index 0000000..7f8214b
--- /dev/null
+++ b/contrib/gcc/config/mips/mips.opt
@@ -0,0 +1,222 @@
+; Options for the MIPS port of the compiler
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mabi=
+Target RejectNegative Joined
+-mabi=ABI Generate code that conforms to the given ABI
+
+mabicalls
+Target Report Mask(ABICALLS)
+Generate code that can be used in SVR4-style dynamic objects
+
+mad
+Target Report Var(TARGET_MAD)
+Use PMC-style 'mad' instructions
+
+march=
+Target RejectNegative Joined Var(mips_arch_string)
+-march=ISA Generate code for the given ISA
+
+mbranch-likely
+Target Report Mask(BRANCHLIKELY)
+Use Branch Likely instructions, overriding the architecture default
+
+mcheck-zero-division
+Target Report Mask(CHECK_ZERO_DIV)
+Trap on integer divide by zero
+
+mdivide-breaks
+Target Report RejectNegative Mask(DIVIDE_BREAKS)
+Use branch-and-break sequences to check for integer divide by zero
+
+mdivide-traps
+Target Report RejectNegative InverseMask(DIVIDE_BREAKS, DIVIDE_TRAPS)
+Use trap instructions to check for integer divide by zero
+
+mdouble-float
+Target Report RejectNegative InverseMask(SINGLE_FLOAT, DOUBLE_FLOAT)
+Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations
+
+mdsp
+Target Report Mask(DSP)
+Use MIPS-DSP instructions
+
+mdebug
+Target Var(TARGET_DEBUG_MODE) Undocumented
+
+mdebugd
+Target Var(TARGET_DEBUG_D_MODE) Undocumented
+
+meb
+Target Report RejectNegative Mask(BIG_ENDIAN)
+Use big-endian byte order
+
+mel
+Target Report RejectNegative InverseMask(BIG_ENDIAN, LITTLE_ENDIAN)
+Use little-endian byte order
+
+membedded-data
+Target Report Var(TARGET_EMBEDDED_DATA)
+Use ROM instead of RAM
+
+mexplicit-relocs
+Target Report Mask(EXPLICIT_RELOCS)
+Use NewABI-style %reloc() assembly operators
+
+mfix-r4000
+Target Report Mask(FIX_R4000)
+Work around certain R4000 errata
+
+mfix-r4400
+Target Report Mask(FIX_R4400)
+Work around certain R4400 errata
+
+mfix-sb1
+Target Report Var(TARGET_FIX_SB1)
+Work around errata for early SB-1 revision 2 cores
+
+mfix-vr4120
+Target Report Var(TARGET_FIX_VR4120)
+Work around certain VR4120 errata
+
+mfix-vr4130
+Target Report Var(TARGET_FIX_VR4130)
+Work around VR4130 mflo/mfhi errata
+
+mfix4300
+Target Report Var(TARGET_4300_MUL_FIX)
+Work around an early 4300 hardware bug
+
+mfp-exceptions
+Target Report Mask(FP_EXCEPTIONS)
+FP exceptions are enabled
+
+mfp32
+Target Report RejectNegative InverseMask(FLOAT64)
+Use 32-bit floating-point registers
+
+mfp64
+Target Report RejectNegative Mask(FLOAT64)
+Use 64-bit floating-point registers
+
+mflush-func=
+Target RejectNegative Joined Var(mips_cache_flush_func) Init(CACHE_FLUSH_FUNC)
+-mflush-func=FUNC Use FUNC to flush the cache before calling stack trampolines
+
+mfused-madd
+Target Report Mask(FUSED_MADD)
+Generate floating-point multiply-add instructions
+
+mgp32
+Target Report RejectNegative InverseMask(64BIT)
+Use 32-bit general registers
+
+mgp64
+Target Report RejectNegative Mask(64BIT)
+Use 64-bit general registers
+
+mhard-float
+Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+Allow the use of hardware floating-point instructions
+
+mips
+Target RejectNegative Joined
+-mipsN Generate code for ISA level N
+
+mips16
+Target Report RejectNegative Mask(MIPS16)
+Generate mips16 code
+
+mips3d
+Target Report RejectNegative Mask(MIPS3D)
+Use MIPS-3D instructions
+
+mlong-calls
+Target Report Var(TARGET_LONG_CALLS)
+Use indirect calls
+
+mlong32
+Target Report RejectNegative InverseMask(LONG64, LONG32)
+Use a 32-bit long type
+
+mlong64
+Target Report RejectNegative Mask(LONG64)
+Use a 64-bit long type
+
+mmemcpy
+Target Report Var(TARGET_MEMCPY)
+Don't optimize block moves
+
+mmips-tfile
+Target
+Use the mips-tfile postpass
+
+mno-flush-func
+Target RejectNegative
+Do not use a cache-flushing function before calling stack trampolines
+
+mno-mips16
+Target Report RejectNegative InverseMask(MIPS16)
+Generate normal-mode code
+
+mno-mips3d
+Target Report RejectNegative InverseMask(MIPS3D)
+Do not use MIPS-3D instructions
+
+mpaired-single
+Target Report Mask(PAIRED_SINGLE_FLOAT)
+Use paired-single floating-point instructions
+
+mshared
+Target Report Var(TARGET_SHARED) Init(1)
+When generating -mabicalls code, make the code suitable for use in shared libraries
+
+msingle-float
+Target Report RejectNegative Mask(SINGLE_FLOAT)
+Restrict the use of hardware floating-point instructions to 32-bit operations
+
+msoft-float
+Target Report RejectNegative Mask(SOFT_FLOAT)
+Prevent the use of all hardware floating-point instructions
+
+msplit-addresses
+Target Report Mask(SPLIT_ADDRESSES)
+Optimize lui/addiu address loads
+
+msym32
+Target Report Var(TARGET_SYM32)
+Assume all symbols have 32-bit values
+
+mtune=
+Target RejectNegative Joined Var(mips_tune_string)
+-mtune=PROCESSOR Optimize the output for PROCESSOR
+
+muninit-const-in-rodata
+Target Report Var(TARGET_UNINIT_CONST_IN_RODATA)
+Put uninitialized constants in ROM (needs -membedded-data)
+
+mvr4130-align
+Target Report Mask(VR4130_ALIGN)
+Perform VR4130-specific alignment optimizations
+
+mxgot
+Target Report Var(TARGET_XGOT)
+Lift restrictions on GOT size
diff --git a/contrib/gcc/config/mips/mips16.S b/contrib/gcc/config/mips/mips16.S
new file mode 100644
index 0000000..a6afa0c
--- /dev/null
+++ b/contrib/gcc/config/mips/mips16.S
@@ -0,0 +1,739 @@
+/* mips16 floating point support code
+ Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
+ Contributed by Cygnus Support
+
+This file is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by the
+Free Software Foundation; either version 2, or (at your option) any
+later version.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs 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 another program.)
+
+This file is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, 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. */
+
+/* This file contains mips16 floating point support functions. These
+ functions are called by mips16 code to handle floating point when
+ -msoft-float is not used. They accept the arguments and return
+ values using the soft-float calling convention, but do the actual
+ operation using the hard floating point instructions. */
+
+/* This file contains 32 bit assembly code. */
+ .set nomips16
+
+/* Start a function. */
+
+#define STARTFN(NAME) .globl NAME; .ent NAME; NAME:
+
+/* Finish a function. */
+
+#define ENDFN(NAME) .end NAME
+
+/* Single precision math. */
+
+/* This macro defines a function which loads two single precision
+ values, performs an operation, and returns the single precision
+ result. */
+
+#define SFOP(NAME, OPCODE) \
+STARTFN (NAME); \
+ .set noreorder; \
+ mtc1 $4,$f0; \
+ mtc1 $5,$f2; \
+ nop; \
+ OPCODE $f0,$f0,$f2; \
+ mfc1 $2,$f0; \
+ j $31; \
+ nop; \
+ .set reorder; \
+ ENDFN (NAME)
+
+#ifdef L_m16addsf3
+SFOP(__mips16_addsf3, add.s)
+#endif
+#ifdef L_m16subsf3
+SFOP(__mips16_subsf3, sub.s)
+#endif
+#ifdef L_m16mulsf3
+SFOP(__mips16_mulsf3, mul.s)
+#endif
+#ifdef L_m16divsf3
+SFOP(__mips16_divsf3, div.s)
+#endif
+
+#define SFOP2(NAME, OPCODE) \
+STARTFN (NAME); \
+ .set noreorder; \
+ mtc1 $4,$f0; \
+ nop; \
+ OPCODE $f0,$f0; \
+ mfc1 $2,$f0; \
+ j $31; \
+ nop; \
+ .set reorder; \
+ ENDFN (NAME)
+
+#ifdef L_m16negsf2
+SFOP2(__mips16_negsf2, neg.s)
+#endif
+#ifdef L_m16abssf2
+SFOP2(__mips16_abssf2, abs.s)
+#endif
+
+/* Single precision comparisons. */
+
+/* This macro defines a function which loads two single precision
+ values, performs a floating point comparison, and returns the
+ specified values according to whether the comparison is true or
+ false. */
+
+#define SFCMP(NAME, OPCODE, TRUE, FALSE) \
+STARTFN (NAME); \
+ mtc1 $4,$f0; \
+ mtc1 $5,$f2; \
+ OPCODE $f0,$f2; \
+ li $2,TRUE; \
+ bc1t 1f; \
+ li $2,FALSE; \
+1:; \
+ j $31; \
+ ENDFN (NAME)
+
+/* This macro is like SFCMP, but it reverses the comparison. */
+
+#define SFREVCMP(NAME, OPCODE, TRUE, FALSE) \
+STARTFN (NAME); \
+ mtc1 $4,$f0; \
+ mtc1 $5,$f2; \
+ OPCODE $f2,$f0; \
+ li $2,TRUE; \
+ bc1t 1f; \
+ li $2,FALSE; \
+1:; \
+ j $31; \
+ ENDFN (NAME)
+
+#ifdef L_m16eqsf2
+SFCMP(__mips16_eqsf2, c.eq.s, 0, 1)
+#endif
+#ifdef L_m16nesf2
+SFCMP(__mips16_nesf2, c.eq.s, 0, 1)
+#endif
+#ifdef L_m16gtsf2
+SFREVCMP(__mips16_gtsf2, c.lt.s, 1, 0)
+#endif
+#ifdef L_m16gesf2
+SFREVCMP(__mips16_gesf2, c.le.s, 0, -1)
+#endif
+#ifdef L_m16lesf2
+SFCMP(__mips16_lesf2, c.le.s, 0, 1)
+#endif
+#ifdef L_m16ltsf2
+SFCMP(__mips16_ltsf2, c.lt.s, -1, 0)
+#endif
+
+/* Single precision conversions. */
+
+#ifdef L_m16fltsisf
+STARTFN (__mips16_floatsisf)
+ .set noreorder
+ mtc1 $4,$f0
+ nop
+ cvt.s.w $f0,$f0
+ mfc1 $2,$f0
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_floatsisf)
+#endif
+
+#ifdef L_m16fix_truncsfsi
+STARTFN (__mips16_fix_truncsfsi)
+ .set noreorder
+ mtc1 $4,$f0
+ nop
+ trunc.w.s $f0,$f0,$4
+ mfc1 $2,$f0
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_fix_truncsfsi)
+#endif
+
+#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
+
+/* The double precision operations. We need to use different code
+ based on the preprocessor symbol __mips64, because the way in which
+ double precision values will change. Without __mips64, the value
+ is passed in two 32 bit registers. With __mips64, the value is
+ passed in a single 64 bit register. */
+
+/* Load the first double precision operand. */
+
+#if defined(__mips64)
+#define LDDBL1 dmtc1 $4,$f12
+#elif defined(__mipsfp64)
+#define LDDBL1 sw $4,0($29); sw $5,4($29); l.d $f12,0($29)
+#elif defined(__MIPSEB__)
+#define LDDBL1 mtc1 $4,$f13; mtc1 $5,$f12
+#else
+#define LDDBL1 mtc1 $4,$f12; mtc1 $5,$f13
+#endif
+
+/* Load the second double precision operand. */
+
+#if defined(__mips64)
+/* XXX this should be $6 for Algo arg passing model */
+#define LDDBL2 dmtc1 $5,$f14
+#elif defined(__mipsfp64)
+#define LDDBL2 sw $6,8($29); sw $7,12($29); l.d $f14,8($29)
+#elif defined(__MIPSEB__)
+#define LDDBL2 mtc1 $6,$f15; mtc1 $7,$f14
+#else
+#define LDDBL2 mtc1 $6,$f14; mtc1 $7,$f15
+#endif
+
+/* Move the double precision return value to the right place. */
+
+#if defined(__mips64)
+#define RETDBL dmfc1 $2,$f0
+#elif defined(__mipsfp64)
+#define RETDBL s.d $f0,0($29); lw $2,0($29); lw $3,4($29)
+#elif defined(__MIPSEB__)
+#define RETDBL mfc1 $2,$f1; mfc1 $3,$f0
+#else
+#define RETDBL mfc1 $2,$f0; mfc1 $3,$f1
+#endif
+
+/* Double precision math. */
+
+/* This macro defines a function which loads two double precision
+ values, performs an operation, and returns the double precision
+ result. */
+
+#define DFOP(NAME, OPCODE) \
+STARTFN (NAME); \
+ .set noreorder; \
+ LDDBL1; \
+ LDDBL2; \
+ nop; \
+ OPCODE $f0,$f12,$f14; \
+ RETDBL; \
+ j $31; \
+ nop; \
+ .set reorder; \
+ ENDFN (NAME)
+
+#ifdef L_m16adddf3
+DFOP(__mips16_adddf3, add.d)
+#endif
+#ifdef L_m16subdf3
+DFOP(__mips16_subdf3, sub.d)
+#endif
+#ifdef L_m16muldf3
+DFOP(__mips16_muldf3, mul.d)
+#endif
+#ifdef L_m16divdf3
+DFOP(__mips16_divdf3, div.d)
+#endif
+
+#define DFOP2(NAME, OPCODE) \
+STARTFN (NAME); \
+ .set noreorder; \
+ LDDBL1; \
+ nop; \
+ OPCODE $f0,$f12; \
+ RETDBL; \
+ j $31; \
+ nop; \
+ .set reorder; \
+ ENDFN (NAME)
+
+#ifdef L_m16negdf2
+DFOP2(__mips16_negdf2, neg.d)
+#endif
+#ifdef L_m16absdf2
+DFOP2(__mips16_absdf2, abs.d)
+#endif
+
+
+/* Conversions between single and double precision. */
+
+#ifdef L_m16extsfdf2
+STARTFN (__mips16_extendsfdf2)
+ .set noreorder
+ mtc1 $4,$f12
+ nop
+ cvt.d.s $f0,$f12
+ RETDBL
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_extendsfdf2)
+#endif
+
+#ifdef L_m16trdfsf2
+STARTFN (__mips16_truncdfsf2)
+ .set noreorder
+ LDDBL1
+ nop
+ cvt.s.d $f0,$f12
+ mfc1 $2,$f0
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_truncdfsf2)
+#endif
+
+/* Double precision comparisons. */
+
+/* This macro defines a function which loads two double precision
+ values, performs a floating point comparison, and returns the
+ specified values according to whether the comparison is true or
+ false. */
+
+#define DFCMP(NAME, OPCODE, TRUE, FALSE) \
+STARTFN (NAME); \
+ LDDBL1; \
+ LDDBL2; \
+ OPCODE $f12,$f14; \
+ li $2,TRUE; \
+ bc1t 1f; \
+ li $2,FALSE; \
+1:; \
+ j $31; \
+ ENDFN (NAME)
+
+/* This macro is like DFCMP, but it reverses the comparison. */
+
+#define DFREVCMP(NAME, OPCODE, TRUE, FALSE) \
+STARTFN (NAME); \
+ LDDBL1; \
+ LDDBL2; \
+ OPCODE $f14,$f12; \
+ li $2,TRUE; \
+ bc1t 1f; \
+ li $2,FALSE; \
+1:; \
+ j $31; \
+ ENDFN (NAME)
+
+#ifdef L_m16eqdf2
+DFCMP(__mips16_eqdf2, c.eq.d, 0, 1)
+#endif
+#ifdef L_m16nedf2
+DFCMP(__mips16_nedf2, c.eq.d, 0, 1)
+#endif
+#ifdef L_m16gtdf2
+DFREVCMP(__mips16_gtdf2, c.lt.d, 1, 0)
+#endif
+#ifdef L_m16gedf2
+DFREVCMP(__mips16_gedf2, c.le.d, 0, -1)
+#endif
+#ifdef L_m16ledf2
+DFCMP(__mips16_ledf2, c.le.d, 0, 1)
+#endif
+#ifdef L_m16ltdf2
+DFCMP(__mips16_ltdf2, c.lt.d, -1, 0)
+#endif
+
+/* Double precision conversions. */
+
+#ifdef L_m16fltsidf
+STARTFN (__mips16_floatsidf)
+ .set noreorder
+ mtc1 $4,$f12
+ nop
+ cvt.d.w $f0,$f12
+ RETDBL
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_floatsidf)
+#endif
+
+#ifdef L_m16fix_truncdfsi
+STARTFN (__mips16_fix_truncdfsi)
+ .set noreorder
+ LDDBL1
+ nop
+ trunc.w.d $f0,$f12,$4
+ mfc1 $2,$f0
+ j $31
+ nop
+ .set reorder
+ ENDFN (__mips16_fix_truncdfsi)
+#endif
+#endif /* !__mips_single_float */
+
+/* These functions are used to return floating point values from
+ mips16 functions. In this case we can put mtc1 in a jump delay slot,
+ because we know that the next instruction will not refer to a floating
+ point register. */
+
+#ifdef L_m16retsf
+STARTFN (__mips16_ret_sf)
+ .set noreorder
+ j $31
+ mtc1 $2,$f0
+ .set reorder
+ ENDFN (__mips16_ret_sf)
+#endif
+
+#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
+#ifdef L_m16retdf
+STARTFN (__mips16_ret_df)
+ .set noreorder
+#if defined(__mips64)
+ j $31
+ dmtc1 $2,$f0
+#elif defined(__mipsfp64)
+ sw $2,0($29)
+ sw $3,4($29)
+ l.d $f0,0($29)
+#elif defined(__MIPSEB__)
+ mtc1 $2,$f1
+ j $31
+ mtc1 $3,$f0
+#else
+ mtc1 $2,$f0
+ j $31
+ mtc1 $3,$f1
+#endif
+ .set reorder
+ ENDFN (__mips16_ret_df)
+#endif
+#endif /* !__mips_single_float */
+
+/* These functions are used by 16 bit code when calling via a function
+ pointer. They must copy the floating point arguments from the gp
+ regs into the fp regs. The function to call will be in $2. The
+ exact set of floating point arguments to copy is encoded in the
+ function name; the final number is an fp_code, as described in
+ mips.h in the comment about CUMULATIVE_ARGS. */
+
+#ifdef L_m16stub1
+/* (float) */
+STARTFN (__mips16_call_stub_1)
+ .set noreorder
+ mtc1 $4,$f12
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_1)
+#endif
+
+#ifdef L_m16stub5
+/* (float, float) */
+STARTFN (__mips16_call_stub_5)
+ .set noreorder
+ mtc1 $4,$f12
+ mtc1 $5,$f14
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_5)
+#endif
+
+#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
+
+#ifdef L_m16stub2
+/* (double) */
+STARTFN (__mips16_call_stub_2)
+ .set noreorder
+ LDDBL1
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_2)
+#endif
+
+#ifdef L_m16stub6
+/* (double, float) */
+STARTFN (__mips16_call_stub_6)
+ .set noreorder
+ LDDBL1
+ mtc1 $6,$f14
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_6)
+#endif
+
+#ifdef L_m16stub9
+/* (float, double) */
+STARTFN (__mips16_call_stub_9)
+ .set noreorder
+ mtc1 $4,$f12
+ LDDBL2
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_9)
+#endif
+
+#ifdef L_m16stub10
+/* (double, double) */
+STARTFN (__mips16_call_stub_10)
+ .set noreorder
+ LDDBL1
+ LDDBL2
+ j $2
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_10)
+#endif
+#endif /* !__mips_single_float */
+
+/* Now we have the same set of functions, except that this time the
+ function being called returns an SFmode value. The calling
+ function will arrange to preserve $18, so these functions are free
+ to use it to hold the return address.
+
+ Note that we do not know whether the function we are calling is 16
+ bit or 32 bit. However, it does not matter, because 16 bit
+ functions always return floating point values in both the gp and
+ the fp regs. It would be possible to check whether the function
+ being called is 16 bits, in which case the copy is unnecessary;
+ however, it's faster to always do the copy. */
+
+#ifdef L_m16stubsf0
+/* () */
+STARTFN (__mips16_call_stub_sf_0)
+ .set noreorder
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_0)
+#endif
+
+#ifdef L_m16stubsf1
+/* (float) */
+STARTFN (__mips16_call_stub_sf_1)
+ .set noreorder
+ mtc1 $4,$f12
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_1)
+#endif
+
+#ifdef L_m16stubsf5
+/* (float, float) */
+STARTFN (__mips16_call_stub_sf_5)
+ .set noreorder
+ mtc1 $4,$f12
+ mtc1 $5,$f14
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_5)
+#endif
+
+#if !defined(__mips_single_float) && !defined(__SINGLE_FLOAT)
+#ifdef L_m16stubsf2
+/* (double) */
+STARTFN (__mips16_call_stub_sf_2)
+ .set noreorder
+ LDDBL1
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_2)
+#endif
+
+#ifdef L_m16stubsf6
+/* (double, float) */
+STARTFN (__mips16_call_stub_sf_6)
+ .set noreorder
+ LDDBL1
+ mtc1 $6,$f14
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_6)
+#endif
+
+#ifdef L_m16stubsf9
+/* (float, double) */
+STARTFN (__mips16_call_stub_sf_9)
+ .set noreorder
+ mtc1 $4,$f12
+ LDDBL2
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_9)
+#endif
+
+#ifdef L_m16stubsf10
+/* (double, double) */
+STARTFN (__mips16_call_stub_sf_10)
+ .set noreorder
+ LDDBL1
+ LDDBL2
+ move $18,$31
+ jal $2
+ nop
+ mfc1 $2,$f0
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_sf_10)
+#endif
+
+/* Now we have the same set of functions again, except that this time
+ the function being called returns an DFmode value. */
+
+#ifdef L_m16stubdf0
+/* () */
+STARTFN (__mips16_call_stub_df_0)
+ .set noreorder
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_0)
+#endif
+
+#ifdef L_m16stubdf1
+/* (float) */
+STARTFN (__mips16_call_stub_df_1)
+ .set noreorder
+ mtc1 $4,$f12
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_1)
+#endif
+
+#ifdef L_m16stubdf2
+/* (double) */
+STARTFN (__mips16_call_stub_df_2)
+ .set noreorder
+ LDDBL1
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_2)
+#endif
+
+#ifdef L_m16stubdf5
+/* (float, float) */
+STARTFN (__mips16_call_stub_df_5)
+ .set noreorder
+ mtc1 $4,$f12
+ mtc1 $5,$f14
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_5)
+#endif
+
+#ifdef L_m16stubdf6
+/* (double, float) */
+STARTFN (__mips16_call_stub_df_6)
+ .set noreorder
+ LDDBL1
+ mtc1 $6,$f14
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_6)
+#endif
+
+#ifdef L_m16stubdf9
+/* (float, double) */
+STARTFN (__mips16_call_stub_df_9)
+ .set noreorder
+ mtc1 $4,$f12
+ LDDBL2
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_9)
+#endif
+
+#ifdef L_m16stubdf10
+/* (double, double) */
+STARTFN (__mips16_call_stub_df_10)
+ .set noreorder
+ LDDBL1
+ LDDBL2
+ move $18,$31
+ jal $2
+ nop
+ RETDBL
+ j $18
+ nop
+ .set reorder
+ ENDFN (__mips16_call_stub_df_10)
+#endif
+#endif /* !__mips_single_float */
diff --git a/contrib/gcc/config/mips/netbsd.h b/contrib/gcc/config/mips/netbsd.h
new file mode 100644
index 0000000..6b335ca
--- /dev/null
+++ b/contrib/gcc/config/mips/netbsd.h
@@ -0,0 +1,203 @@
+/* Definitions of target machine for GNU compiler, for MIPS NetBSD systems.
+ Copyright (C) 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002, 2003, 2004
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+
+/* Define default target values. */
+
+#undef MACHINE_TYPE
+#if TARGET_ENDIAN_DEFAULT != 0
+#define MACHINE_TYPE "NetBSD/mipseb ELF"
+#else
+#define MACHINE_TYPE "NetBSD/mipsel ELF"
+#endif
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ NETBSD_OS_CPP_BUILTINS_ELF(); \
+ builtin_define ("__NO_LEADING_UNDERSCORES__"); \
+ builtin_define ("__GP_SUPPORT__"); \
+ if (TARGET_LONG64) \
+ builtin_define ("__LONG64"); \
+ \
+ if (TARGET_ABICALLS) \
+ builtin_define ("__ABICALLS__"); \
+ \
+ if (mips_abi == ABI_EABI) \
+ builtin_define ("__mips_eabi"); \
+ else if (mips_abi == ABI_N32) \
+ builtin_define ("__mips_n32"); \
+ else if (mips_abi == ABI_64) \
+ builtin_define ("__mips_n64"); \
+ else if (mips_abi == ABI_O64) \
+ builtin_define ("__mips_o64"); \
+ } \
+ while (0)
+
+/* The generic MIPS TARGET_CPU_CPP_BUILTINS are incorrect for NetBSD.
+ Specifically, they define too many namespace-invasive macros. Override
+ them here. Note this is structured for easy comparison to the version
+ in mips.h.
+
+ FIXME: This probably isn't the best solution. But in the absence
+ of something better, it will have to do, for now. */
+
+#undef TARGET_CPU_CPP_BUILTINS
+#define TARGET_CPU_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_assert ("cpu=mips"); \
+ builtin_define ("__mips__"); \
+ builtin_define ("_mips"); \
+ \
+ /* No _R3000 or _R4000. */ \
+ if (TARGET_64BIT) \
+ builtin_define ("__mips64"); \
+ \
+ if (TARGET_FLOAT64) \
+ builtin_define ("__mips_fpr=64"); \
+ else \
+ builtin_define ("__mips_fpr=32"); \
+ \
+ if (TARGET_MIPS16) \
+ builtin_define ("__mips16"); \
+ \
+ MIPS_CPP_SET_PROCESSOR ("_MIPS_ARCH", mips_arch_info); \
+ MIPS_CPP_SET_PROCESSOR ("_MIPS_TUNE", mips_tune_info); \
+ \
+ if (ISA_MIPS1) \
+ builtin_define ("__mips=1"); \
+ else if (ISA_MIPS2) \
+ builtin_define ("__mips=2"); \
+ else if (ISA_MIPS3) \
+ builtin_define ("__mips=3"); \
+ else if (ISA_MIPS4) \
+ builtin_define ("__mips=4"); \
+ else if (ISA_MIPS32) \
+ { \
+ builtin_define ("__mips=32"); \
+ builtin_define ("__mips_isa_rev=1"); \
+ } \
+ else if (ISA_MIPS32R2) \
+ { \
+ builtin_define ("__mips=32"); \
+ builtin_define ("__mips_isa_rev=2"); \
+ } \
+ else if (ISA_MIPS64) \
+ { \
+ builtin_define ("__mips=64"); \
+ builtin_define ("__mips_isa_rev=1"); \
+ } \
+ \
+ if (TARGET_HARD_FLOAT) \
+ builtin_define ("__mips_hard_float"); \
+ else if (TARGET_SOFT_FLOAT) \
+ builtin_define ("__mips_soft_float"); \
+ \
+ if (TARGET_SINGLE_FLOAT) \
+ builtin_define ("__mips_single_float"); \
+ \
+ if (TARGET_BIG_ENDIAN) \
+ builtin_define ("__MIPSEB__"); \
+ else \
+ builtin_define ("__MIPSEL__"); \
+ \
+ /* No language dialect defines. */ \
+ \
+ /* ABIs handled in TARGET_OS_CPP_BUILTINS. */ \
+ } \
+ while (0)
+
+
+/* Clean up after the generic MIPS/ELF configuration. */
+#undef MD_EXEC_PREFIX
+#undef MD_STARTFILE_PREFIX
+
+/* Extra specs we need. */
+#undef SUBTARGET_EXTRA_SPECS
+#define SUBTARGET_EXTRA_SPECS \
+ { "netbsd_cpp_spec", NETBSD_CPP_SPEC }, \
+ { "netbsd_link_spec", NETBSD_LINK_SPEC_ELF }, \
+ { "netbsd_entry_point", NETBSD_ENTRY_POINT },
+
+/* Provide a SUBTARGET_CPP_SPEC appropriate for NetBSD. */
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC "%(netbsd_cpp_spec)"
+
+/* Provide a LINK_SPEC appropriate for a NetBSD/mips target.
+ This is a copy of LINK_SPEC from <netbsd-elf.h> tweaked for
+ the MIPS target. */
+
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{EL:-m elf32lmip} \
+ %{EB:-m elf32bmip} \
+ %(endian_spec) \
+ %{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips32r2} %{mips64} \
+ %{bestGnum} %{call_shared} %{no_archive} %{exact_version} \
+ %(netbsd_link_spec)"
+
+#define NETBSD_ENTRY_POINT "__start"
+
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC \
+ "%{!mno-abicalls: \
+ %{!fno-PIC:%{!fno-pic:-KPIC}}}"
+
+
+/* -G is incompatible with -KPIC which is the default, so only allow objects
+ in the small data section if the user explicitly asks for it. */
+
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
+
+
+/* This defines which switch letters take arguments. -G is a MIPS
+ special. */
+
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) \
+ || (CHAR) == 'R' \
+ || (CHAR) == 'G')
+
+
+#undef ASM_FINAL_SPEC
+#undef SET_ASM_OP
+
+
+/* NetBSD hasn't historically provided _flush_cache(), but rather
+ _cacheflush(), which takes the same arguments as the former. */
+#undef CACHE_FLUSH_FUNC
+#define CACHE_FLUSH_FUNC "_cacheflush"
+
+
+/* Make gcc agree with <machine/ansi.h> */
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+#undef WINT_TYPE
+#define WINT_TYPE "int"
diff --git a/contrib/gcc/config/mips/openbsd.h b/contrib/gcc/config/mips/openbsd.h
new file mode 100644
index 0000000..69cc0c6
--- /dev/null
+++ b/contrib/gcc/config/mips/openbsd.h
@@ -0,0 +1,98 @@
+/* Configuration for a MIPS ABI32 OpenBSD target.
+ Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Definitions needed for OpenBSD, to avoid picking mips 'defaults'. */
+
+/* GAS must know this. */
+#undef SUBTARGET_ASM_SPEC
+#define SUBTARGET_ASM_SPEC "%{fPIC|fPIE:-KPIC}"
+
+#define AS_NEEDS_DASH_FOR_PIPED_INPUT
+
+/* CPP specific OpenBSD specs. */
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC OBSD_CPP_SPEC
+
+/* Needed for ELF (inspired by netbsd-elf). */
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* The profiling lib spec here is not really correct but we leave
+ it as it is until we have some kind of profiling working. */
+#define LIB_SPEC OBSD_LIB_SPEC
+
+/* mips assembler uses .set for arcane purposes. __attribute__((alias))
+ and friends won't work until we get recent binutils with .weakext
+ support. */
+#undef SET_ASM_OP
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do { \
+ builtin_define ("__unix__"); \
+ builtin_define ("__SYSTYPE_BSD__"); \
+ builtin_define ("__NO_LEADING_UNDERSCORES__"); \
+ builtin_define ("__GP_SUPPORT__"); \
+ builtin_define ("__OpenBSD__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=OpenBSD"); \
+} while (0)
+
+/* Layout of source language data types. */
+
+/* This must agree with <machine/ansi.h>. */
+#undef SIZE_TYPE
+#define SIZE_TYPE "unsigned int"
+
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "int"
+
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 32
+
+/* Controlling the compilation driver. */
+
+/* LINK_SPEC appropriate for OpenBSD: support for GCC options
+ -static, -assert, and -nostdlib. Dynamic loader control. */
+#undef LINK_SPEC
+#define LINK_SPEC \
+ "%{G*} %{EB} %{EL} %{mips1} %{mips2} %{mips3} \
+ %{bestGnum} %{shared} %{non_shared} \
+ %{call_shared} %{no_archive} %{exact_version} \
+ %{!shared: %{!non_shared: %{!call_shared: -non_shared}}} \
+ %{!dynamic-linker:-dynamic-linker /usr/libexec/ld.so} \
+ %{!nostdlib:%{!r*:%{!e*:-e __start}}} -dc -dp \
+ %{static:-Bstatic} %{!static:-Bdynamic} %{assert*}"
+
+/* -G is incompatible with -KPIC which is the default, so only allow objects
+ in the small data section if the user explicitly asks for it. */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
+
+
+/* Since gas and gld are standard on OpenBSD, we don't need these. */
+#undef ASM_FINAL_SPEC
+#undef STARTFILE_SPEC
+
+/* Switch into a generic section. */
+#undef TARGET_ASM_NAMED_SECTION
+#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
diff --git a/contrib/gcc/config/mips/predicates.md b/contrib/gcc/config/mips/predicates.md
new file mode 100644
index 0000000..9a6756c
--- /dev/null
+++ b/contrib/gcc/config/mips/predicates.md
@@ -0,0 +1,286 @@
+;; Predicate definitions for MIPS.
+;; Copyright (C) 2004 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_predicate "const_uns_arith_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND_UNSIGNED (INTVAL (op))")))
+
+(define_predicate "uns_arith_operand"
+ (ior (match_operand 0 "const_uns_arith_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_arith_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND (INTVAL (op))")))
+
+(define_predicate "arith_operand"
+ (ior (match_operand 0 "const_arith_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_uimm6_operand"
+ (and (match_code "const_int")
+ (match_test "UIMM6_OPERAND (INTVAL (op))")))
+
+(define_predicate "const_imm10_operand"
+ (and (match_code "const_int")
+ (match_test "IMM10_OPERAND (INTVAL (op))")))
+
+(define_predicate "reg_imm10_operand"
+ (ior (match_operand 0 "const_imm10_operand")
+ (match_operand 0 "register_operand")))
+
+(define_predicate "sle_operand"
+ (and (match_code "const_int")
+ (match_test "SMALL_OPERAND (INTVAL (op) + 1)")))
+
+(define_predicate "sleu_operand"
+ (and (match_operand 0 "sle_operand")
+ (match_test "INTVAL (op) + 1 != 0")))
+
+(define_predicate "const_0_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (GET_MODE (op))")))
+
+(define_predicate "reg_or_0_operand"
+ (ior (and (match_operand 0 "const_0_operand")
+ (match_test "!TARGET_MIPS16"))
+ (match_operand 0 "register_operand")))
+
+(define_predicate "const_1_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST1_RTX (GET_MODE (op))")))
+
+(define_predicate "reg_or_1_operand"
+ (ior (match_operand 0 "const_1_operand")
+ (match_operand 0 "register_operand")))
+
+;; This is used for indexing into vectors, and hence only accepts const_int.
+(define_predicate "const_0_or_1_operand"
+ (and (match_code "const_int")
+ (ior (match_test "op == CONST0_RTX (GET_MODE (op))")
+ (match_test "op == CONST1_RTX (GET_MODE (op))"))))
+
+(define_predicate "fpr_operand"
+ (and (match_code "reg")
+ (match_test "FP_REG_P (REGNO (op))")))
+
+(define_predicate "lo_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == LO_REGNUM")))
+
+(define_predicate "fcc_reload_operand"
+ (and (match_code "reg,subreg")
+ (match_test "ST_REG_P (true_regnum (op))")))
+
+(define_special_predicate "pc_or_label_operand"
+ (match_code "pc,label_ref"))
+
+(define_predicate "const_call_insn_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type symbol_type;
+
+ if (!mips_symbolic_constant_p (op, &symbol_type))
+ return false;
+
+ switch (symbol_type)
+ {
+ case SYMBOL_GENERAL:
+ /* We can only use direct calls for TARGET_ABSOLUTE_ABICALLS if we
+ are sure that the target function does not need $25 to be live
+ on entry. This is true for any locally-defined function because
+ any such function will use %hi/%lo accesses to set up $gp. */
+ if (TARGET_ABSOLUTE_ABICALLS
+ && !(GET_CODE (op) == SYMBOL_REF
+ && SYMBOL_REF_DECL (op)
+ && !DECL_EXTERNAL (SYMBOL_REF_DECL (op))))
+ return false;
+
+ /* If -mlong-calls, force all calls to use register addressing. Also,
+ if this function has the long_call attribute, we must use register
+ addressing. */
+ return !TARGET_LONG_CALLS && !SYMBOL_REF_LONG_CALL_P (op);
+
+ case SYMBOL_GOT_GLOBAL:
+ /* Without explicit relocs, there is no special syntax for
+ loading the address of a call destination into a register.
+ Using "la $25,foo; jal $25" would prevent the lazy binding
+ of "foo", so keep the address of global symbols with the
+ jal macro. */
+ return !TARGET_EXPLICIT_RELOCS;
+
+ default:
+ return false;
+ }
+})
+
+(define_predicate "call_insn_operand"
+ (ior (match_operand 0 "const_call_insn_operand")
+ (match_operand 0 "register_operand")))
+
+;; A legitimate CONST_INT operand that takes more than one instruction
+;; to load.
+(define_predicate "splittable_const_int_operand"
+ (match_code "const_int")
+{
+ /* When generating mips16 code, LEGITIMATE_CONSTANT_P rejects
+ CONST_INTs that can't be loaded using simple insns. */
+ if (TARGET_MIPS16)
+ return false;
+
+ /* Don't handle multi-word moves this way; we don't want to introduce
+ the individual word-mode moves until after reload. */
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ return false;
+
+ /* Otherwise check whether the constant can be loaded in a single
+ instruction. */
+ return !LUI_INT (op) && !SMALL_INT (op) && !SMALL_INT_UNSIGNED (op);
+})
+
+;; A legitimate symbolic operand that takes more than one instruction
+;; to load.
+(define_predicate "splittable_symbolic_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type symbol_type;
+ return (mips_symbolic_constant_p (op, &symbol_type)
+ && mips_split_p[symbol_type]);
+})
+
+(define_predicate "move_operand"
+ (match_operand 0 "general_operand")
+{
+ enum mips_symbol_type symbol_type;
+
+ /* The thinking here is as follows:
+
+ (1) The move expanders should split complex load sequences into
+ individual instructions. Those individual instructions can
+ then be optimized by all rtl passes.
+
+ (2) The target of pre-reload load sequences should not be used
+ to store temporary results. If the target register is only
+ assigned one value, reload can rematerialize that value
+ on demand, rather than spill it to the stack.
+
+ (3) If we allowed pre-reload passes like combine and cse to recreate
+ complex load sequences, we would want to be able to split the
+ sequences before reload as well, so that the pre-reload scheduler
+ can see the individual instructions. This falls foul of (2);
+ the splitter would be forced to reuse the target register for
+ intermediate results.
+
+ (4) We want to define complex load splitters for combine. These
+ splitters can request a temporary scratch register, which avoids
+ the problem in (2). They allow things like:
+
+ (set (reg T1) (high SYM))
+ (set (reg T2) (low (reg T1) SYM))
+ (set (reg X) (plus (reg T2) (const_int OFFSET)))
+
+ to be combined into:
+
+ (set (reg T3) (high SYM+OFFSET))
+ (set (reg X) (lo_sum (reg T3) SYM+OFFSET))
+
+ if T2 is only used this once. */
+ switch (GET_CODE (op))
+ {
+ case CONST_INT:
+ return !splittable_const_int_operand (op, mode);
+
+ case CONST:
+ case SYMBOL_REF:
+ case LABEL_REF:
+ if (CONST_GP_P (op))
+ return true;
+ return (mips_symbolic_constant_p (op, &symbol_type)
+ && !mips_split_p[symbol_type]);
+
+ default:
+ return true;
+ }
+})
+
+(define_predicate "consttable_operand"
+ (match_test "CONSTANT_P (op)"))
+
+(define_predicate "symbolic_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type);
+})
+
+(define_predicate "general_symbolic_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GENERAL;
+})
+
+(define_predicate "global_got_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_GLOBAL;
+})
+
+(define_predicate "local_got_operand"
+ (match_code "const,symbol_ref,label_ref")
+{
+ enum mips_symbol_type type;
+ return mips_symbolic_constant_p (op, &type) && type == SYMBOL_GOT_LOCAL;
+})
+
+(define_predicate "stack_operand"
+ (and (match_code "mem")
+ (match_test "mips_stack_address_p (XEXP (op, 0), GET_MODE (op))")))
+
+(define_predicate "macc_msac_operand"
+ (ior (and (match_code "plus") (match_test "ISA_HAS_MACC"))
+ (and (match_code "minus") (match_test "ISA_HAS_MSAC")))
+{
+ rtx mult = XEXP (op, GET_CODE (op) == PLUS ? 0 : 1);
+ rtx accum = XEXP (op, GET_CODE (op) == PLUS ? 1 : 0);
+ return (GET_CODE (mult) == MULT
+ && REG_P (XEXP (mult, 0))
+ && REG_P (XEXP (mult, 1))
+ && REG_P (accum));
+})
+
+
+(define_predicate "equality_operator"
+ (match_code "eq,ne"))
+
+(define_predicate "extend_operator"
+ (match_code "zero_extend,sign_extend"))
+
+(define_predicate "trap_comparison_operator"
+ (match_code "eq,ne,lt,ltu,ge,geu"))
+
+(define_predicate "order_operator"
+ (match_code "lt,ltu,le,leu,ge,geu,gt,gtu"))
+
+
+(define_predicate "small_data_pattern"
+ (and (match_code "set,parallel,unspec,unspec_volatile,prefetch")
+ (match_test "mips_small_data_pattern_p (op)")))
diff --git a/contrib/gcc/config/mips/r3900.h b/contrib/gcc/config/mips/r3900.h
new file mode 100644
index 0000000..d524689
--- /dev/null
+++ b/contrib/gcc/config/mips/r3900.h
@@ -0,0 +1,37 @@
+/* Definitions of MIPS sub target machine for GNU compiler.
+ Toshiba r3900. You should include mips.h after this.
+
+ Copyright (C) 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2004
+ Free Software Foundation, Inc.
+ Contributed by Gavin Koch (gavin@cygnus.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#define MIPS_CPU_STRING_DEFAULT "r3900"
+#define MIPS_ISA_DEFAULT 1
+
+#define MULTILIB_DEFAULTS { MULTILIB_ENDIAN_DEFAULT, "msoft-float" }
+
+/* We use the MIPS EABI by default. */
+#define MIPS_ABI_DEFAULT ABI_EABI
+
+/* By default (if not mips-something-else) produce code for the r3900 */
+#define SUBTARGET_CC1_SPEC "\
+%{mhard-float:%e-mhard-float not supported} \
+%{msingle-float:%{msoft-float: \
+ %e-msingle-float and -msoft-float cannot both be specified}}"
diff --git a/contrib/gcc/config/mips/rtems.h b/contrib/gcc/config/mips/rtems.h
new file mode 100644
index 0000000..0143de7
--- /dev/null
+++ b/contrib/gcc/config/mips/rtems.h
@@ -0,0 +1,36 @@
+/* Definitions for rtems targeting a MIPS using ELF.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2005
+ Free Software Foundation, Inc.
+ Contributed by Joel Sherrill (joel@OARcorp.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Specify predefined symbols in preprocessor. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+do { \
+ builtin_define ("__rtems__"); \
+ builtin_define ("__USE_INIT_FINI__"); \
+ builtin_assert ("system=rtems"); \
+} while (0)
+
+/* No sdata.
+ * The RTEMS BSPs expect -G0
+ */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
diff --git a/contrib/gcc/config/mips/sb1.md b/contrib/gcc/config/mips/sb1.md
new file mode 100644
index 0000000..7db31ef
--- /dev/null
+++ b/contrib/gcc/config/mips/sb1.md
@@ -0,0 +1,564 @@
+;;
+;; DFA-based pipeline description for Broadcom SB-1
+;;
+
+;; The Broadcom SB-1 core is 4-way superscalar, in-order. It has 2 load/store
+;; pipes (one of which can support some ALU operations), 2 alu pipes, 2 FP
+;; pipes, and 1 MDMX pipes. It can issue 2 ls insns and 2 exe/fpu/mdmx insns
+;; each cycle.
+
+;; We model the 4-way issue by ordering unit choices. The possible choices are
+;; {ex1,fp1}|{ex0,fp0}|ls1|ls0. Instructions issue to the first eligible unit
+;; in the list in most cases. Non-indexed load/stores issue to ls0 first.
+;; simple alu operations issue to ls1 if it is still available, and their
+;; operands are ready (no co-issue with loads), otherwise to the first
+;; available ex unit.
+
+;; When exceptions are enabled, can only issue FP insns to fp1. This is
+;; to ensure that instructions complete in order. The -mfp-exceptions option
+;; can be used to specify whether the system has FP exceptions enabled or not.
+
+;; In 32-bit mode, dependent FP can't co-issue with load, and only one FP exe
+;; insn can issue per cycle (fp1).
+
+;; The A1 MDMX pipe is separate from the FP pipes, but uses the same register
+;; file. As a result, once an MDMX insn is issued, no FP insns can be issued
+;; for 3 cycles. When an FP insn is issued, no MDMX insn can be issued for
+;; 5 cycles. This is currently not handled because there is no MDMX insn
+;; support as yet.
+
+;;
+;; We use two automata. sb1_cpu_div is for the integer divides, which are
+;; not pipelined. sb1_cpu is for everything else.
+;;
+(define_automaton "sb1_cpu, sb1_cpu_div")
+
+;; Load/store function units.
+(define_cpu_unit "sb1_ls0" "sb1_cpu")
+(define_cpu_unit "sb1_ls1" "sb1_cpu")
+
+;; CPU function units.
+(define_cpu_unit "sb1_ex0" "sb1_cpu")
+(define_cpu_unit "sb1_ex1" "sb1_cpu")
+
+;; The divide unit is not pipelined, and blocks hi/lo reads and writes.
+(define_cpu_unit "sb1_div" "sb1_cpu_div")
+;; DMULT block any multiply from issuing in the next cycle.
+(define_cpu_unit "sb1_mul" "sb1_cpu")
+
+;; Floating-point units.
+(define_cpu_unit "sb1_fp0" "sb1_cpu")
+(define_cpu_unit "sb1_fp1" "sb1_cpu")
+
+;; Can only issue to one of the ex and fp pipes at a time.
+(exclusion_set "sb1_ex0" "sb1_fp0")
+(exclusion_set "sb1_ex1" "sb1_fp1")
+
+;; Define an SB-1 specific attribute to simplify some FP descriptions.
+;; We can use 2 FP pipes only if we have 64-bit FP code, and exceptions are
+;; disabled.
+
+(define_attr "sb1_fp_pipes" "one,two"
+ (cond [(and (ne (symbol_ref "TARGET_FLOAT64") (const_int 0))
+ (eq (symbol_ref "TARGET_FP_EXCEPTIONS") (const_int 0)))
+ (const_string "two")]
+ (const_string "one")))
+
+;; Define reservations for common combinations.
+
+;; For long cycle operations, the FPU has a 4 cycle pipeline that repeats,
+;; effectively re-issuing the operation every 4 cycles. This means that we
+;; can have at most 4 long-cycle operations per pipe.
+
+;; ??? The fdiv operations should be e.g.
+;; sb1_fp1_4cycles*7" | "sb1_fp0_4cycle*7
+;; but the DFA is too large when we do that. Perhaps have to use scheduler
+;; hooks here.
+
+;; ??? Try limiting scheduler to 2 long latency operations, and see if this
+;; results in a usable DFA, and whether it helps code performance.
+
+;;(define_reservation "sb1_fp0_4cycles" "sb1_fp0, nothing*3")
+;;(define_reservation "sb1_fp1_4cycles" "sb1_fp1, nothing*3")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+(define_insn_reservation "ir_sb1_unknown" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "unknown,multi"))
+ "sb1_ls0+sb1_ls1+sb1_ex0+sb1_ex1+sb1_fp0+sb1_fp1")
+
+;; predicted taken branch causes 2 cycle ifetch bubble. predicted not
+;; taken branch causes 0 cycle ifetch bubble. mispredicted branch causes 8
+;; cycle ifetch bubble. We assume all branches predicted not taken.
+
+;; ??? This assumption that branches are predicated not taken should be
+;; investigated. Maybe using 2 here will give better results.
+
+(define_insn_reservation "ir_sb1_branch" 0
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "branch,jump,call"))
+ "sb1_ex0")
+
+;; ??? This is 1 cycle for ldl/ldr to ldl/ldr when they use the same data
+;; register as destination.
+
+;; ??? SB-1 can co-issue a load with a dependent arith insn if it executes on
+;; an EX unit. Can not co-issue if the dependent insn executes on an LS unit.
+;; SB-1A can always co-issue here.
+
+;; A load normally has a latency of zero cycles. In some cases, dependent
+;; insns can be issued in the same cycle. However, a value of 1 gives
+;; better performance in empirical testing.
+
+(define_insn_reservation "ir_sb1_load" 1
+ (and (eq_attr "cpu" "sb1")
+ (eq_attr "type" "load,prefetch"))
+ "sb1_ls0 | sb1_ls1")
+
+(define_insn_reservation "ir_sb1a_load" 0
+ (and (eq_attr "cpu" "sb1a")
+ (eq_attr "type" "load,prefetch"))
+ "sb1_ls0 | sb1_ls1")
+
+;; Can not co-issue fpload with fp exe when in 32-bit mode.
+
+(define_insn_reservation "ir_sb1_fpload" 0
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fpload")
+ (ne (symbol_ref "TARGET_FLOAT64")
+ (const_int 0))))
+ "sb1_ls0 | sb1_ls1")
+
+(define_insn_reservation "ir_sb1_fpload_32bitfp" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fpload")
+ (eq (symbol_ref "TARGET_FLOAT64")
+ (const_int 0))))
+ "sb1_ls0 | sb1_ls1")
+
+;; Indexed loads can only execute on LS1 pipe.
+
+(define_insn_reservation "ir_sb1_fpidxload" 0
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fpidxload")
+ (ne (symbol_ref "TARGET_FLOAT64")
+ (const_int 0))))
+ "sb1_ls1")
+
+(define_insn_reservation "ir_sb1_fpidxload_32bitfp" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fpidxload")
+ (eq (symbol_ref "TARGET_FLOAT64")
+ (const_int 0))))
+ "sb1_ls1")
+
+;; prefx can only execute on the ls1 pipe.
+
+(define_insn_reservation "ir_sb1_prefetchx" 0
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "prefetchx"))
+ "sb1_ls1")
+
+;; ??? There is a 4.5 cycle latency if a store is followed by a load, and
+;; there is a RAW dependency.
+
+(define_insn_reservation "ir_sb1_store" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "store"))
+ "sb1_ls0+sb1_ex1 | sb1_ls0+sb1_ex0 | sb1_ls1+sb1_ex1 | sb1_ls1+sb1_ex0")
+
+(define_insn_reservation "ir_sb1_fpstore" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "fpstore"))
+ "sb1_ls0+sb1_fp1 | sb1_ls0+sb1_fp0 | sb1_ls1+sb1_fp1 | sb1_ls1+sb1_fp0")
+
+;; Indexed stores can only execute on LS1 pipe.
+
+(define_insn_reservation "ir_sb1_fpidxstore" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "fpidxstore"))
+ "sb1_ls1+sb1_fp1 | sb1_ls1+sb1_fp0")
+
+;; Load latencies are 3 cycles for one load to another load or store (address
+;; only). This is 0 cycles for one load to a store using it as the data
+;; written.
+
+;; This assumes that if a load is dependent on a previous insn, then it must
+;; be an address dependence.
+
+(define_bypass 3
+ "ir_sb1_load,ir_sb1a_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,
+ ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp"
+ "ir_sb1_load,ir_sb1a_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,
+ ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx")
+
+(define_bypass 3
+ "ir_sb1_load,ir_sb1a_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,
+ ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp"
+ "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore"
+ "mips_store_data_bypass_p")
+
+;; On SB-1, simple alu instructions can execute on the LS1 unit.
+
+;; ??? A simple alu insn issued on an LS unit has 0 cycle latency to an EX
+;; insn, to a store (for data), and to an xfer insn. It has 1 cycle latency to
+;; another LS insn (excluding store data). A simple alu insn issued on an EX
+;; unit has a latency of 5 cycles when the results goes to a LS unit (excluding
+;; store data), otherwise a latency of 1 cycle.
+
+;; ??? We cannot handle latencies properly for simple alu instructions
+;; within the DFA pipeline model. Latencies can be defined only from one
+;; insn reservation to another. We can't make them depend on which function
+;; unit was used. This isn't a DFA flaw. There is a conflict here, as we
+;; need to know the latency before we can determine which unit will be
+;; available, but we need to know which unit it is issued to before we can
+;; compute the latency. Perhaps this can be handled via scheduler hooks.
+;; This needs to be investigated.
+
+;; ??? Optimal scheduling taking the LS units into account seems to require
+;; a pre-scheduling pass. We need to determine which instructions feed results
+;; into store/load addresses, and thus benefit most from being issued to the
+;; LS unit. Also, we need to prune the list to ensure we don't overschedule
+;; insns to the LS unit, and that we don't conflict with insns that need LS1
+;; such as indexed loads. We then need to emit nops to ensure that simple
+;; alu instructions that are not supposed to be scheduled to LS1 don't
+;; accidentally end up there because LS1 is free when they are issued. This
+;; will be a lot of work, and it isn't clear how useful it will be.
+
+;; Empirical testing shows that 2 gives the best result.
+
+(define_insn_reservation "ir_sb1_simple_alu" 2
+ (and (eq_attr "cpu" "sb1")
+ (eq_attr "type" "const,arith"))
+ "sb1_ls1 | sb1_ex1 | sb1_ex0")
+
+;; On SB-1A, simple alu instructions can not execute on the LS1 unit, and we
+;; have none of the above problems.
+
+(define_insn_reservation "ir_sb1a_simple_alu" 1
+ (and (eq_attr "cpu" "sb1a")
+ (eq_attr "type" "const,arith"))
+ "sb1_ex1 | sb1_ex0")
+
+;; ??? condmove also includes some FP instructions that execute on the FP
+;; units. This needs to be clarified.
+
+(define_insn_reservation "ir_sb1_alu" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "condmove,nop,shift"))
+ "sb1_ex1 | sb1_ex0")
+
+;; These are type arith/darith that only execute on the EX0 unit.
+
+(define_insn_reservation "ir_sb1_alu_0" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "slt,clz,trap"))
+ "sb1_ex0")
+
+;; An alu insn issued on an EX unit has a latency of 5 cycles when the
+;; result goes to a LS unit (excluding store data).
+
+;; This assumes that if a load is dependent on a previous insn, then it must
+;; be an address dependence.
+
+(define_bypass 5
+ "ir_sb1a_simple_alu,ir_sb1_alu,ir_sb1_alu_0,ir_sb1_mfhi,ir_sb1_mflo"
+ "ir_sb1_load,ir_sb1a_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,
+ ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx")
+
+(define_bypass 5
+ "ir_sb1a_simple_alu,ir_sb1_alu,ir_sb1_alu_0,ir_sb1_mfhi,ir_sb1_mflo"
+ "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore"
+ "mips_store_data_bypass_p")
+
+;; mf{hi,lo} is 1 cycle.
+
+(define_insn_reservation "ir_sb1_mfhi" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "mfhilo")
+ (not (match_operand 1 "lo_operand"))))
+ "sb1_ex1")
+
+(define_insn_reservation "ir_sb1_mflo" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "mfhilo")
+ (match_operand 1 "lo_operand")))
+ "sb1_ex1")
+
+;; mt{hi,lo} to mul/div is 4 cycles.
+
+(define_insn_reservation "ir_sb1_mthilo" 4
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "mthilo"))
+ "sb1_ex1")
+
+;; mt{hi,lo} to mf{hi,lo} is 3 cycles.
+
+(define_bypass 3 "ir_sb1_mthilo" "ir_sb1_mfhi,ir_sb1_mflo")
+
+;; multiply latency to an EX operation is 3 cycles.
+
+;; ??? Should check whether we need to make multiply conflict with moves
+;; to/from hilo registers.
+
+(define_insn_reservation "ir_sb1_mulsi" 3
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI")))
+ "sb1_ex1+sb1_mul")
+
+;; muldi to mfhi is 4 cycles.
+;; Blocks any other multiply insn issue for 1 cycle.
+
+(define_insn_reservation "ir_sb1_muldi" 4
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "imul,imul3")
+ (eq_attr "mode" "DI")))
+ "sb1_ex1+sb1_mul, sb1_mul")
+
+;; muldi to mflo is 3 cycles.
+
+(define_bypass 3 "ir_sb1_muldi" "ir_sb1_mflo")
+
+;; mul latency is 7 cycles if the result is used by any LS insn.
+
+;; This assumes that if a load is dependent on a previous insn, then it must
+;; be an address dependence.
+
+(define_bypass 7
+ "ir_sb1_mulsi,ir_sb1_muldi"
+ "ir_sb1_load,ir_sb1a_load,ir_sb1_fpload,ir_sb1_fpload_32bitfp,
+ ir_sb1_fpidxload,ir_sb1_fpidxload_32bitfp,ir_sb1_prefetchx")
+
+(define_bypass 7
+ "ir_sb1_mulsi,ir_sb1_muldi"
+ "ir_sb1_store,ir_sb1_fpstore,ir_sb1_fpidxstore"
+ "mips_store_data_bypass_p")
+
+;; The divide unit is not pipelined. Divide busy is asserted in the 4th
+;; cycle, and then deasserted on the latency cycle. So only one divide at
+;; a time, but the first/last 4 cycles can overlap.
+
+;; ??? All divides block writes to hi/lo regs. hi/lo regs are written 4 cycles
+;; after the latency cycle for divides (e.g. 40/72). dmult writes lo in
+;; cycle 7, and hi in cycle 8. All other insns write hi/lo regs in cycle 7.
+;; Default for output dependencies is the difference in latencies, which is
+;; only 1 cycle off here, e.g. div to mtlo stalls for 32 cycles, but should
+;; stall for 33 cycles. This does not seem significant enough to worry about.
+
+(define_insn_reservation "ir_sb1_divsi" 36
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "sb1_ex1, nothing*3, sb1_div*32")
+
+(define_insn_reservation "ir_sb1_divdi" 68
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "sb1_ex1, nothing*3, sb1_div*64")
+
+(define_insn_reservation "ir_sb1_fpu_2pipes" 4
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fmove,fadd,fmul,fabs,fneg,fcvt,frdiv1,frsqrt1")
+ (eq_attr "sb1_fp_pipes" "two")))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_fpu_1pipe" 4
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fmove,fadd,fmul,fabs,fneg,fcvt,frdiv1,frsqrt1")
+ (eq_attr "sb1_fp_pipes" "one")))
+ "sb1_fp1")
+
+(define_insn_reservation "ir_sb1_fpu_step2_2pipes" 8
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv2,frsqrt2")
+ (eq_attr "sb1_fp_pipes" "two")))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_fpu_step2_1pipe" 8
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv2,frsqrt2")
+ (eq_attr "sb1_fp_pipes" "one")))
+ "sb1_fp1")
+
+;; ??? madd/msub 4-cycle latency to itself (same fr?), but 8 cycle latency
+;; otherwise.
+
+;; ??? Blocks issue of another non-madd/msub after 4 cycles.
+
+(define_insn_reservation "ir_sb1_fmadd_2pipes" 8
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "sb1_fp_pipes" "two")))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_fmadd_1pipe" 8
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fmadd")
+ (eq_attr "sb1_fp_pipes" "one")))
+ "sb1_fp1")
+
+(define_insn_reservation "ir_sb1_fcmp" 4
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (eq_attr "type" "fcmp"))
+ "sb1_fp1")
+
+;; mtc1 latency 5 cycles.
+
+(define_insn_reservation "ir_sb1_mtxfer" 5
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "xfer")
+ (match_operand 0 "fpr_operand")))
+ "sb1_fp0")
+
+;; mfc1 latency 1 cycle.
+
+(define_insn_reservation "ir_sb1_mfxfer" 1
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "xfer")
+ (not (match_operand 0 "fpr_operand"))))
+ "sb1_fp0")
+
+;; ??? Can deliver at most 1 result per every 6 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_divsf_2pipes" 24
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_divsf_1pipe" 24
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 8 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_divdf_2pipes" 32
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_divdf_1pipe" 32
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 3 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_recipsf_2pipes" 12
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_recipsf_1pipe" 12
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 5 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_recipdf_2pipes" 20
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_recipdf_1pipe" 20
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frdiv")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 7 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_sqrtsf_2pipes" 28
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_sqrtsf_1pipe" 28
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 10 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_sqrtdf_2pipes" 40
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_sqrtdf_1pipe" 40
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "fsqrt")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 4 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_rsqrtsf_2pipes" 16
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frsqrt")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_rsqrtsf_1pipe" 16
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frsqrt")
+ (and (eq_attr "mode" "SF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
+
+;; ??? Can deliver at most 1 result per every 7 cycles because of issue
+;; restrictions.
+
+(define_insn_reservation "ir_sb1_rsqrtdf_2pipes" 28
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frsqrt")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "two"))))
+ "sb1_fp1 | sb1_fp0")
+
+(define_insn_reservation "ir_sb1_rsqrtdf_1pipe" 28
+ (and (eq_attr "cpu" "sb1,sb1a")
+ (and (eq_attr "type" "frsqrt")
+ (and (eq_attr "mode" "DF")
+ (eq_attr "sb1_fp_pipes" "one"))))
+ "sb1_fp1")
diff --git a/contrib/gcc/config/mips/sdb.h b/contrib/gcc/config/mips/sdb.h
new file mode 100644
index 0000000..a26826e
--- /dev/null
+++ b/contrib/gcc/config/mips/sdb.h
@@ -0,0 +1,88 @@
+/* Generate SDB debugging info.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* Note that no configuration uses sdb as its preferred format. */
+
+#define SDB_DEBUGGING_INFO 1
+
+/* Forward references to tags are allowed. */
+#define SDB_ALLOW_FORWARD_REFERENCES
+
+/* Unknown tags are also allowed. */
+#define SDB_ALLOW_UNKNOWN_REFERENCES
+
+/* Block start/end next label #. */
+extern int sdb_label_count;
+
+/* Starting line of current function. */
+extern int sdb_begin_function_line;
+
+/* For block start and end, we create labels, so that
+ later we can figure out where the correct offset is.
+ The normal .ent/.end serve well enough for functions,
+ so those are just commented out. */
+
+#define PUT_SDB_BLOCK_START(LINE) \
+do { \
+ fprintf (asm_out_file, \
+ "%sLb%d:\n\t.begin\t%sLb%d\t%d\n", \
+ LOCAL_LABEL_PREFIX, \
+ sdb_label_count, \
+ LOCAL_LABEL_PREFIX, \
+ sdb_label_count, \
+ (LINE)); \
+ sdb_label_count++; \
+} while (0)
+
+#define PUT_SDB_BLOCK_END(LINE) \
+do { \
+ fprintf (asm_out_file, \
+ "%sLe%d:\n\t.bend\t%sLe%d\t%d\n", \
+ LOCAL_LABEL_PREFIX, \
+ sdb_label_count, \
+ LOCAL_LABEL_PREFIX, \
+ sdb_label_count, \
+ (LINE)); \
+ sdb_label_count++; \
+} while (0)
+
+#define PUT_SDB_FUNCTION_START(LINE)
+
+#define PUT_SDB_FUNCTION_END(LINE) \
+do { \
+ SDB_OUTPUT_SOURCE_LINE (asm_out_file, LINE + sdb_begin_function_line); \
+} while (0)
+
+#define PUT_SDB_EPILOGUE_END(NAME)
+
+/* We need to use .esize and .etype instead of .size and .type to
+ avoid conflicting with ELF directives. */
+#undef PUT_SDB_SIZE
+#define PUT_SDB_SIZE(a) \
+do { \
+ fprintf (asm_out_file, "\t.esize\t" HOST_WIDE_INT_PRINT_DEC ";", \
+ (HOST_WIDE_INT) (a)); \
+} while (0)
+
+#undef PUT_SDB_TYPE
+#define PUT_SDB_TYPE(a) \
+do { \
+ fprintf (asm_out_file, "\t.etype\t0x%x;", (a)); \
+} while (0)
diff --git a/contrib/gcc/config/mips/sr71k.md b/contrib/gcc/config/mips/sr71k.md
new file mode 100644
index 0000000..268bc48
--- /dev/null
+++ b/contrib/gcc/config/mips/sr71k.md
@@ -0,0 +1,321 @@
+;; .........................
+;;
+;; DFA-based pipeline description for Sandcraft SR3 (MIPS64 based)
+;;
+;; The SR3 is described as:
+;; - nine-stage pipeline, insn buffering with out-of-order issue to
+;; multiple function units, with an average dispatch rate of 2
+;; insn.s per cycle (max 6 insns: 2 fpu, 4 cpu).
+;;
+;; The details on this are scant except for a diagram in
+;; Chap. 6 of Rev. 1.0 SR3 Spec.
+;;
+;; The model employed below is designed to closely approximate the
+;; published latencies. Emulation of out-of-order issue and the insn
+;; buffering is done via a VLIW dispatch style (with a packing of 6 insns);
+;; the function unit reservations restrictions (define_*_set) are
+;; contrived to support published timings.
+;;
+;; Reference:
+;; "SR3 Microprocessor Specification, System development information,"
+;; Revision 1.0, 13 December 2000.
+;;
+;;
+;; Reservation model is based on:
+;; 1) Figure 6-1, from the 1.0 specification.
+;; 2) Chapter 19, from the 1.0 specification.
+;; 3) following questions(Red Hat)/answers(Sandcraft):
+;; RH> From Section 19.1
+;; RH> 1) In terms of figure 6-1, are all the instructions in
+;; RH> table 19-1 restricted
+;; RH> to ALUx? When ALUx is not in use for an instruction in table;; RH> 19-1 is
+;; RH> it fully compatible with all insns that issue to ALUy?
+;;
+;; Yes, all the instructions in Table 19-1 only go to ALUX, and all the
+;; instructions that can be issued to ALUY can also be issued to ALUX.
+;;
+;;
+;; RH> From Section 19.2
+;; RH> 2) Explain conditional moves execution path (in terms of
+;; RH> figure 6-1)
+;;
+;; Conditional move of integer registers (based on floating point condition
+;; codes or integer register value) go to ALUX or ALUY.
+;;
+;; RH> 3) Explain floating point store execution path (in terms of
+;; RH> figure 6-1)
+;;
+;; Floating point stores go to Ld/St and go to MOV in the floating point
+;; pipeline.
+;;
+;; Floating point loads go to Ld/St and go to LOAD in the floating point
+;; pipeline.
+;;
+;; RH> 4) Explain branch on floating condition (in terms of figure 6-1);;
+;; Branch on floating condition go to BRU.
+;;
+;; RH> 5) Is the column for single RECIP instruction latency correct?
+;; RH> What about for RSQRT single and double?
+;;
+;; The latency/repeat for RECIP and RSQRT are correct.
+;;
+
+;;
+;; Use four automata to isolate long latency operations, and to
+;; reduce the complexity of cpu+fpu, reducing space.
+;;
+(define_automaton "sr71_cpu, sr71_cpu1, sr71_cp1, sr71_cp2, sr71_fextra, sr71_imacc")
+
+;; feeders for CPU function units and feeders for fpu (CP1 interface)
+(define_cpu_unit "sr_iss0,sr_iss1,sr_iss2,sr_iss3,sr_iss4,sr_iss5" "sr71_cpu")
+
+;; CPU function units
+(define_cpu_unit "ipu_bru" "sr71_cpu1")
+(define_cpu_unit "ipu_alux" "sr71_cpu1")
+(define_cpu_unit "ipu_aluy" "sr71_cpu1")
+(define_cpu_unit "ipu_ldst" "sr71_cpu1")
+(define_cpu_unit "ipu_macc_iter" "sr71_imacc")
+
+
+;; Floating-point unit (Co-processor interface 1).
+(define_cpu_unit "fpu_mov" "sr71_cp1")
+(define_cpu_unit "fpu_load" "sr71_cp1")
+(define_cpu_unit "fpu_fpu" "sr71_cp2")
+
+;; fictitous unit to track long float insns with separate automaton
+(define_cpu_unit "fpu_iter" "sr71_fextra")
+
+
+;;
+;; Define common execution path (reservation) combinations
+;;
+
+;;
+(define_reservation "cpu_iss" "sr_iss0|sr_iss1|sr_iss2|sr_iss3")
+
+;; two cycles are used for instruction using the fpu as it runs
+;; at half the clock speed of the cpu. By adding an extra cycle
+;; to the issue units, the default/minimum "repeat" dispatch delay is
+;; accounted for all insn.s
+(define_reservation "cp1_iss" "(sr_iss4*2)|(sr_iss5*2)")
+
+(define_reservation "serial_dispatch" "sr_iss0+sr_iss1+sr_iss2+sr_iss3+sr_iss4+sr_iss5")
+
+;; Simulate a 6 insn VLIW dispatch, 1 cycle in dispatch followed by
+;; reservation of function unit.
+(define_reservation "ri_insns" "cpu_iss,(ipu_alux|ipu_aluy)")
+(define_reservation "ri_mem" "cpu_iss,ipu_ldst")
+(define_reservation "ri_alux" "cpu_iss,ipu_alux")
+(define_reservation "ri_branch" "cpu_iss,ipu_bru")
+
+(define_reservation "rf_insn" "cp1_iss,fpu_fpu")
+(define_reservation "rf_ldmem" "cp1_iss,fpu_load")
+
+; simultaneous reservation of pseudo-unit keeps cp1 fpu tied
+; up until long cycle insn is finished...
+(define_reservation "rf_multi1" "rf_insn+fpu_iter")
+
+;;
+;; The ordering of the instruction-execution-path/resource-usage
+;; descriptions (also known as reservation RTL) is roughly ordered
+;; based on the define attribute RTL for the "type" classification.
+;; When modifying, remember that the first test that matches is the
+;; reservation used!
+;;
+
+
+(define_insn_reservation "ir_sr70_unknown" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "unknown"))
+ "serial_dispatch")
+
+
+;; Assume prediction fails.
+(define_insn_reservation "ir_sr70_branch" 6
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "branch,jump,call"))
+ "ri_branch")
+
+(define_insn_reservation "ir_sr70_load" 2
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "load"))
+ "ri_mem")
+
+(define_insn_reservation "ir_sr70_store" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "store"))
+ "ri_mem")
+
+
+;;
+;; float loads/stores flow through both cpu and cp1...
+;;
+(define_insn_reservation "ir_sr70_fload" 9
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "fpload,fpidxload"))
+ "(cpu_iss+cp1_iss),(ri_mem+rf_ldmem)")
+
+(define_insn_reservation "ir_sr70_fstore" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "fpstore,fpidxstore"))
+ "(cpu_iss+cp1_iss),(fpu_mov+ri_mem)")
+
+
+;; This reservation is for conditional move based on integer
+;; or floating point CC.
+(define_insn_reservation "ir_sr70_condmove" 4
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "condmove"))
+ "ri_insns")
+
+;; Try to discriminate move-from-cp1 versus move-to-cp1 as latencies
+;; are different. Like float load/store, these insns use multiple
+;; resources simultaneously
+(define_insn_reservation "ir_sr70_xfer_from" 6
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "xfer")
+ (eq_attr "mode" "!SF,DF,FPSW")))
+ "(cpu_iss+cp1_iss),(fpu_mov+ri_mem)")
+
+(define_insn_reservation "ir_sr70_xfer_to" 9
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "xfer")
+ (eq_attr "mode" "SF,DF")))
+ "(cpu_iss+cp1_iss),(ri_mem+rf_ldmem)")
+
+(define_insn_reservation "ir_sr70_hilo" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "mthilo,mfhilo"))
+ "ri_insns")
+
+(define_insn_reservation "ir_sr70_arith" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "arith,shift,slt,clz,const,trap"))
+ "ri_insns")
+
+;; emulate repeat (dispatch stall) by spending extra cycle(s) in
+;; in iter unit
+(define_insn_reservation "ir_sr70_imul_si" 4
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "SI")))
+ "ri_alux,ipu_alux,ipu_macc_iter")
+
+(define_insn_reservation "ir_sr70_imul_di" 6
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "imul,imul3,imadd")
+ (eq_attr "mode" "DI")))
+ "ri_alux,ipu_alux,(ipu_macc_iter*3)")
+
+;; Divide algorithm is early out with best latency of 7 pcycles.
+;; Use worst case for scheduling purposes.
+(define_insn_reservation "ir_sr70_idiv_si" 41
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "SI")))
+ "ri_alux,ipu_alux,(ipu_macc_iter*38)")
+
+(define_insn_reservation "ir_sr70_idiv_di" 73
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "idiv")
+ (eq_attr "mode" "DI")))
+ "ri_alux,ipu_alux,(ipu_macc_iter*70)")
+
+;; extra reservations of fpu_fpu are for repeat latency
+(define_insn_reservation "ir_sr70_fadd_sf" 8
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fadd")
+ (eq_attr "mode" "SF")))
+ "rf_insn,fpu_fpu")
+
+(define_insn_reservation "ir_sr70_fadd_df" 10
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fadd")
+ (eq_attr "mode" "DF")))
+ "rf_insn,fpu_fpu")
+
+;; Latencies for MADD,MSUB, NMADD, NMSUB assume the Multiply is fused
+;; with the sub or add.
+(define_insn_reservation "ir_sr70_fmul_sf" 8
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "SF")))
+ "rf_insn,fpu_fpu")
+
+;; tie up the fpu unit to emulate the balance for the "repeat
+;; rate" of 8 (2 are spent in the iss unit)
+(define_insn_reservation "ir_sr70_fmul_df" 16
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fmul,fmadd")
+ (eq_attr "mode" "DF")))
+ "rf_insn,fpu_fpu*6")
+
+
+;; RECIP insn uses same type attr as div, and for SR3, has same
+;; timings for double. However, single RECIP has a latency of
+;; 28 -- only way to fix this is to introduce new insn attrs.
+;; cycles spent in iter unit are designed to satisfy balance
+;; of "repeat" latency after insn uses up rf_multi1 reservation
+(define_insn_reservation "ir_sr70_fdiv_sf" 60
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "SF")))
+ "rf_multi1+(fpu_iter*51)")
+
+(define_insn_reservation "ir_sr70_fdiv_df" 120
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fdiv,frdiv")
+ (eq_attr "mode" "DF")))
+ "rf_multi1+(fpu_iter*109)")
+
+(define_insn_reservation "ir_sr70_fabs" 4
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "fabs,fneg,fmove"))
+ "rf_insn,fpu_fpu")
+
+(define_insn_reservation "ir_sr70_fcmp" 10
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "fcmp"))
+ "rf_insn,fpu_fpu")
+
+;; "fcvt" type attribute covers a number of diff insns, most have the same
+;; latency descriptions, a few vary. We use the
+;; most common timing (which is also worst case).
+(define_insn_reservation "ir_sr70_fcvt" 12
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "fcvt"))
+ "rf_insn,fpu_fpu*4")
+
+(define_insn_reservation "ir_sr70_fsqrt_sf" 62
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fsqrt")
+ (eq_attr "mode" "SF")))
+ "rf_multi1+(fpu_iter*53)")
+
+(define_insn_reservation "ir_sr70_fsqrt_df" 122
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "fsqrt")
+ (eq_attr "mode" "DF")))
+ "rf_multi1+(fpu_iter*111)")
+
+(define_insn_reservation "ir_sr70_frsqrt_sf" 48
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "SF")))
+ "rf_multi1+(fpu_iter*39)")
+
+(define_insn_reservation "ir_sr70_frsqrt_df" 240
+ (and (eq_attr "cpu" "sr71000")
+ (and (eq_attr "type" "frsqrt")
+ (eq_attr "mode" "DF")))
+ "rf_multi1+(fpu_iter*229)")
+
+(define_insn_reservation "ir_sr70_multi" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "multi"))
+ "serial_dispatch")
+
+(define_insn_reservation "ir_sr70_nop" 1
+ (and (eq_attr "cpu" "sr71000")
+ (eq_attr "type" "nop"))
+ "ri_insns")
diff --git a/contrib/gcc/config/mips/t-elf b/contrib/gcc/config/mips/t-elf
new file mode 100644
index 0000000..f2da07d
--- /dev/null
+++ b/contrib/gcc/config/mips/t-elf
@@ -0,0 +1,40 @@
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
+
+LIB1ASMSRC = mips/mips16.S
+LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
+ _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \
+ _m16fltsisf _m16fix_truncsfsi \
+ _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \
+ _m16extsfdf2 _m16trdfsf2 \
+ _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
+ _m16fltsidf _m16fix_truncdfsi \
+ _m16retsf _m16retdf \
+ _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
+ _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
+ _m16stubsf9 _m16stubsf10 \
+ _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
+ _m16stubdf9 _m16stubdf10
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = msoft-float EL/EB
+MULTILIB_DIRNAMES = soft-float el eb
+MULTILIB_MATCHES = EL=mel EB=meb msingle-float=m4650
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/mips/t-gofast b/contrib/gcc/config/mips/t-gofast
new file mode 100644
index 0000000..a6c60d4
--- /dev/null
+++ b/contrib/gcc/config/mips/t-gofast
@@ -0,0 +1,19 @@
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __MIPSEL__' > dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#ifdef __MIPSEL__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
diff --git a/contrib/gcc/config/mips/t-iris b/contrib/gcc/config/mips/t-iris
new file mode 100644
index 0000000..4a7143f
--- /dev/null
+++ b/contrib/gcc/config/mips/t-iris
@@ -0,0 +1,12 @@
+# Find all of the declarations from the header files
+FIXPROTO_DEFINES = -D__EXTENSIONS__ -D_SGI_SOURCE -D_LANGUAGE_C_PLUS_PLUS
+
+$(T)irix-crti.o: $(srcdir)/config/mips/irix-crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $@ -x assembler-with-cpp $<
+
+$(T)irix-crtn.o: $(srcdir)/config/mips/irix-crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $@ -x assembler-with-cpp $<
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o irix-crti.o irix-crtn.o
diff --git a/contrib/gcc/config/mips/t-iris6 b/contrib/gcc/config/mips/t-iris6
new file mode 100644
index 0000000..5155472
--- /dev/null
+++ b/contrib/gcc/config/mips/t-iris6
@@ -0,0 +1,19 @@
+MULTILIB_OPTIONS=mabi=n32/mabi=32/mabi=64
+MULTILIB_DIRNAMES=n32 32 64
+MULTILIB_MATCHES=
+MULTILIB_OSDIRNAMES=../lib32 ../lib ../lib64
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+TPBIT = tp-bit.c
+
+tp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __MIPSEL__' > tp-bit.c
+ echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
+ echo '#endif' >> tp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> tp-bit.c
+ echo '#if __LDBL_MANT_DIG__ == 106' >> tp-bit.c
+ echo '# define TFLOAT' >> tp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> tp-bit.c
+ echo '#endif' >> tp-bit.c
diff --git a/contrib/gcc/config/mips/t-isa3264 b/contrib/gcc/config/mips/t-isa3264
new file mode 100644
index 0000000..6604fbe
--- /dev/null
+++ b/contrib/gcc/config/mips/t-isa3264
@@ -0,0 +1,40 @@
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
+
+LIB1ASMSRC = mips/mips16.S
+LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
+ _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \
+ _m16fltsisf _m16fix_truncsfsi \
+ _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \
+ _m16extsfdf2 _m16trdfsf2 \
+ _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
+ _m16fltsidf _m16fix_truncdfsi \
+ _m16retsf _m16retdf \
+ _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
+ _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
+ _m16stubsf9 _m16stubsf10 \
+ _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
+ _m16stubdf9 _m16stubdf10
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = msoft-float EL/EB mips32/mips32r2/mips64
+MULTILIB_DIRNAMES = soft-float el eb mips32 mips32r2 mips64
+MULTILIB_MATCHES = EL=mel EB=meb
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/mips/t-linux64 b/contrib/gcc/config/mips/t-linux64
new file mode 100644
index 0000000..0592e7f
--- /dev/null
+++ b/contrib/gcc/config/mips/t-linux64
@@ -0,0 +1,17 @@
+MULTILIB_OPTIONS = mabi=n32/mabi=32/mabi=64
+MULTILIB_DIRNAMES = n32 32 64
+MULTILIB_OSDIRNAMES = ../lib32 ../lib ../lib64
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
+
+TPBIT = tp-bit.c
+
+tp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __MIPSEL__' > tp-bit.c
+ echo '# define FLOAT_BIT_ORDER_MISMATCH' >> tp-bit.c
+ echo '#endif' >> tp-bit.c
+ echo '#if __LDBL_MANT_DIG__ == 113' >> tp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> tp-bit.c
+ echo '# define TFLOAT' >> tp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> tp-bit.c
+ echo '#endif' >> tp-bit.c
diff --git a/contrib/gcc/config/mips/t-mips b/contrib/gcc/config/mips/t-mips
new file mode 100644
index 0000000..c431dcc
--- /dev/null
+++ b/contrib/gcc/config/mips/t-mips
@@ -0,0 +1,23 @@
+# fp-bit and dp-bit are really part of libgcc1, but this will cause
+# them to be built correctly, so... [taken from t-sparclite]
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __MIPSEL__' > dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#ifdef __MIPSEL__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+ echo '#define QUIET_NAN_NEGATED' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+LIB2_SIDITI_CONV_FUNCS=yes
diff --git a/contrib/gcc/config/mips/t-r3900 b/contrib/gcc/config/mips/t-r3900
new file mode 100644
index 0000000..3bc8c47
--- /dev/null
+++ b/contrib/gcc/config/mips/t-r3900
@@ -0,0 +1,31 @@
+LIB1ASMSRC = mips/mips16.S
+LIB1ASMFUNCS = _m16addsf3 _m16subsf3 _m16mulsf3 _m16divsf3 \
+ _m16eqsf2 _m16nesf2 _m16gtsf2 _m16gesf2 _m16lesf2 _m16ltsf2 \
+ _m16fltsisf _m16fix_truncsfsi \
+ _m16adddf3 _m16subdf3 _m16muldf3 _m16divdf3 \
+ _m16extsfdf2 _m16trdfsf2 \
+ _m16eqdf2 _m16nedf2 _m16gtdf2 _m16gedf2 _m16ledf2 _m16ltdf2 \
+ _m16fltsidf _m16fix_truncdfsi \
+ _m16retsf _m16retdf \
+ _m16stub1 _m16stub2 _m16stub5 _m16stub6 _m16stub9 _m16stub10 \
+ _m16stubsf0 _m16stubsf1 _m16stubsf2 _m16stubsf5 _m16stubsf6 \
+ _m16stubsf9 _m16stubsf10 \
+ _m16stubdf0 _m16stubdf1 _m16stubdf2 _m16stubdf5 _m16stubdf6 \
+ _m16stubdf9 _m16stubdf10
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = msoft-float EL/EB
+MULTILIB_DIRNAMES = soft-float el eb
+MULTILIB_MATCHES = EL=mel EB=meb
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/mips/t-rtems b/contrib/gcc/config/mips/t-rtems
new file mode 100644
index 0000000..b012100
--- /dev/null
+++ b/contrib/gcc/config/mips/t-rtems
@@ -0,0 +1,16 @@
+# Custom multilibs for RTEMS
+
+# default is mips1 EB hard-float
+MULTILIB_OPTIONS = mips1/mips3/mips32 EB/EL msoft-float
+MULTILIB_DIRNAMES = mips1 mips3 mips32 eb el soft-float
+MULTILIB_MATCHES = EL=mel EB=meb
+
+MULTILIB_EXCEPTIONS =
+
+# Big endian only
+MULTILIB_EXCEPTIONS += EL*
+MULTILIB_EXCEPTIONS += mips32/EL*
+
+# Little endian only
+MULTILIB_EXCEPTIONS += mips3
+MULTILIB_EXCEPTIONS += mips3/msoft-float
diff --git a/contrib/gcc/config/mips/t-sb1 b/contrib/gcc/config/mips/t-sb1
new file mode 100644
index 0000000..b181bb7
--- /dev/null
+++ b/contrib/gcc/config/mips/t-sb1
@@ -0,0 +1,44 @@
+# GP-rel: G0 only
+#
+# Endianness: EB or EL
+#
+# ABIs: mabi=32
+# mabi=o64
+# mabi=o64/mlong64
+#
+# FPU: (default mhard-float)
+# msoft-float (only for mabi=32)
+#
+
+MULTILIB_EXTRA_OPTS = G0
+
+MULTILIB_OPTIONS = \
+ EB/EL \
+ mabi=32/mabi=o64 \
+ mips32/mips64 \
+ mlong64/msoft-float \
+
+MULTILIB_DIRNAMES = \
+ eb el \
+ o32 o64 \
+ mips32 mips64 \
+ long64 soft-float \
+
+MULTILIB_MATCHES = \
+ EB=meb EL=mel \
+
+MULTILIB_EXCEPTIONS = \
+ *mabi=32/*mlong64* \
+
+MULTILIB_EXCLUSIONS = \
+ mips32/!mabi=32 \
+ mabi=32/!mips32 \
+ msoft-float/!mabi=32 \
+
+# Small multilib list for quick builds and tests.
+# Must either comment out everything above these lines, or everything below
+# these lines.
+
+#MULTILIB_OPTIONS = EB/EL msoft-float
+#MULTILIB_DIRNAMES = eb el soft-float
+#MULTILIB_MATCHES = EB=meb EL=mel
diff --git a/contrib/gcc/config/mips/t-slibgcc-irix b/contrib/gcc/config/mips/t-slibgcc-irix
new file mode 100644
index 0000000..cfb4bf4
--- /dev/null
+++ b/contrib/gcc/config/mips/t-slibgcc-irix
@@ -0,0 +1,34 @@
+# Build a shared libgcc library.
+
+SHLIB_EXT = .so
+SHLIB_SOLINK = @shlib_base_name@.so
+SHLIB_SOVERSION = 1
+SHLIB_SONAME = @shlib_base_name@.so.$(SHLIB_SOVERSION)
+SHLIB_MAP = @shlib_map_file@
+SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@
+SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+SHLIB_LC = -lc
+
+SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
+ -Wl,-soname,$(SHLIB_SONAME) \
+ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
+ $(SHLIB_OBJS) $(SHLIB_LC) && \
+ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
+ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
+ else true; fi && \
+ mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
+ $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
+# $(slibdir) double quoted to protect it from expansion while building
+# libgcc.mk. We want this delayed until actual install time.
+SHLIB_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
+ rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
+ $(LN_S) $(SHLIB_SONAME) \
+ $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver
diff --git a/contrib/gcc/config/mips/t-sr71k b/contrib/gcc/config/mips/t-sr71k
new file mode 100644
index 0000000..2b2c27a
--- /dev/null
+++ b/contrib/gcc/config/mips/t-sr71k
@@ -0,0 +1,51 @@
+# Suppress building libgcc1.a, since the MIPS compiler port is complete
+# and does not need anything from libgcc1.a.
+LIBGCC1 =
+CROSS_LIBGCC1 =
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+# fp-bit and dp-bit are really part of libgcc1, but this will cause
+# them to be built correctly, so... [taken from t-sparclite]
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#ifdef __MIPSEL__' > dp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> dp-bit.c
+ echo '#endif' >> dp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> dp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ echo '#ifdef __MIPSEL__' >> fp-bit.c
+ echo '#define FLOAT_BIT_ORDER_MISMATCH' >> fp-bit.c
+ echo '#endif' >> fp-bit.c
+ echo '#define US_SOFTWARE_GOFAST' >> fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+# Build the libraries for both hard and soft floating point
+
+MULTILIB_OPTIONS = EL/EB msoft-float mips2
+MULTILIB_DIRNAMES = el eb soft-float mips2
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
diff --git a/contrib/gcc/config/mips/t-vr b/contrib/gcc/config/mips/t-vr
new file mode 100644
index 0000000..9c046b0
--- /dev/null
+++ b/contrib/gcc/config/mips/t-vr
@@ -0,0 +1,112 @@
+# BEGIN boiler-plate MIPS stuff
+
+# Don't let CTOR_LIST end up in sdata section.
+CRTSTUFF_T_CFLAGS = -G 0
+
+# We must build libgcc2.a with -G 0, in case the user wants to link
+# without the $gp register.
+TARGET_LIBGCC2_CFLAGS = -G 0
+
+LIB2FUNCS_STATIC_EXTRA = $(srcdir)/config/mips/mips16.S \
+ $(srcdir)/config/mips/vr4120-div.S
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
+
+# Assemble startup files.
+$(T)crti.o: $(srcdir)/config/mips/crti.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/mips/crti.asm
+
+$(T)crtn.o: $(srcdir)/config/mips/crtn.asm $(GCC_PASSES)
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
+ -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/mips/crtn.asm
+
+# END boiler-plate
+
+# Main multilibs
+# --------------
+#
+# Endianness: EB or EL
+#
+# ABIs: mabi=32
+# mabi=o64
+# mabi=eabi
+# mabi=eabi/mlong32
+# mabi=eabi/mgp32
+# mabi=eabi/mgp32/mlong64
+#
+# Architecture: march=vr4120 with -mfix-vr4120
+# march=vr4130 with -mfix-vr4130 (default)
+# march=vr5000
+# march=vr5400
+# march=vr5500
+#
+# Total: 2 * 6 * 5 = 60 multilibs.
+#
+#
+# Extra vr4300 multilibs
+# ----------------------
+#
+# Endianness: EB or EL
+#
+# ABI: o64
+#
+# Architecture: vr4300.
+#
+# Total: 2 * 1 * 2 = 2 multilibs.
+#
+#
+# Extra MIPS16 multilibs
+# ----------------------
+#
+# Endianness: EB or EL
+#
+# ABIs: mabi=o64
+# mabi=eabi/mlong32
+# mabi=eabi/mgp32
+#
+# Architecture: march=vr4120 with -mfix-vr4120
+# march=vr4130 with -mfix-vr4130 (default)
+#
+# Total: 2 * 3 * 2 = 12 multilibs.
+MULTILIB_OPTIONS = \
+ EL/EB \
+ mabi=32/mabi=o64/mabi=eabi \
+ mgp32 \
+ mlong64 \
+ mips16 \
+ mfix-vr4120/mfix-vr4130/march=vr4300/march=vr5000/march=vr5400/march=vr5500
+
+MULTILIB_DIRNAMES = \
+ el eb \
+ o32 o64 eabi \
+ gp32 \
+ long64 \
+ mips16 \
+ vr4120 vr4130 vr4300 vr5000 vr5400 vr5500
+
+MULTILIB_MATCHES = EL=mel EB=meb mfix-vr4120=march?vr4120 \
+ mfix-vr4130=march?vr4130
+
+# Assume a 41xx-series is the default: we'd need a *mips16 entry if
+# the default processor didn't support mips16. Also assume the
+# default ABI is EABI64 -mlong32.
+MULTILIB_EXCEPTIONS = \
+ *mabi=32/mlong64* \
+ *mabi=32/mgp32* \
+ *mabi=o64/mgp32* \
+ *mabi=o64/mlong64* \
+ *mips16/march=vr5* \
+ *mips16/march=vr4300 \
+ $(MIPS16_EXCEPTIONS) \
+ $(VR4300_EXCEPTIONS)
+
+MIPS16_EXCEPTIONS = \
+ *mabi=32*mips16* \
+ *mlong64*mips16*
+
+VR4300_EXCEPTIONS = \
+ *mabi=32*march=vr4300 \
+ *mgp32*march=vr4300 \
+ *mlong64*march=vr4300 \
+ march=vr4300 \
+ E[LB]/march=vr4300
diff --git a/contrib/gcc/config/mips/t-vxworks b/contrib/gcc/config/mips/t-vxworks
new file mode 100644
index 0000000..51e006a
--- /dev/null
+++ b/contrib/gcc/config/mips/t-vxworks
@@ -0,0 +1,16 @@
+# Multilibs for VxWorks.
+
+# default is mips1 EB hard-float
+MULTILIB_OPTIONS = mips2/mips3 EL msoft-float
+MULTILIB_MATCHES = EL=mel mips2=mips32 mips3=mips4 mips3=mips64
+
+MULTILIB_EXCEPTIONS = EL EL/msoft-float mips3/msoft-float mips3/EL/msoft-float
+
+MUTLILIB_EXTRA_OPTS = -G 0 -mno-branch-likely
+
+MULTILIB_OSDIRNAMES = msoft-float=!MIPS32sfr3kgnu \
+ mips2=!MIPS32gnu mips2/msoft-float=!MIPS32sfgnu \
+ mips2/EL=!MIPS32gnule \
+ mips2/EL/msoft-float=!MIPS32sfgnule \
+ mips3=!MIPS64gnu mips3/EL=!MIPS64gnule
+
diff --git a/contrib/gcc/config/mips/vr.h b/contrib/gcc/config/mips/vr.h
new file mode 100644
index 0000000..a723a48
--- /dev/null
+++ b/contrib/gcc/config/mips/vr.h
@@ -0,0 +1,53 @@
+/* Definitions of target machine for GNU compiler.
+ NEC VR Series Processors
+ Copyright (c) 2002, 2004, 2005 Free Software Foundation, Inc.
+ Contributed by Red Hat, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#define DEFAULT_VR_ARCH "mfix-vr4130"
+#define MIPS_ABI_DEFAULT ABI_EABI
+#define MIPS_MARCH_CONTROLS_SOFT_FLOAT 1
+#define MULTILIB_DEFAULTS \
+ { MULTILIB_ENDIAN_DEFAULT, \
+ MULTILIB_ABI_DEFAULT, \
+ DEFAULT_VR_ARCH }
+
+#define DRIVER_SELF_SPECS \
+ /* Enforce the default architecture. This is mostly for \
+ the assembler's benefit. */ \
+ "%{!march=*:%{!mfix-vr4120:%{!mfix-vr4130:" \
+ "-" DEFAULT_VR_ARCH "}}}", \
+ \
+ /* Make -mfix-vr4120 imply -march=vr4120. This cuts down \
+ on command-line tautology and makes it easier for t-vr to \
+ provide a -mfix-vr4120 multilib. */ \
+ "%{mfix-vr4120:%{!march=*:-march=vr4120}}", \
+ \
+ /* Same idea for -mfix-vr4130. */ \
+ "%{mfix-vr4130:%{!march=*:-march=vr4130}}", \
+ \
+ /* Make -mabi=eabi -mlong32 the default. */ \
+ "%{!mabi=*:-mabi=eabi %{!mlong*:-mlong32}}", \
+ \
+ /* Make sure -mlong64 multilibs are chosen when 64-bit longs \
+ are needed. */ \
+ "%{mabi=eabi:%{!mlong*:%{!mgp32:-mlong64}}}", \
+ \
+ /* Remove -mgp32 if it is redundant. */ \
+ "%{mabi=32:%<mgp32}"
diff --git a/contrib/gcc/config/mips/vr4120-div.S b/contrib/gcc/config/mips/vr4120-div.S
new file mode 100644
index 0000000..1cef997
--- /dev/null
+++ b/contrib/gcc/config/mips/vr4120-div.S
@@ -0,0 +1,75 @@
+/* Support file for -mfix-vr4120.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* This file contains functions which implement divsi3 and modsi3 for
+ -mfix-vr4120. div and ddiv do not give the correct result when one
+ of the operands is negative. */
+
+ .set nomips16
+
+#define DIV \
+ xor $3,$4,$5 /* t = x ^ y */ ; \
+ li $2,0x80000000; \
+ .set noreorder; \
+ bgez $4,1f /* x >= 0 */; \
+ and $3,$3,$2 /* t = (x ^ y) & 0x80000000 in delay slot */ ;\
+ .set reorder; \
+ subu $4,$0,$4 /* x = -x */ ; \
+1:; \
+ .set noreorder; \
+ bgez $5,2f /* y >= 0 */ ; \
+ nop; \
+ subu $5,$0,$5 /* y = -y */ ; \
+ .set reorder; \
+2:; \
+ divu $0,$4,$5; /* we use divu because of INT_MIN */ \
+ .set noreorder; \
+ bne $5,$0,3f; \
+ nop; \
+ break 7 /* division on zero y */ ; \
+3:; \
+ .set reorder; \
+ mflo $2 /* r = x / y */ ; \
+ .set noreorder; \
+ beq $3,$0,4f /* t == 0 */ ; \
+ nop; \
+ subu $2,$0,$2 /* r = -r */ ; \
+ .set reorder; \
+4:
+
+ .globl __vr4120_divsi3
+ .ent __vr4120_divsi3
+__vr4120_divsi3:
+ DIV
+ j $31
+ .end __vr4120_divsi3
+
+ .globl __vr4120_modsi3
+ .ent __vr4120_modsi3
+__vr4120_modsi3:
+ move $6,$4 # x1 = x
+ move $7,$5 # y1 = y
+ DIV
+ mult $2,$7 # r = r * y1
+ mflo $2
+ .set noreorder
+ j $31
+ subu $2,$6,$2 # r = x1 - r in delay slot
+ .end __vr4120_modsi3
diff --git a/contrib/gcc/config/mips/vxworks.h b/contrib/gcc/config/mips/vxworks.h
new file mode 100644
index 0000000..bf37901
--- /dev/null
+++ b/contrib/gcc/config/mips/vxworks.h
@@ -0,0 +1,68 @@
+/* Copyright (C) 1999, 2003, 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (MIPS, VxWorks syntax)");
+
+/* Combination of mips.h and svr4.h. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) \
+ || (CHAR) == 'G' \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'x' \
+ || (CHAR) == 'z')
+
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{!G:-G 0} %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
+%{mips32} %{mips32r2} %{mips64} \
+%{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
+%(subtarget_asm_optimizing_spec) \
+%(subtarget_asm_debugging_spec) \
+%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
+%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
+%{mtune=*} %{v} \
+%(subtarget_asm_spec)"
+
+#undef LINK_SPEC
+/* LINK_SPEC is clobbered in svr4.h. ugh! */
+#define LINK_SPEC "\
+%(endian_spec) \
+%{!G:-G 0} %{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips64} \
+%{bestGnum}"
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__vxworks"); \
+ builtin_assert ("system=unix"); \
+ } \
+ while (0)
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC \
+"%{!DCPU=*: %{mips3|mips4|mips64:-DCPU=MIPS64;:-DCPU=MIPS32}} \
+ %{EL|mel:-DMIPSEL;:-DMIPSEB} \
+ %{msoft-float:-DSOFT_FLOAT} \
+ %{mips1:-D_WRS_R3K_EXC_SUPPORT}"
+
+/* No sdata. */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
diff --git a/contrib/gcc/config/mips/windiss.h b/contrib/gcc/config/mips/windiss.h
new file mode 100644
index 0000000..bd69621
--- /dev/null
+++ b/contrib/gcc/config/mips/windiss.h
@@ -0,0 +1,101 @@
+/* Support for GCC on MIPS using WindISS simulator.
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (MIPS WindISS)");
+
+/* Combination of mips.h and svr4.h. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG (CHAR) \
+ || (CHAR) == 'G' \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'x' \
+ || (CHAR) == 'z')
+
+#undef SUBTARGET_CPP_SPEC
+#define SUBTARGET_CPP_SPEC \
+"%{!DCPU=*: %{mips3|mips4|mips64:-DCPU=MIPS64;:-DCPU=MIPS32}} \
+ %{EL|mel:-DMIPSEL;:-DMIPSEB} \
+ %{msoft-float:-DSOFT_FLOAT} \
+ %{mips1:-D_WRS_R3K_EXC_SUPPORT}"
+
+#undef ASM_SPEC
+#define ASM_SPEC "\
+%{!G:-G 0} %{G*} %(endian_spec) %{mips1} %{mips2} %{mips3} %{mips4} \
+%{mips32} %{mips32r2} %{mips64} \
+%{mips16:%{!mno-mips16:-mips16}} %{mno-mips16:-no-mips16} \
+%(subtarget_asm_optimizing_spec) \
+%(subtarget_asm_debugging_spec) \
+%{mabi=*} %{!mabi*: %(asm_abi_default_spec)} \
+%{mgp32} %{mgp64} %{march=*} %{mxgot:-xgot} \
+%{mtune=*} %{v} \
+%(subtarget_asm_spec)"
+
+#undef LINK_SPEC
+/* LINK_SPEC is clobbered in svr4.h. ugh! */
+#define LINK_SPEC "\
+-m elf32mipswindiss \
+%{!G:-G 0} %{G*} %{mips1} %{mips2} %{mips3} %{mips4} %{mips32} %{mips64} \
+%{bestGnum}"
+
+/* Diab libs MIPS{,E,F,L,M,W,X,Y,Z}{,H,N,S}
+
+ .
+ E - Elf (small-data/const=8
+ F - Elf Far (small-data/const=0)
+ L - Little Elf
+ M - Little Elf Far
+ W - elf32 bigmips
+ X - elf32 bigmips (far?)
+ Y - elf32 littlemips
+ Z - elf32 littlemips (far?)
+
+ . - Integer routines
+ H - Hard float
+ N - No float
+ S - Soft float
+
+ Want {F,M}{,H,S}
+
+*/
+
+#undef LIB_SPEC
+#define LIB_SPEC "--start-group -li -lcfp -lwindiss -lram -limpl -limpfp --end-group"
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s crtbegin.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtend.o%s"
+
+/* We have no shared libraries. These two shouldn't be necessary. */
+#undef LINK_SHLIB_SPEC
+#define LINK_SHLIB_SPEC ""
+#undef LINK_EH_SPEC
+#define LINK_EH_SPEC ""
+
+#undef CRTSAVRES_DEFAULT_SPEC
+#define CRTSAVRES_DEFAULT_SPEC ""
+
+/* No sdata. */
+#undef MIPS_DEFAULT_GVALUE
+#define MIPS_DEFAULT_GVALUE 0
diff --git a/contrib/gcc/config/netbsd-aout.h b/contrib/gcc/config/netbsd-aout.h
index 53e6570..fe5b3ec 100644
--- a/contrib/gcc/config/netbsd-aout.h
+++ b/contrib/gcc/config/netbsd-aout.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* TARGET_OS_CPP_BUILTINS() common to all NetBSD a.out targets. */
#define NETBSD_OS_CPP_BUILTINS_AOUT() \
diff --git a/contrib/gcc/config/netbsd-elf.h b/contrib/gcc/config/netbsd-elf.h
index a87699c..9a56de2 100644
--- a/contrib/gcc/config/netbsd-elf.h
+++ b/contrib/gcc/config/netbsd-elf.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* TARGET_OS_CPP_BUILTINS() common to all NetBSD ELF targets. */
#define NETBSD_OS_CPP_BUILTINS_ELF() \
diff --git a/contrib/gcc/config/netbsd.h b/contrib/gcc/config/netbsd.h
index 121dda2..5386b65 100644
--- a/contrib/gcc/config/netbsd.h
+++ b/contrib/gcc/config/netbsd.h
@@ -1,5 +1,5 @@
/* Base configuration file for all NetBSD targets.
- Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+ Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,14 +16,16 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* TARGET_OS_CPP_BUILTINS() common to all NetBSD targets. */
#define NETBSD_OS_CPP_BUILTINS_COMMON() \
do \
{ \
builtin_define ("__NetBSD__"); \
+ builtin_define ("__unix__"); \
+ builtin_assert ("system=bsd"); \
builtin_assert ("system=unix"); \
builtin_assert ("system=NetBSD"); \
} \
@@ -154,18 +156,16 @@ Boston, MA 02111-1307, USA. */
fprintf ((STREAM), "void __fini() {\n\t%s();\n}\n", (FUNC)); \
} while (0)
-#undef TARGET_HAS_F_SETLKW
-#define TARGET_HAS_F_SETLKW
-
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-
-#undef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS 1
+#undef TARGET_POSIX_IO
+#define TARGET_POSIX_IO
/* Handle #pragma weak and #pragma pack. */
#define HANDLE_SYSV_PRAGMA 1
+/* Don't assume anything about the header files. */
+#undef NO_IMPLICIT_EXTERN_C
+#define NO_IMPLICIT_EXTERN_C 1
/* Define some types that are the same on all NetBSD platforms,
making them agree with <machine/ansi.h>. */
diff --git a/contrib/gcc/config/openbsd-oldgas.h b/contrib/gcc/config/openbsd-oldgas.h
index 423a15c..5ca617b 100644
--- a/contrib/gcc/config/openbsd-oldgas.h
+++ b/contrib/gcc/config/openbsd-oldgas.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define OBSD_OLD_GAS
diff --git a/contrib/gcc/config/openbsd.h b/contrib/gcc/config/openbsd.h
index 670a0a0..68eb948 100644
--- a/contrib/gcc/config/openbsd.h
+++ b/contrib/gcc/config/openbsd.h
@@ -1,5 +1,5 @@
/* Base configuration file for all OpenBSD targets.
- Copyright (C) 1999, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Common OpenBSD configuration.
All OpenBSD architectures include this file, which is intended as
@@ -52,29 +52,41 @@ Boston, MA 02111-1307, USA. */
#ifdef OPENBSD_NATIVE
-#undef GCC_INCLUDE_DIR
-#define GCC_INCLUDE_DIR "/usr/include"
-
/* The compiler is configured with ONLY the gcc/g++ standard headers. */
#undef INCLUDE_DEFAULTS
#define INCLUDE_DEFAULTS \
{ \
{ GPLUSPLUS_INCLUDE_DIR, "G++", 1, 1 }, \
- { GCC_INCLUDE_DIR, "GCC", 0, 0 }, \
+ { GPLUSPLUS_TOOL_INCLUDE_DIR, "G++", 1, 1 }, \
+ { GPLUSPLUS_BACKWARD_INCLUDE_DIR, "G++", 1, 1 }, \
+ { STANDARD_INCLUDE_DIR, STANDARD_INCLUDE_COMPONENT, 0, 0 }, \
{ 0, 0, 0, 0 } \
}
/* Under OpenBSD, the normal location of the various *crt*.o files is the
/usr/lib directory. */
-#define STANDARD_STARTFILE_PREFIX "/usr/lib/"
+#undef STANDARD_STARTFILE_PREFIX
+#define STANDARD_STARTFILE_PREFIX "/usr/local/lib/"
#endif
/* Controlling the compilation driver. */
+/* TARGET_OS_CPP_BUILTINS() common to all OpenBSD targets. */
+#define OPENBSD_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__OpenBSD__"); \
+ builtin_define ("__unix__"); \
+ builtin_define ("__ANSI_COMPAT"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=bsd"); \
+ builtin_assert ("system=OpenBSD"); \
+ } \
+ while (0)
/* CPP_SPEC appropriate for OpenBSD. We deal with -posix and -pthread.
- XXX the way threads are handling currently is not very satisfying,
+ XXX the way threads are handled currently is not very satisfying,
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. */
@@ -84,10 +96,15 @@ Boston, MA 02111-1307, USA. */
#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 "%{!shared:-lc%{pthread:_r}%{p:_p}%{!p:%{pg:_p}}}"
+/* LIB_SPEC appropriate for OpenBSD. */
+#ifdef HAS_LIBC_R
+/* -lc(_r)?(_p)?, select _r for threads, and _p for p or pg. */
+# define OBSD_LIB_SPEC "%{!shared:-lc%{pthread:_r}%{p:_p}%{!p:%{pg:_p}}}"
+#else
+/* Include -lpthread if -pthread is specified on the command line. */
+# define OBSD_LIB_SPEC "%{!shared:%{pthread:-lpthread%{p:_p}%{!p:%{pg:_p}}}} %{!shared:-lc%{p:_p}%{!p:%{pg:_p}}}"
+#endif
+
#ifndef OBSD_HAS_CORRECT_SPECS
@@ -130,13 +147,6 @@ Boston, MA 02111-1307, USA. */
/* Runtime target specification. */
-/* Implicit calls to library routines. */
-
-/* Use memcpy and memset instead of bcopy and bzero. */
-#ifndef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-#endif
-
/* Miscellaneous parameters. */
/* Controlling debugging info: dbx options. */
@@ -282,3 +292,20 @@ do { \
as this depends on a few other details as well... */
#define HANDLE_SYSV_PRAGMA 1
+/* Stack is explicitly denied execution rights on OpenBSD platforms. */
+#define ENABLE_EXECUTE_STACK \
+extern void __enable_execute_stack (void *); \
+void \
+__enable_execute_stack (void *addr) \
+{ \
+ long size = getpagesize (); \
+ long mask = ~(size-1); \
+ char *page = (char *) (((long) addr) & mask); \
+ char *end = (char *) ((((long) (addr + TRAMPOLINE_SIZE)) & mask) + size); \
+ \
+ if (mprotect (page, end - page, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) \
+ perror ("mprotect of trampoline code"); \
+}
+
+#include <sys/types.h>
+#include <sys/mman.h>
diff --git a/contrib/gcc/config/ptx4.h b/contrib/gcc/config/ptx4.h
index 33e91d1..8c23102 100644
--- a/contrib/gcc/config/ptx4.h
+++ b/contrib/gcc/config/ptx4.h
@@ -1,6 +1,7 @@
/* Operating system specific defines to be used when targeting GCC for
Sequent's Dynix/ptx v4 and later.
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004
+ Free Software Foundation, Inc.
Generic SysV4 file Contributed by Ron Guilmette (rfg@monkeys.com).
Renamed and changed to suit Dynix/ptx v4 and later.
Modified by Tim Wright (timw@sequent.com).
@@ -20,8 +21,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
*/
@@ -136,7 +137,7 @@ Boston, MA 02111-1307, USA.
#undef LINK_SPEC
#define LINK_SPEC "%{h*} %{v:-V} \
- %{b} %{Wl,*:%*} \
+ %{b} \
%{static:-dn -Bstatic} \
%{shared:-G -dy -z text} \
%{symbolic:-Bsymbolic -G -dy -z text} \
@@ -184,26 +185,13 @@ Boston, MA 02111-1307, USA.
/* Like block addresses, stabs line numbers are relative to the
current function. */
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(file, line, counter) \
-do \
- { \
- fprintf (file, ".stabn 68,0,%d,.LM%d-", \
- line, counter); \
- assemble_name (file, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
- fprintf (file, "\n.LM%d:\n", counter); \
- } \
-while (0)
+#define DBX_LINES_FUNCTION_RELATIVE 1
/* Generate a blank trailing N_SO to mark the end of the .o file, since
we can't depend upon the linker to mark .o file boundaries with
embedded stabs. */
-#undef DBX_OUTPUT_MAIN_SOURCE_FILE_END
-#define DBX_OUTPUT_MAIN_SOURCE_FILE_END(FILE, FILENAME) \
- fprintf (FILE, \
- "\t.text\n\t.stabs \"\",%d,0,0,.Letext\n.Letext:\n", N_SO)
+#define DBX_OUTPUT_NULL_N_SO_AT_MAIN_SOURCE_FILE_END
/* Define the actual types of some ANSI-mandated types. (These
definitions should work for most SVR4 systems). */
diff --git a/contrib/gcc/config/rs6000/40x.md b/contrib/gcc/config/rs6000/40x.md
index 9d229b4..94b6c45 100644
--- a/contrib/gcc/config/rs6000/40x.md
+++ b/contrib/gcc/config/rs6000/40x.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM PowerPC 403 and PowerPC 405 processors.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,22 +15,24 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
-(define_automaton "ppc40x")
-(define_cpu_unit "iu_40x,bpu_40x,fpu_405" "ppc40x")
+(define_automaton "ppc40x,ppc40xiu")
+(define_cpu_unit "bpu_40x,fpu_405" "ppc40x")
+(define_cpu_unit "iu_40x" "ppc40xiu")
;; PPC401 / PPC403 / PPC405 32-bit integer only IU BPU
;; Embedded PowerPC controller
;; In-order execution
;; Max issue two insns/cycle (includes one branch)
(define_insn_reservation "ppc403-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,store_c,sync")
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
-(define_insn_reservation "ppc403-store" 1
+(define_insn_reservation "ppc403-store" 2
(and (eq_attr "type" "store,store_ux,store_u")
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
@@ -40,6 +42,16 @@
(eq_attr "cpu" "ppc403,ppc405"))
"iu_40x")
+(define_insn_reservation "ppc403-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc403,ppc405"))
+ "iu_40x,iu_40x")
+
+(define_insn_reservation "ppc403-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc403,ppc405"))
+ "iu_40x,iu_40x,iu_40x")
+
(define_insn_reservation "ppc403-compare" 3
(and (eq_attr "type" "cmp,fast_compare,compare,delayed_compare")
(eq_attr "cpu" "ppc403,ppc405"))
@@ -91,7 +103,7 @@
"iu_40x")
(define_insn_reservation "ppc403-jmpreg" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "ppc403,ppc405"))
"bpu_40x")
@@ -101,7 +113,7 @@
"bpu_40x")
(define_insn_reservation "ppc405-float" 11
- (and (eq_attr "type" "fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,fpcompare,fp,dmul,sdiv,ddiv")
+ (and (eq_attr "type" "fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,\
+ fpcompare,fp,dmul,sdiv,ddiv")
(eq_attr "cpu" "ppc405"))
"fpu_405*10")
-
diff --git a/contrib/gcc/config/rs6000/440.md b/contrib/gcc/config/rs6000/440.md
index e98d5be..60e0f72 100644
--- a/contrib/gcc/config/rs6000/440.md
+++ b/contrib/gcc/config/rs6000/440.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM PowerPC 440 processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; PPC440 Embedded PowerPC controller
;; dual issue
@@ -34,11 +34,12 @@
(define_insn_reservation "ppc440-load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,store_c,sync")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
-(define_insn_reservation "ppc440-store" 1
+(define_insn_reservation "ppc440-store" 3
(and (eq_attr "type" "store,store_ux,store_u")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_l_pipe")
@@ -58,6 +59,18 @@
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe|ppc440_j_pipe")
+(define_insn_reservation "ppc440-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc440"))
+ "ppc440_issue_0+ppc440_issue_1,\
+ ppc440_i_pipe|ppc440_j_pipe,ppc440_i_pipe|ppc440_j_pipe")
+
+(define_insn_reservation "ppc440-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc440"))
+ "ppc440_issue_0+ppc440_issue_1,ppc440_i_pipe|ppc440_j_pipe,\
+ ppc440_i_pipe|ppc440_j_pipe,ppc440_i_pipe|ppc440_j_pipe")
+
(define_insn_reservation "ppc440-imul" 3
(and (eq_attr "type" "imul,imul_compare")
(eq_attr "cpu" "ppc440"))
@@ -74,7 +87,7 @@
"ppc440_issue,ppc440_i_pipe*33")
(define_insn_reservation "ppc440-branch" 1
- (and (eq_attr "type" "branch,jmpreg")
+ (and (eq_attr "type" "branch,jmpreg,isync")
(eq_attr "cpu" "ppc440"))
"ppc440_issue,ppc440_i_pipe")
diff --git a/contrib/gcc/config/rs6000/603.md b/contrib/gcc/config/rs6000/603.md
index 7ae038e..4721aca 100644
--- a/contrib/gcc/config/rs6000/603.md
+++ b/contrib/gcc/config/rs6000/603.md
@@ -1,5 +1,5 @@
;; Scheduling description for PowerPC 603 processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,8 +15,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "ppc603,ppc603fp")
(define_cpu_unit "iu_603" "ppc603")
@@ -39,25 +39,40 @@
;; CR insns get executed in the SRU. Not modelled.
(define_insn_reservation "ppc603-load" 2
- (and (eq_attr "type" "load,load_ext,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ux,load_u,load_l")
(eq_attr "cpu" "ppc603"))
"lsu_603")
-(define_insn_reservation "ppc603-store" 1
+(define_insn_reservation "ppc603-store" 2
(and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
(eq_attr "cpu" "ppc603"))
- "lsu_603")
+ "lsu_603*2")
(define_insn_reservation "ppc603-fpload" 2
(and (eq_attr "type" "fpload,fpload_ux,fpload_u")
(eq_attr "cpu" "ppc603"))
"lsu_603")
+(define_insn_reservation "ppc603-storec" 8
+ (and (eq_attr "type" "store_c")
+ (eq_attr "cpu" "ppc603"))
+ "lsu_603")
+
(define_insn_reservation "ppc603-integer" 1
(and (eq_attr "type" "integer,insert_word")
(eq_attr "cpu" "ppc603"))
"iu_603")
+(define_insn_reservation "ppc603-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc603"))
+ "iu_603,iu_603")
+
+(define_insn_reservation "ppc603-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc603"))
+ "iu_603,iu_603,iu_603")
+
; This takes 2 or 3 cycles
(define_insn_reservation "ppc603-imul" 3
(and (eq_attr "type" "imul,imul_compare")
@@ -116,7 +131,7 @@
"sru_603")
(define_insn_reservation "ppc603-mfjmpr" 2
- (and (eq_attr "type" "mfjmpr")
+ (and (eq_attr "type" "mfjmpr,isync,sync")
(eq_attr "cpu" "ppc603"))
"sru_603")
diff --git a/contrib/gcc/config/rs6000/6xx.md b/contrib/gcc/config/rs6000/6xx.md
index d28d373..31aa606 100644
--- a/contrib/gcc/config/rs6000/6xx.md
+++ b/contrib/gcc/config/rs6000/6xx.md
@@ -1,6 +1,6 @@
;; Scheduling description for PowerPC 604, PowerPC 604e, PowerPC 620,
;; and PowerPC 630 processors.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -16,8 +16,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "ppc6xx,ppc6xxfp,ppc6xxfp2")
(define_cpu_unit "iu1_6xx,iu2_6xx,mciu_6xx" "ppc6xx")
@@ -58,16 +58,36 @@
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"lsu_6xx")
-(define_insn_reservation "ppc604-store" 1
+(define_insn_reservation "ppc604-store" 3
(and (eq_attr "type" "store,fpstore,store_ux,store_u,fpstore_ux,fpstore_u")
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"lsu_6xx")
+(define_insn_reservation "ppc604-llsc" 3
+ (and (eq_attr "type" "load_l,store_c")
+ (eq_attr "cpu" "ppc604,ppc604e"))
+ "lsu_6xx")
+
+(define_insn_reservation "ppc630-llsc" 4
+ (and (eq_attr "type" "load_l,store_c")
+ (eq_attr "cpu" "ppc620,ppc630"))
+ "lsu_6xx")
+
(define_insn_reservation "ppc604-integer" 1
(and (eq_attr "type" "integer,insert_word")
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"iu1_6xx|iu2_6xx")
+(define_insn_reservation "ppc604-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
+ "iu1_6xx|iu2_6xx,iu1_6xx|iu2_6xx")
+
+(define_insn_reservation "ppc604-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
+ "iu1_6xx|iu2_6xx,iu1_6xx|iu2_6xx,iu1_6xx|iu2_6xx")
+
(define_insn_reservation "ppc604-imul" 4
(and (eq_attr "type" "imul,imul2,imul3,imul_compare")
(eq_attr "cpu" "ppc604"))
@@ -232,3 +252,23 @@
(eq_attr "cpu" "ppc604,ppc604e,ppc620,ppc630"))
"bpu_6xx")
+(define_insn_reservation "ppc604-isync" 0
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "ppc604,ppc604e"))
+ "bpu_6xx")
+
+(define_insn_reservation "ppc630-isync" 6
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "ppc620,ppc630"))
+ "bpu_6xx")
+
+(define_insn_reservation "ppc604-sync" 35
+ (and (eq_attr "type" "sync")
+ (eq_attr "cpu" "ppc604,ppc604e"))
+ "lsu_6xx")
+
+(define_insn_reservation "ppc630-sync" 26
+ (and (eq_attr "type" "sync")
+ (eq_attr "cpu" "ppc620,ppc630"))
+ "lsu_6xx")
+
diff --git a/contrib/gcc/config/rs6000/7450.md b/contrib/gcc/config/rs6000/7450.md
index 55bd4d8..99e8712 100644
--- a/contrib/gcc/config/rs6000/7450.md
+++ b/contrib/gcc/config/rs6000/7450.md
@@ -1,5 +1,5 @@
;; Scheduling description for Motorola PowerPC 7450 processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,11 +15,12 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
-(define_automaton "ppc7450,ppc7450fp,ppc7450vec")
-(define_cpu_unit "iu1_7450,iu2_7450,iu3_7450,mciu_7450" "ppc7450")
+(define_automaton "ppc7450,ppc7450mciu,ppc7450fp,ppc7450vec")
+(define_cpu_unit "iu1_7450,iu2_7450,iu3_7450" "ppc7450")
+(define_cpu_unit "mciu_7450" "ppc7450mciu")
(define_cpu_unit "fpu_7450" "ppc7450fp")
(define_cpu_unit "lsu_7450,bpu_7450" "ppc7450")
(define_cpu_unit "du1_7450,du2_7450,du3_7450" "ppc7450")
@@ -63,10 +64,31 @@
(eq_attr "cpu" "ppc7450"))
"ppc7450_du,lsu_7450*3")
+(define_insn_reservation "ppc7450-llsc" 3
+ (and (eq_attr "type" "load_l,store_c")
+ (eq_attr "cpu" "ppc7450"))
+ "ppc7450_du,lsu_7450")
+
+(define_insn_reservation "ppc7450-sync" 35
+ (and (eq_attr "type" "sync")
+ (eq_attr "cpu" "ppc7450"))
+ "ppc7450_du,lsu_7450")
+
(define_insn_reservation "ppc7450-integer" 1
(and (eq_attr "type" "integer,insert_word")
(eq_attr "cpu" "ppc7450"))
- "ppc7450_du,(iu1_7450|iu2_7450|iu3_7450)")
+ "ppc7450_du,iu1_7450|iu2_7450|iu3_7450")
+
+(define_insn_reservation "ppc7450-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc7450"))
+ "ppc7450_du,iu1_7450|iu2_7450|iu3_7450,iu1_7450|iu2_7450|iu3_7450")
+
+(define_insn_reservation "ppc7450-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc7450"))
+ "ppc7450_du,iu1_7450|iu2_7450|iu3_7450,\
+ iu1_7450|iu2_7450|iu3_7450,iu1_7450|iu2_7450|iu3_7450")
(define_insn_reservation "ppc7450-imul" 4
(and (eq_attr "type" "imul,imul_compare")
@@ -130,7 +152,7 @@
"nothing,mciu_7450*2")
(define_insn_reservation "ppc7450-jmpreg" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "ppc7450"))
"nothing,bpu_7450")
diff --git a/contrib/gcc/config/rs6000/7xx.md b/contrib/gcc/config/rs6000/7xx.md
index de8a7b7..77e58a3 100644
--- a/contrib/gcc/config/rs6000/7xx.md
+++ b/contrib/gcc/config/rs6000/7xx.md
@@ -1,5 +1,5 @@
;; Scheduling description for Motorola PowerPC 750 and PowerPC 7400 processors.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,8 +15,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "ppc7xx,ppc7xxfp")
(define_cpu_unit "iu1_7xx,iu2_7xx" "ppc7xx")
@@ -48,20 +48,36 @@
(define_insn_reservation "ppc750-load" 2
(and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
- load_ux,load_u,fpload,fpload_ux,fpload_u,vecload")
+ load_ux,load_u,fpload,fpload_ux,fpload_u,\
+ vecload,load_l")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,lsu_7xx")
-(define_insn_reservation "ppc750-store" 1
+(define_insn_reservation "ppc750-store" 2
(and (eq_attr "type" "store,store_ux,store_u,\
fpstore,fpstore_ux,fpstore_u,vecstore")
(eq_attr "cpu" "ppc750,ppc7400"))
"ppc750_du,lsu_7xx")
+(define_insn_reservation "ppc750-storec" 8
+ (and (eq_attr "type" "store_c")
+ (eq_attr "cpu" "ppc750,ppc7400"))
+ "ppc750_du,lsu_7xx")
+
(define_insn_reservation "ppc750-integer" 1
(and (eq_attr "type" "integer,insert_word")
(eq_attr "cpu" "ppc750,ppc7400"))
- "ppc750_du,(iu1_7xx|iu2_7xx)")
+ "ppc750_du,iu1_7xx|iu2_7xx")
+
+(define_insn_reservation "ppc750-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc750,ppc7400"))
+ "ppc750_du,iu1_7xx|iu2_7xx,iu1_7xx|iu2_7xx")
+
+(define_insn_reservation "ppc750-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc750,ppc7400"))
+ "ppc750_du,iu1_7xx|iu2_7xx,iu1_7xx|iu2_7xx,iu1_7xx|iu2_7xx")
(define_insn_reservation "ppc750-imul" 4
(and (eq_attr "type" "imul,imul_compare")
@@ -127,10 +143,10 @@
(define_insn_reservation "ppc750-crlogical" 3
(and (eq_attr "type" "cr_logical,delayed_cr")
(eq_attr "cpu" "ppc750,ppc7400"))
- "ppc750_du,sru_7xx*2")
+ "nothing,sru_7xx*2")
(define_insn_reservation "ppc750-mtjmpr" 2
- (and (eq_attr "type" "mtjmpr")
+ (and (eq_attr "type" "mtjmpr,isync,sync")
(eq_attr "cpu" "ppc750,ppc7400"))
"nothing,sru_7xx*2")
@@ -140,7 +156,7 @@
"nothing,sru_7xx*2")
(define_insn_reservation "ppc750-jmpreg" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "ppc750,ppc7400"))
"nothing,bpu_7xx")
diff --git a/contrib/gcc/config/rs6000/8540.md b/contrib/gcc/config/rs6000/8540.md
index 737c399..b42e247 100644
--- a/contrib/gcc/config/rs6000/8540.md
+++ b/contrib/gcc/config/rs6000/8540.md
@@ -1,5 +1,5 @@
;; Pipeline description for Motorola PowerPC 8540 processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,14 +15,14 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "ppc8540_most,ppc8540_long,ppc8540_retire")
(define_cpu_unit "ppc8540_decode_0,ppc8540_decode_1" "ppc8540_most")
;; We don't simulate general issue queue (GIC). If we have SU insn
-;; and then SU1 insn, they can not be issued on the same cycle
+;; and then SU1 insn, they cannot be issued on the same cycle
;; (although SU1 insn and then SU insn can be issued) because the SU
;; insn will go to SU1 from GIC0 entry. Fortunately, the first cycle
;; multipass insn scheduling will find the situation and issue the SU1
@@ -31,7 +31,7 @@
;; We could describe completion buffers slots in combination with the
;; retirement units and the order of completion but the result
-;; automaton would behave in the same way because we can not describe
+;; automaton would behave in the same way because we cannot describe
;; real latency time with taking in order completion into account.
;; Actually we could define the real latency time by querying reserved
;; automaton units but the current scheduler uses latency time before
@@ -89,9 +89,22 @@
(eq_attr "cpu" "ppc8540"))
"ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
+(define_insn_reservation "ppc8540_two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "ppc8540"))
+ "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
+ ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
+
+(define_insn_reservation "ppc8540_three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "ppc8540"))
+ "ppc8540_decode,ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
+ ppc8540_issue+ppc8540_su_stage0+ppc8540_retire,\
+ ppc8540_issue+ppc8540_su_stage0+ppc8540_retire")
+
;; Branch. Actually this latency time is not used by the scheduler.
(define_insn_reservation "ppc8540_branch" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "ppc8540"))
"ppc8540_decode,ppc8540_bu,ppc8540_retire")
@@ -138,13 +151,14 @@
;; Loads
(define_insn_reservation "ppc8540_load" 3
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,sync")
(eq_attr "cpu" "ppc8540"))
"ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
;; Stores.
(define_insn_reservation "ppc8540_store" 3
- (and (eq_attr "type" "store,store_ux,store_u")
+ (and (eq_attr "type" "store,store_ux,store_u,store_c")
(eq_attr "cpu" "ppc8540"))
"ppc8540_decode,ppc8540_issue+ppc8540_lsu,nothing,ppc8540_retire")
diff --git a/contrib/gcc/config/rs6000/aix.h b/contrib/gcc/config/rs6000/aix.h
index b14107f..57f4876 100644
--- a/contrib/gcc/config/rs6000/aix.h
+++ b/contrib/gcc/config/rs6000/aix.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Yes! We are AIX! */
#define DEFAULT_ABI ABI_AIX
@@ -32,13 +33,17 @@
/* AIX allows r13 to be used in 32-bit mode. */
#define FIXED_R13 0
+/* 32-bit and 64-bit AIX stack boundary is 128. */
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY 128
+
/* AIX does not support Altivec. */
#undef TARGET_ALTIVEC
#define TARGET_ALTIVEC 0
#undef TARGET_ALTIVEC_ABI
#define TARGET_ALTIVEC_ABI 0
-#undef TARGET_ALTIVEC_VRSAVE
-#define TARGET_ALTIVEC_VRSAVE 0
+#undef TARGET_IEEEQUAD
+#define TARGET_IEEEQUAD 0
/* The AIX linker will discard static constructors in object files before
collect has a chance to see them, so scan the object files directly. */
@@ -51,26 +56,52 @@
#define REAL_NM_FILE_NAME "/usr/ucb/nm"
#define USER_LABEL_PREFIX ""
+
/* Don't turn -B into -L if the argument specifies a relative file name. */
#define RELATIVE_PREFIX_NOT_LINKDIR
/* Because of the above, we must have gcc search itself to find libgcc.a. */
#define LINK_LIBGCC_SPECIAL_1
+#define MFWRAP_SPEC " %{static: %{fmudflap|fmudflapth: \
+ -brename:malloc,__wrap_malloc -brename:__real_malloc,malloc \
+ -brename:free,__wrap_free -brename:__real_free,free \
+ -brename:calloc,__wrap_calloc -brename:__real_calloc,calloc \
+ -brename:realloc,__wrap_realloc -brename:__real_realloc,realloc \
+ -brename:mmap,__wrap_mmap -brename:__real_mmap,mmap \
+ -brename:munmap,__wrap_munmap -brename:__real_munmap,munmap \
+ -brename:alloca,__wrap_alloca -brename:__real_alloca,alloca \
+} %{fmudflapth: \
+ -brename:pthread_create,__wrap_pthread_create \
+ -brename:__real_pthread_create,pthread_create \
+ -brename:pthread_join,__wrap_pthread_join \
+ -brename:__real_pthread_join,pthread_join \
+ -brename:pthread_exit,__wrap_pthread_exit \
+ -brename:__real_pthread_exit,pthread_exit \
+}} %{fmudflap|fmudflapth: \
+ -brename:main,__wrap_main -brename:__real_main,main \
+}"
+
+#define MFLIB_SPEC " %{fmudflap: -lmudflap \
+ %{static:%(link_gcc_c_sequence) -lmudflap}} \
+ %{fmudflapth: -lmudflapth -lpthread \
+ %{static:%(link_gcc_c_sequence) -lmudflapth}} "
+
/* Names to predefine in the preprocessor for this target machine. */
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_IBMR2"); \
- builtin_define ("_POWER"); \
- builtin_define ("_AIX"); \
- builtin_define ("_AIX32"); \
- builtin_define ("_LONG_LONG"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=aix"); \
- builtin_assert ("cpu=rs6000"); \
- builtin_assert ("machine=rs6000"); \
- } \
+#define TARGET_OS_AIX_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_IBMR2"); \
+ builtin_define ("_POWER"); \
+ builtin_define ("_AIX"); \
+ builtin_define ("_AIX32"); \
+ builtin_define ("_AIX41"); \
+ builtin_define ("_LONG_LONG"); \
+ if (TARGET_LONG_DOUBLE_128) \
+ builtin_define ("__LONGDOUBLE128"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=aix"); \
+ } \
while (0)
/* Define appropriate architecture macros for preprocessor depending on
@@ -139,12 +170,12 @@
/* AIX increases natural record alignment to doubleword if the first
field is an FP double while the FP fields remain word aligned. */
-#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
- ((TREE_CODE (STRUCT) == RECORD_TYPE \
- || TREE_CODE (STRUCT) == UNION_TYPE \
- || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
- && TARGET_ALIGN_NATURAL == 0 \
- ? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED) \
+#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
+ ((TREE_CODE (STRUCT) == RECORD_TYPE \
+ || TREE_CODE (STRUCT) == UNION_TYPE \
+ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
+ && TARGET_ALIGN_NATURAL == 0 \
+ ? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED) \
: MAX ((COMPUTED), (SPECIFIED)))
/* The AIX ABI isn't explicit on whether aggregates smaller than a
@@ -157,13 +188,6 @@
#define AGGREGATE_PADDING_FIXED 1
#define AGGREGATES_PAD_UPWARD_ALWAYS 1
-/* We don't want anything in the reg parm area being passed on the
- stack. */
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE)))
-
/* Specify padding for the last element of a block move between
registers and memory. FIRST is nonzero if this is the only
element. */
@@ -174,19 +198,6 @@
#define JUMP_TABLES_IN_TEXT_SECTION 1
-/* Enable AIX XL compiler calling convention breakage compatibility. */
-#undef TARGET_XL_COMPAT
-#define MASK_XL_COMPAT 0x40000000
-#define TARGET_XL_COMPAT (target_flags & MASK_XL_COMPAT)
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- {"xl-compat", MASK_XL_COMPAT, \
- N_("Conform more closely to IBM XLC semantics") }, \
- {"no-xl-compat", - MASK_XL_COMPAT, \
- N_("Default GCC semantics that differ from IBM XLC") }, \
- SUBSUBTARGET_SWITCHES
-#define SUBSUBTARGET_SWITCHES
-
/* Define any extra SPECS that the compiler needs to generate. */
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
@@ -244,3 +255,6 @@
32-bit mode. */
#define OS_MISSING_POWERPC64 1
#define OS_MISSING_ALTIVEC 1
+
+/* WINT_TYPE */
+#define WINT_TYPE "int"
diff --git a/contrib/gcc/config/rs6000/aix.opt b/contrib/gcc/config/rs6000/aix.opt
new file mode 100644
index 0000000..e6dadce
--- /dev/null
+++ b/contrib/gcc/config/rs6000/aix.opt
@@ -0,0 +1,25 @@
+; AIX options.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mxl-compat
+Target Var(has_xl_compat_option)
+Conform more closely to IBM XLC semantics
diff --git a/contrib/gcc/config/rs6000/aix41.h b/contrib/gcc/config/rs6000/aix41.h
index 542f928..44b1390 100644
--- a/contrib/gcc/config/rs6000/aix41.h
+++ b/contrib/gcc/config/rs6000/aix41.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX version 4.1.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004,
+ 2005
Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@gnu.org).
@@ -18,13 +19,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
-
-#undef SUBSUBTARGET_SWITCHES
-#define SUBSUBTARGET_SWITCHES \
- {"pe", 0, \
- N_("Support message passing with the Parallel Environment") },
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef ASM_SPEC
#define ASM_SPEC "-u %(asm_cpu)"
@@ -33,18 +29,11 @@
#define ASM_DEFAULT_SPEC "-mcom"
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_IBMR2"); \
- builtin_define ("_POWER"); \
- builtin_define ("_AIX"); \
- builtin_define ("_AIX32"); \
- builtin_define ("_AIX41"); \
- builtin_define ("_LONG_LONG"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=aix"); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ TARGET_OS_AIX_CPP_BUILTINS (); \
+ } \
while (0)
#undef CPP_SPEC
@@ -102,3 +91,6 @@
.set directives. We handle this by deferring the output of .set
directives to the end of the compilation unit. */
#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) true
+
+#undef TARGET_64BIT
+#define TARGET_64BIT 0
diff --git a/contrib/gcc/config/rs6000/aix41.opt b/contrib/gcc/config/rs6000/aix41.opt
new file mode 100644
index 0000000..a1f7665
--- /dev/null
+++ b/contrib/gcc/config/rs6000/aix41.opt
@@ -0,0 +1,25 @@
+; Options for AIX4.1.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mpe
+Target Report RejectNegative Var(internal_nothing_1)
+Support message passing with the Parallel Environment
diff --git a/contrib/gcc/config/rs6000/aix43.h b/contrib/gcc/config/rs6000/aix43.h
index 50bd304..b99f1a8 100644
--- a/contrib/gcc/config/rs6000/aix43.h
+++ b/contrib/gcc/config/rs6000/aix43.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX version 4.3.
- Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@gnu.org).
This file is part of GCC.
@@ -17,18 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
-
-/* AIX 4.3 and above support 64-bit executables. */
-#undef SUBSUBTARGET_SWITCHES
-#define SUBSUBTARGET_SWITCHES \
- {"aix64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
- N_("Compile for 64-bit pointers") }, \
- {"aix32", - (MASK_64BIT | MASK_POWERPC64), \
- N_("Compile for 32-bit pointers") }, \
- {"pe", 0, \
- N_("Support message passing with the Parallel Environment") },
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -45,12 +36,18 @@ do { \
if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS)) \
{ \
target_flags &= ~NON_POWERPC_MASKS; \
- warning ("-maix64 and POWER architecture are incompatible"); \
+ warning (0, "-maix64 and POWER architecture are incompatible"); \
} \
if (TARGET_64BIT && ! TARGET_POWERPC64) \
{ \
target_flags |= MASK_POWERPC64; \
- warning ("-maix64 requires PowerPC64 architecture remain enabled"); \
+ warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
+ } \
+ if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
+ { \
+ rs6000_long_double_type_size = 64; \
+ if (rs6000_explicit_options.long_double) \
+ warning (0, "soft-float and long-double-128 are incompatible"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
{ \
@@ -96,19 +93,12 @@ do { \
#define ASM_DEFAULT_SPEC "-mcom"
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_IBMR2"); \
- builtin_define ("_POWER"); \
- builtin_define ("_AIX"); \
- builtin_define ("_AIX32"); \
- builtin_define ("_AIX41"); \
- builtin_define ("_AIX43"); \
- builtin_define ("_LONG_LONG"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=aix"); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_AIX43"); \
+ TARGET_OS_AIX_CPP_BUILTINS (); \
+ } \
while (0)
#undef CPP_SPEC
@@ -122,10 +112,7 @@ do { \
defined. */
#undef CPLUSPLUS_CPP_SPEC
#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
+ "-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
%{mpe: -I/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
@@ -192,3 +179,6 @@ do { \
.set directives. We handle this by deferring the output of .set
directives to the end of the compilation unit. */
#define TARGET_DEFERRED_OUTPUT_DEFS(DECL,TARGET) true
+
+/* This target uses the aix64.opt file. */
+#define TARGET_USES_AIX64_OPT 1
diff --git a/contrib/gcc/config/rs6000/aix51.h b/contrib/gcc/config/rs6000/aix51.h
index 863b97f..ad0afee 100644
--- a/contrib/gcc/config/rs6000/aix51.h
+++ b/contrib/gcc/config/rs6000/aix51.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX V5.
- Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@gnu.org).
This file is part of GCC.
@@ -17,18 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
-
-/* AIX V5 and above support 64-bit executables. */
-#undef SUBSUBTARGET_SWITCHES
-#define SUBSUBTARGET_SWITCHES \
- {"aix64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
- N_("Compile for 64-bit pointers") }, \
- {"aix32", - (MASK_64BIT | MASK_POWERPC64), \
- N_("Compile for 32-bit pointers") }, \
- {"pe", 0, \
- N_("Support message passing with the Parallel Environment") },
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -45,12 +35,12 @@ do { \
if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS)) \
{ \
target_flags &= ~NON_POWERPC_MASKS; \
- warning ("-maix64 and POWER architecture are incompatible"); \
+ warning (0, "-maix64 and POWER architecture are incompatible"); \
} \
if (TARGET_64BIT && ! TARGET_POWERPC64) \
{ \
target_flags |= MASK_POWERPC64; \
- warning ("-maix64 requires PowerPC64 architecture remain enabled"); \
+ warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
{ \
@@ -90,26 +80,21 @@ do { \
%{mcpu=604: -m604} \
%{mcpu=604e: -m604} \
%{mcpu=620: -m620} \
-%{mcpu=630: -m620}"
+%{mcpu=630: -m620} \
+%{mcpu=970: -m620} \
+%{mcpu=G5: -m620}"
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mcom"
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_IBMR2"); \
- builtin_define ("_POWER"); \
- builtin_define ("_LONG_LONG"); \
- builtin_define ("_AIX"); \
- builtin_define ("_AIX32"); \
- builtin_define ("_AIX41"); \
- builtin_define ("_AIX43"); \
- builtin_define ("_AIX51"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=aix"); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_AIX43"); \
+ builtin_define ("_AIX51"); \
+ TARGET_OS_AIX_CPP_BUILTINS (); \
+ } \
while (0)
#undef CPP_SPEC
@@ -123,10 +108,7 @@ do { \
defined. */
#undef CPLUSPLUS_CPP_SPEC
#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
+ "-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
%{mpe: -I/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
@@ -181,7 +163,6 @@ do { \
/* Width of wchar_t in bits. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
-#define MAX_WCHAR_TYPE_SIZE 32
/* AIX V5 uses PowerPC nop (ori 0,0,0) instruction as call glue for PowerPC
and "cror 31,31,31" for POWER architecture. */
@@ -197,3 +178,5 @@ do { \
#undef LD_INIT_SWITCH
#define LD_INIT_SWITCH "-binitfini"
+/* This target uses the aix64.opt file. */
+#define TARGET_USES_AIX64_OPT 1
diff --git a/contrib/gcc/config/rs6000/aix52.h b/contrib/gcc/config/rs6000/aix52.h
index 6f12619..87d2157 100644
--- a/contrib/gcc/config/rs6000/aix52.h
+++ b/contrib/gcc/config/rs6000/aix52.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for IBM RS/6000 POWER running AIX V5.2.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by David Edelsohn (edelsohn@gnu.org).
This file is part of GCC.
@@ -17,18 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
-
-/* AIX V5 and above support 64-bit executables. */
-#undef SUBSUBTARGET_SWITCHES
-#define SUBSUBTARGET_SWITCHES \
- {"aix64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
- N_("Compile for 64-bit pointers") }, \
- {"aix32", - (MASK_64BIT | MASK_POWERPC64), \
- N_("Compile for 32-bit pointers") }, \
- {"pe", 0, \
- N_("Support message passing with the Parallel Environment") },
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -45,12 +35,18 @@ do { \
if (TARGET_64BIT && (target_flags & NON_POWERPC_MASKS)) \
{ \
target_flags &= ~NON_POWERPC_MASKS; \
- warning ("-maix64 and POWER architecture are incompatible"); \
+ warning (0, "-maix64 and POWER architecture are incompatible"); \
} \
if (TARGET_64BIT && ! TARGET_POWERPC64) \
{ \
target_flags |= MASK_POWERPC64; \
- warning ("-maix64 requires PowerPC64 architecture remain enabled"); \
+ warning (0, "-maix64 requires PowerPC64 architecture remain enabled"); \
+ } \
+ if (TARGET_SOFT_FLOAT && TARGET_LONG_DOUBLE_128) \
+ { \
+ rs6000_long_double_type_size = 64; \
+ if (rs6000_explicit_options.long_double) \
+ warning (0, "soft-float and long-double-128 are incompatible"); \
} \
if (TARGET_POWERPC64 && ! TARGET_64BIT) \
{ \
@@ -70,6 +66,9 @@ do { \
%{!mpower64: %(asm_default)}}} \
%{mcpu=power3: -m620} \
%{mcpu=power4: -m620} \
+%{mcpu=power5: -m620} \
+%{mcpu=power5+: -m620} \
+%{mcpu=power6: -m620} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rs64a: -mppc} \
%{mcpu=603: -m603} \
@@ -77,27 +76,22 @@ do { \
%{mcpu=604: -m604} \
%{mcpu=604e: -m604} \
%{mcpu=620: -m620} \
-%{mcpu=630: -m620}"
+%{mcpu=630: -m620} \
+%{mcpu=970: -m620} \
+%{mcpu=G5: -m620}"
#undef ASM_DEFAULT_SPEC
#define ASM_DEFAULT_SPEC "-mppc"
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define ("_IBMR2"); \
- builtin_define ("_POWER"); \
- builtin_define ("_LONG_LONG"); \
- builtin_define ("_AIX"); \
- builtin_define ("_AIX32"); \
- builtin_define ("_AIX41"); \
- builtin_define ("_AIX43"); \
- builtin_define ("_AIX51"); \
- builtin_define ("_AIX52"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=aix"); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("_AIX43"); \
+ builtin_define ("_AIX51"); \
+ builtin_define ("_AIX52"); \
+ TARGET_OS_AIX_CPP_BUILTINS (); \
+ } \
while (0)
#undef CPP_SPEC
@@ -108,13 +102,10 @@ do { \
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
- defined. */
+ defined. Synchronize with libstdc++ os_defines.h. */
#undef CPLUSPLUS_CPP_SPEC
#define CPLUSPLUS_CPP_SPEC \
- "-D_XOPEN_SOURCE=500 \
- -D_XOPEN_SOURCE_EXTENDED=1 \
- -D_LARGE_FILE_API \
- -D_ALL_SOURCE \
+ "-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
%{mpe: -I/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
@@ -123,7 +114,7 @@ do { \
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
#undef PROCESSOR_DEFAULT
-#define PROCESSOR_DEFAULT PROCESSOR_PPC630
+#define PROCESSOR_DEFAULT PROCESSOR_POWER4
#undef PROCESSOR_DEFAULT64
#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
@@ -173,7 +164,6 @@ do { \
/* Width of wchar_t in bits. */
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE (!TARGET_64BIT ? 16 : 32)
-#define MAX_WCHAR_TYPE_SIZE 32
/* AIX V5 uses PowerPC nop (ori 0,0,0) instruction as call glue for PowerPC
and "cror 31,31,31" for POWER architecture. */
@@ -197,3 +187,5 @@ do { \
extern long long int atoll(const char *);
#endif
+/* This target uses the aix64.opt file. */
+#define TARGET_USES_AIX64_OPT 1
diff --git a/contrib/gcc/config/rs6000/aix64.opt b/contrib/gcc/config/rs6000/aix64.opt
new file mode 100644
index 0000000..817e985
--- /dev/null
+++ b/contrib/gcc/config/rs6000/aix64.opt
@@ -0,0 +1,33 @@
+; Options for the 64-bit flavor of AIX.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+maix64
+Target Report RejectNegative Mask(64BIT)
+Compile for 64-bit pointers
+
+maix32
+Target Report RejectNegative InverseMask(64BIT)
+Compile for 32-bit pointers
+
+mpe
+Target Report RejectNegative Var(internal_nothing_1)
+Support message passing with the Parallel Environment
diff --git a/contrib/gcc/config/rs6000/altivec.h b/contrib/gcc/config/rs6000/altivec.h
index 779b428..dacb6d0 100644
--- a/contrib/gcc/config/rs6000/altivec.h
+++ b/contrib/gcc/config/rs6000/altivec.h
@@ -1,6 +1,7 @@
/* PowerPC AltiVec include file.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Aldy Hernandez (aldyh@redhat.com).
+ Rewritten by Paolo Bonzini (bonzini@gnu.org).
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
@@ -55,8 +56,7 @@
#define __CR6_LT 2
#define __CR6_LT_REV 3
-/* These are easy... Same exact arguments. */
-
+/* Synonyms. */
#define vec_vaddcuw vec_addc
#define vec_vand vec_and
#define vec_vandc vec_andc
@@ -99,11409 +99,363 @@
#define vec_vrfiz vec_trunc
#define vec_vxor vec_xor
-#ifdef __cplusplus
-
-extern "C++" {
-
-/* Prototypes for builtins that take literals and must always be
- inlined. */
-inline __vector float vec_ctf (__vector unsigned int, const int) __attribute__ ((always_inline));
-inline __vector float vec_ctf (__vector signed int, const int) __attribute__ ((always_inline));
-inline __vector float vec_vcfsx (__vector signed int a1, const int a2) __attribute__ ((always_inline));
-inline __vector float vec_vcfux (__vector unsigned int a1, const int a2) __attribute__ ((always_inline));
-inline __vector signed int vec_cts (__vector float, const int) __attribute__ ((always_inline));
-inline __vector unsigned int vec_ctu (__vector float, const int) __attribute__ ((always_inline));
-inline void vec_dss (const int) __attribute__ ((always_inline));
-
-inline void vec_dst (const __vector unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector __bool char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector signed short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector __bool short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector __pixel *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector signed int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector __bool int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const __vector float *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const unsigned long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dst (const float *, int, const int) __attribute__ ((always_inline));
-
-inline void vec_dstst (const __vector unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector __bool char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector signed short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector __bool short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector __pixel *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector signed int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector __bool int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const __vector float *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const unsigned long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstst (const float *, int, const int) __attribute__ ((always_inline));
-
-inline void vec_dststt (const __vector unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector __bool char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector signed short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector __bool short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector __pixel *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector signed int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector __bool int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const __vector float *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const unsigned long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dststt (const float *, int, const int) __attribute__ ((always_inline));
-
-inline void vec_dstt (const __vector unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector __bool char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector signed short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector __bool short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector __pixel *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector signed int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector __bool int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const __vector float *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const unsigned char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const signed char *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const unsigned short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const short *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const unsigned int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const int *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const unsigned long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const long *, int, const int) __attribute__ ((always_inline));
-inline void vec_dstt (const float *, int, const int) __attribute__ ((always_inline));
-
-inline __vector float vec_sld (__vector float, __vector float, const int) __attribute__ ((always_inline));
-inline __vector signed int vec_sld (__vector signed int, __vector signed int, const int) __attribute__ ((always_inline));
-inline __vector unsigned int vec_sld (__vector unsigned int, __vector unsigned int, const int) __attribute__ ((always_inline));
-inline __vector __bool int vec_sld (__vector __bool int, __vector __bool int, const int) __attribute__ ((always_inline));
-inline __vector signed short vec_sld (__vector signed short, __vector signed short, const int) __attribute__ ((always_inline));
-inline __vector unsigned short vec_sld (__vector unsigned short, __vector unsigned short, const int) __attribute__ ((always_inline));
-inline __vector __bool short vec_sld (__vector __bool short, __vector __bool short, const int) __attribute__ ((always_inline));
-inline __vector __pixel vec_sld (__vector __pixel, __vector __pixel, const int) __attribute__ ((always_inline));
-inline __vector signed char vec_sld (__vector signed char, __vector signed char, const int) __attribute__ ((always_inline));
-inline __vector unsigned char vec_sld (__vector unsigned char, __vector unsigned char, const int) __attribute__ ((always_inline));
-inline __vector __bool char vec_sld (__vector __bool char, __vector __bool char, const int) __attribute__ ((always_inline));
-inline __vector signed char vec_splat (__vector signed char, const int) __attribute__ ((always_inline));
-inline __vector unsigned char vec_splat (__vector unsigned char, const int) __attribute__ ((always_inline));
-inline __vector __bool char vec_splat (__vector __bool char, const int) __attribute__ ((always_inline));
-inline __vector signed short vec_splat (__vector signed short, const int) __attribute__ ((always_inline));
-inline __vector unsigned short vec_splat (__vector unsigned short, const int) __attribute__ ((always_inline));
-inline __vector __bool short vec_splat (__vector __bool short, const int) __attribute__ ((always_inline));
-inline __vector __pixel vec_splat (__vector __pixel, const int) __attribute__ ((always_inline));
-inline __vector float vec_splat (__vector float, const int) __attribute__ ((always_inline));
-inline __vector signed int vec_splat (__vector signed int, const int) __attribute__ ((always_inline));
-inline __vector unsigned int vec_splat (__vector unsigned int, const int) __attribute__ ((always_inline));
-inline __vector __bool int vec_splat (__vector __bool int, const int) __attribute__ ((always_inline));
-inline __vector signed char vec_splat_s8 (const int) __attribute__ ((always_inline));
-inline __vector signed short vec_splat_s16 (const int) __attribute__ ((always_inline));
-inline __vector signed int vec_splat_s32 (const int) __attribute__ ((always_inline));
-inline __vector unsigned char vec_splat_u8 (const int) __attribute__ ((always_inline));
-inline __vector unsigned short vec_splat_u16 (const int) __attribute__ ((always_inline));
-inline __vector unsigned int vec_splat_u32 (const int) __attribute__ ((always_inline));
-inline __vector float vec_vspltw (__vector float a1, const int a2) __attribute__ ((always_inline));
-inline __vector __bool int vec_vspltw (__vector __bool int a1, const int a2) __attribute__ ((always_inline));
-inline __vector signed int vec_vspltw (__vector signed int a1, const int a2) __attribute__ ((always_inline));
-inline __vector unsigned int vec_vspltw (__vector unsigned int a1, const int a2) __attribute__ ((always_inline));
-inline __vector __bool short vec_vsplth (__vector __bool short a1, const int a2) __attribute__ ((always_inline));
-inline __vector signed short vec_vsplth (__vector signed short a1, const int a2) __attribute__ ((always_inline));
-inline __vector unsigned short vec_vsplth (__vector unsigned short a1, const int a2) __attribute__ ((always_inline));
-inline __vector __pixel vec_vsplth (__vector __pixel a1, const int a2) __attribute__ ((always_inline));
-inline __vector __bool char vec_vspltb (__vector __bool char a1, const int a2) __attribute__ ((always_inline));
-inline __vector signed char vec_vspltb (__vector signed char a1, const int a2) __attribute__ ((always_inline));
-inline __vector unsigned char vec_vspltb (__vector unsigned char a1, const int a2) __attribute__ ((always_inline));
-
-/* vec_step */
-
-template<typename _Tp>
-struct __vec_step_help
-{
- // All proper __vector types will specialize _S_elem.
-};
-
-template<>
-struct __vec_step_help<__vector signed short>
-{
- static const int _S_elem = 8;
+/* Functions that are resolved by the backend to one of the
+ typed builtins. */
+#define vec_vaddfp __builtin_vec_vaddfp
+#define vec_addc __builtin_vec_addc
+#define vec_vaddsws __builtin_vec_vaddsws
+#define vec_vaddshs __builtin_vec_vaddshs
+#define vec_vaddsbs __builtin_vec_vaddsbs
+#define vec_vavgsw __builtin_vec_vavgsw
+#define vec_vavguw __builtin_vec_vavguw
+#define vec_vavgsh __builtin_vec_vavgsh
+#define vec_vavguh __builtin_vec_vavguh
+#define vec_vavgsb __builtin_vec_vavgsb
+#define vec_vavgub __builtin_vec_vavgub
+#define vec_ceil __builtin_vec_ceil
+#define vec_cmpb __builtin_vec_cmpb
+#define vec_vcmpeqfp __builtin_vec_vcmpeqfp
+#define vec_cmpge __builtin_vec_cmpge
+#define vec_vcmpgtfp __builtin_vec_vcmpgtfp
+#define vec_vcmpgtsw __builtin_vec_vcmpgtsw
+#define vec_vcmpgtuw __builtin_vec_vcmpgtuw
+#define vec_vcmpgtsh __builtin_vec_vcmpgtsh
+#define vec_vcmpgtuh __builtin_vec_vcmpgtuh
+#define vec_vcmpgtsb __builtin_vec_vcmpgtsb
+#define vec_vcmpgtub __builtin_vec_vcmpgtub
+#define vec_vcfsx __builtin_vec_vcfsx
+#define vec_vcfux __builtin_vec_vcfux
+#define vec_cts __builtin_vec_cts
+#define vec_ctu __builtin_vec_ctu
+#define vec_expte __builtin_vec_expte
+#define vec_floor __builtin_vec_floor
+#define vec_loge __builtin_vec_loge
+#define vec_madd __builtin_vec_madd
+#define vec_madds __builtin_vec_madds
+#define vec_mtvscr __builtin_vec_mtvscr
+#define vec_vmaxfp __builtin_vec_vmaxfp
+#define vec_vmaxsw __builtin_vec_vmaxsw
+#define vec_vmaxsh __builtin_vec_vmaxsh
+#define vec_vmaxsb __builtin_vec_vmaxsb
+#define vec_vminfp __builtin_vec_vminfp
+#define vec_vminsw __builtin_vec_vminsw
+#define vec_vminsh __builtin_vec_vminsh
+#define vec_vminsb __builtin_vec_vminsb
+#define vec_mradds __builtin_vec_mradds
+#define vec_vmsumshm __builtin_vec_vmsumshm
+#define vec_vmsumuhm __builtin_vec_vmsumuhm
+#define vec_vmsummbm __builtin_vec_vmsummbm
+#define vec_vmsumubm __builtin_vec_vmsumubm
+#define vec_vmsumshs __builtin_vec_vmsumshs
+#define vec_vmsumuhs __builtin_vec_vmsumuhs
+#define vec_vmulesb __builtin_vec_vmulesb
+#define vec_vmulesh __builtin_vec_vmulesh
+#define vec_vmuleuh __builtin_vec_vmuleuh
+#define vec_vmuleub __builtin_vec_vmuleub
+#define vec_vmulosh __builtin_vec_vmulosh
+#define vec_vmulouh __builtin_vec_vmulouh
+#define vec_vmulosb __builtin_vec_vmulosb
+#define vec_vmuloub __builtin_vec_vmuloub
+#define vec_nmsub __builtin_vec_nmsub
+#define vec_packpx __builtin_vec_packpx
+#define vec_vpkswss __builtin_vec_vpkswss
+#define vec_vpkuwus __builtin_vec_vpkuwus
+#define vec_vpkshss __builtin_vec_vpkshss
+#define vec_vpkuhus __builtin_vec_vpkuhus
+#define vec_vpkswus __builtin_vec_vpkswus
+#define vec_vpkshus __builtin_vec_vpkshus
+#define vec_re __builtin_vec_re
+#define vec_round __builtin_vec_round
+#define vec_rsqrte __builtin_vec_rsqrte
+#define vec_vsubfp __builtin_vec_vsubfp
+#define vec_subc __builtin_vec_subc
+#define vec_vsubsws __builtin_vec_vsubsws
+#define vec_vsubshs __builtin_vec_vsubshs
+#define vec_vsubsbs __builtin_vec_vsubsbs
+#define vec_sum4s __builtin_vec_sum4s
+#define vec_vsum4shs __builtin_vec_vsum4shs
+#define vec_vsum4sbs __builtin_vec_vsum4sbs
+#define vec_vsum4ubs __builtin_vec_vsum4ubs
+#define vec_sum2s __builtin_vec_sum2s
+#define vec_sums __builtin_vec_sums
+#define vec_trunc __builtin_vec_trunc
+#define vec_vupkhpx __builtin_vec_vupkhpx
+#define vec_vupkhsh __builtin_vec_vupkhsh
+#define vec_vupkhsb __builtin_vec_vupkhsb
+#define vec_vupklpx __builtin_vec_vupklpx
+#define vec_vupklsh __builtin_vec_vupklsh
+#define vec_vupklsb __builtin_vec_vupklsb
+#define vec_abs __builtin_vec_abs
+#define vec_abss __builtin_vec_abss
+#define vec_add __builtin_vec_add
+#define vec_adds __builtin_vec_adds
+#define vec_and __builtin_vec_and
+#define vec_andc __builtin_vec_andc
+#define vec_avg __builtin_vec_avg
+#define vec_cmpeq __builtin_vec_cmpeq
+#define vec_cmpgt __builtin_vec_cmpgt
+#define vec_ctf __builtin_vec_ctf
+#define vec_dst __builtin_vec_dst
+#define vec_dstst __builtin_vec_dstst
+#define vec_dststt __builtin_vec_dststt
+#define vec_dstt __builtin_vec_dstt
+#define vec_ld __builtin_vec_ld
+#define vec_lde __builtin_vec_lde
+#define vec_ldl __builtin_vec_ldl
+#define vec_lvebx __builtin_vec_lvebx
+#define vec_lvehx __builtin_vec_lvehx
+#define vec_lvewx __builtin_vec_lvewx
+#define vec_lvsl __builtin_vec_lvsl
+#define vec_lvsr __builtin_vec_lvsr
+#define vec_max __builtin_vec_max
+#define vec_mergeh __builtin_vec_mergeh
+#define vec_mergel __builtin_vec_mergel
+#define vec_min __builtin_vec_min
+#define vec_mladd __builtin_vec_mladd
+#define vec_msum __builtin_vec_msum
+#define vec_msums __builtin_vec_msums
+#define vec_mule __builtin_vec_mule
+#define vec_mulo __builtin_vec_mulo
+#define vec_nor __builtin_vec_nor
+#define vec_or __builtin_vec_or
+#define vec_pack __builtin_vec_pack
+#define vec_packs __builtin_vec_packs
+#define vec_packsu __builtin_vec_packsu
+#define vec_perm __builtin_vec_perm
+#define vec_rl __builtin_vec_rl
+#define vec_sel __builtin_vec_sel
+#define vec_sl __builtin_vec_sl
+#define vec_sld __builtin_vec_sld
+#define vec_sll __builtin_vec_sll
+#define vec_slo __builtin_vec_slo
+#define vec_splat __builtin_vec_splat
+#define vec_sr __builtin_vec_sr
+#define vec_sra __builtin_vec_sra
+#define vec_srl __builtin_vec_srl
+#define vec_sro __builtin_vec_sro
+#define vec_st __builtin_vec_st
+#define vec_ste __builtin_vec_ste
+#define vec_stl __builtin_vec_stl
+#define vec_stvebx __builtin_vec_stvebx
+#define vec_stvehx __builtin_vec_stvehx
+#define vec_stvewx __builtin_vec_stvewx
+#define vec_sub __builtin_vec_sub
+#define vec_subs __builtin_vec_subs
+#define vec_sum __builtin_vec_sum
+#define vec_unpackh __builtin_vec_unpackh
+#define vec_unpackl __builtin_vec_unpackl
+#define vec_vaddubm __builtin_vec_vaddubm
+#define vec_vaddubs __builtin_vec_vaddubs
+#define vec_vadduhm __builtin_vec_vadduhm
+#define vec_vadduhs __builtin_vec_vadduhs
+#define vec_vadduwm __builtin_vec_vadduwm
+#define vec_vadduws __builtin_vec_vadduws
+#define vec_vcmpequb __builtin_vec_vcmpequb
+#define vec_vcmpequh __builtin_vec_vcmpequh
+#define vec_vcmpequw __builtin_vec_vcmpequw
+#define vec_vmaxub __builtin_vec_vmaxub
+#define vec_vmaxuh __builtin_vec_vmaxuh
+#define vec_vmaxuw __builtin_vec_vmaxuw
+#define vec_vminub __builtin_vec_vminub
+#define vec_vminuh __builtin_vec_vminuh
+#define vec_vminuw __builtin_vec_vminuw
+#define vec_vmrghb __builtin_vec_vmrghb
+#define vec_vmrghh __builtin_vec_vmrghh
+#define vec_vmrghw __builtin_vec_vmrghw
+#define vec_vmrglb __builtin_vec_vmrglb
+#define vec_vmrglh __builtin_vec_vmrglh
+#define vec_vmrglw __builtin_vec_vmrglw
+#define vec_vpkuhum __builtin_vec_vpkuhum
+#define vec_vpkuwum __builtin_vec_vpkuwum
+#define vec_vrlb __builtin_vec_vrlb
+#define vec_vrlh __builtin_vec_vrlh
+#define vec_vrlw __builtin_vec_vrlw
+#define vec_vslb __builtin_vec_vslb
+#define vec_vslh __builtin_vec_vslh
+#define vec_vslw __builtin_vec_vslw
+#define vec_vspltb __builtin_vec_vspltb
+#define vec_vsplth __builtin_vec_vsplth
+#define vec_vspltw __builtin_vec_vspltw
+#define vec_vsrab __builtin_vec_vsrab
+#define vec_vsrah __builtin_vec_vsrah
+#define vec_vsraw __builtin_vec_vsraw
+#define vec_vsrb __builtin_vec_vsrb
+#define vec_vsrh __builtin_vec_vsrh
+#define vec_vsrw __builtin_vec_vsrw
+#define vec_vsububs __builtin_vec_vsububs
+#define vec_vsububm __builtin_vec_vsububm
+#define vec_vsubuhm __builtin_vec_vsubuhm
+#define vec_vsubuhs __builtin_vec_vsubuhs
+#define vec_vsubuwm __builtin_vec_vsubuwm
+#define vec_vsubuws __builtin_vec_vsubuws
+#define vec_xor __builtin_vec_xor
+
+/* Predicates.
+ For C++, we use templates in order to allow non-parenthesized arguments.
+ For C, instead, we use macros since non-parenthesized arguments were
+ not allowed even in older GCC implementation of AltiVec.
+
+ In the future, we may add more magic to the back-end, so that no
+ one- or two-argument macros are used. */
+
+#ifdef __cplusplus__
+#define __altivec_unary_pred(NAME, CALL) \
+template <class T> int NAME (T a1) { return CALL; }
+
+#define __altivec_scalar_pred(NAME, CALL) \
+template <class T, class U> int NAME (T a1, U a2) { return CALL; }
+
+/* Given the vec_step of a type, return the corresponding bool type. */
+template <int STEP> class __altivec_bool_ret { };
+template <> class __altivec_bool_ret <4> {
+ typedef __vector __bool int __ret;
};
-
-template<>
-struct __vec_step_help<__vector unsigned short>
-{
- static const int _S_elem = 8;
-};
-
-template<>
-struct __vec_step_help<__vector __bool short>
-{
- static const int _S_elem = 8;
-};
-
-template<>
-struct __vec_step_help<__vector __pixel>
-{
- static const int _S_elem = 8;
-};
-
-template<>
-struct __vec_step_help<__vector signed int>
-{
- static const int _S_elem = 4;
-};
-
-template<>
-struct __vec_step_help<__vector unsigned int>
-{
- static const int _S_elem = 4;
+template <> class __altivec_bool_ret <8> {
+ typedef __vector __bool short __ret;
};
-
-template<>
-struct __vec_step_help<__vector __bool int>
-{
- static const int _S_elem = 4;
-};
-
-template<>
-struct __vec_step_help<__vector unsigned char>
-{
- static const int _S_elem = 16;
+template <> class __altivec_bool_ret <16> {
+ typedef __vector __bool char __ret;
};
-template<>
-struct __vec_step_help<__vector signed char>
-{
- static const int _S_elem = 16;
-};
-
-template<>
-struct __vec_step_help<__vector __bool char>
-{
- static const int _S_elem = 16;
-};
-
-template<>
-struct __vec_step_help<__vector float>
-{
- static const int _S_elem = 4;
-};
-
-#define vec_step(t) __vec_step_help<typeof(t)>::_S_elem
-
-/* vec_abs */
-
-inline __vector signed char
-vec_abs (__vector signed char a1)
-{
- return __builtin_altivec_abs_v16qi (a1);
-}
-
-inline __vector signed short
-vec_abs (__vector signed short a1)
-{
- return __builtin_altivec_abs_v8hi (a1);
-}
-
-inline __vector signed int
-vec_abs (__vector signed int a1)
-{
- return __builtin_altivec_abs_v4si (a1);
-}
-
-inline __vector float
-vec_abs (__vector float a1)
-{
- return __builtin_altivec_abs_v4sf (a1);
-}
-
-/* vec_abss */
-
-inline __vector signed char
-vec_abss (__vector signed char a1)
-{
- return __builtin_altivec_abss_v16qi (a1);
-}
-
-inline __vector signed short
-vec_abss (__vector signed short a1)
-{
- return __builtin_altivec_abss_v8hi (a1);
-}
-
-inline __vector signed int
-vec_abss (__vector signed int a1)
-{
- return __builtin_altivec_abss_v4si (a1);
-}
-
-/* vec_add */
-
-inline __vector signed char
-vec_add (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_add (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_add (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_add (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_add (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_add (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_add (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_add (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_add (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_add (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_add (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_add (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_add (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_add (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_add (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_add (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_add (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_add (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_add (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vaddfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vaddfp */
-
-inline __vector float
-vec_vaddfp (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vaddfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vadduwm */
-
-inline __vector signed int
-vec_vadduwm (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vadduwm (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vadduwm (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vadduwm (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vadduwm (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vadduwm (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vadduhm */
-
-inline __vector signed short
-vec_vadduhm (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vadduhm (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vadduhm (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vadduhm (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vadduhm (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vadduhm (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vaddubm */
-
-inline __vector signed char
-vec_vaddubm (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vaddubm (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vaddubm (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vaddubm (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vaddubm (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vaddubm (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_addc */
-
-inline __vector unsigned int
-vec_addc (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vaddcuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_adds */
-
-inline __vector unsigned char
-vec_adds (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_adds (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_adds (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_adds (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_adds (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_adds (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned short
-vec_adds (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_adds (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_adds (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_adds (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_adds (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_adds (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned int
-vec_adds (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_adds (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_adds (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_adds (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_adds (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_adds (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vaddsws */
-
-inline __vector signed int
-vec_vaddsws (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vaddsws (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vaddsws (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vadduws */
-
-inline __vector unsigned int
-vec_vadduws (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vadduws (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vadduws (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vaddshs */
-
-inline __vector signed short
-vec_vaddshs (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vaddshs (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vaddshs (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vadduhs */
-
-inline __vector unsigned short
-vec_vadduhs (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vadduhs (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vadduhs (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vaddsbs */
-
-inline __vector signed char
-vec_vaddsbs (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vaddsbs (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vaddsbs (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vaddubs */
-
-inline __vector unsigned char
-vec_vaddubs (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vaddubs (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vaddubs (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_and */
-
-inline __vector float
-vec_and (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_and (__vector float a1, __vector __bool int a2)
-{
- return (__vector float) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_and (__vector __bool int a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_and (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_and (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_and (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_and (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_and (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_and (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_and (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_and (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_and (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_and (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_and (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_and (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_and (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_and (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_and (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_and (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_and (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_and (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_and (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_and (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_and (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vand ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_andc */
-
-inline __vector float
-vec_andc (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_andc (__vector float a1, __vector __bool int a2)
-{
- return (__vector float) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_andc (__vector __bool int a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_andc (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_andc (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_andc (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_andc (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_andc (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_andc (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_andc (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_andc (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_andc (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_andc (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_andc (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_andc (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_andc (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_andc (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_andc (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_andc (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_andc (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_andc (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_andc (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_andc (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_andc (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_avg */
-
-inline __vector unsigned char
-vec_avg (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vavgub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_avg (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vavgsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned short
-vec_avg (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vavguh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_avg (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vavgsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned int
-vec_avg (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vavguw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_avg (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vavgsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vavgsw */
-
-inline __vector signed int
-vec_vavgsw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vavgsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vavguw */
-
-inline __vector unsigned int
-vec_vavguw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vavguw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vavgsh */
-
-inline __vector signed short
-vec_vavgsh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vavgsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vavguh */
-
-inline __vector unsigned short
-vec_vavguh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vavguh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vavgsb */
-
-inline __vector signed char
-vec_vavgsb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vavgsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vavgub */
-
-inline __vector unsigned char
-vec_vavgub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vavgub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_ceil */
-
-inline __vector float
-vec_ceil (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrfip ((__vector float) a1);
-}
-
-/* vec_cmpb */
-
-inline __vector signed int
-vec_cmpb (__vector float a1, __vector float a2)
-{
- return (__vector signed int) __builtin_altivec_vcmpbfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_cmpeq */
-
-inline __vector __bool char
-vec_cmpeq (__vector signed char a1, __vector signed char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool char
-vec_cmpeq (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool short
-vec_cmpeq (__vector signed short a1, __vector signed short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool short
-vec_cmpeq (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool int
-vec_cmpeq (__vector signed int a1, __vector signed int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_cmpeq (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_cmpeq (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpeqfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vcmpeqfp */
-
-inline __vector __bool int
-vec_vcmpeqfp (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpeqfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vcmpequw */
-
-inline __vector __bool int
-vec_vcmpequw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_vcmpequw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vcmpequh */
-
-inline __vector __bool short
-vec_vcmpequh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool short
-vec_vcmpequh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vcmpequb */
-
-inline __vector __bool char
-vec_vcmpequb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool char
-vec_vcmpequb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_cmpge */
-
-inline __vector __bool int
-vec_cmpge (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgefp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_cmpgt */
-
-inline __vector __bool char
-vec_cmpgt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool char
-vec_cmpgt (__vector signed char a1, __vector signed char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool short
-vec_cmpgt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool short
-vec_cmpgt (__vector signed short a1, __vector signed short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool int
-vec_cmpgt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_cmpgt (__vector signed int a1, __vector signed int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_cmpgt (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vcmpgtfp */
-
-inline __vector __bool int
-vec_vcmpgtfp (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vcmpgtsw */
-
-inline __vector __bool int
-vec_vcmpgtsw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vcmpgtuw */
-
-inline __vector __bool int
-vec_vcmpgtuw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vcmpgtsh */
-
-inline __vector __bool short
-vec_vcmpgtsh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vcmpgtuh */
-
-inline __vector __bool short
-vec_vcmpgtuh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vcmpgtsb */
-
-inline __vector __bool char
-vec_vcmpgtsb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vcmpgtub */
-
-inline __vector __bool char
-vec_vcmpgtub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_cmple */
-
-inline __vector __bool int
-vec_cmple (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgefp ((__vector float) a2, (__vector float) a1);
-}
-
-/* vec_cmplt */
-
-inline __vector __bool char
-vec_cmplt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline __vector __bool char
-vec_cmplt (__vector signed char a1, __vector signed char a2)
-{
- return (__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline __vector __bool short
-vec_cmplt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline __vector __bool short
-vec_cmplt (__vector signed short a1, __vector signed short a2)
-{
- return (__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline __vector __bool int
-vec_cmplt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline __vector __bool int
-vec_cmplt (__vector signed int a1, __vector signed int a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline __vector __bool int
-vec_cmplt (__vector float a1, __vector float a2)
-{
- return (__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) a2, (__vector float) a1);
-}
-
-/* vec_ctf */
-
-inline __vector float
-vec_ctf (__vector unsigned int a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vcfux ((__vector signed int) a1, a2);
-}
-
-inline __vector float
-vec_ctf (__vector signed int a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vcfsx ((__vector signed int) a1, a2);
-}
-
-/* vec_vcfsx */
-
-inline __vector float
-vec_vcfsx (__vector signed int a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vcfsx ((__vector signed int) a1, a2);
-}
-
-/* vec_vcfux */
-
-inline __vector float
-vec_vcfux (__vector unsigned int a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vcfux ((__vector signed int) a1, a2);
-}
-
-/* vec_cts */
-
-inline __vector signed int
-vec_cts (__vector float a1, const int a2)
-{
- return (__vector signed int) __builtin_altivec_vctsxs ((__vector float) a1, a2);
-}
-
-/* vec_ctu */
-
-inline __vector unsigned int
-vec_ctu (__vector float a1, const int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vctuxs ((__vector float) a1, a2);
-}
-
-/* vec_dss */
-
-inline void
-vec_dss (const int a1)
-{
- __builtin_altivec_dss (a1);
-}
-
-/* vec_dssall */
-
-inline void
-vec_dssall (void)
-{
- __builtin_altivec_dssall ();
-}
-
-/* vec_dst */
-
-inline void
-vec_dst (const __vector unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector __bool char *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector signed short *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector __bool short *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector __pixel *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector signed int *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector __bool int *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const __vector float *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const short *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const int *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const unsigned long *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const long *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dst (const float *a1, int a2, const int a3)
-{
- __builtin_altivec_dst ((void *) a1, a2, a3);
-}
-
-/* vec_dstst */
-
-inline void
-vec_dstst (const __vector unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector __bool char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector signed short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector __bool short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector __pixel *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector signed int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector __bool int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const __vector float *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const unsigned long *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const long *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstst (const float *a1, int a2, const int a3)
-{
- __builtin_altivec_dstst ((void *) a1, a2, a3);
-}
-
-/* vec_dststt */
-
-inline void
-vec_dststt (const __vector unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector __bool char *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector signed short *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector __bool short *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector __pixel *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector signed int *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector __bool int *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const __vector float *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const short *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const int *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const unsigned long *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const long *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dststt (const float *a1, int a2, const int a3)
-{
- __builtin_altivec_dststt ((void *) a1, a2, a3);
-}
-
-/* vec_dstt */
-
-inline void
-vec_dstt (const __vector unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector __bool char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector signed short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector __bool short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector __pixel *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector signed int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector __bool int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const __vector float *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const unsigned char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const signed char *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const unsigned short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const short *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const unsigned int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const int *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const unsigned long *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const long *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-inline void
-vec_dstt (const float *a1, int a2, const int a3)
-{
- __builtin_altivec_dstt ((void *) a1, a2, a3);
-}
-
-/* vec_expte */
-
-inline __vector float
-vec_expte (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vexptefp ((__vector float) a1);
-}
-
-/* vec_floor */
-
-inline __vector float
-vec_floor (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrfim ((__vector float) a1);
-}
-
-/* vec_ld */
-
-inline __vector float
-vec_ld (int a1, const __vector float *a2)
-{
- return (__vector float) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector float
-vec_ld (int a1, const float *a2)
-{
- return (__vector float) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector __bool int
-vec_ld (int a1, const __vector __bool int *a2)
-{
- return (__vector __bool int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ld (int a1, const __vector signed int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ld (int a1, const int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ld (int a1, const long *a2)
-{
- return (__vector signed int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ld (int a1, const __vector unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ld (int a1, const unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ld (int a1, const unsigned long *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector __bool short
-vec_ld (int a1, const __vector __bool short *a2)
-{
- return (__vector __bool short) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector __pixel
-vec_ld (int a1, const __vector __pixel *a2)
-{
- return (__vector __pixel) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed short
-vec_ld (int a1, const __vector signed short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed short
-vec_ld (int a1, const short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_ld (int a1, const __vector unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_ld (int a1, const unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector __bool char
-vec_ld (int a1, const __vector __bool char *a2)
-{
- return (__vector __bool char) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed char
-vec_ld (int a1, const __vector signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector signed char
-vec_ld (int a1, const signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_ld (int a1, const __vector unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_ld (int a1, const unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvx (a1, (void *) a2);
-}
-
-/* vec_lde */
-
-inline __vector signed char
-vec_lde (int a1, const signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvebx (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lde (int a1, const unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvebx (a1, (void *) a2);
-}
-
-inline __vector signed short
-vec_lde (int a1, const short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvehx (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_lde (int a1, const unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvehx (a1, (void *) a2);
-}
-
-inline __vector float
-vec_lde (int a1, const float *a2)
-{
- return (__vector float) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_lde (int a1, const int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_lde (int a1, const unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_lde (int a1, const long *a2)
-{
- return (__vector signed int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_lde (int a1, const unsigned long *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-/* vec_lvewx */
-
-inline __vector float
-vec_lvewx (int a1, float *a2)
-{
- return (__vector float) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_lvewx (int a1, int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_lvewx (int a1, unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_lvewx (int a1, long *a2)
-{
- return (__vector signed int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_lvewx (int a1, unsigned long *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvewx (a1, (void *) a2);
-}
-
-/* vec_lvehx */
-
-inline __vector signed short
-vec_lvehx (int a1, short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvehx (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_lvehx (int a1, unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvehx (a1, (void *) a2);
-}
-
-/* vec_lvebx */
-
-inline __vector signed char
-vec_lvebx (int a1, signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvebx (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvebx (int a1, unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvebx (a1, (void *) a2);
-}
-
-/* vec_ldl */
-
-inline __vector float
-vec_ldl (int a1, const __vector float *a2)
-{
- return (__vector float) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector float
-vec_ldl (int a1, const float *a2)
-{
- return (__vector float) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector __bool int
-vec_ldl (int a1, const __vector __bool int *a2)
-{
- return (__vector __bool int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ldl (int a1, const __vector signed int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ldl (int a1, const int *a2)
-{
- return (__vector signed int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed int
-vec_ldl (int a1, const long *a2)
-{
- return (__vector signed int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ldl (int a1, const __vector unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ldl (int a1, const unsigned int *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned int
-vec_ldl (int a1, const unsigned long *a2)
-{
- return (__vector unsigned int) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector __bool short
-vec_ldl (int a1, const __vector __bool short *a2)
-{
- return (__vector __bool short) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector __pixel
-vec_ldl (int a1, const __vector __pixel *a2)
-{
- return (__vector __pixel) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed short
-vec_ldl (int a1, const __vector signed short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed short
-vec_ldl (int a1, const short *a2)
-{
- return (__vector signed short) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_ldl (int a1, const __vector unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned short
-vec_ldl (int a1, const unsigned short *a2)
-{
- return (__vector unsigned short) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector __bool char
-vec_ldl (int a1, const __vector __bool char *a2)
-{
- return (__vector __bool char) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed char
-vec_ldl (int a1, const __vector signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector signed char
-vec_ldl (int a1, const signed char *a2)
-{
- return (__vector signed char) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_ldl (int a1, const __vector unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_ldl (int a1, const unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvxl (a1, (void *) a2);
-}
-
-/* vec_loge */
-
-inline __vector float
-vec_loge (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vlogefp ((__vector float) a1);
-}
-
-/* vec_lvsl */
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile signed char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile unsigned short *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile short *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile unsigned int *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile int *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile unsigned long *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile long *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsl (int a1, const volatile float *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsl (a1, (void *) a2);
-}
-
-/* vec_lvsr */
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile unsigned char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile signed char *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile unsigned short *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile short *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile unsigned int *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile int *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile unsigned long *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile long *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-inline __vector unsigned char
-vec_lvsr (int a1, const volatile float *a2)
-{
- return (__vector unsigned char) __builtin_altivec_lvsr (a1, (void *) a2);
-}
-
-/* vec_madd */
-
-inline __vector float
-vec_madd (__vector float a1, __vector float a2, __vector float a3)
-{
- return (__vector float) __builtin_altivec_vmaddfp ((__vector float) a1, (__vector float) a2, (__vector float) a3);
-}
-
-/* vec_madds */
-
-inline __vector signed short
-vec_madds (__vector signed short a1, __vector signed short a2, __vector signed short a3)
-{
- return (__vector signed short) __builtin_altivec_vmhaddshs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-/* vec_max */
-
-inline __vector unsigned char
-vec_max (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_max (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_max (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_max (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_max (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_max (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned short
-vec_max (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_max (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_max (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_max (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_max (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_max (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned int
-vec_max (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_max (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_max (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_max (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_max (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_max (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_max (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmaxfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vmaxfp */
-
-inline __vector float
-vec_vmaxfp (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmaxfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vmaxsw */
-
-inline __vector signed int
-vec_vmaxsw (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vmaxsw (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vmaxsw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmaxuw */
-
-inline __vector unsigned int
-vec_vmaxuw (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vmaxuw (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vmaxuw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmaxsh */
-
-inline __vector signed short
-vec_vmaxsh (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vmaxsh (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vmaxsh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmaxuh */
-
-inline __vector unsigned short
-vec_vmaxuh (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vmaxuh (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vmaxuh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmaxsb */
-
-inline __vector signed char
-vec_vmaxsb (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vmaxsb (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vmaxsb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vmaxub */
-
-inline __vector unsigned char
-vec_vmaxub (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vmaxub (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vmaxub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_mergeh */
-
-inline __vector __bool char
-vec_mergeh (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_mergeh (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_mergeh (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool short
-vec_mergeh (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __pixel
-vec_mergeh (__vector __pixel a1, __vector __pixel a2)
-{
- return (__vector __pixel) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_mergeh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_mergeh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector float
-vec_mergeh (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_mergeh (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_mergeh (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_mergeh (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmrghw */
-
-inline __vector float
-vec_vmrghw (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_vmrghw (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vmrghw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vmrghw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmrghw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmrghh */
-
-inline __vector __bool short
-vec_vmrghh (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vmrghh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vmrghh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __pixel
-vec_vmrghh (__vector __pixel a1, __vector __pixel a2)
-{
- return (__vector __pixel) __builtin_altivec_vmrghh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmrghb */
-
-inline __vector __bool char
-vec_vmrghb (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vmrghb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vmrghb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmrghb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_mergel */
-
-inline __vector __bool char
-vec_mergel (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_mergel (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_mergel (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector __bool short
-vec_mergel (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __pixel
-vec_mergel (__vector __pixel a1, __vector __pixel a2)
-{
- return (__vector __pixel) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_mergel (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_mergel (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector float
-vec_mergel (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_mergel (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_mergel (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_mergel (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmrglw */
-
-inline __vector float
-vec_vmrglw (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vmrglw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vmrglw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_vmrglw (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vmrglw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vmrglh */
-
-inline __vector __bool short
-vec_vmrglh (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vmrglh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vmrglh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __pixel
-vec_vmrglh (__vector __pixel a1, __vector __pixel a2)
-{
- return (__vector __pixel) __builtin_altivec_vmrglh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmrglb */
-
-inline __vector __bool char
-vec_vmrglb (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vmrglb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vmrglb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vmrglb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_mfvscr */
-
-inline __vector unsigned short
-vec_mfvscr (void)
-{
- return (__vector unsigned short) __builtin_altivec_mfvscr ();
-}
-
-/* vec_min */
-
-inline __vector unsigned char
-vec_min (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_min (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_min (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_min (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_min (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_min (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned short
-vec_min (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_min (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_min (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_min (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_min (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_min (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned int
-vec_min (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_min (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_min (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_min (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_min (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_min (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_min (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vminfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vminfp */
-
-inline __vector float
-vec_vminfp (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vminfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vminsw */
-
-inline __vector signed int
-vec_vminsw (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vminsw (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vminsw (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vminsw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vminuw */
-
-inline __vector unsigned int
-vec_vminuw (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vminuw (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vminuw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vminsh */
-
-inline __vector signed short
-vec_vminsh (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vminsh (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vminsh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vminsh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vminuh */
-
-inline __vector unsigned short
-vec_vminuh (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vminuh (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vminuh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vminsb */
-
-inline __vector signed char
-vec_vminsb (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vminsb (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vminsb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vminsb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vminub */
-
-inline __vector unsigned char
-vec_vminub (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vminub (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vminub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_mladd */
-
-inline __vector signed short
-vec_mladd (__vector signed short a1, __vector signed short a2, __vector signed short a3)
-{
- return (__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-inline __vector signed short
-vec_mladd (__vector signed short a1, __vector unsigned short a2, __vector unsigned short a3)
-{
- return (__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-inline __vector signed short
-vec_mladd (__vector unsigned short a1, __vector signed short a2, __vector signed short a3)
-{
- return (__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-inline __vector unsigned short
-vec_mladd (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned short a3)
-{
- return (__vector unsigned short) __builtin_altivec_vmladduhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-/* vec_mradds */
-
-inline __vector signed short
-vec_mradds (__vector signed short a1, __vector signed short a2, __vector signed short a3)
-{
- return (__vector signed short) __builtin_altivec_vmhraddshs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed short) a3);
-}
-
-/* vec_msum */
-
-inline __vector unsigned int
-vec_msum (__vector unsigned char a1, __vector unsigned char a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumubm ((__vector signed char) a1, (__vector signed char) a2, (__vector signed int) a3);
-}
-
-inline __vector signed int
-vec_msum (__vector signed char a1, __vector unsigned char a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsummbm ((__vector signed char) a1, (__vector signed char) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned int
-vec_msum (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumuhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-inline __vector signed int
-vec_msum (__vector signed short a1, __vector signed short a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsumshm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsumshm */
-
-inline __vector signed int
-vec_vmsumshm (__vector signed short a1, __vector signed short a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsumshm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsumuhm */
-
-inline __vector unsigned int
-vec_vmsumuhm (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumuhm ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsummbm */
-
-inline __vector signed int
-vec_vmsummbm (__vector signed char a1, __vector unsigned char a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsummbm ((__vector signed char) a1, (__vector signed char) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsumubm */
-
-inline __vector unsigned int
-vec_vmsumubm (__vector unsigned char a1, __vector unsigned char a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumubm ((__vector signed char) a1, (__vector signed char) a2, (__vector signed int) a3);
-}
-
-/* vec_msums */
-
-inline __vector unsigned int
-vec_msums (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumuhs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-inline __vector signed int
-vec_msums (__vector signed short a1, __vector signed short a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsumshs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsumshs */
-
-inline __vector signed int
-vec_vmsumshs (__vector signed short a1, __vector signed short a2, __vector signed int a3)
-{
- return (__vector signed int) __builtin_altivec_vmsumshs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_vmsumuhs */
-
-inline __vector unsigned int
-vec_vmsumuhs (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vmsumuhs ((__vector signed short) a1, (__vector signed short) a2, (__vector signed int) a3);
-}
-
-/* vec_mtvscr */
-
-inline void
-vec_mtvscr (__vector signed int a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector unsigned int a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector __bool int a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector signed short a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector unsigned short a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector __bool short a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector __pixel a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector signed char a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector unsigned char a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-inline void
-vec_mtvscr (__vector __bool char a1)
-{
- __builtin_altivec_mtvscr ((__vector signed int) a1);
-}
-
-/* vec_mule */
-
-inline __vector unsigned short
-vec_mule (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmuleub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_mule (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vmulesb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned int
-vec_mule (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmuleuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_mule (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed int) __builtin_altivec_vmulesh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmulesh */
-
-inline __vector signed int
-vec_vmulesh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed int) __builtin_altivec_vmulesh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmuleuh */
-
-inline __vector unsigned int
-vec_vmuleuh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmuleuh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmulesb */
-
-inline __vector signed short
-vec_vmulesb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vmuleub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vmuleub */
-
-inline __vector unsigned short
-vec_vmuleub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmuleub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_mulo */
-
-inline __vector unsigned short
-vec_mulo (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmuloub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_mulo (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vmulosb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned int
-vec_mulo (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmulouh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_mulo (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed int) __builtin_altivec_vmulosh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmulosh */
-
-inline __vector signed int
-vec_vmulosh (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed int) __builtin_altivec_vmulosh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmulouh */
-
-inline __vector unsigned int
-vec_vmulouh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vmulouh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vmulosb */
-
-inline __vector signed short
-vec_vmulosb (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vmulosb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vmuloub */
-
-inline __vector unsigned short
-vec_vmuloub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vmuloub ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_nmsub */
-
-inline __vector float
-vec_nmsub (__vector float a1, __vector float a2, __vector float a3)
-{
- return (__vector float) __builtin_altivec_vnmsubfp ((__vector float) a1, (__vector float) a2, (__vector float) a3);
-}
-
-/* vec_nor */
-
-inline __vector float
-vec_nor (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_nor (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_nor (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_nor (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_nor (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_nor (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_nor (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_nor (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_nor (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_nor (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vnor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_or */
-
-inline __vector float
-vec_or (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_or (__vector float a1, __vector __bool int a2)
-{
- return (__vector float) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_or (__vector __bool int a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_or (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_or (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_or (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_or (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_or (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_or (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_or (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_or (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_or (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_or (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_or (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_or (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_or (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_or (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_or (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_or (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_or (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_or (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_or (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_or (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_or (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_pack */
-
-inline __vector signed char
-vec_pack (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned char
-vec_pack (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector __bool char
-vec_pack (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_pack (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_pack (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_pack (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkuwum */
-
-inline __vector __bool short
-vec_vpkuwum (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_vpkuwum (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_vpkuwum (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkuwum ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkuhum */
-
-inline __vector __bool char
-vec_vpkuhum (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed char
-vec_vpkuhum (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned char
-vec_vpkuhum (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkuhum ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_packpx */
-
-inline __vector __pixel
-vec_packpx (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector __pixel) __builtin_altivec_vpkpx ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_packs */
-
-inline __vector unsigned char
-vec_packs (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed char
-vec_packs (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed char) __builtin_altivec_vpkshss ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_packs (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_packs (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed short) __builtin_altivec_vpkswss ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkswss */
-
-inline __vector signed short
-vec_vpkswss (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed short) __builtin_altivec_vpkswss ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkuwus */
-
-inline __vector unsigned short
-vec_vpkuwus (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkshss */
-
-inline __vector signed char
-vec_vpkshss (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed char) __builtin_altivec_vpkshss ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vpkuhus */
-
-inline __vector unsigned char
-vec_vpkuhus (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_packsu */
-
-inline __vector unsigned char
-vec_packsu (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned char
-vec_packsu (__vector signed short a1, __vector signed short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkshus ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_packsu (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_packsu (__vector signed int a1, __vector signed int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkswus ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkswus */
-
-inline __vector unsigned short
-vec_vpkswus (__vector signed int a1, __vector signed int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vpkswus ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vpkshus */
-
-inline __vector unsigned char
-vec_vpkshus (__vector signed short a1, __vector signed short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vpkshus ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_perm */
-
-inline __vector float
-vec_perm (__vector float a1, __vector float a2, __vector unsigned char a3)
-{
- return (__vector float) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector signed int
-vec_perm (__vector signed int a1, __vector signed int a2, __vector unsigned char a3)
-{
- return (__vector signed int) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector unsigned int
-vec_perm (__vector unsigned int a1, __vector unsigned int a2, __vector unsigned char a3)
-{
- return (__vector unsigned int) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector __bool int
-vec_perm (__vector __bool int a1, __vector __bool int a2, __vector unsigned char a3)
-{
- return (__vector __bool int) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector signed short
-vec_perm (__vector signed short a1, __vector signed short a2, __vector unsigned char a3)
-{
- return (__vector signed short) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector unsigned short
-vec_perm (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned char a3)
-{
- return (__vector unsigned short) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector __bool short
-vec_perm (__vector __bool short a1, __vector __bool short a2, __vector unsigned char a3)
-{
- return (__vector __bool short) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector __pixel
-vec_perm (__vector __pixel a1, __vector __pixel a2, __vector unsigned char a3)
-{
- return (__vector __pixel) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector signed char
-vec_perm (__vector signed char a1, __vector signed char a2, __vector unsigned char a3)
-{
- return (__vector signed char) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector unsigned char
-vec_perm (__vector unsigned char a1, __vector unsigned char a2, __vector unsigned char a3)
-{
- return (__vector unsigned char) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-inline __vector __bool char
-vec_perm (__vector __bool char a1, __vector __bool char a2, __vector unsigned char a3)
-{
- return (__vector __bool char) __builtin_altivec_vperm_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed char) a3);
-}
-
-/* vec_re */
-
-inline __vector float
-vec_re (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrefp ((__vector float) a1);
-}
-
-/* vec_rl */
-
-inline __vector signed char
-vec_rl (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vrlb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_rl (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vrlb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_rl (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vrlh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_rl (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vrlh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_rl (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vrlw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_rl (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vrlw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vrlw */
-
-inline __vector signed int
-vec_vrlw (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vrlw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vrlw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vrlw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vrlh */
-
-inline __vector signed short
-vec_vrlh (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vrlh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vrlh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vrlh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vrlb */
-
-inline __vector signed char
-vec_vrlb (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vrlb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vrlb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vrlb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_round */
-
-inline __vector float
-vec_round (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrfin ((__vector float) a1);
-}
-
-/* vec_rsqrte */
-
-inline __vector float
-vec_rsqrte (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrsqrtefp ((__vector float) a1);
-}
-
-/* vec_sel */
-
-inline __vector float
-vec_sel (__vector float a1, __vector float a2, __vector __bool int a3)
-{
- return (__vector float) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector float
-vec_sel (__vector float a1, __vector float a2, __vector unsigned int a3)
-{
- return (__vector float) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed int
-vec_sel (__vector signed int a1, __vector signed int a2, __vector __bool int a3)
-{
- return (__vector signed int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed int
-vec_sel (__vector signed int a1, __vector signed int a2, __vector unsigned int a3)
-{
- return (__vector signed int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned int
-vec_sel (__vector unsigned int a1, __vector unsigned int a2, __vector __bool int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned int
-vec_sel (__vector unsigned int a1, __vector unsigned int a2, __vector unsigned int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool int
-vec_sel (__vector __bool int a1, __vector __bool int a2, __vector __bool int a3)
-{
- return (__vector __bool int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool int
-vec_sel (__vector __bool int a1, __vector __bool int a2, __vector unsigned int a3)
-{
- return (__vector __bool int) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed short
-vec_sel (__vector signed short a1, __vector signed short a2, __vector __bool short a3)
-{
- return (__vector signed short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed short
-vec_sel (__vector signed short a1, __vector signed short a2, __vector unsigned short a3)
-{
- return (__vector signed short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned short
-vec_sel (__vector unsigned short a1, __vector unsigned short a2, __vector __bool short a3)
-{
- return (__vector unsigned short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned short
-vec_sel (__vector unsigned short a1, __vector unsigned short a2, __vector unsigned short a3)
-{
- return (__vector unsigned short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool short
-vec_sel (__vector __bool short a1, __vector __bool short a2, __vector __bool short a3)
-{
- return (__vector __bool short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool short
-vec_sel (__vector __bool short a1, __vector __bool short a2, __vector unsigned short a3)
-{
- return (__vector __bool short) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed char
-vec_sel (__vector signed char a1, __vector signed char a2, __vector __bool char a3)
-{
- return (__vector signed char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector signed char
-vec_sel (__vector signed char a1, __vector signed char a2, __vector unsigned char a3)
-{
- return (__vector signed char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned char
-vec_sel (__vector unsigned char a1, __vector unsigned char a2, __vector __bool char a3)
-{
- return (__vector unsigned char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector unsigned char
-vec_sel (__vector unsigned char a1, __vector unsigned char a2, __vector unsigned char a3)
-{
- return (__vector unsigned char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool char
-vec_sel (__vector __bool char a1, __vector __bool char a2, __vector __bool char a3)
-{
- return (__vector __bool char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-inline __vector __bool char
-vec_sel (__vector __bool char a1, __vector __bool char a2, __vector unsigned char a3)
-{
- return (__vector __bool char) __builtin_altivec_vsel_4si ((__vector signed int) a1, (__vector signed int) a2, (__vector signed int) a3);
-}
-
-/* vec_sl */
-
-inline __vector signed char
-vec_sl (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vslb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sl (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vslb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_sl (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vslh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sl (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vslh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_sl (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vslw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sl (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vslw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vslw */
-
-inline __vector signed int
-vec_vslw (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vslw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vslw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vslw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vslh */
-
-inline __vector signed short
-vec_vslh (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vslh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vslh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vslh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vslb */
-
-inline __vector signed char
-vec_vslb (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vslb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vslb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vslb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_sld */
-
-inline __vector float
-vec_sld (__vector float a1, __vector float a2, const int a3)
-{
- return (__vector float) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector signed int
-vec_sld (__vector signed int a1, __vector signed int a2, const int a3)
-{
- return (__vector signed int) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector unsigned int
-vec_sld (__vector unsigned int a1, __vector unsigned int a2, const int a3)
-{
- return (__vector unsigned int) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector __bool int
-vec_sld (__vector __bool int a1, __vector __bool int a2, const int a3)
-{
- return (__vector __bool int) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector signed short
-vec_sld (__vector signed short a1, __vector signed short a2, const int a3)
-{
- return (__vector signed short) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector unsigned short
-vec_sld (__vector unsigned short a1, __vector unsigned short a2, const int a3)
-{
- return (__vector unsigned short) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector __bool short
-vec_sld (__vector __bool short a1, __vector __bool short a2, const int a3)
-{
- return (__vector __bool short) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector __pixel
-vec_sld (__vector __pixel a1, __vector __pixel a2, const int a3)
-{
- return (__vector __pixel) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector signed char
-vec_sld (__vector signed char a1, __vector signed char a2, const int a3)
-{
- return (__vector signed char) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector unsigned char
-vec_sld (__vector unsigned char a1, __vector unsigned char a2, const int a3)
-{
- return (__vector unsigned char) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-inline __vector __bool char
-vec_sld (__vector __bool char a1, __vector __bool char a2, const int a3)
-{
- return (__vector __bool char) __builtin_altivec_vsldoi_4si ((__vector signed int) a1, (__vector signed int) a2, a3);
-}
-
-/* vec_sll */
-
-inline __vector signed int
-vec_sll (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sll (__vector signed int a1, __vector unsigned short a2)
-{
- return (__vector signed int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sll (__vector signed int a1, __vector unsigned char a2)
-{
- return (__vector signed int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sll (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sll (__vector unsigned int a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sll (__vector unsigned int a1, __vector unsigned char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_sll (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_sll (__vector __bool int a1, __vector unsigned short a2)
-{
- return (__vector __bool int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_sll (__vector __bool int a1, __vector unsigned char a2)
-{
- return (__vector __bool int) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_sll (__vector signed short a1, __vector unsigned int a2)
-{
- return (__vector signed short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_sll (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_sll (__vector signed short a1, __vector unsigned char a2)
-{
- return (__vector signed short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_sll (__vector unsigned short a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_sll (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_sll (__vector unsigned short a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_sll (__vector __bool short a1, __vector unsigned int a2)
-{
- return (__vector __bool short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_sll (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_sll (__vector __bool short a1, __vector unsigned char a2)
-{
- return (__vector __bool short) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_sll (__vector __pixel a1, __vector unsigned int a2)
-{
- return (__vector __pixel) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_sll (__vector __pixel a1, __vector unsigned short a2)
-{
- return (__vector __pixel) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_sll (__vector __pixel a1, __vector unsigned char a2)
-{
- return (__vector __pixel) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_sll (__vector signed char a1, __vector unsigned int a2)
-{
- return (__vector signed char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_sll (__vector signed char a1, __vector unsigned short a2)
-{
- return (__vector signed char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_sll (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_sll (__vector unsigned char a1, __vector unsigned int a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_sll (__vector unsigned char a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_sll (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_sll (__vector __bool char a1, __vector unsigned int a2)
-{
- return (__vector __bool char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_sll (__vector __bool char a1, __vector unsigned short a2)
-{
- return (__vector __bool char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_sll (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vsl ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_slo */
-
-inline __vector float
-vec_slo (__vector float a1, __vector signed char a2)
-{
- return (__vector float) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_slo (__vector float a1, __vector unsigned char a2)
-{
- return (__vector float) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_slo (__vector signed int a1, __vector signed char a2)
-{
- return (__vector signed int) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_slo (__vector signed int a1, __vector unsigned char a2)
-{
- return (__vector signed int) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_slo (__vector unsigned int a1, __vector signed char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_slo (__vector unsigned int a1, __vector unsigned char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_slo (__vector signed short a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_slo (__vector signed short a1, __vector unsigned char a2)
-{
- return (__vector signed short) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_slo (__vector unsigned short a1, __vector signed char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_slo (__vector unsigned short a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_slo (__vector __pixel a1, __vector signed char a2)
-{
- return (__vector __pixel) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_slo (__vector __pixel a1, __vector unsigned char a2)
-{
- return (__vector __pixel) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_slo (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_slo (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_slo (__vector unsigned char a1, __vector signed char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_slo (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vslo ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_splat */
-
-inline __vector signed char
-vec_splat (__vector signed char a1, const int a2)
-{
- return (__vector signed char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-inline __vector unsigned char
-vec_splat (__vector unsigned char a1, const int a2)
-{
- return (__vector unsigned char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-inline __vector __bool char
-vec_splat (__vector __bool char a1, const int a2)
-{
- return (__vector __bool char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-inline __vector signed short
-vec_splat (__vector signed short a1, const int a2)
-{
- return (__vector signed short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector unsigned short
-vec_splat (__vector unsigned short a1, const int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector __bool short
-vec_splat (__vector __bool short a1, const int a2)
-{
- return (__vector __bool short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector __pixel
-vec_splat (__vector __pixel a1, const int a2)
-{
- return (__vector __pixel) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector float
-vec_splat (__vector float a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector signed int
-vec_splat (__vector signed int a1, const int a2)
-{
- return (__vector signed int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector unsigned int
-vec_splat (__vector unsigned int a1, const int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector __bool int
-vec_splat (__vector __bool int a1, const int a2)
-{
- return (__vector __bool int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-/* vec_vspltw */
-
-inline __vector float
-vec_vspltw (__vector float a1, const int a2)
-{
- return (__vector float) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector signed int
-vec_vspltw (__vector signed int a1, const int a2)
-{
- return (__vector signed int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector unsigned int
-vec_vspltw (__vector unsigned int a1, const int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-inline __vector __bool int
-vec_vspltw (__vector __bool int a1, const int a2)
-{
- return (__vector __bool int) __builtin_altivec_vspltw ((__vector signed int) a1, a2);
-}
-
-/* vec_vsplth */
-
-inline __vector __bool short
-vec_vsplth (__vector __bool short a1, const int a2)
-{
- return (__vector __bool short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector signed short
-vec_vsplth (__vector signed short a1, const int a2)
-{
- return (__vector signed short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector unsigned short
-vec_vsplth (__vector unsigned short a1, const int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-inline __vector __pixel
-vec_vsplth (__vector __pixel a1, const int a2)
-{
- return (__vector __pixel) __builtin_altivec_vsplth ((__vector signed short) a1, a2);
-}
-
-/* vec_vspltb */
-
-inline __vector signed char
-vec_vspltb (__vector signed char a1, const int a2)
-{
- return (__vector signed char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-inline __vector unsigned char
-vec_vspltb (__vector unsigned char a1, const int a2)
-{
- return (__vector unsigned char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-inline __vector __bool char
-vec_vspltb (__vector __bool char a1, const int a2)
-{
- return (__vector __bool char) __builtin_altivec_vspltb ((__vector signed char) a1, a2);
-}
-
-/* vec_splat_s8 */
-
-inline __vector signed char
-vec_splat_s8 (const int a1)
-{
- return (__vector signed char) __builtin_altivec_vspltisb (a1);
-}
-
-/* vec_splat_s16 */
-
-inline __vector signed short
-vec_splat_s16 (const int a1)
-{
- return (__vector signed short) __builtin_altivec_vspltish (a1);
-}
-
-/* vec_splat_s32 */
-
-inline __vector signed int
-vec_splat_s32 (const int a1)
-{
- return (__vector signed int) __builtin_altivec_vspltisw (a1);
-}
-
-/* vec_splat_u8 */
-
-inline __vector unsigned char
-vec_splat_u8 (const int a1)
-{
- return (__vector unsigned char) __builtin_altivec_vspltisb (a1);
-}
-
-/* vec_splat_u16 */
-
-inline __vector unsigned short
-vec_splat_u16 (const int a1)
-{
- return (__vector unsigned short) __builtin_altivec_vspltish (a1);
-}
-
-/* vec_splat_u32 */
-
-inline __vector unsigned int
-vec_splat_u32 (const int a1)
-{
- return (__vector unsigned int) __builtin_altivec_vspltisw (a1);
-}
-
-/* vec_sr */
-
-inline __vector signed char
-vec_sr (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsrb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sr (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsrb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_sr (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsrh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sr (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsrh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_sr (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsrw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sr (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsrw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsrw */
-
-inline __vector signed int
-vec_vsrw (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsrw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsrw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsrw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsrh */
-
-inline __vector signed short
-vec_vsrh (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsrh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsrh (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsrh ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vsrb */
-
-inline __vector signed char
-vec_vsrb (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsrb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsrb (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsrb ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_sra */
-
-inline __vector signed char
-vec_sra (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsrab ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sra (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsrab ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_sra (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsrah ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sra (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsrah ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_sra (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsraw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sra (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsraw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsraw */
-
-inline __vector signed int
-vec_vsraw (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsraw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsraw (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsraw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsrah */
-
-inline __vector signed short
-vec_vsrah (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsrah ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsrah (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsrah ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vsrab */
-
-inline __vector signed char
-vec_vsrab (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsrab ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsrab (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsrab ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_srl */
-
-inline __vector signed int
-vec_srl (__vector signed int a1, __vector unsigned int a2)
-{
- return (__vector signed int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_srl (__vector signed int a1, __vector unsigned short a2)
-{
- return (__vector signed int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_srl (__vector signed int a1, __vector unsigned char a2)
-{
- return (__vector signed int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_srl (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_srl (__vector unsigned int a1, __vector unsigned short a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_srl (__vector unsigned int a1, __vector unsigned char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_srl (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector __bool int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_srl (__vector __bool int a1, __vector unsigned short a2)
-{
- return (__vector __bool int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_srl (__vector __bool int a1, __vector unsigned char a2)
-{
- return (__vector __bool int) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_srl (__vector signed short a1, __vector unsigned int a2)
-{
- return (__vector signed short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_srl (__vector signed short a1, __vector unsigned short a2)
-{
- return (__vector signed short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_srl (__vector signed short a1, __vector unsigned char a2)
-{
- return (__vector signed short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_srl (__vector unsigned short a1, __vector unsigned int a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_srl (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_srl (__vector unsigned short a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_srl (__vector __bool short a1, __vector unsigned int a2)
-{
- return (__vector __bool short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_srl (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector __bool short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_srl (__vector __bool short a1, __vector unsigned char a2)
-{
- return (__vector __bool short) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_srl (__vector __pixel a1, __vector unsigned int a2)
-{
- return (__vector __pixel) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_srl (__vector __pixel a1, __vector unsigned short a2)
-{
- return (__vector __pixel) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_srl (__vector __pixel a1, __vector unsigned char a2)
-{
- return (__vector __pixel) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_srl (__vector signed char a1, __vector unsigned int a2)
-{
- return (__vector signed char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_srl (__vector signed char a1, __vector unsigned short a2)
-{
- return (__vector signed char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_srl (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_srl (__vector unsigned char a1, __vector unsigned int a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_srl (__vector unsigned char a1, __vector unsigned short a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_srl (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_srl (__vector __bool char a1, __vector unsigned int a2)
-{
- return (__vector __bool char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_srl (__vector __bool char a1, __vector unsigned short a2)
-{
- return (__vector __bool char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_srl (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector __bool char) __builtin_altivec_vsr ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_sro */
-
-inline __vector float
-vec_sro (__vector float a1, __vector signed char a2)
-{
- return (__vector float) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_sro (__vector float a1, __vector unsigned char a2)
-{
- return (__vector float) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sro (__vector signed int a1, __vector signed char a2)
-{
- return (__vector signed int) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sro (__vector signed int a1, __vector unsigned char a2)
-{
- return (__vector signed int) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sro (__vector unsigned int a1, __vector signed char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sro (__vector unsigned int a1, __vector unsigned char a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_sro (__vector signed short a1, __vector signed char a2)
-{
- return (__vector signed short) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_sro (__vector signed short a1, __vector unsigned char a2)
-{
- return (__vector signed short) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_sro (__vector unsigned short a1, __vector signed char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_sro (__vector unsigned short a1, __vector unsigned char a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_sro (__vector __pixel a1, __vector signed char a2)
-{
- return (__vector __pixel) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __pixel
-vec_sro (__vector __pixel a1, __vector unsigned char a2)
-{
- return (__vector __pixel) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_sro (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_sro (__vector signed char a1, __vector unsigned char a2)
-{
- return (__vector signed char) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_sro (__vector unsigned char a1, __vector signed char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_sro (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsro ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_st */
-
-inline void
-vec_st (__vector float a1, int a2, __vector float *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector float a1, int a2, float *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed int a1, int a2, __vector signed int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed int a1, int a2, int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned int a1, int a2, __vector unsigned int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool int a1, int a2, __vector __bool int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool int a1, int a2, int *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed short a1, int a2, __vector signed short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed short a1, int a2, short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned short a1, int a2, __vector unsigned short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool short a1, int a2, __vector __bool short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __pixel a1, int a2, __vector __pixel *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __pixel a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __pixel a1, int a2, short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool short a1, int a2, short *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed char a1, int a2, __vector signed char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector signed char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned char a1, int a2, __vector unsigned char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector unsigned char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool char a1, int a2, __vector __bool char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_st (__vector __bool char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-/* vec_ste */
-
-inline void
-vec_ste (__vector signed char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector unsigned char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector signed short a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector unsigned short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool short a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __pixel a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __pixel a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector float a1, int a2, float *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector signed int a1, int a2, int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector unsigned int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool int a1, int a2, int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_ste (__vector __bool int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-/* vec_stvewx */
-
-inline void
-vec_stvewx (__vector float a1, int a2, float *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvewx (__vector signed int a1, int a2, int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvewx (__vector unsigned int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvewx (__vector __bool int a1, int a2, int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvewx (__vector __bool int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvewx ((__vector signed int) a1, a2, (void *) a3);
-}
-
-/* vec_stvehx */
-
-inline void
-vec_stvehx (__vector signed short a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvehx (__vector unsigned short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvehx (__vector __bool short a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvehx (__vector __bool short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvehx (__vector __pixel a1, int a2, short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvehx (__vector __pixel a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvehx ((__vector signed short) a1, a2, (void *) a3);
-}
-
-/* vec_stvebx */
-
-inline void
-vec_stvebx (__vector signed char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvebx (__vector unsigned char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvebx (__vector __bool char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stvebx (__vector __bool char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvebx ((__vector signed char) a1, a2, (void *) a3);
-}
-
-/* vec_stl */
-
-inline void
-vec_stl (__vector float a1, int a2, __vector float *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector float a1, int a2, float *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed int a1, int a2, __vector signed int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed int a1, int a2, int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned int a1, int a2, __vector unsigned int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool int a1, int a2, __vector __bool int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool int a1, int a2, unsigned int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool int a1, int a2, int *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed short a1, int a2, __vector signed short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed short a1, int a2, short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned short a1, int a2, __vector unsigned short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool short a1, int a2, __vector __bool short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool short a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool short a1, int a2, short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __pixel a1, int a2, __vector __pixel *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __pixel a1, int a2, unsigned short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __pixel a1, int a2, short *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed char a1, int a2, __vector signed char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector signed char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned char a1, int a2, __vector unsigned char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector unsigned char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool char a1, int a2, __vector __bool char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool char a1, int a2, unsigned char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-inline void
-vec_stl (__vector __bool char a1, int a2, signed char *a3)
-{
- __builtin_altivec_stvxl ((__vector signed int) a1, a2, (void *) a3);
-}
-
-/* vec_sub */
-
-inline __vector signed char
-vec_sub (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_sub (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_sub (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sub (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sub (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_sub (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed short
-vec_sub (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_sub (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_sub (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sub (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sub (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_sub (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed int
-vec_sub (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sub (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sub (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sub (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sub (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_sub (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_sub (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vsubfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vsubfp */
-
-inline __vector float
-vec_vsubfp (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vsubfp ((__vector float) a1, (__vector float) a2);
-}
-
-/* vec_vsubuwm */
-
-inline __vector signed int
-vec_vsubuwm (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vsubuwm (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vsubuwm (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsubuwm (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsubuwm (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsubuwm (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsubuhm */
-
-inline __vector signed short
-vec_vsubuhm (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vsubuhm (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vsubuhm (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsubuhm (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsubuhm (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsubuhm (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vsububm */
-
-inline __vector signed char
-vec_vsububm (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vsububm (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vsububm (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsububm (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsububm (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsububm (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_subc */
-
-inline __vector unsigned int
-vec_subc (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubcuw ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_subs */
-
-inline __vector unsigned char
-vec_subs (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_subs (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_subs (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_subs (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_subs (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_subs (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned short
-vec_subs (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_subs (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_subs (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_subs (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_subs (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_subs (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned int
-vec_subs (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_subs (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_subs (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_subs (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_subs (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_subs (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsubsws */
-
-inline __vector signed int
-vec_vsubsws (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vsubsws (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_vsubsws (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsubuws */
-
-inline __vector unsigned int
-vec_vsubuws (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsubuws (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_vsubuws (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_vsubshs */
-
-inline __vector signed short
-vec_vsubshs (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vsubshs (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector signed short
-vec_vsubshs (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vsubuhs */
-
-inline __vector unsigned short
-vec_vsubuhs (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsubuhs (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline __vector unsigned short
-vec_vsubuhs (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) a1, (__vector signed short) a2);
-}
-
-/* vec_vsubsbs */
-
-inline __vector signed char
-vec_vsubsbs (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vsubsbs (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector signed char
-vec_vsubsbs (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_vsububs */
-
-inline __vector unsigned char
-vec_vsububs (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsububs (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline __vector unsigned char
-vec_vsububs (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) a1, (__vector signed char) a2);
-}
-
-/* vec_sum4s */
-
-inline __vector unsigned int
-vec_sum4s (__vector unsigned char a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsum4ubs ((__vector signed char) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sum4s (__vector signed char a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsum4sbs ((__vector signed char) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_sum4s (__vector signed short a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsum4shs ((__vector signed short) a1, (__vector signed int) a2);
-}
-
-/* vec_vsum4shs */
-
-inline __vector signed int
-vec_vsum4shs (__vector signed short a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsum4shs ((__vector signed short) a1, (__vector signed int) a2);
-}
-
-/* vec_vsum4sbs */
-
-inline __vector signed int
-vec_vsum4sbs (__vector signed char a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsum4sbs ((__vector signed char) a1, (__vector signed int) a2);
-}
-
-/* vec_vsum4ubs */
-
-inline __vector unsigned int
-vec_vsum4ubs (__vector unsigned char a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vsum4ubs ((__vector signed char) a1, (__vector signed int) a2);
-}
-
-/* vec_sum2s */
-
-inline __vector signed int
-vec_sum2s (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsum2sws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_sums */
-
-inline __vector signed int
-vec_sums (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vsumsws ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_trunc */
-
-inline __vector float
-vec_trunc (__vector float a1)
-{
- return (__vector float) __builtin_altivec_vrfiz ((__vector float) a1);
-}
-
-/* vec_unpackh */
-
-inline __vector signed short
-vec_unpackh (__vector signed char a1)
-{
- return (__vector signed short) __builtin_altivec_vupkhsb ((__vector signed char) a1);
-}
-
-inline __vector __bool short
-vec_unpackh (__vector __bool char a1)
-{
- return (__vector __bool short) __builtin_altivec_vupkhsb ((__vector signed char) a1);
-}
-
-inline __vector signed int
-vec_unpackh (__vector signed short a1)
-{
- return (__vector signed int) __builtin_altivec_vupkhsh ((__vector signed short) a1);
-}
-
-inline __vector __bool int
-vec_unpackh (__vector __bool short a1)
-{
- return (__vector __bool int) __builtin_altivec_vupkhsh ((__vector signed short) a1);
-}
-
-inline __vector unsigned int
-vec_unpackh (__vector __pixel a1)
-{
- return (__vector unsigned int) __builtin_altivec_vupkhpx ((__vector signed short) a1);
-}
-
-/* vec_vupkhsh */
-
-inline __vector __bool int
-vec_vupkhsh (__vector __bool short a1)
-{
- return (__vector __bool int) __builtin_altivec_vupkhsh ((__vector signed short) a1);
-}
-
-inline __vector signed int
-vec_vupkhsh (__vector signed short a1)
-{
- return (__vector signed int) __builtin_altivec_vupkhsh ((__vector signed short) a1);
-}
-
-/* vec_vupkhpx */
-
-inline __vector unsigned int
-vec_vupkhpx (__vector __pixel a1)
-{
- return (__vector unsigned int) __builtin_altivec_vupkhpx ((__vector signed short) a1);
-}
-
-/* vec_vupkhsb */
-
-inline __vector __bool short
-vec_vupkhsb (__vector __bool char a1)
-{
- return (__vector __bool short) __builtin_altivec_vupkhsb ((__vector signed char) a1);
-}
-
-inline __vector signed short
-vec_vupkhsb (__vector signed char a1)
-{
- return (__vector signed short) __builtin_altivec_vupkhsb ((__vector signed char) a1);
-}
-
-/* vec_unpackl */
-
-inline __vector signed short
-vec_unpackl (__vector signed char a1)
-{
- return (__vector signed short) __builtin_altivec_vupklsb ((__vector signed char) a1);
-}
-
-inline __vector __bool short
-vec_unpackl (__vector __bool char a1)
-{
- return (__vector __bool short) __builtin_altivec_vupklsb ((__vector signed char) a1);
-}
-
-inline __vector unsigned int
-vec_unpackl (__vector __pixel a1)
-{
- return (__vector unsigned int) __builtin_altivec_vupklpx ((__vector signed short) a1);
-}
-
-inline __vector signed int
-vec_unpackl (__vector signed short a1)
-{
- return (__vector signed int) __builtin_altivec_vupklsh ((__vector signed short) a1);
-}
-
-inline __vector __bool int
-vec_unpackl (__vector __bool short a1)
-{
- return (__vector __bool int) __builtin_altivec_vupklsh ((__vector signed short) a1);
-}
-
-/* vec_vupklpx */
-
-inline __vector unsigned int
-vec_vupklpx (__vector __pixel a1)
-{
- return (__vector unsigned int) __builtin_altivec_vupklpx ((__vector signed short) a1);
-}
-
-/* vec_upklsh */
-
-inline __vector __bool int
-vec_vupklsh (__vector __bool short a1)
-{
- return (__vector __bool int) __builtin_altivec_vupklsh ((__vector signed short) a1);
-}
-
-inline __vector signed int
-vec_vupklsh (__vector signed short a1)
-{
- return (__vector signed int) __builtin_altivec_vupklsh ((__vector signed short) a1);
-}
-
-/* vec_vupklsb */
-
-inline __vector __bool short
-vec_vupklsb (__vector __bool char a1)
-{
- return (__vector __bool short) __builtin_altivec_vupklsb ((__vector signed char) a1);
-}
-
-inline __vector signed short
-vec_vupklsb (__vector signed char a1)
-{
- return (__vector signed short) __builtin_altivec_vupklsb ((__vector signed char) a1);
-}
-
-/* vec_xor */
-
-inline __vector float
-vec_xor (__vector float a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_xor (__vector float a1, __vector __bool int a2)
-{
- return (__vector float) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector float
-vec_xor (__vector __bool int a1, __vector float a2)
-{
- return (__vector float) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool int
-vec_xor (__vector __bool int a1, __vector __bool int a2)
-{
- return (__vector __bool int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_xor (__vector __bool int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_xor (__vector signed int a1, __vector __bool int a2)
-{
- return (__vector signed int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed int
-vec_xor (__vector signed int a1, __vector signed int a2)
-{
- return (__vector signed int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_xor (__vector __bool int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_xor (__vector unsigned int a1, __vector __bool int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned int
-vec_xor (__vector unsigned int a1, __vector unsigned int a2)
-{
- return (__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool short
-vec_xor (__vector __bool short a1, __vector __bool short a2)
-{
- return (__vector __bool short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_xor (__vector __bool short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_xor (__vector signed short a1, __vector __bool short a2)
-{
- return (__vector signed short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed short
-vec_xor (__vector signed short a1, __vector signed short a2)
-{
- return (__vector signed short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_xor (__vector __bool short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_xor (__vector unsigned short a1, __vector __bool short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned short
-vec_xor (__vector unsigned short a1, __vector unsigned short a2)
-{
- return (__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_xor (__vector __bool char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector __bool char
-vec_xor (__vector __bool char a1, __vector __bool char a2)
-{
- return (__vector __bool char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_xor (__vector signed char a1, __vector __bool char a2)
-{
- return (__vector signed char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector signed char
-vec_xor (__vector signed char a1, __vector signed char a2)
-{
- return (__vector signed char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_xor (__vector __bool char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_xor (__vector unsigned char a1, __vector __bool char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline __vector unsigned char
-vec_xor (__vector unsigned char a1, __vector unsigned char a2)
-{
- return (__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) a1, (__vector signed int) a2);
-}
-
-/* vec_all_eq */
-
-inline int
-vec_all_eq (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, a1, a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_eq (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector __pixel a1, __vector __pixel a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_eq (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_eq (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_LT, a1, a2);
-}
-
-/* vec_all_ge */
-
-inline int
-vec_all_ge (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_ge (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_ge (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_ge (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_LT, a1, a2);
-}
-
-/* vec_all_gt */
-
-inline int
-vec_all_gt (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_gt (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_gt (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_gt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_LT, a1, a2);
-}
-
-/* vec_all_in */
-
-inline int
-vec_all_in (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpbfp_p (__CR6_EQ, a1, a2);
-}
-
-/* vec_all_le */
-
-inline int
-vec_all_le (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_le (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_le (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_le (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_LT, a2, a1);
-}
-
-/* vec_all_lt */
-
-inline int
-vec_all_lt (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_all_lt (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_all_lt (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_all_lt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_LT, a2, a1);
-}
-
-/* vec_all_nan */
-
-inline int
-vec_all_nan (__vector float a1)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_EQ, a1, a1);
-}
-
-/* vec_all_ne */
-
-inline int
-vec_all_ne (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_all_ne (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector __pixel a1, __vector __pixel a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_all_ne (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_all_ne (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_EQ, a1, a2);
-}
-
-/* vec_all_nge */
-
-inline int
-vec_all_nge (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_EQ, a1, a2);
-}
-
-/* vec_all_ngt */
-
-inline int
-vec_all_ngt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a1, a2);
-}
-
-/* vec_all_nle */
-
-inline int
-vec_all_nle (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_EQ, a2, a1);
-}
-
-/* vec_all_nlt */
-
-inline int
-vec_all_nlt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a2, a1);
-}
-
-/* vec_all_numeric */
-
-inline int
-vec_all_numeric (__vector float a1)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_LT, a1, a1);
-}
-
-/* vec_any_eq */
-
-inline int
-vec_any_eq (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_eq (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector __pixel a1, __vector __pixel a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_eq (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_eq (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, a1, a2);
-}
-
-/* vec_any_ge */
-
-inline int
-vec_any_ge (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_ge (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_ge (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_EQ_REV, a1, a2);
-}
-
-/* vec_any_gt */
-
-inline int
-vec_any_gt (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_gt (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_gt (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_gt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_EQ_REV, a1, a2);
-}
-
-/* vec_any_le */
-
-inline int
-vec_any_le (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_le (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_le (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_le (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_EQ_REV, a2, a1);
-}
-
-/* vec_any_lt */
-
-inline int
-vec_any_lt (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) a2, (__vector signed char) a1);
-}
-
-inline int
-vec_any_lt (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) a2, (__vector signed short) a1);
-}
-
-inline int
-vec_any_lt (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) a2, (__vector signed int) a1);
-}
-
-inline int
-vec_any_lt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_EQ_REV, a2, a1);
-}
-
-/* vec_any_nan */
-
-inline int
-vec_any_nan (__vector float a1)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, a1, a1);
-}
-
-/* vec_any_ne */
-
-inline int
-vec_any_ne (__vector signed char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector signed char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool char a1, __vector __bool char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool char a1, __vector unsigned char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool char a1, __vector signed char a2)
-{
- return __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) a1, (__vector signed char) a2);
-}
-
-inline int
-vec_any_ne (__vector signed short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector signed short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool short a1, __vector __bool short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool short a1, __vector unsigned short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool short a1, __vector signed short a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector __pixel a1, __vector __pixel a2)
-{
- return __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) a1, (__vector signed short) a2);
-}
-
-inline int
-vec_any_ne (__vector signed int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector signed int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector unsigned int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool int a1, __vector __bool int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool int a1, __vector unsigned int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector __bool int a1, __vector signed int a2)
-{
- return __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) a1, (__vector signed int) a2);
-}
-
-inline int
-vec_any_ne (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, a1, a2);
-}
-
-/* vec_any_nge */
-
-inline int
-vec_any_nge (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a1, a2);
-}
-
-/* vec_any_ngt */
-
-inline int
-vec_any_ngt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a1, a2);
-}
-
-/* vec_any_nle */
-
-inline int
-vec_any_nle (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a2, a1);
-}
-
-/* vec_any_nlt */
-
-inline int
-vec_any_nlt (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a2, a1);
-}
-
-/* vec_any_numeric */
-
-inline int
-vec_any_numeric (__vector float a1)
-{
- return __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, a1, a1);
-}
-
-/* vec_any_out */
-
-inline int
-vec_any_out (__vector float a1, __vector float a2)
-{
- return __builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, a1, a2);
-}
-
-} /* extern "C++" */
-
-#else /* not C++ */
-
-/* "... and so I think no man in a century will suffer as greatly as
- you will." */
-
-/* Helper macros. */
-
-#define __un_args_eq(xtype, x) \
- __builtin_types_compatible_p (xtype, typeof (x))
-
-#define __bin_args_eq(xtype, x, ytype, y) \
- (__builtin_types_compatible_p (xtype, typeof (x)) \
- && __builtin_types_compatible_p (ytype, typeof (y)))
-
-#define __tern_args_eq(xtype, x, ytype, y, ztype, z) \
- (__builtin_types_compatible_p (xtype, typeof (x)) \
- && __builtin_types_compatible_p (ytype, typeof (y)) \
- && __builtin_types_compatible_p (ztype, typeof (z)))
-
-#define __ch(x, y, z) __builtin_choose_expr (x, y, z)
-
-#define vec_step(t) \
- __ch (__builtin_types_compatible_p (typeof (t), __vector signed int), 4, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector unsigned int), 4, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector __bool int), 4, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector signed short), 8, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector unsigned short), 8, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector __bool short), 8, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector __pixel), 8, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector signed char), 16, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector unsigned char), 16, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector __bool char), 16, \
- __ch (__builtin_types_compatible_p (typeof (t), __vector float), 4, \
- __builtin_altivec_compiletime_error ("vec_step"))))))))))))
-
-#define vec_abs(a) \
- __ch (__un_args_eq (__vector signed char, (a)), \
- ((__vector signed char) __builtin_altivec_abs_v16qi ((__vector signed char) (a))), \
- __ch (__un_args_eq (__vector signed short, (a)), \
- ((__vector signed short) __builtin_altivec_abs_v8hi ((__vector signed short) (a))), \
- __ch (__un_args_eq (__vector signed int, (a)), \
- ((__vector signed int) __builtin_altivec_abs_v4si ((__vector signed int) (a))), \
- __ch (__un_args_eq (__vector float, (a)), \
- ((__vector float) __builtin_altivec_abs_v4sf ((__vector float) (a))), \
- __builtin_altivec_compiletime_error ("vec_abs")))))
-
-#define vec_abss(a) \
- __ch (__un_args_eq (__vector signed char, (a)), \
- ((__vector signed char) __builtin_altivec_abss_v16qi ((__vector signed char) (a))), \
- __ch (__un_args_eq (__vector signed short, (a)), \
- ((__vector signed short) __builtin_altivec_abss_v8hi ((__vector signed short) (a))), \
- __ch (__un_args_eq (__vector signed int, (a)), \
- ((__vector signed int) __builtin_altivec_abss_v4si ((__vector signed int) (a))), \
- __builtin_altivec_compiletime_error ("vec_abss"))))
-
-#define vec_vaddubm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddubm")))))))
-
-#define vec_vadduhm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vadduhm")))))))
-
-#define vec_vadduwm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vadduwm")))))))
-
-#define vec_vaddfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vaddfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddfp"))
-
-#define vec_add(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vaddfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_add"))))))))))))))))))))
-
-#define vec_addc(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vaddcuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_addc"))
-
-#define vec_adds(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_adds")))))))))))))))))))
-
-#define vec_vaddsws(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vaddsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddsws"))))
-
-#define vec_vadduws(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vadduws ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vadduws"))))
-
-#define vec_vaddshs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vaddshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddshs"))))
-
-#define vec_vadduhs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vadduhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vadduhs"))))
-
-#define vec_vaddsbs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vaddsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddsbs"))))
-
-#define vec_vaddubs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vaddubs ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vaddubs"))))
-
-#define vec_and(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector __bool int, (a2)), \
- ((__vector float) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vand ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_and")))))))))))))))))))))))))
-
-#define vec_andc(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector __bool int, (a2)), \
- ((__vector float) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vandc ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_andc")))))))))))))))))))))))))
-
-#define vec_avg(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vavgub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vavgsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vavguh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vavgsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vavguw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vavgsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_avg")))))))
-
-#define vec_vavgsw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vavgsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavgsw"))
-
-#define vec_vavguw(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vavguw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavguw"))
-
-#define vec_vavgsh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vavgsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavgsh"))
-
-#define vec_vavguh(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vavguh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavguh"))
-
-#define vec_vavgsb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vavgsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavgsb"))
-
-#define vec_vavgub(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vavgub ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vavgub"))
-
-#define vec_ceil(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrfip ((__vector float) (a1))), \
- __builtin_altivec_compiletime_error ("vec_ceil"))
-
-#define vec_cmpb(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector signed int) __builtin_altivec_vcmpbfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cmpb"))
-
-#define vec_cmpeq(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpeqfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cmpeq"))))))))
-
-#define vec_vcmpeqfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpeqfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpeqfp"))
-
-#define vec_vcmpequw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpequw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpequw")))
-
-#define vec_vcmpequh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpequh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpequh")))
-
-#define vec_vcmpequb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpequb ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpequb")))
-
-#define vec_cmpge(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgefp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cmpge"))
-
-#define vec_cmpgt(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cmpgt"))))))))
-
-#define vec_vcmpgtfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtfp"))
-
-#define vec_vcmpgtsw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtsw"))
-
-#define vec_vcmpgtuw(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtuw"))
-
-#define vec_vcmpgtsh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtsh"))
-
-#define vec_vcmpgtuh(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtuh"))
-
-#define vec_vcmpgtsb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtsb"))
-
-#define vec_vcmpgtub(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) (a1), (__vector signed char) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcmpgtub"))
-
-#define vec_cmple(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgefp ((__vector float) (a2), (__vector float) (a1))), \
- __builtin_altivec_compiletime_error ("vec_cmple"))
-
-#define vec_cmplt(a2, a1) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vcmpgtsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vcmpgtsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector __bool int) __builtin_altivec_vcmpgtfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cmplt"))))))))
-
-#define vec_ctf(a1, a2) \
-__ch (__un_args_eq (__vector unsigned int, (a1)), \
- ((__vector float) __builtin_altivec_vcfux ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed int, (a1)), \
- ((__vector float) __builtin_altivec_vcfsx ((__vector signed int) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_ctf")))
-
-#define vec_vcfsx(a1, a2) \
-__ch (__un_args_eq (__vector signed int, (a1)), \
- ((__vector float) __builtin_altivec_vcfsx ((__vector signed int) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcfsx"))
-
-#define vec_vcfux(a1, a2) \
-__ch (__un_args_eq (__vector unsigned int, (a1)), \
- ((__vector float) __builtin_altivec_vcfux ((__vector signed int) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_vcfux"))
-
-#define vec_cts(a1, a2) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector signed int) __builtin_altivec_vctsxs ((__vector float) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_cts"))
-
-#define vec_ctu(a1, a2) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vctuxs ((__vector float) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_ctu"))
-
-#define vec_dss(a1) __builtin_altivec_dss ((const int) (a1));
+/* Be very liberal in the pairs we accept. Mistakes such as passing
+ a `vector char' and `vector short' will be caught by the middle-end,
+ while any attempt to detect them here would produce hard to understand
+ error messages involving the implementation details of AltiVec. */
+#define __altivec_binary_pred(NAME, CALL) \
+template <class T, class U> \
+typename __altivec_bool_ret <vec_step (T)>::__ret \
+NAME (T a1, U a2) \
+{ \
+ return CALL; \
+}
+
+__altivec_binary_pred(vec_cmplt,
+ __builtin_vec_cmpgt (a2, a1))
+__altivec_binary_pred(vec_cmple,
+ __builtin_altivec_cmpge (a2, a1))
+
+__altivec_scalar_pred(vec_all_in,
+ __builtin_altivec_vcmpbfp_p (__CR6_EQ, a1, a2))
+__altivec_scalar_pred(vec_any_out,
+ __builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, a1, a2))
+
+__altivec_unary_pred(vec_all_nan,
+ __builtin_altivec_vcmpeqfp_p (__CR6_EQ, a1, a1))
+__altivec_unary_pred(vec_any_nan,
+ __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, a1, a1))
+
+__altivec_unary_pred(vec_all_numeric,
+ __builtin_altivec_vcmpeqfp_p (__CR6_LT, a1, a1))
+__altivec_unary_pred(vec_any_numeric,
+ __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, a1, a1))
+
+__altivec_scalar_pred(vec_all_eq,
+ __builtin_vec_vcmpeq_p (__CR6_LT, a1, a2))
+__altivec_scalar_pred(vec_all_ne,
+ __builtin_vec_vcmpeq_p (__CR6_EQ, a1, a2))
+__altivec_scalar_pred(vec_any_eq,
+ __builtin_vec_vcmpeq_p (__CR6_EQ_REV, a1, a2))
+__altivec_scalar_pred(vec_any_ne,
+ __builtin_vec_vcmpeq_p (__CR6_LT_REV, a1, a2))
+
+__altivec_scalar_pred(vec_all_gt,
+ __builtin_vec_vcmpgt_p (__CR6_LT, a1, a2))
+__altivec_scalar_pred(vec_all_lt,
+ __builtin_vec_vcmpgt_p (__CR6_LT, a2, a1))
+__altivec_scalar_pred(vec_any_gt,
+ __builtin_vec_vcmpgt_p (__CR6_EQ_REV, a1, a2))
+__altivec_scalar_pred(vec_any_lt,
+ __builtin_vec_vcmpgt_p (__CR6_EQ_REV, a2, a1))
+
+__altivec_scalar_pred(vec_all_ngt,
+ __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a1, a2))
+__altivec_scalar_pred(vec_all_nlt,
+ __builtin_altivec_vcmpgtfp_p (__CR6_EQ, a2, a1))
+__altivec_scalar_pred(vec_any_ngt,
+ __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a1, a2))
+__altivec_scalar_pred(vec_any_nlt,
+ __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, a2, a1))
+
+/* __builtin_vec_vcmpge_p is vcmpgefp for floating-point vector types,
+ while for integer types it is converted to __builtin_vec_vcmpgt_p,
+ with inverted args and condition code. */
+__altivec_scalar_pred(vec_all_le,
+ __builtin_vec_vcmpge_p (__CR6_LT, a2, a1))
+__altivec_scalar_pred(vec_all_ge,
+ __builtin_vec_vcmpge_p (__CR6_LT, a1, a2))
+__altivec_scalar_pred(vec_any_le,
+ __builtin_vec_vcmpge_p (__CR6_EQ_REV, a2, a1))
+__altivec_scalar_pred(vec_any_ge,
+ __builtin_vec_vcmpge_p (__CR6_EQ_REV, a1, a2))
+
+__altivec_scalar_pred(vec_all_nge,
+ __builtin_altivec_vcmpgefp_p (__CR6_EQ, a1, a2))
+__altivec_scalar_pred(vec_all_nle,
+ __builtin_altivec_vcmpgefp_p (__CR6_EQ, a2, a1))
+__altivec_scalar_pred(vec_any_nge,
+ __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a1, a2))
+__altivec_scalar_pred(vec_any_nle,
+ __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, a2, a1))
+
+#undef __altivec_scalar_pred
+#undef __altivec_unary_pred
+#undef __altivec_binary_pred
+#else
+#define vec_cmplt(a1, a2) __builtin_vec_cmpgt ((a2), (a1))
+#define vec_cmple(a1, a2) __builtin_altivec_vcmpgefp ((a2), (a1))
+
+#define vec_all_in(a1, a2) __builtin_altivec_vcmpbfp_p (__CR6_EQ, (a1), (a2))
+#define vec_any_out(a1, a2) __builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, (a1), (a2))
+
+#define vec_all_nan(a1) __builtin_altivec_vcmpeqfp_p (__CR6_EQ, (a1), (a1))
+#define vec_any_nan(a1) __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, (a1), (a1))
+
+#define vec_all_numeric(a1) __builtin_altivec_vcmpeqfp_p (__CR6_LT, (a1), (a1))
+#define vec_any_numeric(a1) __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, (a1), (a1))
+
+#define vec_all_eq(a1, a2) __builtin_vec_vcmpeq_p (__CR6_LT, (a1), (a2))
+#define vec_all_ne(a1, a2) __builtin_vec_vcmpeq_p (__CR6_EQ, (a1), (a2))
+#define vec_any_eq(a1, a2) __builtin_vec_vcmpeq_p (__CR6_EQ_REV, (a1), (a2))
+#define vec_any_ne(a1, a2) __builtin_vec_vcmpeq_p (__CR6_LT_REV, (a1), (a2))
+
+#define vec_all_gt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_LT, (a1), (a2))
+#define vec_all_lt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_LT, (a2), (a1))
+#define vec_any_gt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ_REV, (a1), (a2))
+#define vec_any_lt(a1, a2) __builtin_vec_vcmpgt_p (__CR6_EQ_REV, (a2), (a1))
+
+#define vec_all_ngt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a1), (a2))
+#define vec_all_nlt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a2), (a1))
+#define vec_any_ngt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a1), (a2))
+#define vec_any_nlt(a1, a2) __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a2), (a1))
+
+/* __builtin_vec_vcmpge_p is vcmpgefp for floating-point vector types,
+ while for integer types it is converted to __builtin_vec_vcmpgt_p,
+ with inverted args and condition code. */
+#define vec_all_le(a1, a2) __builtin_vec_vcmpge_p (__CR6_LT, (a2), (a1))
+#define vec_all_ge(a1, a2) __builtin_vec_vcmpge_p (__CR6_LT, (a1), (a2))
+#define vec_any_le(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ_REV, (a2), (a1))
+#define vec_any_ge(a1, a2) __builtin_vec_vcmpge_p (__CR6_EQ_REV, (a1), (a2))
+
+#define vec_all_nge(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a1), (a2))
+#define vec_all_nle(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a2), (a1))
+#define vec_any_nge(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a1), (a2))
+#define vec_any_nle(a1, a2) __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a2), (a1))
+#endif
+/* These do not accept vectors, so they do not have a __builtin_vec_*
+ counterpart. */
+#define vec_dss(x) __builtin_altivec_dss((x))
#define vec_dssall() __builtin_altivec_dssall ()
-
-#define vec_dst(a1, a2, a3) \
-__ch (__un_args_eq (const __vector unsigned char, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed char, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool char, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned short, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed short, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool short, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __pixel, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned int, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed int, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool int, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector float, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned char, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const signed char, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned short, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const short, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned int, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const int, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned long, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const long, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const float, *(a1)), \
- __builtin_altivec_dst ((void *) (a1), (a2), (a3)), \
- __builtin_altivec_compiletime_error ("vec_dst")))))))))))))))))))))
-
-#define vec_dstst(a1, a2, a3) \
-__ch (__un_args_eq (const __vector unsigned char, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed char, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool char, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned short, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed short, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool short, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __pixel, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned int, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed int, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool int, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector float, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned char, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const signed char, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned short, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const short, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned int, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const int, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned long, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const long, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const float, *(a1)), \
- __builtin_altivec_dstst ((void *) (a1), (a2), (a3)), \
- __builtin_altivec_compiletime_error ("vec_dstst")))))))))))))))))))))
-
-#define vec_dststt(a1, a2, a3) \
-__ch (__un_args_eq (const __vector unsigned char, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed char, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool char, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned short, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed short, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool short, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __pixel, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned int, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed int, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool int, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector float, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned char, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const signed char, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned short, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const short, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned int, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const int, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned long, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const long, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const float, *(a1)), \
- __builtin_altivec_dststt ((void *) (a1), (a2), (a3)), \
- __builtin_altivec_compiletime_error ("vec_dststt")))))))))))))))))))))
-
-#define vec_dstt(a1, a2, a3) \
-__ch (__un_args_eq (const __vector unsigned char, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed char, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool char, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned short, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed short, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool short, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __pixel, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector unsigned int, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector signed int, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector __bool int, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const __vector float, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned char, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const signed char, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned short, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const short, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned int, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const int, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const unsigned long, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const long, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
-__ch (__un_args_eq (const float, *(a1)), \
- __builtin_altivec_dstt ((void *) (a1), (a2), (a3)), \
- __builtin_altivec_compiletime_error ("vec_dstt")))))))))))))))))))))
-
-#define vec_expte(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vexptefp ((__vector float) (a1))), \
- __builtin_altivec_compiletime_error ("vec_expte"))
-
-#define vec_floor(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrfim ((__vector float) (a1))), \
- __builtin_altivec_compiletime_error ("vec_floor"))
-
-#define vec_ld(a, b) \
-__ch (__un_args_eq (const __vector unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool char, *(b)), \
- ((__vector __bool char) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector signed short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool short, *(b)), \
- ((__vector __bool short) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector __pixel, *(b)), \
- ((__vector __pixel) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const unsigned long, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector signed int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const long, *(b)), \
- ((__vector signed int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool int, *(b)), \
- ((__vector __bool int) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const __vector float, *(b)), \
- ((__vector float) __builtin_altivec_lvx ((a), (b))), \
-__ch (__un_args_eq (const float, *(b)), \
- ((__vector float) __builtin_altivec_lvx ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_ld")))))))))))))))))))))
-
-#define vec_lde(a, b) \
-__ch (__un_args_eq (const unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvebx ((a), (b))), \
-__ch (__un_args_eq (const signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvebx ((a), (b))), \
-__ch (__un_args_eq (const unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvehx ((a), (b))), \
-__ch (__un_args_eq (const short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvehx ((a), (b))), \
-__ch (__un_args_eq (const unsigned long, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (const long, *(b)), \
- ((__vector signed int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (const unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (const int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (const float, *(b)), \
- ((__vector float) __builtin_altivec_lvewx ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_lde"))))))))))
-
-#define vec_lvewx(a, b) \
-__ch (__un_args_eq (unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (signed int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (unsigned long, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (signed long, *(b)), \
- ((__vector signed int) __builtin_altivec_lvewx ((a), (b))), \
-__ch (__un_args_eq (float, *(b)), \
- ((__vector float) __builtin_altivec_lvewx ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_lvewx"))))))
-
-#define vec_lvehx(a, b) \
-__ch (__un_args_eq (unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvehx ((a), (b))), \
-__ch (__un_args_eq (signed short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvehx ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_lvehx")))
-
-#define vec_lvebx(a, b) \
-__ch (__un_args_eq (unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvebx ((a), (b))), \
-__ch (__un_args_eq (signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvebx ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_lvebx")))
-
-#define vec_ldl(a, b) \
-__ch (__un_args_eq (const __vector unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const unsigned char, *(b)), \
- ((__vector unsigned char) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const signed char, *(b)), \
- ((__vector signed char) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool char, *(b)), \
- ((__vector __bool char) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const unsigned short, *(b)), \
- ((__vector unsigned short) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector signed short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const short, *(b)), \
- ((__vector signed short) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool short, *(b)), \
- ((__vector __bool short) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector __pixel, *(b)), \
- ((__vector __pixel) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const unsigned int, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const unsigned long, *(b)), \
- ((__vector unsigned int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector signed int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const int, *(b)), \
- ((__vector signed int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const long, *(b)), \
- ((__vector signed int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector __bool int, *(b)), \
- ((__vector __bool int) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const __vector float, *(b)), \
- ((__vector float) __builtin_altivec_lvxl ((a), (b))), \
-__ch (__un_args_eq (const float, *(b)), \
- ((__vector float) __builtin_altivec_lvxl ((a), (b))), \
-__builtin_altivec_compiletime_error ("vec_ldl")))))))))))))))))))))
-
-#define vec_loge(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vlogefp ((__vector float) (a1))), \
- __builtin_altivec_compiletime_error ("vec_loge"))
-
-#define vec_lvsl(a1, a2) \
-__ch (__un_args_eq (const volatile unsigned char, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed char, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned short, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed short, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned int, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed int, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned long, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed long, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile float, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsl ((a1), (void *) (a2))), \
-__builtin_altivec_compiletime_error ("vec_lvsl"))))))))))
-
-#define vec_lvsr(a1, a2) \
-__ch (__un_args_eq (const volatile unsigned char, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed char, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned short, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed short, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned int, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed int, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile unsigned long, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile signed long, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__ch (__un_args_eq (const volatile float, *(a2)), \
- ((__vector unsigned char) __builtin_altivec_lvsr ((a1), (void *) (a2))), \
-__builtin_altivec_compiletime_error ("vec_lvsr"))))))))))
-
-#define vec_madd(a1, a2, a3) \
-__ch (__tern_args_eq (__vector float, (a1), __vector float, (a2), __vector float, (a3)), \
- ((__vector float) __builtin_altivec_vmaddfp ((a1), (a2), (a3))), \
-__builtin_altivec_compiletime_error ("vec_madd"))
-
-#define vec_madds(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed short, (a3)), \
- ((__vector signed short) __builtin_altivec_vmhaddshs ((a1), (a2), (a3))), \
-__builtin_altivec_compiletime_error ("vec_madds"))
-
-#define vec_max(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmaxfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_max"))))))))))))))))))))
-
-#define vec_vmaxfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmaxfp ((__vector float) (a1), (__vector float) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxfp"))
-
-#define vec_vmaxsw(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmaxsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxsw"))))
-
-#define vec_vmaxuw(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmaxuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxuw"))))
-
-#define vec_vmaxsh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmaxsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxsh"))))
-
-#define vec_vmaxuh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmaxuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxuh"))))
-
-#define vec_vmaxsb(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmaxsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxsb"))))
-
-#define vec_vmaxub(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmaxub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmaxub"))))
-
-#define vec_mergeh(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- ((__vector __pixel) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_mergeh"))))))))))))
-
-#define vec_vmrghw(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmrghw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrghw")))))
-
-#define vec_vmrghh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- ((__vector __pixel) __builtin_altivec_vmrghh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrghh")))))
-
-#define vec_vmrghb(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmrghb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrghb"))))
-
-#define vec_mergel(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- ((__vector __pixel) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_mergel"))))))))))))
-
-#define vec_vmrglw(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vmrglw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrglw")))))
-
-#define vec_vmrglh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- ((__vector __pixel) __builtin_altivec_vmrglh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrglh")))))
-
-#define vec_vmrglb(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vmrglb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmrglb"))))
-
-#define vec_mfvscr() (((__vector unsigned short) __builtin_altivec_mfvscr ()))
-
-#define vec_min(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vminfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_min"))))))))))))))))))))
-
-#define vec_vminfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vminfp ((__vector float) (a1), (__vector float) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminfp"))
-
-#define vec_vminsw(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vminsw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminsw"))))
-
-#define vec_vminuw(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vminuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminuw"))))
-
-#define vec_vminsh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vminsh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminsh"))))
-
-#define vec_vminuh(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vminuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminuh"))))
-
-#define vec_vminsb(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vminsb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_minsb"))))
-
-#define vec_vminub(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vminub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vminub"))))
-
-#define vec_mladd(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed short, (a3)), \
- ((__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed short) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector unsigned short, (a2), __vector unsigned short, (a3)), \
- ((__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed short) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector signed short, (a2), __vector signed short, (a3)), \
- ((__vector signed short) __builtin_altivec_vmladduhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed short) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned short, (a3)), \
- ((__vector unsigned short) __builtin_altivec_vmladduhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed short) (a3))), \
- __builtin_altivec_compiletime_error ("vec_mladd")))))
-
-#define vec_mradds(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed short, (a3)), \
- ((__vector signed short) __builtin_altivec_vmhraddshs ((a1), (a2), (a3))), \
-__builtin_altivec_compiletime_error ("vec_mradds"))
-
-#define vec_msum(a1, a2, a3) \
-__ch (__tern_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumubm ((__vector signed char) (a1), (__vector signed char) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed char, (a1), __vector unsigned char, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsummbm ((__vector signed char) (a1), (__vector signed char) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumuhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsumshm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
- __builtin_altivec_compiletime_error ("vec_msum")))))
-
-#define vec_vmsumshm(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsumshm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsumshm"))
-
-#define vec_vmsumuhm(a1, a2, a3) \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumuhm ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsumuhm"))
-
-#define vec_vmsummbm(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed char, (a1), __vector unsigned char, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsummbm ((__vector signed char) (a1), (__vector signed char) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsummbm"))
-
-#define vec_vmsumubm(a1, a2, a3) \
-__ch (__tern_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumubm ((__vector signed char) (a1), (__vector signed char) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsummbm"))
-
-#define vec_msums(a1, a2, a3) \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumuhs ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsumshs ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
- __builtin_altivec_compiletime_error ("vec_msums")))
-
-#define vec_vmsumshs(a1, a2, a3) \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector signed int, (a3)), \
- ((__vector signed int) __builtin_altivec_vmsumshs ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsumshs"))
-
-#define vec_vmsumuhs(a1, a2, a3) \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vmsumuhs ((__vector signed short) (a1), (__vector signed short) (a2), (__vector signed int) (a3))), \
-__builtin_altivec_compiletime_error ("vec_vmsumuhs"))
-
-#define vec_mtvscr(a1) \
-__ch (__un_args_eq (__vector signed int, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector unsigned int, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector __bool int, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector unsigned short, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector unsigned char, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- __builtin_altivec_mtvscr ((__vector signed int) (a1)), \
- __builtin_altivec_compiletime_error ("vec_mtvscr")))))))))))
-
-#define vec_mule(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmuleub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vmulesb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmuleuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed int) __builtin_altivec_vmulesh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_mule")))))
-
-#define vec_vmulesh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed int) __builtin_altivec_vmulesh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmulesh"))
-
-#define vec_vmuleuh(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmuleuh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmuleuh"))
-
-#define vec_vmulesb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vmulesb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmulesb"))
-
-#define vec_vmuleub(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmuleub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmuleub"))
-
-#define vec_mulo(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmuloub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vmulosb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmulouh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed int) __builtin_altivec_vmulosh ((__vector signed short) (a1), (__vector signed short) (a2))), \
- __builtin_altivec_compiletime_error ("vec_mulo")))))
-
-#define vec_vmulosh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed int) __builtin_altivec_vmulosh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmulosh"))
-
-#define vec_vmulouh(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vmulouh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmulouh"))
-
-#define vec_vmulosb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vmulosb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmulosb"))
-
-#define vec_vmuloub(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vmuloub ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vmuloub"))
-
-#define vec_nmsub(a1, a2, a3) \
-__ch (__tern_args_eq (__vector float, (a1), __vector float, (a2), __vector float, (a3)), \
- ((__vector float) __builtin_altivec_vnmsubfp ((__vector float) (a1), (__vector float) (a2), (__vector float) (a3))), \
- __builtin_altivec_compiletime_error ("vec_nmsub"))
-
-#define vec_nor(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vnor ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_nor")))))))))))
-
-#define vec_or(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector __bool int, (a2)), \
- ((__vector float) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vor ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_or")))))))))))))))))))))))))
-
-#define vec_pack(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_pack")))))))
-
-#define vec_vpkuwum(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkuwum ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkuwum"))))
-
-#define vec_vpkuhum(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkuhum ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkuhum"))))
-
-#define vec_packpx(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector __pixel) __builtin_altivec_vpkpx ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_packpx"))
-
-#define vec_packs(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed char) __builtin_altivec_vpkshss ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed short) __builtin_altivec_vpkswss ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_packs")))))
-
-#define vec_vpkswss(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed short) __builtin_altivec_vpkswss ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkswss"))
-
-#define vec_vpkuwus(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkuwus"))
-
-#define vec_vpkshss(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed char) __builtin_altivec_vpkshss ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkshss"))
-
-#define vec_vpkuhus(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkuhus"))
-
-#define vec_packsu(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkuhus ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkshus ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkuwus ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkswus ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_packsu")))))
-
-#define vec_vpkswus(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vpkswus ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkswus"))
-
-#define vec_vpkshus(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vpkshus ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vpkshus"))
-
-#define vec_perm(a1, a2, a3) \
-__ch (__tern_args_eq (__vector float, (a1), __vector float, (a2), __vector unsigned char, (a3)), \
- ((__vector float) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector signed int, (a1), __vector signed int, (a2), __vector unsigned char, (a3)), \
- ((__vector signed int) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2), __vector unsigned char, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector __bool int, (a1), __vector __bool int, (a2), __vector unsigned char, (a3)), \
- ((__vector __bool int) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector unsigned char, (a3)), \
- ((__vector signed short) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned char, (a3)), \
- ((__vector unsigned short) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector __bool short, (a1), __vector __bool short, (a2), __vector unsigned char, (a3)), \
- ((__vector __bool short) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector __pixel, (a1), __vector __pixel, (a2), __vector unsigned char, (a3)), \
- ((__vector __pixel) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector signed char, (a1), __vector signed char, (a2), __vector unsigned char, (a3)), \
- ((__vector signed char) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2), __vector unsigned char, (a3)), \
- ((__vector unsigned char) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
-__ch (__tern_args_eq (__vector __bool char, (a1), __vector __bool char, (a2), __vector unsigned char, (a3)), \
- ((__vector __bool char) __builtin_altivec_vperm_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed char) (a3))), \
- __builtin_altivec_compiletime_error ("vec_perm"))))))))))))
-
-#define vec_re(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrefp ((__vector float) (a1))), \
-__builtin_altivec_compiletime_error ("vec_re"))
-
-#define vec_rl(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vrlb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vrlb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vrlh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vrlh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vrlw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vrlw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_rl")))))))
-
-#define vec_vrlw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vrlw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vrlw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vrlw")))
-
-#define vec_vrlh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vrlh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vrlh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vrlh")))
-
-#define vec_vrlb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vrlb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vrlb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vrlb")))
-
-#define vec_round(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrfin ((__vector float) (a1))), \
-__builtin_altivec_compiletime_error ("vec_round"))
-
-#define vec_rsqrte(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrsqrtefp ((__vector float) (a1))), \
-__builtin_altivec_compiletime_error ("vec_rsqrte"))
-
-#define vec_sel(a1, a2, a3) \
-__ch (__tern_args_eq (__vector float, (a1), __vector float, (a2), __vector __bool int, (a3)), \
- ((__vector float) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector float, (a1), __vector float, (a2), __vector unsigned int, (a3)), \
- ((__vector float) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool int, (a1), __vector __bool int, (a2), __vector __bool int, (a3)), \
- ((__vector __bool int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool int, (a1), __vector __bool int, (a2), __vector unsigned int, (a3)), \
- ((__vector __bool int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed int, (a1), __vector signed int, (a2), __vector __bool int, (a3)), \
- ((__vector signed int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed int, (a1), __vector signed int, (a2), __vector unsigned int, (a3)), \
- ((__vector signed int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2), __vector __bool int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2), __vector unsigned int, (a3)), \
- ((__vector unsigned int) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool short, (a1), __vector __bool short, (a2), __vector __bool short, (a3)), \
- ((__vector __bool short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool short, (a1), __vector __bool short, (a2), __vector unsigned short, (a3)), \
- ((__vector __bool short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector __bool short, (a3)), \
- ((__vector signed short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed short, (a1), __vector signed short, (a2), __vector unsigned short, (a3)), \
- ((__vector signed short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector __bool short, (a3)), \
- ((__vector unsigned short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2), __vector unsigned short, (a3)), \
- ((__vector unsigned short) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool char, (a1), __vector __bool char, (a2), __vector __bool char, (a3)), \
- ((__vector __bool char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector __bool char, (a1), __vector __bool char, (a2), __vector unsigned char, (a3)), \
- ((__vector __bool char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed char, (a1), __vector signed char, (a2), __vector __bool char, (a3)), \
- ((__vector signed char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector signed char, (a1), __vector signed char, (a2), __vector unsigned char, (a3)), \
- ((__vector signed char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2), __vector __bool char, (a3)), \
- ((__vector unsigned char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
-__ch (__tern_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2), __vector unsigned char, (a3)), \
- ((__vector unsigned char) __builtin_altivec_vsel_4si ((__vector signed int) (a1), (__vector signed int) (a2), (__vector signed int) (a3))), \
- __builtin_altivec_compiletime_error ("vec_sel")))))))))))))))))))))
-
-#define vec_sl(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vslb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vslb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vslh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vslh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vslw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vslw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sl")))))))
-
-#define vec_vslw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vslw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vslw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vslw")))
-
-#define vec_vslh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vslh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vslh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vslh")))
-
-#define vec_vslb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vslb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vslb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vslb")))
-
-#define vec_sld(a1, a2, a3) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsldoi_4si ((__vector signed int) (a1), (__vector signed int) (a2), (const int) (a3))), \
- __builtin_altivec_compiletime_error ("vec_sld"))))))))))))
-
-#define vec_sll(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned short, (a2)), \
- ((__vector signed int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned char, (a2)), \
- ((__vector signed int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned int, (a2)), \
- ((__vector signed short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned char, (a2)), \
- ((__vector signed short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned int, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned short, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned int, (a2)), \
- ((__vector signed char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned short, (a2)), \
- ((__vector signed char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsl ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sll")))))))))))))))))))))))))))))))
-
-#define vec_slo(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector signed char, (a2)), \
- ((__vector float) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector unsigned char, (a2)), \
- ((__vector float) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed char, (a2)), \
- ((__vector signed int) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned char, (a2)), \
- ((__vector signed int) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector signed char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned char, (a2)), \
- ((__vector signed short) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector signed char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector signed char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector signed char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vslo ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_slo")))))))))))))))))
-
-#define vec_splat(a1, a2) \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned char, (a1)), \
- ((__vector unsigned char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned short, (a1)), \
- ((__vector unsigned short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector __pixel) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed int, (a1)), \
- ((__vector signed int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned int, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __bool int, (a1)), \
- ((__vector __bool int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_splat"))))))))))))
-
-#define vec_vspltw(a1, a2) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __bool int, (a1)), \
- ((__vector __bool int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed int, (a1)), \
- ((__vector signed int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned int, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vspltw ((__vector signed int) (a1), (const int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vspltw")))))
-
-#define vec_vsplth(a1, a2) \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned short, (a1)), \
- ((__vector unsigned short) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector __pixel) __builtin_altivec_vsplth ((__vector signed short) (a1), (const int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsplth")))))
-
-#define vec_vspltb(a1, a2) \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__ch (__un_args_eq (__vector unsigned char, (a1)), \
- ((__vector unsigned char) __builtin_altivec_vspltb ((__vector signed char) (a1), (const int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vspltb"))))
-
-#define vec_splat_s8(a1) ((__vector signed char) __builtin_altivec_vspltisb (a1))
-
-#define vec_splat_s16(a1) ((__vector signed short) __builtin_altivec_vspltish (a1))
-
-#define vec_splat_s32(a1) ((__vector signed int) __builtin_altivec_vspltisw (a1))
-
-#define vec_splat_u8(a1) ((__vector unsigned char) __builtin_altivec_vspltisb (a1))
-
-#define vec_splat_u16(a1) ((__vector unsigned short) __builtin_altivec_vspltish (a1))
-
-#define vec_splat_u32(a1) ((__vector unsigned int) __builtin_altivec_vspltisw (a1))
-
-#define vec_sr(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsrb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsrb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsrh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsrh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsrw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsrw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sr")))))))
-
-#define vec_vsrw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsrw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsrw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsrw")))
-
-#define vec_vsrh(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsrh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsrh ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsrh")))
-
-#define vec_vsrb(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsrb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsrb ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsrb")))
-
-#define vec_sra(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsrab ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsrab ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsrah ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsrah ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsraw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsraw ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sra")))))))
-
-#define vec_vsraw(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsraw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsraw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsraw")))
-
-#define vec_vsrah(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsrah ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsrah ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsrah")))
-
-#define vec_vsrab(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsrab ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsrab ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsrab")))
-
-#define vec_srl(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned short, (a2)), \
- ((__vector signed int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned char, (a2)), \
- ((__vector signed int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool int) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned int, (a2)), \
- ((__vector signed short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned char, (a2)), \
- ((__vector signed short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool short) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned int, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned short, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned int, (a2)), \
- ((__vector signed char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned short, (a2)), \
- ((__vector signed char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned int, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned short, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vsr ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_srl")))))))))))))))))))))))))))))))
-
-#define vec_sro(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector signed char, (a2)), \
- ((__vector float) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector unsigned char, (a2)), \
- ((__vector float) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed char, (a2)), \
- ((__vector signed int) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector unsigned char, (a2)), \
- ((__vector signed int) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector signed char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed char, (a2)), \
- ((__vector signed short) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector unsigned char, (a2)), \
- ((__vector signed short) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector signed char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector unsigned char, (a2)), \
- ((__vector __pixel) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector signed char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector unsigned char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector signed char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsro ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sro")))))))))))))))))
-
-#define vec_st(a1, a2, a3) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), unsigned char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed char, (a1), signed char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), unsigned char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), signed char, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed short, (a1), short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), short, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), unsigned int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed int, (a1), int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), unsigned int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), int, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector float, (a1), float, *(a3)), \
- __builtin_altivec_stvx ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__builtin_altivec_compiletime_error ("vec_st")))))))))))))))))))))))))))
-
-#define vec_stl(a1, a2, a3) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), unsigned char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed char, (a1), signed char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), unsigned char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), signed char, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed short, (a1), short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), unsigned short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), short, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), unsigned int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector signed int, (a1), int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), unsigned int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), int, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__ch (__bin_args_eq (__vector float, (a1), float, *(a3)), \
- __builtin_altivec_stvxl ((__vector signed int) (a1), (a2), (void *) (a3)), \
-__builtin_altivec_compiletime_error ("vec_stl")))))))))))))))))))))))))))
-
-#define vec_ste(a, b, c) \
-__ch (__bin_args_eq (__vector unsigned char, (a), unsigned char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector signed char, (a), signed char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool char, (a), unsigned char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool char, (a), signed char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector unsigned short, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector signed short, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool short, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool short, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __pixel, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __pixel, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector unsigned int, (a), unsigned int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector signed int, (a), int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool int, (a), unsigned int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector __bool int, (a), int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (void *) (c)), \
-__ch (__bin_args_eq (__vector float, (a), float, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (void *) (c)), \
- __builtin_altivec_compiletime_error ("vec_ste"))))))))))))))))
-
-#define vec_stvewx(a, b, c) \
-__ch (__bin_args_eq (__vector unsigned int, (a), unsigned int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector signed int, (a), int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool int, (a), unsigned int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool int, (a), int, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector float, (a), float, *(c)), \
- __builtin_altivec_stvewx ((__vector signed int) (a), (b), (c)), \
-__builtin_altivec_compiletime_error ("vec_stvewx"))))))
-
-#define vec_stvehx(a, b, c) \
-__ch (__bin_args_eq (__vector unsigned short, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector signed short, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool short, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool short, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __pixel, (a), unsigned short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __pixel, (a), short, *(c)), \
- __builtin_altivec_stvehx ((__vector signed short) (a), (b), (c)), \
-__builtin_altivec_compiletime_error ("vec_stvehx")))))))
-
-#define vec_stvebx(a, b, c) \
-__ch (__bin_args_eq (__vector unsigned char, (a), unsigned char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector signed char, (a), signed char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool char, (a), unsigned char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (c)), \
-__ch (__bin_args_eq (__vector __bool char, (a), signed char, *(c)), \
- __builtin_altivec_stvebx ((__vector signed char) (a), (b), (c)), \
-__builtin_altivec_compiletime_error ("vec_stvebx")))))
-
-#define vec_sub(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vsubfp ((__vector float) (a1), (__vector float) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sub"))))))))))))))))))))
-
-#define vec_vsubfp(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vsubfp ((__vector float) (a1), (__vector float) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubfp"))
-
-#define vec_vsubuwm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuwm ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubuwm")))))))
-
-#define vec_vsubuhm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhm ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubuhm")))))))
-
-#define vec_vsububm(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububm ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsububm")))))))
-
-#define vec_subc(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubcuw ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_subc"))
-
-#define vec_subs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_subs")))))))))))))))))))
-
-#define vec_vsubsws(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsubsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubsws"))))
-
-#define vec_vsubuws(a1, a2) \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsubuws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubuws"))))
-
-#define vec_vsubshs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vsubshs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubshs"))))
-
-#define vec_vsubuhs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vsubuhs ((__vector signed short) (a1), (__vector signed short) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubuhs"))))
-
-#define vec_vsubsbs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vsubsbs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsubsbs"))))
-
-#define vec_vsububs(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vsububs ((__vector signed char) (a1), (__vector signed char) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsububs"))))
-
-#define vec_sum4s(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsum4ubs ((__vector signed char) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsum4sbs ((__vector signed char) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsum4shs ((__vector signed short) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_sum4s"))))
-
-#define vec_vsum4shs(a1, a2) \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsum4shs ((__vector signed short) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsum4shs"))
-
-#define vec_vsum4sbs(a1, a2) \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsum4sbs ((__vector signed char) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsum4sbs"))
-
-#define vec_vsum4ubs(a1, a2) \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vsum4ubs ((__vector signed char) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_vsum4ubs"))
-
-#define vec_sum2s(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsum2sws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_sum2s"))
-
-#define vec_sums(a1, a2) \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vsumsws ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__builtin_altivec_compiletime_error ("vec_sums"))
-
-#define vec_trunc(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- ((__vector float) __builtin_altivec_vrfiz ((__vector float) (a1))), \
-__builtin_altivec_compiletime_error ("vec_trunc"))
-
-#define vec_unpackh(a1) \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed short) __builtin_altivec_vupkhsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool short) __builtin_altivec_vupkhsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vupkhpx ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed int) __builtin_altivec_vupkhsh ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool int) __builtin_altivec_vupkhsh ((__vector signed short) (a1))), \
- __builtin_altivec_compiletime_error ("vec_unpackh"))))))
-
-#define vec_vupkhsh(a1) \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool int) __builtin_altivec_vupkhsh ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed int) __builtin_altivec_vupkhsh ((__vector signed short) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupkhsh")))
-
-#define vec_vupkhpx(a1) \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vupkhpx ((__vector signed short) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupkhpx"))
-
-#define vec_vupkhsb(a1) \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool short) __builtin_altivec_vupkhsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed short) __builtin_altivec_vupkhsb ((__vector signed char) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupkhsb")))
-
-#define vec_unpackl(a1) \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed short) __builtin_altivec_vupklsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool short) __builtin_altivec_vupklsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vupklpx ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed int) __builtin_altivec_vupklsh ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool int) __builtin_altivec_vupklsh ((__vector signed short) (a1))), \
- __builtin_altivec_compiletime_error ("vec_unpackl"))))))
-
-#define vec_vupklsh(a1) \
-__ch (__un_args_eq (__vector __bool short, (a1)), \
- ((__vector __bool int) __builtin_altivec_vupklsh ((__vector signed short) (a1))), \
-__ch (__un_args_eq (__vector signed short, (a1)), \
- ((__vector signed int) __builtin_altivec_vupklsh ((__vector signed short) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupklsh")))
-
-#define vec_vupklpx(a1) \
-__ch (__un_args_eq (__vector __pixel, (a1)), \
- ((__vector unsigned int) __builtin_altivec_vupklpx ((__vector signed short) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupklpx"))
-
-#define vec_vupklsb(a1) \
-__ch (__un_args_eq (__vector __bool char, (a1)), \
- ((__vector __bool short) __builtin_altivec_vupklsb ((__vector signed char) (a1))), \
-__ch (__un_args_eq (__vector signed char, (a1)), \
- ((__vector signed short) __builtin_altivec_vupklsb ((__vector signed char) (a1))), \
-__builtin_altivec_compiletime_error ("vec_vupklsb")))
-
-#define vec_xor(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector float, (a1), __vector __bool int, (a2)), \
- ((__vector float) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector float, (a2)), \
- ((__vector float) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- ((__vector __bool int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- ((__vector signed int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- ((__vector signed int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- ((__vector unsigned int) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- ((__vector __bool short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- ((__vector signed short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- ((__vector signed short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- ((__vector unsigned short) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- ((__vector __bool char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- ((__vector signed char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- ((__vector signed char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- ((__vector unsigned char) __builtin_altivec_vxor ((__vector signed int) (a1), (__vector signed int) (a2))), \
- __builtin_altivec_compiletime_error ("vec_xor")))))))))))))))))))))))))
-
-/* Predicates. */
-
-#define vec_all_eq(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_LT, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_eq"))))))))))))))))))))))))
-
-#define vec_all_ge(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_LT, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_ge"))))))))))))))))))))
-
-#define vec_all_gt(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_LT, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_gt"))))))))))))))))))))
-
-#define vec_all_in(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpbfp_p (__CR6_EQ, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_in"))
-
-#define vec_all_le(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_LT, (__vector float) (a2), (__vector float) (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_le"))))))))))))))))))))
-
-#define vec_all_lt(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_LT, (__vector float) (a2), (__vector float) (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_lt"))))))))))))))))))))
-
-#define vec_all_nan(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ, (a1), (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_nan"))
-
-#define vec_all_ne(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_ne"))))))))))))))))))))))))
-
-#define vec_all_nge(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_nge"))
-
-#define vec_all_ngt(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_all_ngt"))
-
-#define vec_all_nle(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_EQ, (a2), (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_nle"))
-
-#define vec_all_nlt(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ, (a2), (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_nlt"))
-
-#define vec_all_numeric(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_LT, (a1), (a1)), \
- __builtin_altivec_compiletime_error ("vec_all_numeric"))
-
-#define vec_any_eq(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_eq"))))))))))))))))))))))))
-
-#define vec_any_ge(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_EQ_REV, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_ge"))))))))))))))))))))
-
-#define vec_any_gt(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ_REV, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_gt"))))))))))))))))))))
-
-#define vec_any_le(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_EQ_REV, (__vector float) (a2), (__vector float) (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_le"))))))))))))))))))))
-
-#define vec_any_lt(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpgtub_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpgtsb_p (__CR6_EQ_REV, (__vector signed char) (a2), (__vector signed char) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpgtuh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpgtsh_p (__CR6_EQ_REV, (__vector signed short) (a2), (__vector signed short) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpgtuw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpgtsw_p (__CR6_EQ_REV, (__vector signed int) (a2), (__vector signed int) (a1)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_EQ_REV, (__vector float) (a2), (__vector float) (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_lt"))))))))))))))))))))
-
-#define vec_any_nan(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, (a1), (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_nan"))
-
-#define vec_any_ne(a1, a2) \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector signed char, (a1), __vector signed char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector unsigned char, (a1), __vector unsigned char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool char, (a1), __vector __bool char, (a2)), \
- __builtin_altivec_vcmpequb_p (__CR6_LT_REV, (__vector signed char) (a1), (__vector signed char) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector signed short, (a1), __vector signed short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector unsigned short, (a1), __vector unsigned short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool short, (a1), __vector __bool short, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __pixel, (a1), __vector __pixel, (a2)), \
- __builtin_altivec_vcmpequh_p (__CR6_LT_REV, (__vector signed short) (a1), (__vector signed short) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector signed int, (a1), __vector signed int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector unsigned int, (a1), __vector unsigned int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector __bool int, (a1), __vector __bool int, (a2)), \
- __builtin_altivec_vcmpequw_p (__CR6_LT_REV, (__vector signed int) (a1), (__vector signed int) (a2)), \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_LT_REV, (__vector float) (a1), (__vector float) (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_ne"))))))))))))))))))))))))
-
-#define vec_any_nge(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_nge"))
-
-#define vec_any_ngt(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_ngt"))
-
-#define vec_any_nle(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgefp_p (__CR6_LT_REV, (a2), (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_nle"))
-
-#define vec_any_nlt(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpgtfp_p (__CR6_LT_REV, (a2), (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_nlt"))
-
-#define vec_any_numeric(a1) \
-__ch (__un_args_eq (__vector float, (a1)), \
- __builtin_altivec_vcmpeqfp_p (__CR6_EQ_REV, (a1), (a1)), \
- __builtin_altivec_compiletime_error ("vec_any_numeric"))
-
-#define vec_any_out(a1, a2) \
-__ch (__bin_args_eq (__vector float, (a1), __vector float, (a2)), \
- __builtin_altivec_vcmpbfp_p (__CR6_EQ_REV, (a1), (a2)), \
- __builtin_altivec_compiletime_error ("vec_any_out"))
-
-
-#endif /* __cplusplus */
+#define vec_mfvscr() ((__vector unsigned short) __builtin_altivec_mfvscr ())
+#define vec_splat_s8(x) __builtin_altivec_vspltisb ((x))
+#define vec_splat_s16(x) __builtin_altivec_vspltish ((x))
+#define vec_splat_s32(x) __builtin_altivec_vspltisw ((x))
+#define vec_splat_u8(x) ((__vector unsigned char) vec_splat_s8 ((x)))
+#define vec_splat_u16(x) ((__vector unsigned short) vec_splat_s16 ((x)))
+#define vec_splat_u32(x) ((__vector unsigned int) vec_splat_s32 ((x)))
+
+/* This also accepts a type for its parameter, so it is not enough
+ to #define vec_step to __builtin_vec_step. */
+#define vec_step(x) __builtin_vec_step (* (__typeof__ (x) *) 0)
#endif /* _ALTIVEC_H */
diff --git a/contrib/gcc/config/rs6000/altivec.md b/contrib/gcc/config/rs6000/altivec.md
index 505a573..e032685 100644
--- a/contrib/gcc/config/rs6000/altivec.md
+++ b/contrib/gcc/config/rs6000/altivec.md
@@ -1,5 +1,5 @@
;; AltiVec patterns.
-;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
;; This file is part of GCC.
@@ -16,100 +16,178 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_constants
- [(UNSPEC_VSPLTISW 141)
- (UNSPEC_VSPLTISH 140)
- (UNSPEC_VSPLTISB 139)
+ [(UNSPEC_VCMPBFP 50)
+ (UNSPEC_VCMPEQUB 51)
+ (UNSPEC_VCMPEQUH 52)
+ (UNSPEC_VCMPEQUW 53)
+ (UNSPEC_VCMPEQFP 54)
+ (UNSPEC_VCMPGEFP 55)
+ (UNSPEC_VCMPGTUB 56)
+ (UNSPEC_VCMPGTSB 57)
+ (UNSPEC_VCMPGTUH 58)
+ (UNSPEC_VCMPGTSH 59)
+ (UNSPEC_VCMPGTUW 60)
+ (UNSPEC_VCMPGTSW 61)
+ (UNSPEC_VCMPGTFP 62)
+ (UNSPEC_VMSUMU 65)
+ (UNSPEC_VMSUMM 66)
+ (UNSPEC_VMSUMSHM 68)
+ (UNSPEC_VMSUMUHS 69)
+ (UNSPEC_VMSUMSHS 70)
+ (UNSPEC_VMHADDSHS 71)
+ (UNSPEC_VMHRADDSHS 72)
+ (UNSPEC_VMLADDUHM 73)
+ (UNSPEC_VADDCUW 75)
+ (UNSPEC_VADDU 76)
+ (UNSPEC_VADDS 77)
+ (UNSPEC_VAVGU 80)
+ (UNSPEC_VAVGS 81)
+ (UNSPEC_VMULEUB 83)
+ (UNSPEC_VMULESB 84)
+ (UNSPEC_VMULEUH 85)
+ (UNSPEC_VMULESH 86)
+ (UNSPEC_VMULOUB 87)
+ (UNSPEC_VMULOSB 88)
+ (UNSPEC_VMULOUH 89)
+ (UNSPEC_VMULOSH 90)
+ (UNSPEC_VPKUHUM 93)
+ (UNSPEC_VPKUWUM 94)
+ (UNSPEC_VPKPX 95)
+ (UNSPEC_VPKSHSS 97)
+ (UNSPEC_VPKSWSS 99)
+ (UNSPEC_VPKUHUS 100)
+ (UNSPEC_VPKSHUS 101)
+ (UNSPEC_VPKUWUS 102)
+ (UNSPEC_VPKSWUS 103)
+ (UNSPEC_VRL 104)
+ (UNSPEC_VSL 107)
+ (UNSPEC_VSLV4SI 110)
+ (UNSPEC_VSLO 111)
+ (UNSPEC_VSR 118)
+ (UNSPEC_VSRO 119)
+ (UNSPEC_VSUBCUW 124)
+ (UNSPEC_VSUBU 125)
+ (UNSPEC_VSUBS 126)
+ (UNSPEC_VSUM4UBS 131)
+ (UNSPEC_VSUM4S 132)
+ (UNSPEC_VSUM2SWS 134)
+ (UNSPEC_VSUMSWS 135)
+ (UNSPEC_VPERM 144)
+ (UNSPEC_VRFIP 148)
+ (UNSPEC_VRFIN 149)
+ (UNSPEC_VRFIM 150)
+ (UNSPEC_VCFUX 151)
+ (UNSPEC_VCFSX 152)
+ (UNSPEC_VCTUXS 153)
+ (UNSPEC_VCTSXS 154)
+ (UNSPEC_VLOGEFP 155)
+ (UNSPEC_VEXPTEFP 156)
+ (UNSPEC_VRSQRTEFP 157)
+ (UNSPEC_VREFP 158)
+ (UNSPEC_VSEL4SI 159)
+ (UNSPEC_VSEL4SF 160)
+ (UNSPEC_VSEL8HI 161)
+ (UNSPEC_VSEL16QI 162)
+ (UNSPEC_VLSDOI 163)
+ (UNSPEC_VUPKHSB 167)
+ (UNSPEC_VUPKHPX 168)
+ (UNSPEC_VUPKHSH 169)
+ (UNSPEC_VUPKLSB 170)
+ (UNSPEC_VUPKLPX 171)
+ (UNSPEC_VUPKLSH 172)
+ (UNSPEC_PREDICATE 173)
+ (UNSPEC_DST 190)
+ (UNSPEC_DSTT 191)
+ (UNSPEC_DSTST 192)
+ (UNSPEC_DSTSTT 193)
+ (UNSPEC_LVSL 194)
+ (UNSPEC_LVSR 195)
+ (UNSPEC_LVE 196)
+ (UNSPEC_STVX 201)
+ (UNSPEC_STVXL 202)
+ (UNSPEC_STVE 203)
+ (UNSPEC_SET_VSCR 213)
+ (UNSPEC_GET_VRSAVE 214)
+ (UNSPEC_REALIGN_LOAD 215)
+ (UNSPEC_REDUC_PLUS 217)
+ (UNSPEC_VECSH 219)
+ (UNSPEC_VCOND_V4SI 301)
+ (UNSPEC_VCOND_V4SF 302)
+ (UNSPEC_VCOND_V8HI 303)
+ (UNSPEC_VCOND_V16QI 304)
+ (UNSPEC_VCONDU_V4SI 305)
+ (UNSPEC_VCONDU_V8HI 306)
+ (UNSPEC_VCONDU_V16QI 307)
])
-;; Generic LVX load instruction.
-(define_insn "altivec_lvx_4si"
- [(set (match_operand:V4SI 0 "altivec_register_operand" "=v")
- (match_operand:V4SI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx_8hi"
- [(set (match_operand:V8HI 0 "altivec_register_operand" "=v")
- (match_operand:V8HI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvx_16qi"
- [(set (match_operand:V16QI 0 "altivec_register_operand" "=v")
- (match_operand:V16QI 1 "memory_operand" "m"))]
- "TARGET_ALTIVEC"
- "lvx %0,%y1"
- [(set_attr "type" "vecload")])
+(define_constants
+ [(UNSPECV_SET_VRSAVE 30)
+ (UNSPECV_MTVSCR 186)
+ (UNSPECV_MFVSCR 187)
+ (UNSPECV_DSSALL 188)
+ (UNSPECV_DSS 189)
+ ])
+
+;; Vec int modes
+(define_mode_macro VI [V4SI V8HI V16QI])
+;; Short vec in modes
+(define_mode_macro VIshort [V8HI V16QI])
+;; Vec float modes
+(define_mode_macro VF [V4SF])
+;; Vec modes, pity mode macros are not composable
+(define_mode_macro V [V4SI V8HI V16QI V4SF])
+
+(define_mode_attr VI_char [(V4SI "w") (V8HI "h") (V16QI "b")])
-(define_insn "altivec_lvx_4sf"
- [(set (match_operand:V4SF 0 "altivec_register_operand" "=v")
- (match_operand:V4SF 1 "memory_operand" "m"))]
+;; Generic LVX load instruction.
+(define_insn "altivec_lvx_<mode>"
+ [(set (match_operand:V 0 "altivec_register_operand" "=v")
+ (match_operand:V 1 "memory_operand" "Z"))]
"TARGET_ALTIVEC"
"lvx %0,%y1"
[(set_attr "type" "vecload")])
;; Generic STVX store instruction.
-(define_insn "altivec_stvx_4si"
- [(set (match_operand:V4SI 0 "memory_operand" "=m")
- (match_operand:V4SI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_8hi"
- [(set (match_operand:V8HI 0 "memory_operand" "=m")
- (match_operand:V8HI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_16qi"
- [(set (match_operand:V16QI 0 "memory_operand" "=m")
- (match_operand:V16QI 1 "altivec_register_operand" "v"))]
- "TARGET_ALTIVEC"
- "stvx %1,%y0"
- [(set_attr "type" "vecstore")])
-
-(define_insn "altivec_stvx_4sf"
- [(set (match_operand:V4SF 0 "memory_operand" "=m")
- (match_operand:V4SF 1 "altivec_register_operand" "v"))]
+(define_insn "altivec_stvx_<mode>"
+ [(set (match_operand:V 0 "memory_operand" "=Z")
+ (match_operand:V 1 "altivec_register_operand" "v"))]
"TARGET_ALTIVEC"
"stvx %1,%y0"
[(set_attr "type" "vecstore")])
;; Vector move instructions.
-(define_expand "movv4si"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "")
- (match_operand:V4SI 1 "any_operand" ""))]
+(define_expand "mov<mode>"
+ [(set (match_operand:V 0 "nonimmediate_operand" "")
+ (match_operand:V 1 "any_operand" ""))]
"TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V4SImode); DONE; }")
+{
+ rs6000_emit_move (operands[0], operands[1], <MODE>mode);
+ DONE;
+})
-(define_insn "*movv4si_internal"
- [(set (match_operand:V4SI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
- (match_operand:V4SI 1 "input_operand" "v,m,v,r,o,r,W"))]
+(define_insn "*mov<mode>_internal"
+ [(set (match_operand:V 0 "nonimmediate_operand" "=Z,v,v,o,r,r,v")
+ (match_operand:V 1 "input_operand" "v,Z,v,r,o,r,W"))]
"TARGET_ALTIVEC
- && (register_operand (operands[0], V4SImode)
- || register_operand (operands[1], V4SImode))"
- "*
+ && (register_operand (operands[0], <MODE>mode)
+ || register_operand (operands[1], <MODE>mode))"
{
switch (which_alternative)
{
- case 0: return \"stvx %1,%y0\";
- case 1: return \"lvx %0,%y1\";
- case 2: return \"vor %0,%1,%1\";
- case 3: return \"#\";
- case 4: return \"#\";
- case 5: return \"#\";
+ case 0: return "stvx %1,%y0";
+ case 1: return "lvx %0,%y1";
+ case 2: return "vor %0,%1,%1";
+ case 3: return "#";
+ case 4: return "#";
+ case 5: return "#";
case 6: return output_vec_const_move (operands);
- default: abort();
+ default: gcc_unreachable ();
}
-}"
+}
[(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
(define_split
@@ -118,48 +196,9 @@
"TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-
-(define_split
- [(set (match_operand:V4SI 0 "altivec_register_operand" "")
- (match_operand:V4SI 1 "easy_vector_constant_add_self" ""))]
- "TARGET_ALTIVEC && reload_completed"
- [(set (match_dup 0) (match_dup 3))
- (set (match_dup 0)
- (plus:V4SI (match_dup 0)
- (match_dup 0)))]
- "
-{
- operands[3] = gen_easy_vector_constant_add_self (operands[1]);
-}")
-
-(define_expand "movv8hi"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "")
- (match_operand:V8HI 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V8HImode); DONE; }")
-
-(define_insn "*movv8hi_internal1"
- [(set (match_operand:V8HI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
- (match_operand:V8HI 1 "input_operand" "v,m,v,r,o,r,W"))]
- "TARGET_ALTIVEC
- && (register_operand (operands[0], V8HImode)
- || register_operand (operands[1], V8HImode))"
- "*
{
- switch (which_alternative)
- {
- case 0: return \"stvx %1,%y0\";
- case 1: return \"lvx %0,%y1\";
- case 2: return \"vor %0,%1,%1\";
- case 3: return \"#\";
- case 4: return \"#\";
- case 5: return \"#\";
- case 6: return output_vec_const_move (operands);
- default: abort ();
- }
-}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
+ rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+})
(define_split
[(set (match_operand:V8HI 0 "nonimmediate_operand" "")
@@ -170,47 +209,6 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
- [(set (match_operand:V8HI 0 "altivec_register_operand" "")
- (match_operand:V8HI 1 "easy_vector_constant_add_self" ""))]
- "TARGET_ALTIVEC && reload_completed"
- [(set (match_dup 0) (match_dup 3))
- (set (match_dup 0)
- (plus:V8HI (match_dup 0)
- (match_dup 0)))]
- "
-{
- operands[3] = gen_easy_vector_constant_add_self (operands[1]);
-}")
-
-(define_expand "movv16qi"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "")
- (match_operand:V16QI 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V16QImode); DONE; }")
-
-(define_insn "*movv16qi_internal1"
- [(set (match_operand:V16QI 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
- (match_operand:V16QI 1 "input_operand" "v,m,v,r,o,r,W"))]
- "TARGET_ALTIVEC
- && (register_operand (operands[0], V16QImode)
- || register_operand (operands[1], V16QImode))"
- "*
-{
- switch (which_alternative)
- {
- case 0: return \"stvx %1,%y0\";
- case 1: return \"lvx %0,%y1\";
- case 2: return \"vor %0,%1,%1\";
- case 3: return \"#\";
- case 4: return \"#\";
- case 5: return \"#\";
- case 6: return output_vec_const_move (operands);
- default: abort ();
- }
-}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
-
-(define_split
[(set (match_operand:V16QI 0 "nonimmediate_operand" "")
(match_operand:V16QI 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed
@@ -219,106 +217,91 @@
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
(define_split
- [(set (match_operand:V16QI 0 "altivec_register_operand" "")
- (match_operand:V16QI 1 "easy_vector_constant_add_self" ""))]
- "TARGET_ALTIVEC && reload_completed"
- [(set (match_dup 0) (match_dup 3))
- (set (match_dup 0)
- (plus:V16QI (match_dup 0)
- (match_dup 0)))]
- "
-{
- operands[3] = gen_easy_vector_constant_add_self (operands[1]);
-}")
-
-(define_expand "movv4sf"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "")
- (match_operand:V4SF 1 "any_operand" ""))]
- "TARGET_ALTIVEC"
- "{ rs6000_emit_move (operands[0], operands[1], V4SFmode); DONE; }")
-
-(define_insn "*movv4sf_internal1"
- [(set (match_operand:V4SF 0 "nonimmediate_operand" "=m,v,v,o,r,r,v")
- (match_operand:V4SF 1 "input_operand" "v,m,v,r,o,r,W"))]
- "TARGET_ALTIVEC
- && (register_operand (operands[0], V4SFmode)
- || register_operand (operands[1], V4SFmode))"
- "*
-{
- switch (which_alternative)
- {
- case 0: return \"stvx %1,%y0\";
- case 1: return \"lvx %0,%y1\";
- case 2: return \"vor %0,%1,%1\";
- case 3: return \"#\";
- case 4: return \"#\";
- case 5: return \"#\";
- case 6: return output_vec_const_move (operands);
- default: abort ();
- }
-}"
- [(set_attr "type" "vecstore,vecload,vecsimple,store,load,*,*")])
-
-(define_split
[(set (match_operand:V4SF 0 "nonimmediate_operand" "")
(match_operand:V4SF 1 "input_operand" ""))]
"TARGET_ALTIVEC && reload_completed
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
-{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
+{
+ rs6000_split_multireg_move (operands[0], operands[1]); DONE;
+})
+
+(define_split
+ [(set (match_operand:VI 0 "altivec_register_operand" "")
+ (match_operand:VI 1 "easy_vector_constant_add_self" ""))]
+ "TARGET_ALTIVEC && reload_completed"
+ [(set (match_dup 0) (match_dup 3))
+ (set (match_dup 0) (plus:VI (match_dup 0)
+ (match_dup 0)))]
+{
+ rtx dup = gen_easy_altivec_constant (operands[1]);
+ rtx const_vec;
+
+ /* Divide the operand of the resulting VEC_DUPLICATE, and use
+ simplify_rtx to make a CONST_VECTOR. */
+ XEXP (dup, 0) = simplify_const_binary_operation (ASHIFTRT, QImode,
+ XEXP (dup, 0), const1_rtx);
+ const_vec = simplify_rtx (dup);
+
+ if (GET_MODE (const_vec) == <MODE>mode)
+ operands[3] = const_vec;
+ else
+ operands[3] = gen_lowpart (<MODE>mode, const_vec);
+})
(define_insn "get_vrsave_internal"
[(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(reg:SI 109)] 214))]
+ (unspec:SI [(reg:SI 109)] UNSPEC_GET_VRSAVE))]
"TARGET_ALTIVEC"
- "*
{
if (TARGET_MACHO)
- return \"mfspr %0,256\";
+ return "mfspr %0,256";
else
- return \"mfvrsave %0\";
-}"
+ return "mfvrsave %0";
+}
[(set_attr "type" "*")])
(define_insn "*set_vrsave_internal"
[(match_parallel 0 "vrsave_operation"
[(set (reg:SI 109)
(unspec_volatile:SI [(match_operand:SI 1 "register_operand" "r")
- (reg:SI 109)] 30))])]
+ (reg:SI 109)] UNSPECV_SET_VRSAVE))])]
"TARGET_ALTIVEC"
- "*
{
if (TARGET_MACHO)
- return \"mtspr 256,%1\";
+ return "mtspr 256,%1";
else
- return \"mtvrsave %1\";
-}"
+ return "mtvrsave %1";
+}
[(set_attr "type" "*")])
-;; Simple binary operations.
+(define_insn "*save_world"
+ [(match_parallel 0 "save_world_operation"
+ [(clobber (match_operand:SI 1 "register_operand" "=l"))
+ (use (match_operand:SI 2 "call_operand" "s"))])]
+ "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
+ "bl %z2"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*restore_world"
+ [(match_parallel 0 "restore_world_operation"
+ [(return)
+ (use (match_operand:SI 1 "register_operand" "l"))
+ (use (match_operand:SI 2 "call_operand" "s"))
+ (clobber (match_operand:SI 3 "gpc_reg_operand" "=r"))])]
+ "TARGET_MACHO && (DEFAULT_ABI == ABI_DARWIN) && TARGET_32BIT"
+ "b %z2")
-(define_insn "addv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (plus:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vaddubm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+;; Simple binary operations.
-(define_insn "addv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (plus:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
+;; add
+(define_insn "add<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (plus:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vadduhm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "addv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (plus:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vadduwm %0,%1,%2"
+ "vaddu<VI_char>m %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "addv4sf3"
@@ -332,133 +315,102 @@
(define_insn "altivec_vaddcuw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 35))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VADDCUW))]
"TARGET_ALTIVEC"
"vaddcuw %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vaddubs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 36))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vaddubs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vaddsbs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 37))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+(define_insn "altivec_vaddu<VI_char>s"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VADDU))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
- "vaddsbs %0,%1,%2"
+ "vaddu<VI_char>s %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vadduhs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 38))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+(define_insn "altivec_vadds<VI_char>s"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VADDS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
- "vadduhs %0,%1,%2"
+ "vadds<VI_char>s %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vaddshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 39))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+;; sub
+(define_insn "sub<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (minus:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vaddshs %0,%1,%2"
+ "vsubu<VI_char>m %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vadduws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 40))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+(define_insn "subv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vadduws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+ "vsubfp %0,%1,%2"
+ [(set_attr "type" "vecfloat")])
-(define_insn "altivec_vaddsws"
+(define_insn "altivec_vsubcuw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 41))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vaddsws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "andv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vand %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vandc"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (and:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (not:V4SI (match_operand:V4SI 2 "register_operand" "v"))))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUBCUW))]
"TARGET_ALTIVEC"
- "vandc %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgub"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 44))]
- "TARGET_ALTIVEC"
- "vavgub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vavgsb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 45))]
- "TARGET_ALTIVEC"
- "vavgsb %0,%1,%2"
+ "vsubcuw %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vavguh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 46))]
+(define_insn "altivec_vsubu<VI_char>s"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VSUBU))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
- "vavguh %0,%1,%2"
+ "vsubu<VI_char>s %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vavgsh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 47))]
+(define_insn "altivec_vsubs<VI_char>s"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VSUBS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
- "vavgsh %0,%1,%2"
+ "vsubs<VI_char>s %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vavguw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 48))]
+;;
+(define_insn "altivec_vavgu<VI_char>"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VAVGU))]
"TARGET_ALTIVEC"
- "vavguw %0,%1,%2"
+ "vavgu<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vavgsw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 49))]
+(define_insn "altivec_vavgs<VI_char>"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VAVGS))]
"TARGET_ALTIVEC"
- "vavgsw %0,%1,%2"
+ "vavgs<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vcmpbfp"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 50))]
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_VCMPBFP))]
"TARGET_ALTIVEC"
"vcmpbfp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -466,7 +418,8 @@
(define_insn "altivec_vcmpequb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 51))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VCMPEQUB))]
"TARGET_ALTIVEC"
"vcmpequb %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -474,7 +427,8 @@
(define_insn "altivec_vcmpequh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 52))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VCMPEQUH))]
"TARGET_ALTIVEC"
"vcmpequh %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -482,7 +436,8 @@
(define_insn "altivec_vcmpequw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 53))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VCMPEQUW))]
"TARGET_ALTIVEC"
"vcmpequw %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -490,7 +445,8 @@
(define_insn "altivec_vcmpeqfp"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 54))]
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_VCMPEQFP))]
"TARGET_ALTIVEC"
"vcmpeqfp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -498,7 +454,8 @@
(define_insn "altivec_vcmpgefp"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 55))]
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_VCMPGEFP))]
"TARGET_ALTIVEC"
"vcmpgefp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -506,7 +463,8 @@
(define_insn "altivec_vcmpgtub"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 56))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTUB))]
"TARGET_ALTIVEC"
"vcmpgtub %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -514,7 +472,8 @@
(define_insn "altivec_vcmpgtsb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 57))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTSB))]
"TARGET_ALTIVEC"
"vcmpgtsb %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -522,7 +481,8 @@
(define_insn "altivec_vcmpgtuh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 58))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTUH))]
"TARGET_ALTIVEC"
"vcmpgtuh %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -530,7 +490,8 @@
(define_insn "altivec_vcmpgtsh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 59))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTSH))]
"TARGET_ALTIVEC"
"vcmpgtsh %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -538,7 +499,8 @@
(define_insn "altivec_vcmpgtuw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 60))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTUW))]
"TARGET_ALTIVEC"
"vcmpgtuw %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -546,7 +508,8 @@
(define_insn "altivec_vcmpgtsw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 61))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VCMPGTSW))]
"TARGET_ALTIVEC"
"vcmpgtsw %0,%1,%2"
[(set_attr "type" "vecsimple")])
@@ -554,7 +517,8 @@
(define_insn "altivec_vcmpgtfp"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 62))]
+ (match_operand:V4SF 2 "register_operand" "v")]
+ UNSPEC_VCMPGTFP))]
"TARGET_ALTIVEC"
"vcmpgtfp %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -581,16 +545,75 @@
rtx neg0;
/* Generate [-0.0, -0.0, -0.0, -0.0]. */
- neg0 = gen_reg_rtx (V4SFmode);
- emit_insn (gen_altivec_vspltisw_v4sf (neg0, GEN_INT (-1)));
- emit_insn (gen_altivec_vslw_v4sf (neg0, neg0, neg0));
+ neg0 = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
+ emit_insn (gen_altivec_vslw (neg0, neg0, neg0));
/* Use the multiply-add. */
emit_insn (gen_altivec_vmaddfp (operands[0], operands[1], operands[2],
- neg0));
+ gen_lowpart (V4SFmode, neg0)));
DONE;
}")
+;; 32 bit integer multiplication
+;; A_high = Operand_0 & 0xFFFF0000 >> 16
+;; A_low = Operand_0 & 0xFFFF
+;; B_high = Operand_1 & 0xFFFF0000 >> 16
+;; B_low = Operand_1 & 0xFFFF
+;; result = A_low * B_low + (A_high * B_low + B_high * A_low) << 16
+
+;; (define_insn "mulv4si3"
+;; [(set (match_operand:V4SI 0 "register_operand" "=v")
+;; (mult:V4SI (match_operand:V4SI 1 "register_operand" "v")
+;; (match_operand:V4SI 2 "register_operand" "v")))]
+(define_expand "mulv4si3"
+ [(use (match_operand:V4SI 0 "register_operand" ""))
+ (use (match_operand:V4SI 1 "register_operand" ""))
+ (use (match_operand:V4SI 2 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+ "
+ {
+ rtx zero;
+ rtx swap;
+ rtx small_swap;
+ rtx sixteen;
+ rtx one;
+ rtx two;
+ rtx low_product;
+ rtx high_product;
+
+ zero = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltisw (zero, const0_rtx));
+
+ sixteen = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltisw (sixteen, gen_rtx_CONST_INT (V4SImode, -16)));
+
+ swap = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vrlw (swap, operands[2], sixteen));
+
+ one = gen_reg_rtx (V8HImode);
+ convert_move (one, operands[1], 0);
+
+ two = gen_reg_rtx (V8HImode);
+ convert_move (two, operands[2], 0);
+
+ small_swap = gen_reg_rtx (V8HImode);
+ convert_move (small_swap, swap, 0);
+
+ low_product = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vmulouh (low_product, one, two));
+
+ high_product = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vmsumuhm (high_product, one, small_swap, zero));
+
+ emit_insn (gen_altivec_vslw (high_product, high_product, sixteen));
+
+ emit_insn (gen_addv4si3 (operands[0], high_product, low_product));
+
+ DONE;
+ }")
+
+
;; Fused multiply subtract
(define_insn "altivec_vnmsubfp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
@@ -601,39 +624,32 @@
"vnmsubfp %0,%1,%2,%3"
[(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vmsumubm"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 65))]
- "TARGET_ALTIVEC"
- "vmsumubm %0,%1,%2,%3"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vmsummbm"
+(define_insn "altivec_vmsumu<VI_char>m"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 66))]
+ (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
+ (match_operand:VIshort 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VMSUMU))]
"TARGET_ALTIVEC"
- "vmsummbm %0,%1,%2,%3"
+ "vmsumu<VI_char>m %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
-(define_insn "altivec_vmsumuhm"
+(define_insn "altivec_vmsumm<VI_char>m"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 67))]
+ (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
+ (match_operand:VIshort 2 "register_operand" "v")
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VMSUMM))]
"TARGET_ALTIVEC"
- "vmsumuhm %0,%1,%2,%3"
+ "vmsumm<VI_char>m %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vmsumshm"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 68))]
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VMSUMSHM))]
"TARGET_ALTIVEC"
"vmsumshm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
@@ -642,8 +658,9 @@
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 69))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VMSUMUHS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmsumuhs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
@@ -652,91 +669,91 @@
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 70))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VMSUMSHS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmsumshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
-(define_insn "umaxv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (umax:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vmaxub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+;; max
-(define_insn "smaxv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (smax:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
+(define_insn "umax<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (umax:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxsb %0,%1,%2"
+ "vmaxu<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "umaxv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (umax:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
+(define_insn "smax<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (smax:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxuh %0,%1,%2"
+ "vmaxs<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "smaxv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (smax:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
+(define_insn "smaxv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
+ "vmaxfp %0,%1,%2"
+ [(set_attr "type" "veccmp")])
-(define_insn "umaxv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (umax:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
+(define_insn "umin<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (umin:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxuw %0,%1,%2"
+ "vminu<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "smaxv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (smax:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
+(define_insn "smin<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (smin:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxsw %0,%1,%2"
+ "vmins<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "smaxv4sf3"
+(define_insn "sminv4sf3"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (smax:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vmaxfp %0,%1,%2"
+ "vminfp %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "altivec_vmhaddshs"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 71))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V8HI 3 "register_operand" "v")]
+ UNSPEC_VMHADDSHS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmhaddshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
+
(define_insn "altivec_vmhraddshs"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 72))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V8HI 3 "register_operand" "v")]
+ UNSPEC_VMHRADDSHS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vmhraddshs %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
+
(define_insn "altivec_vmladduhm"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 73))]
+ (match_operand:V8HI 3 "register_operand" "v")]
+ UNSPEC_VMLADDUHM))]
"TARGET_ALTIVEC"
"vmladduhm %0,%1,%2,%3"
[(set_attr "type" "veccomplex")])
@@ -744,24 +761,40 @@
(define_insn "altivec_vmrghb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (parallel [(const_int 8)
+ (parallel [(const_int 0)
+ (const_int 8)
+ (const_int 1)
(const_int 9)
+ (const_int 2)
(const_int 10)
- (const_int 11)
+ (const_int 3)
+ (const_int 11)
+ (const_int 4)
(const_int 12)
+ (const_int 5)
(const_int 13)
- (const_int 14)
- (const_int 15)
+ (const_int 6)
+ (const_int 14)
+ (const_int 7)
+ (const_int 15)]))
+ (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
+ (parallel [(const_int 8)
(const_int 0)
+ (const_int 9)
(const_int 1)
+ (const_int 10)
(const_int 2)
- (const_int 3)
+ (const_int 11)
+ (const_int 3)
+ (const_int 12)
(const_int 4)
+ (const_int 13)
(const_int 5)
+ (const_int 14)
(const_int 6)
+ (const_int 15)
(const_int 7)]))
- (match_operand:V16QI 2 "register_operand" "v")
- (const_int 255)))]
+ (const_int 21845)))]
"TARGET_ALTIVEC"
"vmrghb %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -769,16 +802,24 @@
(define_insn "altivec_vmrghh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (parallel [(const_int 4)
+ (parallel [(const_int 0)
+ (const_int 4)
+ (const_int 1)
(const_int 5)
+ (const_int 2)
(const_int 6)
- (const_int 7)
+ (const_int 3)
+ (const_int 7)]))
+ (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
+ (parallel [(const_int 4)
(const_int 0)
+ (const_int 5)
(const_int 1)
+ (const_int 6)
(const_int 2)
+ (const_int 7)
(const_int 3)]))
- (match_operand:V8HI 2 "register_operand" "v")
- (const_int 15)))]
+ (const_int 85)))]
"TARGET_ALTIVEC"
"vmrghh %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -786,131 +827,108 @@
(define_insn "altivec_vmrghw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (parallel [(const_int 0)
+ (const_int 2)
+ (const_int 1)
+ (const_int 3)]))
+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
(parallel [(const_int 2)
- (const_int 3)
- (const_int 0)
+ (const_int 0)
+ (const_int 3)
(const_int 1)]))
- (match_operand:V4SI 2 "register_operand" "v")
- (const_int 12)))]
+ (const_int 5)))]
"TARGET_ALTIVEC"
"vmrghw %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
- (parallel [(const_int 0)
+ (vec_merge:V16QI (vec_select:V16QI (match_operand:V16QI 1 "register_operand" "v")
+ (parallel [(const_int 8)
+ (const_int 0)
+ (const_int 9)
(const_int 1)
+ (const_int 10)
(const_int 2)
- (const_int 3)
+ (const_int 11)
+ (const_int 3)
+ (const_int 12)
(const_int 4)
+ (const_int 13)
(const_int 5)
- (const_int 6)
- (const_int 7)
+ (const_int 14)
+ (const_int 6)
+ (const_int 15)
+ (const_int 7)]))
+ (vec_select:V16QI (match_operand:V16QI 2 "register_operand" "v")
+ (parallel [(const_int 0)
(const_int 8)
+ (const_int 1)
(const_int 9)
+ (const_int 2)
(const_int 10)
- (const_int 11)
+ (const_int 3)
+ (const_int 11)
+ (const_int 4)
(const_int 12)
+ (const_int 5)
(const_int 13)
+ (const_int 6)
(const_int 14)
+ (const_int 7)
(const_int 15)]))
- (match_operand:V16QI 1 "register_operand" "v")
- (const_int 255)))]
+ (const_int 21845)))]
"TARGET_ALTIVEC"
"vmrglb %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglh"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
- (parallel [(const_int 0)
+ (vec_merge:V8HI (vec_select:V8HI (match_operand:V8HI 1 "register_operand" "v")
+ (parallel [(const_int 4)
+ (const_int 0)
+ (const_int 5)
(const_int 1)
+ (const_int 6)
(const_int 2)
- (const_int 3)
+ (const_int 7)
+ (const_int 3)]))
+ (vec_select:V8HI (match_operand:V8HI 2 "register_operand" "v")
+ (parallel [(const_int 0)
(const_int 4)
+ (const_int 1)
(const_int 5)
+ (const_int 2)
(const_int 6)
+ (const_int 3)
(const_int 7)]))
- (match_operand:V8HI 1 "register_operand" "v")
- (const_int 15)))]
+ (const_int 85)))]
"TARGET_ALTIVEC"
"vmrglh %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vmrglw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (vec_merge:V4SI (vec_select:V4SI (match_operand:V4SI 1 "register_operand" "v")
+ (parallel [(const_int 2)
+ (const_int 0)
+ (const_int 3)
+ (const_int 1)]))
+ (vec_select:V4SI (match_operand:V4SI 2 "register_operand" "v")
(parallel [(const_int 0)
- (const_int 1)
- (const_int 2)
+ (const_int 2)
+ (const_int 1)
(const_int 3)]))
- (match_operand:V4SI 1 "register_operand" "v")
- (const_int 12)))]
+ (const_int 5)))]
"TARGET_ALTIVEC"
"vmrglw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "uminv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (umin:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminub %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (smin:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "uminv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (umin:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminuh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (smin:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "uminv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (umin:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (smin:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminsw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "sminv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (smin:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vminfp %0,%1,%2"
- [(set_attr "type" "veccmp")])
-
(define_insn "altivec_vmuleub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 83))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMULEUB))]
"TARGET_ALTIVEC"
"vmuleub %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -918,7 +936,8 @@
(define_insn "altivec_vmulesb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 84))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMULESB))]
"TARGET_ALTIVEC"
"vmulesb %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -926,7 +945,8 @@
(define_insn "altivec_vmuleuh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 85))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULEUH))]
"TARGET_ALTIVEC"
"vmuleuh %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -934,7 +954,8 @@
(define_insn "altivec_vmulesh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 86))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULESH))]
"TARGET_ALTIVEC"
"vmulesh %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -942,7 +963,8 @@
(define_insn "altivec_vmuloub"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 87))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMULOUB))]
"TARGET_ALTIVEC"
"vmuloub %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -950,7 +972,8 @@
(define_insn "altivec_vmulosb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 88))]
+ (match_operand:V16QI 2 "register_operand" "v")]
+ UNSPEC_VMULOSB))]
"TARGET_ALTIVEC"
"vmulosb %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -958,7 +981,8 @@
(define_insn "altivec_vmulouh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 89))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULOUH))]
"TARGET_ALTIVEC"
"vmulouh %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -966,31 +990,83 @@
(define_insn "altivec_vmulosh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 90))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMULOSH))]
"TARGET_ALTIVEC"
"vmulosh %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "altivec_vnor"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (not:V4SI (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v"))))]
+
+;; logical ops
+
+(define_insn "and<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (and:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
- "vnor %0,%1,%2"
+ "vand %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "iorv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (ior:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
+(define_insn "ior<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (ior:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
"TARGET_ALTIVEC"
"vor %0,%1,%2"
[(set_attr "type" "vecsimple")])
+(define_insn "xor<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (xor:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "xorv4sf3"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (xor:V4SF (match_operand:V4SF 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vxor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (not:VI (match_operand:VI 1 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vnor %0,%1,%1"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "altivec_nor<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (not:VI (ior:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v"))))]
+ "TARGET_ALTIVEC"
+ "vnor %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "andc<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (and:VI (not:VI (match_operand:VI 2 "register_operand" "v"))
+ (match_operand:VI 1 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
+(define_insn "*andc3_v4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (and:V4SF (not:V4SF (match_operand:V4SF 2 "register_operand" "v"))
+ (match_operand:V4SF 1 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+ "vandc %0,%1,%2"
+ [(set_attr "type" "vecsimple")])
+
(define_insn "altivec_vpkuhum"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 93))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VPKUHUM))]
"TARGET_ALTIVEC"
"vpkuhum %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -998,7 +1074,8 @@
(define_insn "altivec_vpkuwum"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 94))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VPKUWUM))]
"TARGET_ALTIVEC"
"vpkuwum %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1006,43 +1083,28 @@
(define_insn "altivec_vpkpx"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 95))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VPKPX))]
"TARGET_ALTIVEC"
"vpkpx %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vpkuhss"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 96))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vpkuhss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
(define_insn "altivec_vpkshss"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 97))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VPKSHSS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkshss %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vpkuwss"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 98))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vpkuwss %0,%1,%2"
- [(set_attr "type" "vecperm")])
-
(define_insn "altivec_vpkswss"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 99))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VPKSWSS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkswss %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1050,8 +1112,9 @@
(define_insn "altivec_vpkuhus"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 100))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VPKUHUS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkuhus %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1059,8 +1122,9 @@
(define_insn "altivec_vpkshus"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 101))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VPKSHUS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkshus %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1068,8 +1132,9 @@
(define_insn "altivec_vpkuwus"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 102))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VPKUWUS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkuwus %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1077,72 +1142,36 @@
(define_insn "altivec_vpkswus"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 103))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VPKSWUS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vpkswus %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vrlb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 104))]
- "TARGET_ALTIVEC"
- "vrlb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vrlh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 105))]
- "TARGET_ALTIVEC"
- "vrlh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vrlw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 106))]
- "TARGET_ALTIVEC"
- "vrlw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 107))]
+(define_insn "altivec_vrl<VI_char>"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VRL))]
"TARGET_ALTIVEC"
- "vslb %0,%1,%2"
+ "vrl<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vslh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 108))]
+(define_insn "altivec_vsl<VI_char>"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (unspec:VI [(match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v")]
+ UNSPEC_VSL))]
"TARGET_ALTIVEC"
- "vslh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 109))]
- "TARGET_ALTIVEC"
- "vslw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vslw_v4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")] 109))]
- "TARGET_ALTIVEC"
- "vslw %0,%1,%2"
+ "vsl<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsl"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 110))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSLV4SI))]
"TARGET_ALTIVEC"
"vsl %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1150,63 +1179,33 @@
(define_insn "altivec_vslo"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 111))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSLO))]
"TARGET_ALTIVEC"
"vslo %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsrb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 112))]
- "TARGET_ALTIVEC"
- "vsrb %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrh"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 113))]
- "TARGET_ALTIVEC"
- "vsrh %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 114))]
+(define_insn "lshr<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (lshiftrt:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v") ))]
"TARGET_ALTIVEC"
- "vsrw %0,%1,%2"
+ "vsr<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
-(define_insn "altivec_vsrab"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 115))]
+(define_insn "ashr<mode>3"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (ashiftrt:VI (match_operand:VI 1 "register_operand" "v")
+ (match_operand:VI 2 "register_operand" "v") ))]
"TARGET_ALTIVEC"
- "vsrab %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsrah"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 116))]
- "TARGET_ALTIVEC"
- "vsrah %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsraw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 117))]
- "TARGET_ALTIVEC"
- "vsraw %0,%1,%2"
+ "vsra<VI_char> %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_vsr"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 118))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSR))]
"TARGET_ALTIVEC"
"vsr %0,%1,%2"
[(set_attr "type" "vecperm")])
@@ -1214,137 +1213,38 @@
(define_insn "altivec_vsro"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 119))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSRO))]
"TARGET_ALTIVEC"
"vsro %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "subv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (minus:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsububm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (minus:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubuhm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (minus:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubuwm %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "subv4sf3"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (minus:V4SF (match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vsubfp %0,%1,%2"
- [(set_attr "type" "vecfloat")])
-
-(define_insn "altivec_vsubcuw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 124))]
- "TARGET_ALTIVEC"
- "vsubcuw %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsububs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 125))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsububs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubsbs"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")] 126))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsubsbs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubuhs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 127))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsubuhs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubshs"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")] 128))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsubshs %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubuws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 129))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsubuws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "altivec_vsubsws"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 130))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsubsws %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
(define_insn "altivec_vsum4ubs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 131))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUM4UBS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsum4ubs %0,%1,%2"
[(set_attr "type" "veccomplex")])
-(define_insn "altivec_vsum4sbs"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 132))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
- "TARGET_ALTIVEC"
- "vsum4sbs %0,%1,%2"
- [(set_attr "type" "veccomplex")])
-
-(define_insn "altivec_vsum4shs"
+(define_insn "altivec_vsum4s<VI_char>s"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 133))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUM4S))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
- "vsum4shs %0,%1,%2"
+ "vsum4s<VI_char>s %0,%1,%2"
[(set_attr "type" "veccomplex")])
(define_insn "altivec_vsum2sws"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 134))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUM2SWS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsum2sws %0,%1,%2"
[(set_attr "type" "veccomplex")])
@@ -1352,91 +1252,59 @@
(define_insn "altivec_vsumsws"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")] 135))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUMSWS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vsumsws %0,%1,%2"
[(set_attr "type" "veccomplex")])
-;; Vector xor's
-(define_insn "xorv4si3"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (xor:V4SI (match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "xorv8hi3"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (xor:V8HI (match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
-(define_insn "xorv16qi3"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (xor:V16QI (match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")))]
- "TARGET_ALTIVEC"
- "vxor %0,%1,%2"
- [(set_attr "type" "vecsimple")])
-
(define_insn "altivec_vspltb"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 136))]
+ (vec_duplicate:V16QI
+ (vec_select:QI (match_operand:V16QI 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
"TARGET_ALTIVEC"
"vspltb %0,%1,%2"
[(set_attr "type" "vecperm")])
-;; End of vector xor's
(define_insn "altivec_vsplth"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 137))]
+ (vec_duplicate:V8HI
+ (vec_select:HI (match_operand:V8HI 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "")]))))]
"TARGET_ALTIVEC"
"vsplth %0,%1,%2"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vspltw"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 138))]
+ (vec_duplicate:V4SI
+ (vec_select:SI (match_operand:V4SI 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
"TARGET_ALTIVEC"
"vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vspltisb"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:QI 1 "immediate_operand" "i")]
- UNSPEC_VSPLTISB))]
- "TARGET_ALTIVEC"
- "vspltisb %0,%1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vspltish"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:QI 1 "immediate_operand" "i")]
- UNSPEC_VSPLTISH))]
- "TARGET_ALTIVEC"
- "vspltish %0,%1"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vspltisw"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:QI 1 "immediate_operand" "i")]
- UNSPEC_VSPLTISW))]
+(define_insn "*altivec_vspltsf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (vec_duplicate:V4SF
+ (vec_select:SF (match_operand:V4SF 1 "register_operand" "v")
+ (parallel
+ [(match_operand:QI 2 "u5bit_cint_operand" "i")]))))]
"TARGET_ALTIVEC"
- "vspltisw %0,%1"
+ "vspltw %0,%1,%2"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vspltisw_v4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:QI 1 "immediate_operand" "i")] 142))]
+(define_insn "altivec_vspltis<VI_char>"
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (vec_duplicate:VI
+ (match_operand:QI 1 "s5bit_cint_operand" "i")))]
"TARGET_ALTIVEC"
- "vspltisw %0,%1"
+ "vspltis<VI_char> %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "ftruncv4sf2"
@@ -1446,59 +1314,36 @@
"vrfiz %0,%1"
[(set_attr "type" "vecfloat")])
-(define_insn "altivec_vperm_4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 144))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 145))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 146))]
- "TARGET_ALTIVEC"
- "vperm %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vperm_16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 147))]
+(define_insn "altivec_vperm_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+ (match_operand:V 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VPERM))]
"TARGET_ALTIVEC"
"vperm %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vrfip"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 148))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VRFIP))]
"TARGET_ALTIVEC"
"vrfip %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrfin"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 149))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VRFIN))]
"TARGET_ALTIVEC"
"vrfin %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrfim"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 150))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VRFIM))]
"TARGET_ALTIVEC"
"vrfim %0,%1"
[(set_attr "type" "vecfloat")])
@@ -1506,7 +1351,8 @@
(define_insn "altivec_vcfux"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 151))]
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_VCFUX))]
"TARGET_ALTIVEC"
"vcfux %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -1514,7 +1360,8 @@
(define_insn "altivec_vcfsx"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 152))]
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_VCFSX))]
"TARGET_ALTIVEC"
"vcfsx %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -1522,8 +1369,9 @@
(define_insn "altivec_vctuxs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 153))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_VCTUXS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vctuxs %0,%1,%2"
[(set_attr "type" "vecfloat")])
@@ -1531,150 +1379,273 @@
(define_insn "altivec_vctsxs"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:QI 2 "immediate_operand" "i")] 154))
- (set (reg:SI 110) (unspec:SI [(const_int 0)] 213))]
+ (match_operand:QI 2 "immediate_operand" "i")]
+ UNSPEC_VCTSXS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
"TARGET_ALTIVEC"
"vctsxs %0,%1,%2"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vlogefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 155))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VLOGEFP))]
"TARGET_ALTIVEC"
"vlogefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vexptefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 156))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VEXPTEFP))]
"TARGET_ALTIVEC"
"vexptefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrsqrtefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 157))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VRSQRTEFP))]
"TARGET_ALTIVEC"
"vrsqrtefp %0,%1"
[(set_attr "type" "vecfloat")])
(define_insn "altivec_vrefp"
[(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")] 158))]
+ (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")]
+ UNSPEC_VREFP))]
"TARGET_ALTIVEC"
"vrefp %0,%1"
[(set_attr "type" "vecfloat")])
-(define_insn "altivec_vsel_4si"
+(define_expand "vcondv4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "comparison_operator" "")
+ (match_operand:V4SI 4 "register_operand" "v")
+ (match_operand:V4SI 5 "register_operand" "v")
+ ] UNSPEC_VCOND_V4SI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vconduv4si"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")
+ (match_operand:V4SI 3 "comparison_operator" "")
+ (match_operand:V4SI 4 "register_operand" "v")
+ (match_operand:V4SI 5 "register_operand" "v")
+ ] UNSPEC_VCONDU_V4SI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vcondv4sf"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V4SF [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SF 2 "register_operand" "v")
+ (match_operand:V4SF 3 "comparison_operator" "")
+ (match_operand:V4SF 4 "register_operand" "v")
+ (match_operand:V4SF 5 "register_operand" "v")
+ ] UNSPEC_VCOND_V4SF))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vcondv8hi"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "comparison_operator" "")
+ (match_operand:V8HI 4 "register_operand" "v")
+ (match_operand:V8HI 5 "register_operand" "v")
+ ] UNSPEC_VCOND_V8HI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vconduv8hi"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V8HI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")
+ (match_operand:V8HI 3 "comparison_operator" "")
+ (match_operand:V8HI 4 "register_operand" "v")
+ (match_operand:V8HI 5 "register_operand" "v")
+ ] UNSPEC_VCONDU_V8HI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vcondv16qi"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "comparison_operator" "")
+ (match_operand:V16QI 4 "register_operand" "v")
+ (match_operand:V16QI 5 "register_operand" "v")
+ ] UNSPEC_VCOND_V16QI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+(define_expand "vconduv16qi"
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (unspec:V16QI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V16QI 2 "register_operand" "v")
+ (match_operand:V16QI 3 "comparison_operator" "")
+ (match_operand:V16QI 4 "register_operand" "v")
+ (match_operand:V16QI 5 "register_operand" "v")
+ ] UNSPEC_VCONDU_V16QI))]
+ "TARGET_ALTIVEC"
+ "
+{
+ if (rs6000_emit_vector_cond_expr (operands[0], operands[1], operands[2],
+ operands[3], operands[4], operands[5]))
+ DONE;
+ else
+ FAIL;
+}
+ ")
+
+
+(define_insn "altivec_vsel_v4si"
[(set (match_operand:V4SI 0 "register_operand" "=v")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
(match_operand:V4SI 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 159))]
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VSEL4SI))]
"TARGET_ALTIVEC"
"vsel %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsel_4sf"
+(define_insn "altivec_vsel_v4sf"
[(set (match_operand:V4SF 0 "register_operand" "=v")
(unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
(match_operand:V4SF 2 "register_operand" "v")
- (match_operand:V4SI 3 "register_operand" "v")] 160))]
+ (match_operand:V4SI 3 "register_operand" "v")]
+ UNSPEC_VSEL4SF))]
"TARGET_ALTIVEC"
"vsel %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsel_8hi"
+(define_insn "altivec_vsel_v8hi"
[(set (match_operand:V8HI 0 "register_operand" "=v")
(unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
(match_operand:V8HI 2 "register_operand" "v")
- (match_operand:V8HI 3 "register_operand" "v")] 161))]
+ (match_operand:V8HI 3 "register_operand" "v")]
+ UNSPEC_VSEL8HI))]
"TARGET_ALTIVEC"
"vsel %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsel_16qi"
+(define_insn "altivec_vsel_v16qi"
[(set (match_operand:V16QI 0 "register_operand" "=v")
(unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
(match_operand:V16QI 2 "register_operand" "v")
- (match_operand:V16QI 3 "register_operand" "v")] 162))]
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_VSEL16QI))]
"TARGET_ALTIVEC"
"vsel %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
-(define_insn "altivec_vsldoi_4si"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 163))]
- "TARGET_ALTIVEC"
- "vsldoi %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_4sf"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (unspec:V4SF [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 164))]
- "TARGET_ALTIVEC"
- "vsldoi %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 165))]
- "TARGET_ALTIVEC"
- "vsldoi %0,%1,%2,%3"
- [(set_attr "type" "vecperm")])
-
-(define_insn "altivec_vsldoi_16qi"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand:QI 3 "immediate_operand" "i")] 166))]
+(define_insn "altivec_vsldoi_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+ (match_operand:V 2 "register_operand" "v")
+ (match_operand:QI 3 "immediate_operand" "i")]
+ UNSPEC_VLSDOI))]
"TARGET_ALTIVEC"
"vsldoi %0,%1,%2,%3"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhsb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 167))]
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
+ UNSPEC_VUPKHSB))]
"TARGET_ALTIVEC"
"vupkhsb %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 168))]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ UNSPEC_VUPKHPX))]
"TARGET_ALTIVEC"
"vupkhpx %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupkhsh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 169))]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ UNSPEC_VUPKHSH))]
"TARGET_ALTIVEC"
"vupkhsh %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupklsb"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")] 170))]
+ (unspec:V8HI [(match_operand:V16QI 1 "register_operand" "v")]
+ UNSPEC_VUPKLSB))]
"TARGET_ALTIVEC"
"vupklsb %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupklpx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 171))]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ UNSPEC_VUPKLPX))]
"TARGET_ALTIVEC"
"vupklpx %0,%1"
[(set_attr "type" "vecperm")])
(define_insn "altivec_vupklsh"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")] 172))]
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ UNSPEC_VUPKLSH))]
"TARGET_ALTIVEC"
"vupklsh %0,%1"
[(set_attr "type" "vecperm")])
@@ -1714,42 +1685,12 @@
;; We can get away with generating the opcode on the fly (%3 below)
;; because all the predicates have the same scheduling parameters.
-(define_insn "altivec_predicate_v4si"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V4SI 1 "register_operand" "v")
- (match_operand:V4SI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 173))
- (clobber (match_scratch:V4SI 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v4sf"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V4SF 1 "register_operand" "v")
- (match_operand:V4SF 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 174))
- (clobber (match_scratch:V4SF 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v8hi"
- [(set (reg:CC 74)
- (unspec:CC [(match_operand:V8HI 1 "register_operand" "v")
- (match_operand:V8HI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 175))
- (clobber (match_scratch:V8HI 0 "=v"))]
- "TARGET_ALTIVEC"
- "%3 %0,%1,%2"
-[(set_attr "type" "veccmp")])
-
-(define_insn "altivec_predicate_v16qi"
+(define_insn "altivec_predicate_<mode>"
[(set (reg:CC 74)
- (unspec:CC [(match_operand:V16QI 1 "register_operand" "v")
- (match_operand:V16QI 2 "register_operand" "v")
- (match_operand 3 "any_operand" "")] 175))
- (clobber (match_scratch:V16QI 0 "=v"))]
+ (unspec:CC [(match_operand:V 1 "register_operand" "v")
+ (match_operand:V 2 "register_operand" "v")
+ (match_operand 3 "any_operand" "")] UNSPEC_PREDICATE))
+ (clobber (match_scratch:V 0 "=v"))]
"TARGET_ALTIVEC"
"%3 %0,%1,%2"
[(set_attr "type" "veccmp")])
@@ -1757,102 +1698,114 @@
(define_insn "altivec_mtvscr"
[(set (reg:SI 110)
(unspec_volatile:SI
- [(match_operand:V4SI 0 "register_operand" "v")] 186))]
+ [(match_operand:V4SI 0 "register_operand" "v")] UNSPECV_MTVSCR))]
"TARGET_ALTIVEC"
"mtvscr %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_mfvscr"
[(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec_volatile:V8HI [(reg:SI 110)] 187))]
+ (unspec_volatile:V8HI [(reg:SI 110)] UNSPECV_MFVSCR))]
"TARGET_ALTIVEC"
"mfvscr %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dssall"
- [(unspec [(const_int 0)] 188)]
+ [(unspec_volatile [(const_int 0)] UNSPECV_DSSALL)]
"TARGET_ALTIVEC"
"dssall"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dss"
- [(unspec [(match_operand:QI 0 "immediate_operand" "i")] 189)]
+ [(unspec_volatile [(match_operand:QI 0 "immediate_operand" "i")]
+ UNSPECV_DSS)]
"TARGET_ALTIVEC"
"dss %0"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dst"
- [(unspec [(match_operand:V4SI 0 "memory_operand" "Q")
+ [(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 190)]
- "TARGET_ALTIVEC"
- "dst %P0,%1,%2"
+ (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DST)]
+ "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
+ "dst %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dstt"
- [(unspec [(match_operand:V4SI 0 "memory_operand" "Q")
+ [(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 191)]
- "TARGET_ALTIVEC"
- "dstt %P0,%1,%2"
+ (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTT)]
+ "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
+ "dstt %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dstst"
- [(unspec [(match_operand:V4SI 0 "memory_operand" "Q")
+ [(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 192)]
- "TARGET_ALTIVEC"
- "dstst %P0,%1,%2"
+ (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTST)]
+ "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
+ "dstst %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_dststt"
- [(unspec [(match_operand:V4SI 0 "memory_operand" "Q")
+ [(unspec [(match_operand 0 "register_operand" "b")
(match_operand:SI 1 "register_operand" "r")
- (match_operand:QI 2 "immediate_operand" "i")] 193)]
- "TARGET_ALTIVEC"
- "dststt %P0,%1,%2"
+ (match_operand:QI 2 "immediate_operand" "i")] UNSPEC_DSTSTT)]
+ "TARGET_ALTIVEC && GET_MODE (operands[0]) == Pmode"
+ "dststt %0,%1,%2"
[(set_attr "type" "vecsimple")])
(define_insn "altivec_lvsl"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand 1 "memory_operand" "m")] 194))]
+ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] UNSPEC_LVSL))]
"TARGET_ALTIVEC"
"lvsl %0,%y1"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvsr"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand 1 "memory_operand" "m")] 195))]
+ (unspec:V16QI [(match_operand 1 "memory_operand" "Z")] UNSPEC_LVSR))]
"TARGET_ALTIVEC"
"lvsr %0,%y1"
[(set_attr "type" "vecload")])
+(define_expand "build_vector_mask_for_load"
+ [(set (match_operand:V16QI 0 "register_operand" "")
+ (unspec:V16QI [(match_operand 1 "memory_operand" "")] UNSPEC_LVSR))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx addr;
+ rtx temp;
+
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+
+ addr = XEXP (operands[1], 0);
+ temp = gen_reg_rtx (GET_MODE (addr));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_NEG (GET_MODE (addr), addr)));
+ emit_insn (gen_altivec_lvsr (operands[0],
+ replace_equiv_address (operands[1], temp)));
+ DONE;
+}")
+
;; Parallel some of the LVE* and STV*'s with unspecs because some have
;; identical rtl but different instructions-- and gcc gets confused.
-(define_insn "altivec_lvebx"
+(define_insn "altivec_lve<VI_char>x"
[(parallel
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (match_operand:V16QI 1 "memory_operand" "m"))
- (unspec [(const_int 0)] 196)])]
+ [(set (match_operand:VI 0 "register_operand" "=v")
+ (match_operand:VI 1 "memory_operand" "Z"))
+ (unspec [(const_int 0)] UNSPEC_LVE)])]
"TARGET_ALTIVEC"
- "lvebx %0,%y1"
+ "lve<VI_char>x %0,%y1"
[(set_attr "type" "vecload")])
-(define_insn "altivec_lvehx"
+(define_insn "*altivec_lvesfx"
[(parallel
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (match_operand:V8HI 1 "memory_operand" "m"))
- (unspec [(const_int 0)] 197)])]
- "TARGET_ALTIVEC"
- "lvehx %0,%y1"
- [(set_attr "type" "vecload")])
-
-(define_insn "altivec_lvewx"
- [(parallel
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (match_operand:V4SI 1 "memory_operand" "m"))
- (unspec [(const_int 0)] 198)])]
+ [(set (match_operand:V4SF 0 "register_operand" "=v")
+ (match_operand:V4SF 1 "memory_operand" "Z"))
+ (unspec [(const_int 0)] UNSPEC_LVE)])]
"TARGET_ALTIVEC"
"lvewx %0,%y1"
[(set_attr "type" "vecload")])
@@ -1860,130 +1813,412 @@
(define_insn "altivec_lvxl"
[(parallel
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (match_operand:V4SI 1 "memory_operand" "m"))
- (unspec [(const_int 0)] 213)])]
+ (match_operand:V4SI 1 "memory_operand" "Z"))
+ (unspec [(const_int 0)] UNSPEC_SET_VSCR)])]
"TARGET_ALTIVEC"
"lvxl %0,%y1"
[(set_attr "type" "vecload")])
(define_insn "altivec_lvx"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (match_operand:V4SI 1 "memory_operand" "m"))]
+ (match_operand:V4SI 1 "memory_operand" "Z"))]
"TARGET_ALTIVEC"
"lvx %0,%y1"
[(set_attr "type" "vecload")])
(define_insn "altivec_stvx"
[(parallel
- [(set (match_operand:V4SI 0 "memory_operand" "=m")
+ [(set (match_operand:V4SI 0 "memory_operand" "=Z")
(match_operand:V4SI 1 "register_operand" "v"))
- (unspec [(const_int 0)] 201)])]
+ (unspec [(const_int 0)] UNSPEC_STVX)])]
"TARGET_ALTIVEC"
"stvx %1,%y0"
[(set_attr "type" "vecstore")])
(define_insn "altivec_stvxl"
[(parallel
- [(set (match_operand:V4SI 0 "memory_operand" "=m")
+ [(set (match_operand:V4SI 0 "memory_operand" "=Z")
(match_operand:V4SI 1 "register_operand" "v"))
- (unspec [(const_int 0)] 202)])]
+ (unspec [(const_int 0)] UNSPEC_STVXL)])]
"TARGET_ALTIVEC"
"stvxl %1,%y0"
[(set_attr "type" "vecstore")])
-(define_insn "altivec_stvebx"
+(define_insn "altivec_stve<VI_char>x"
[(parallel
- [(set (match_operand:V16QI 0 "memory_operand" "=m")
- (match_operand:V16QI 1 "register_operand" "v"))
- (unspec [(const_int 0)] 203)])]
+ [(set (match_operand:VI 0 "memory_operand" "=Z")
+ (match_operand:VI 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVE)])]
"TARGET_ALTIVEC"
- "stvebx %1,%y0"
+ "stve<VI_char>x %1,%y0"
[(set_attr "type" "vecstore")])
-(define_insn "altivec_stvehx"
+(define_insn "*altivec_stvesfx"
[(parallel
- [(set (match_operand:V8HI 0 "memory_operand" "=m")
- (match_operand:V8HI 1 "register_operand" "v"))
- (unspec [(const_int 0)] 204)])]
+ [(set (match_operand:V4SF 0 "memory_operand" "=Z")
+ (match_operand:V4SF 1 "register_operand" "v"))
+ (unspec [(const_int 0)] UNSPEC_STVE)])]
"TARGET_ALTIVEC"
- "stvehx %1,%y0"
+ "stvewx %1,%y0"
[(set_attr "type" "vecstore")])
-(define_insn "altivec_stvewx"
- [(parallel
- [(set (match_operand:V4SI 0 "memory_operand" "=m")
- (match_operand:V4SI 1 "register_operand" "v"))
- (unspec [(const_int 0)] 205)])]
+(define_expand "vec_init<mode>"
+ [(match_operand:V 0 "register_operand" "")
+ (match_operand 1 "" "")]
"TARGET_ALTIVEC"
- "stvewx %1,%y0"
- [(set_attr "type" "vecstore")])
+{
+ rs6000_expand_vector_init (operands[0], operands[1]);
+ DONE;
+})
-(define_insn "absv16qi2"
- [(set (match_operand:V16QI 0 "register_operand" "=v")
- (abs:V16QI (match_operand:V16QI 1 "register_operand" "v")))
- (clobber (match_scratch:V16QI 2 "=&v"))
- (clobber (match_scratch:V16QI 3 "=&v"))]
+(define_expand "vec_setv4si"
+ [(match_operand:V4SI 0 "register_operand" "")
+ (match_operand:SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsububm %3,%2,%1\;vmaxsb %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+{
+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
-(define_insn "absv8hi2"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (abs:V8HI (match_operand:V8HI 1 "register_operand" "v")))
- (clobber (match_scratch:V8HI 2 "=&v"))
- (clobber (match_scratch:V8HI 3 "=&v"))]
+(define_expand "vec_setv8hi"
+ [(match_operand:V8HI 0 "register_operand" "")
+ (match_operand:HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubuhm %3,%2,%1\;vmaxsh %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+{
+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
-(define_insn "absv4si2"
- [(set (match_operand:V4SI 0 "register_operand" "=v")
- (abs:V4SI (match_operand:V4SI 1 "register_operand" "v")))
- (clobber (match_scratch:V4SI 2 "=&v"))
- (clobber (match_scratch:V4SI 3 "=&v"))]
+(define_expand "vec_setv16qi"
+ [(match_operand:V16QI 0 "register_operand" "")
+ (match_operand:QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubuwm %3,%2,%1\;vmaxsw %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+{
+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
-(define_insn "absv4sf2"
- [(set (match_operand:V4SF 0 "register_operand" "=v")
- (abs:V4SF (match_operand:V4SF 1 "register_operand" "v")))
- (clobber (match_scratch:V4SF 2 "=&v"))
- (clobber (match_scratch:V4SF 3 "=&v"))]
+(define_expand "vec_setv4sf"
+ [(match_operand:V4SF 0 "register_operand" "")
+ (match_operand:SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_ALTIVEC"
+{
+ rs6000_expand_vector_set (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv4si"
+ [(match_operand:SI 0 "register_operand" "")
+ (match_operand:V4SI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_ALTIVEC"
+{
+ rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv8hi"
+ [(match_operand:HI 0 "register_operand" "")
+ (match_operand:V8HI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_ALTIVEC"
+{
+ rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv16qi"
+ [(match_operand:QI 0 "register_operand" "")
+ (match_operand:V16QI 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_ALTIVEC"
+{
+ rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+(define_expand "vec_extractv4sf"
+ [(match_operand:SF 0 "register_operand" "")
+ (match_operand:V4SF 1 "register_operand" "")
+ (match_operand 2 "const_int_operand" "")]
+ "TARGET_ALTIVEC"
+{
+ rs6000_expand_vector_extract (operands[0], operands[1], INTVAL (operands[2]));
+ DONE;
+})
+
+;; Generate
+;; vspltis? SCRATCH0,0
+;; vsubu?m SCRATCH2,SCRATCH1,%1
+;; vmaxs? %0,%1,SCRATCH2"
+(define_expand "abs<mode>2"
+ [(set (match_dup 2) (vec_duplicate:VI (const_int 0)))
+ (set (match_dup 3)
+ (minus:VI (match_dup 2)
+ (match_operand:VI 1 "register_operand" "v")))
+ (set (match_operand:VI 0 "register_operand" "=v")
+ (smax:VI (match_dup 1) (match_dup 3)))]
+ "TARGET_ALTIVEC"
+{
+ operands[2] = gen_reg_rtx (GET_MODE (operands[0]));
+ operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
+})
+
+;; Generate
+;; vspltisw SCRATCH1,-1
+;; vslw SCRATCH2,SCRATCH1,SCRATCH1
+;; vandc %0,%1,SCRATCH2
+(define_expand "absv4sf2"
+ [(set (match_dup 2)
+ (vec_duplicate:V4SI (const_int -1)))
+ (set (match_dup 3)
+ (unspec:V4SI [(match_dup 2) (match_dup 2)] UNSPEC_VSL))
+ (set (match_operand:V4SF 0 "register_operand" "=v")
+ (and:V4SF (not:V4SF (subreg:V4SF (match_dup 3) 0))
+ (match_operand:V4SF 1 "register_operand" "v")))]
+ "TARGET_ALTIVEC"
+{
+ operands[2] = gen_reg_rtx (V4SImode);
+ operands[3] = gen_reg_rtx (V4SImode);
+})
+
+;; Generate
+;; vspltis? SCRATCH0,0
+;; vsubs?s SCRATCH2,SCRATCH1,%1
+;; vmaxs? %0,%1,SCRATCH2"
+(define_expand "altivec_abss_<mode>"
+ [(set (match_dup 2) (vec_duplicate:VI (const_int 0)))
+ (parallel [(set (match_dup 3)
+ (unspec:VI [(match_dup 2)
+ (match_operand:VI 1 "register_operand" "v")]
+ UNSPEC_VSUBS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))])
+ (set (match_operand:VI 0 "register_operand" "=v")
+ (smax:VI (match_dup 1) (match_dup 3)))]
+ "TARGET_ALTIVEC"
+{
+ operands[2] = gen_reg_rtx (GET_MODE (operands[0]));
+ operands[3] = gen_reg_rtx (GET_MODE (operands[0]));
+})
+
+;; Vector shift left in bits. Currently supported ony for shift
+;; amounts that can be expressed as byte shifts (divisible by 8).
+;; General shift amounts can be supported using vslo + vsl. We're
+;; not expecting to see these yet (the vectorizer currently
+;; generates only shifts divisible by byte_size).
+(define_expand "vec_shl_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+ (match_operand:QI 2 "reg_or_short_operand" "")]
+ UNSPEC_VECSH))]
"TARGET_ALTIVEC"
- "vspltisw %2,-1\;vslw %3,%2,%2\;vandc %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+ "
+{
+ rtx bitshift = operands[2];
+ rtx byteshift = gen_reg_rtx (QImode);
+ HOST_WIDE_INT bitshift_val;
+ HOST_WIDE_INT byteshift_val;
+
+ if (! CONSTANT_P (bitshift))
+ FAIL;
+ bitshift_val = INTVAL (bitshift);
+ if (bitshift_val & 0x7)
+ FAIL;
+ byteshift_val = bitshift_val >> 3;
+ byteshift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ byteshift));
+ DONE;
+}")
+
+;; Vector shift left in bits. Currently supported ony for shift
+;; amounts that can be expressed as byte shifts (divisible by 8).
+;; General shift amounts can be supported using vsro + vsr. We're
+;; not expecting to see these yet (the vectorizer currently
+;; generates only shifts divisible by byte_size).
+(define_expand "vec_shr_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+ (match_operand:QI 2 "reg_or_short_operand" "")]
+ UNSPEC_VECSH))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx bitshift = operands[2];
+ rtx byteshift = gen_reg_rtx (QImode);
+ HOST_WIDE_INT bitshift_val;
+ HOST_WIDE_INT byteshift_val;
+
+ if (! CONSTANT_P (bitshift))
+ FAIL;
+ bitshift_val = INTVAL (bitshift);
+ if (bitshift_val & 0x7)
+ FAIL;
+ byteshift_val = 16 - (bitshift_val >> 3);
+ byteshift = gen_rtx_CONST_INT (QImode, byteshift_val);
+ emit_insn (gen_altivec_vsldoi_<mode> (operands[0], operands[1], operands[1],
+ byteshift));
+ DONE;
+}")
+
+(define_insn "altivec_vsumsws_nomode"
+ [(set (match_operand 0 "register_operand" "=v")
+ (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")
+ (match_operand:V4SI 2 "register_operand" "v")]
+ UNSPEC_VSUMSWS))
+ (set (reg:SI 110) (unspec:SI [(const_int 0)] UNSPEC_SET_VSCR))]
+ "TARGET_ALTIVEC"
+ "vsumsws %0,%1,%2"
+ [(set_attr "type" "veccomplex")])
+
+(define_expand "reduc_splus_<mode>"
+ [(set (match_operand:VIshort 0 "register_operand" "=v")
+ (unspec:VIshort [(match_operand:VIshort 1 "register_operand" "v")]
+ UNSPEC_REDUC_PLUS))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx vzero = gen_reg_rtx (V4SImode);
+ rtx vtmp1 = gen_reg_rtx (V4SImode);
+
+ emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
+ emit_insn (gen_altivec_vsum4s<VI_char>s (vtmp1, operands[1], vzero));
+ emit_insn (gen_altivec_vsumsws_nomode (operands[0], vtmp1, vzero));
+ DONE;
+}")
-(define_insn "altivec_abss_v16qi"
+(define_expand "reduc_uplus_v16qi"
[(set (match_operand:V16QI 0 "register_operand" "=v")
- (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")] 210))
- (clobber (match_scratch:V16QI 2 "=&v"))
- (clobber (match_scratch:V16QI 3 "=&v"))]
+ (unspec:V16QI [(match_operand:V16QI 1 "register_operand" "v")]
+ UNSPEC_REDUC_PLUS))]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubsbs %3,%2,%1\;vmaxsb %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+ "
+{
+ rtx vzero = gen_reg_rtx (V4SImode);
+ rtx vtmp1 = gen_reg_rtx (V4SImode);
-(define_insn "altivec_abss_v8hi"
- [(set (match_operand:V8HI 0 "register_operand" "=v")
- (unspec:V8HI [(match_operand:V8HI 1 "register_operand" "v")] 211))
- (clobber (match_scratch:V8HI 2 "=&v"))
- (clobber (match_scratch:V8HI 3 "=&v"))]
+ emit_insn (gen_altivec_vspltisw (vzero, const0_rtx));
+ emit_insn (gen_altivec_vsum4ubs (vtmp1, operands[1], vzero));
+ emit_insn (gen_altivec_vsumsws_nomode (operands[0], vtmp1, vzero));
+ DONE;
+}")
+
+(define_insn "vec_realign_load_<mode>"
+ [(set (match_operand:V 0 "register_operand" "=v")
+ (unspec:V [(match_operand:V 1 "register_operand" "v")
+ (match_operand:V 2 "register_operand" "v")
+ (match_operand:V16QI 3 "register_operand" "v")]
+ UNSPEC_REALIGN_LOAD))]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubshs %3,%2,%1\;vmaxsh %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+ "vperm %0,%1,%2,%3"
+ [(set_attr "type" "vecperm")])
+
+(define_expand "neg<mode>2"
+ [(use (match_operand:VI 0 "register_operand" ""))
+ (use (match_operand:VI 1 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx vzero;
-(define_insn "altivec_abss_v4si"
+ vzero = gen_reg_rtx (GET_MODE (operands[0]));
+ emit_insn (gen_altivec_vspltis<VI_char> (vzero, const0_rtx));
+ emit_insn (gen_sub<mode>3 (operands[0], vzero, operands[1]));
+
+ DONE;
+}")
+
+(define_expand "udot_prod<mode>"
[(set (match_operand:V4SI 0 "register_operand" "=v")
- (unspec:V4SI [(match_operand:V4SI 1 "register_operand" "v")] 212))
- (clobber (match_scratch:V4SI 2 "=&v"))
- (clobber (match_scratch:V4SI 3 "=&v"))]
+ (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
+ (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")
+ (match_operand:VIshort 2 "register_operand" "v")]
+ UNSPEC_VMSUMU)))]
"TARGET_ALTIVEC"
- "vspltisb %2,0\;vsubsws %3,%2,%1\;vmaxsw %0,%1,%3"
- [(set_attr "type" "vecsimple")
- (set_attr "length" "12")])
+ "
+{
+ emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], operands[2], operands[3]));
+ DONE;
+}")
+
+(define_expand "sdot_prodv8hi"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (plus:V4SI (match_operand:V4SI 3 "register_operand" "v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")
+ (match_operand:V8HI 2 "register_operand" "v")]
+ UNSPEC_VMSUMSHM)))]
+ "TARGET_ALTIVEC"
+ "
+{
+ emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], operands[2], operands[3]));
+ DONE;
+}")
+
+(define_expand "widen_usum<mode>3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (unspec:V4SI [(match_operand:VIshort 1 "register_operand" "v")]
+ UNSPEC_VMSUMU)))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx vones = gen_reg_rtx (GET_MODE (operands[1]));
+
+ emit_insn (gen_altivec_vspltis<VI_char> (vones, const1_rtx));
+ emit_insn (gen_altivec_vmsumu<VI_char>m (operands[0], operands[1], vones, operands[2]));
+ DONE;
+}")
+
+(define_expand "widen_ssumv16qi3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (unspec:V4SI [(match_operand:V16QI 1 "register_operand" "v")]
+ UNSPEC_VMSUMM)))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx vones = gen_reg_rtx (V16QImode);
+
+ emit_insn (gen_altivec_vspltisb (vones, const1_rtx));
+ emit_insn (gen_altivec_vmsummbm (operands[0], operands[1], vones, operands[2]));
+ DONE;
+}")
+
+(define_expand "widen_ssumv8hi3"
+ [(set (match_operand:V4SI 0 "register_operand" "=v")
+ (plus:V4SI (match_operand:V4SI 2 "register_operand" "v")
+ (unspec:V4SI [(match_operand:V8HI 1 "register_operand" "v")]
+ UNSPEC_VMSUMSHM)))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx vones = gen_reg_rtx (V8HImode);
+
+ emit_insn (gen_altivec_vspltish (vones, const1_rtx));
+ emit_insn (gen_altivec_vmsumshm (operands[0], operands[1], vones, operands[2]));
+ DONE;
+}")
+
+(define_expand "negv4sf2"
+ [(use (match_operand:V4SF 0 "register_operand" ""))
+ (use (match_operand:V4SF 1 "register_operand" ""))]
+ "TARGET_ALTIVEC"
+ "
+{
+ rtx neg0;
+
+ /* Generate [-0.0, -0.0, -0.0, -0.0]. */
+ neg0 = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltisw (neg0, constm1_rtx));
+ emit_insn (gen_altivec_vslw (neg0, neg0, neg0));
+
+ /* XOR */
+ emit_insn (gen_xorv4sf3 (operands[0],
+ gen_lowpart (V4SFmode, neg0), operands[1]));
+
+ DONE;
+}")
diff --git a/contrib/gcc/config/rs6000/beos.h b/contrib/gcc/config/rs6000/beos.h
index a9e88ac..cea5ca8 100644
--- a/contrib/gcc/config/rs6000/beos.h
+++ b/contrib/gcc/config/rs6000/beos.h
@@ -1,5 +1,6 @@
/* Definitions of target machine for GNU compiler, for BeOS.
- Copyright (C) 1997, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2000, 2001, 2002, 2003, 2005
+ Free Software Foundation, Inc.
Contributed by Fred Fish (fnf@cygnus.com), based on aix41.h
from David Edelsohn (edelsohn@npac.syr.edu).
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (BeOS/PowerPC)");
diff --git a/contrib/gcc/config/rs6000/biarch64.h b/contrib/gcc/config/rs6000/biarch64.h
index 3f8addd..c5cb598 100644
--- a/contrib/gcc/config/rs6000/biarch64.h
+++ b/contrib/gcc/config/rs6000/biarch64.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Specify this in a cover file to provide bi-architecture (32/64) support. */
#define RS6000_BI_ARCH 1
diff --git a/contrib/gcc/config/rs6000/constraints.md b/contrib/gcc/config/rs6000/constraints.md
new file mode 100644
index 0000000..a7d4661
--- /dev/null
+++ b/contrib/gcc/config/rs6000/constraints.md
@@ -0,0 +1,162 @@
+;; Constraint definitions for RS6000
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Register constraints
+
+(define_register_constraint "f" "TARGET_HARD_FLOAT && TARGET_FPRS
+ ? FLOAT_REGS : NO_REGS"
+ "@internal")
+
+(define_register_constraint "b" "BASE_REGS"
+ "@internal")
+
+(define_register_constraint "h" "SPECIAL_REGS"
+ "@internal")
+
+(define_register_constraint "q" "MQ_REGS"
+ "@internal")
+
+(define_register_constraint "c" "CTR_REGS"
+ "@internal")
+
+(define_register_constraint "l" "LINK_REGS"
+ "@internal")
+
+(define_register_constraint "v" "ALTIVEC_REGS"
+ "@internal")
+
+(define_register_constraint "x" "CR0_REGS"
+ "@internal")
+
+(define_register_constraint "y" "CR_REGS"
+ "@internal")
+
+(define_register_constraint "z" "XER_REGS"
+ "@internal")
+
+;; Integer constraints
+
+(define_constraint "I"
+ "A signed 16-bit constant"
+ (and (match_code "const_int")
+ (match_test "(unsigned HOST_WIDE_INT) (ival + 0x8000) < 0x10000")))
+
+(define_constraint "J"
+ "high-order 16 bits nonzero"
+ (and (match_code "const_int")
+ (match_test "(ival & (~ (unsigned HOST_WIDE_INT) 0xffff0000)) == 0")))
+
+(define_constraint "K"
+ "low-order 16 bits nonzero"
+ (and (match_code "const_int")
+ (match_test "(ival & (~ (HOST_WIDE_INT) 0xffff)) == 0")))
+
+(define_constraint "L"
+ "signed 16-bit constant shifted left 16 bits"
+ (and (match_code "const_int")
+ (match_test "((ival & 0xffff) == 0
+ && (ival >> 31 == -1 || ival >> 31 == 0))")))
+
+(define_constraint "M"
+ "constant greater than 31"
+ (and (match_code "const_int")
+ (match_test "ival > 31")))
+
+(define_constraint "N"
+ "positive constant that is an exact power of two"
+ (and (match_code "const_int")
+ (match_test "ival > 0 && exact_log2 (ival) >= 0")))
+
+(define_constraint "O"
+ "constant zero"
+ (and (match_code "const_int")
+ (match_test "ival == 0")))
+
+(define_constraint "P"
+ "constant whose negation is signed 16-bit constant"
+ (and (match_code "const_int")
+ (match_test "(unsigned HOST_WIDE_INT) ((- ival) + 0x8000) < 0x10000")))
+
+;; Floating-point constraints
+
+(define_constraint "G"
+ "Constant that can be copied into GPR with two insns for DF/DI
+ and one for SF."
+ (and (match_code "const_double")
+ (match_test "num_insns_constant (op, mode)
+ == (mode == SFmode ? 1 : 2)")))
+
+(define_constraint "H"
+ "DF/DI constant that takes three insns."
+ (and (match_code "const_double")
+ (match_test "num_insns_constant (op, mode) == 3")))
+
+;; Memory constraints
+
+(define_memory_constraint "Q"
+ "Memory operand that is just an offset from a reg"
+ (and (match_code "mem")
+ (match_test "GET_CODE (XEXP (op, 0)) == REG")))
+
+(define_memory_constraint "Y"
+ "Indexed or word-aligned displacement memory operand"
+ (match_operand 0 "word_offset_memref_operand"))
+
+(define_memory_constraint "Z"
+ "Indexed or indirect memory operand"
+ (match_operand 0 "indexed_or_indirect_operand"))
+
+;; Address constraints
+
+(define_address_constraint "a"
+ "Indexed or indirect address operand"
+ (match_operand 0 "indexed_or_indirect_address"))
+
+(define_constraint "R"
+ "AIX TOC entry"
+ (match_test "legitimate_constant_pool_address_p (op)"))
+
+;; General constraints
+
+(define_constraint "S"
+ "Constant that can be placed into a 64-bit mask operand"
+ (match_operand 0 "mask64_operand"))
+
+(define_constraint "T"
+ "Constant that can be placed into a 32-bit mask operand"
+ (match_operand 0 "mask_operand"))
+
+(define_constraint "U"
+ "V.4 small data reference"
+ (and (match_test "DEFAULT_ABI == ABI_V4")
+ (match_operand 0 "small_data_operand")))
+
+(define_constraint "t"
+ "AND masks that can be performed by two rldic{l,r} insns
+ (but excluding those that could match other constraints of anddi3)"
+ (and (and (and (match_operand 0 "mask64_2_operand")
+ (match_test "(fixed_regs[CR0_REGNO]
+ || !logical_operand (op, DImode))"))
+ (not (match_operand 0 "mask_operand")))
+ (not (match_operand 0 "mask64_operand"))))
+
+(define_constraint "W"
+ "vector constant that does not require memory"
+ (match_operand 0 "easy_vector_constant"))
diff --git a/contrib/gcc/config/rs6000/crtsavres.asm b/contrib/gcc/config/rs6000/crtsavres.asm
index 327048e..498759d 100644
--- a/contrib/gcc/config/rs6000/crtsavres.asm
+++ b/contrib/gcc/config/rs6000/crtsavres.asm
@@ -25,8 +25,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/darwin-asm.h b/contrib/gcc/config/rs6000/darwin-asm.h
new file mode 100644
index 0000000..401b4f8
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-asm.h
@@ -0,0 +1,61 @@
+/* Macro definitions to used to support 32/64-bit code in Darwin's
+ * assembly files.
+ *
+ * Copyright (C) 2004 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 with other programs, and to distribute
+ * those programs 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 another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not 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.
+ */
+
+/* These are donated from /usr/include/architecture/ppc . */
+
+#if defined(__ppc64__)
+#define MODE_CHOICE(x, y) y
+#else
+#define MODE_CHOICE(x, y) x
+#endif
+
+#define cmpg MODE_CHOICE(cmpw, cmpd)
+#define lg MODE_CHOICE(lwz, ld)
+#define stg MODE_CHOICE(stw, std)
+#define lgx MODE_CHOICE(lwzx, ldx)
+#define stgx MODE_CHOICE(stwx, stdx)
+#define lgu MODE_CHOICE(lwzu, ldu)
+#define stgu MODE_CHOICE(stwu, stdu)
+#define lgux MODE_CHOICE(lwzux, ldux)
+#define stgux MODE_CHOICE(stwux, stdux)
+#define lgwa MODE_CHOICE(lwz, lwa)
+
+#define g_long MODE_CHOICE(long, quad) /* usage is ".g_long" */
+
+#define GPR_BYTES MODE_CHOICE(4,8) /* size of a GPR in bytes */
+#define LOG2_GPR_BYTES MODE_CHOICE(2,3) /* log2(GPR_BYTES) */
+
+#define SAVED_LR_OFFSET MODE_CHOICE(8,16) /* position of saved
+ LR in frame */
diff --git a/contrib/gcc/config/rs6000/darwin-fallback.c b/contrib/gcc/config/rs6000/darwin-fallback.c
new file mode 100644
index 0000000..5d3de32
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-fallback.c
@@ -0,0 +1,471 @@
+/* Fallback frame-state unwinder for Darwin.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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 combined
+ executable.)
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+#include "tconfig.h"
+#include "tsystem.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "dwarf2.h"
+#include "unwind.h"
+#include "unwind-dw2.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <signal.h>
+
+typedef unsigned long reg_unit;
+
+/* Place in GPRS the parameters to the first 'sc' instruction that would
+ have been executed if we were returning from this CONTEXT, or
+ return false if an unexpected instruction is encountered. */
+
+static bool
+interpret_libc (reg_unit gprs[32], struct _Unwind_Context *context)
+{
+ uint32_t *pc = (uint32_t *)_Unwind_GetIP (context);
+ uint32_t cr;
+ reg_unit lr = (reg_unit) pc;
+ reg_unit ctr = 0;
+ uint32_t *invalid_address = NULL;
+
+ int i;
+
+ for (i = 0; i < 13; i++)
+ gprs[i] = 1;
+ gprs[1] = _Unwind_GetCFA (context);
+ for (; i < 32; i++)
+ gprs[i] = _Unwind_GetGR (context, i);
+ cr = _Unwind_GetGR (context, CR2_REGNO);
+
+ /* For each supported Libc, we have to track the code flow
+ all the way back into the kernel.
+
+ This code is believed to support all released Libc/Libsystem builds since
+ Jaguar 6C115, including all the security updates. To be precise,
+
+ Libc Libsystem Build(s)
+ 262~1 60~37 6C115
+ 262~1 60.2~4 6D52
+ 262~1 61~3 6F21-6F22
+ 262~1 63~24 6G30-6G37
+ 262~1 63~32 6I34-6I35
+ 262~1 63~64 6L29-6L60
+ 262.4.1~1 63~84 6L123-6R172
+
+ 320~1 71~101 7B85-7D28
+ 320~1 71~266 7F54-7F56
+ 320~1 71~288 7F112
+ 320~1 71~289 7F113
+ 320.1.3~1 71.1.1~29 7H60-7H105
+ 320.1.3~1 71.1.1~30 7H110-7H113
+ 320.1.3~1 71.1.1~31 7H114
+
+ That's a big table! It would be insane to try to keep track of
+ every little detail, so we just read the code itself and do what
+ it would do.
+ */
+
+ for (;;)
+ {
+ uint32_t ins = *pc++;
+
+ if ((ins & 0xFC000003) == 0x48000000) /* b instruction */
+ {
+ pc += ((((int32_t) ins & 0x3FFFFFC) ^ 0x2000000) - 0x2000004) / 4;
+ continue;
+ }
+ if ((ins & 0xFC600000) == 0x2C000000) /* cmpwi */
+ {
+ int32_t val1 = (int16_t) ins;
+ int32_t val2 = gprs[ins >> 16 & 0x1F];
+ /* Only beq and bne instructions are supported, so we only
+ need to set the EQ bit. */
+ uint32_t mask = 0xF << ((ins >> 21 & 0x1C) ^ 0x1C);
+ if (val1 == val2)
+ cr |= mask;
+ else
+ cr &= ~mask;
+ continue;
+ }
+ if ((ins & 0xFEC38003) == 0x40820000) /* forwards beq/bne */
+ {
+ if ((cr >> ((ins >> 16 & 0x1F) ^ 0x1F) & 1) == (ins >> 24 & 1))
+ pc += (ins & 0x7FFC) / 4 - 1;
+ continue;
+ }
+ if ((ins & 0xFC0007FF) == 0x7C000378) /* or, including mr */
+ {
+ gprs [ins >> 16 & 0x1F] = (gprs [ins >> 11 & 0x1F]
+ | gprs [ins >> 21 & 0x1F]);
+ continue;
+ }
+ if (ins >> 26 == 0x0E) /* addi, including li */
+ {
+ reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+ gprs [ins >> 21 & 0x1F] = src + (int16_t) ins;
+ continue;
+ }
+ if (ins >> 26 == 0x0F) /* addis, including lis */
+ {
+ reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+ gprs [ins >> 21 & 0x1F] = src + ((int16_t) ins << 16);
+ continue;
+ }
+ if (ins >> 26 == 0x20) /* lwz */
+ {
+ reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+ uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+ if (p == invalid_address)
+ return false;
+ gprs [ins >> 21 & 0x1F] = *p;
+ continue;
+ }
+ if (ins >> 26 == 0x21) /* lwzu */
+ {
+ uint32_t *p = (uint32_t *)(gprs [ins >> 16 & 0x1F] += (int16_t) ins);
+ if (p == invalid_address)
+ return false;
+ gprs [ins >> 21 & 0x1F] = *p;
+ continue;
+ }
+ if (ins >> 26 == 0x24) /* stw */
+ /* What we hope this is doing is '--in_sigtramp'. We don't want
+ to actually store to memory, so just make a note of the
+ address and refuse to load from it. */
+ {
+ reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+ uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+ if (p == NULL || invalid_address != NULL)
+ return false;
+ invalid_address = p;
+ continue;
+ }
+ if (ins >> 26 == 0x2E) /* lmw */
+ {
+ reg_unit src = (ins >> 16 & 0x1F) == 0 ? 0 : gprs [ins >> 16 & 0x1F];
+ uint32_t *p = (uint32_t *)(src + (int16_t) ins);
+ int i;
+
+ for (i = (ins >> 21 & 0x1F); i < 32; i++)
+ {
+ if (p == invalid_address)
+ return false;
+ gprs[i] = *p++;
+ }
+ continue;
+ }
+ if ((ins & 0xFC1FFFFF) == 0x7c0803a6) /* mtlr */
+ {
+ lr = gprs [ins >> 21 & 0x1F];
+ continue;
+ }
+ if ((ins & 0xFC1FFFFF) == 0x7c0802a6) /* mflr */
+ {
+ gprs [ins >> 21 & 0x1F] = lr;
+ continue;
+ }
+ if ((ins & 0xFC1FFFFF) == 0x7c0903a6) /* mtctr */
+ {
+ ctr = gprs [ins >> 21 & 0x1F];
+ continue;
+ }
+ /* The PowerPC User's Manual says that bit 11 of the mtcrf
+ instruction is reserved and should be set to zero, but it
+ looks like the Darwin assembler doesn't do that... */
+ if ((ins & 0xFC000FFF) == 0x7c000120) /* mtcrf */
+ {
+ int i;
+ uint32_t mask = 0;
+ for (i = 0; i < 8; i++)
+ mask |= ((-(ins >> (12 + i) & 1)) & 0xF) << 4 * i;
+ cr = (cr & ~mask) | (gprs [ins >> 21 & 0x1F] & mask);
+ continue;
+ }
+ if (ins == 0x429f0005) /* bcl- 20,4*cr7+so,.+4, loads pc into LR */
+ {
+ lr = (reg_unit) pc;
+ continue;
+ }
+ if (ins == 0x4e800420) /* bctr */
+ {
+ pc = (uint32_t *) ctr;
+ continue;
+ }
+ if (ins == 0x44000002) /* sc */
+ return true;
+
+ return false;
+ }
+}
+
+/* We used to include <ucontext.h> and <mach/thread_status.h>,
+ but they change so much between different Darwin system versions
+ that it's much easier to just write the structures involved here
+ directly. */
+
+/* These defines are from the kernel's bsd/dev/ppc/unix_signal.c. */
+#define UC_TRAD 1
+#define UC_TRAD_VEC 6
+#define UC_TRAD64 20
+#define UC_TRAD64_VEC 25
+#define UC_FLAVOR 30
+#define UC_FLAVOR_VEC 35
+#define UC_FLAVOR64 40
+#define UC_FLAVOR64_VEC 45
+#define UC_DUAL 50
+#define UC_DUAL_VEC 55
+
+struct gcc_ucontext
+{
+ int onstack;
+ sigset_t sigmask;
+ void * stack_sp;
+ size_t stack_sz;
+ int stack_flags;
+ struct gcc_ucontext *link;
+ size_t mcsize;
+ struct gcc_mcontext32 *mcontext;
+};
+
+struct gcc_float_vector_state
+{
+ double fpregs[32];
+ uint32_t fpscr_pad;
+ uint32_t fpscr;
+ uint32_t save_vr[32][4];
+ uint32_t save_vscr[4];
+};
+
+struct gcc_mcontext32 {
+ uint32_t dar;
+ uint32_t dsisr;
+ uint32_t exception;
+ uint32_t padding1[5];
+ uint32_t srr0;
+ uint32_t srr1;
+ uint32_t gpr[32];
+ uint32_t cr;
+ uint32_t xer;
+ uint32_t lr;
+ uint32_t ctr;
+ uint32_t mq;
+ uint32_t vrsave;
+ struct gcc_float_vector_state fvs;
+};
+
+/* These are based on /usr/include/ppc/ucontext.h and
+ /usr/include/mach/ppc/thread_status.h, but rewritten to be more
+ convenient, to compile on Jaguar, and to work around Radar 3712064
+ on Panther, which is that the 'es' field of 'struct mcontext64' has
+ the wrong type (doh!). */
+
+struct gcc_mcontext64 {
+ uint64_t dar;
+ uint32_t dsisr;
+ uint32_t exception;
+ uint32_t padding1[4];
+ uint64_t srr0;
+ uint64_t srr1;
+ uint32_t gpr[32][2];
+ uint32_t cr;
+ uint32_t xer[2]; /* These are arrays because the original structure has them misaligned. */
+ uint32_t lr[2];
+ uint32_t ctr[2];
+ uint32_t vrsave;
+ struct gcc_float_vector_state fvs;
+};
+
+#define UC_FLAVOR_SIZE \
+ (sizeof (struct gcc_mcontext32) - 33*16)
+
+#define UC_FLAVOR_VEC_SIZE (sizeof (struct gcc_mcontext32))
+
+#define UC_FLAVOR64_SIZE \
+ (sizeof (struct gcc_mcontext64) - 33*16)
+
+#define UC_FLAVOR64_VEC_SIZE (sizeof (struct gcc_mcontext64))
+
+/* Given GPRS as input to a 'sc' instruction, and OLD_CFA, update FS
+ to represent the execution of a signal return; or, if not a signal
+ return, return false. */
+
+static bool
+handle_syscall (_Unwind_FrameState *fs, const reg_unit gprs[32],
+ _Unwind_Ptr old_cfa)
+{
+ struct gcc_ucontext *uctx;
+ bool is_64, is_vector;
+ struct gcc_float_vector_state * float_vector_state;
+ _Unwind_Ptr new_cfa;
+ int i;
+ static _Unwind_Ptr return_addr;
+
+ /* Yay! We're in a Libc that we understand, and it's made a
+ system call. It'll be one of two kinds: either a Jaguar-style
+ SYS_sigreturn, or a Panther-style 'syscall' call with 184, which
+ is also SYS_sigreturn. */
+
+ if (gprs[0] == 0x67 /* SYS_SIGRETURN */)
+ {
+ uctx = (struct gcc_ucontext *) gprs[3];
+ is_vector = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
+ || uctx->mcsize == UC_FLAVOR_VEC_SIZE);
+ is_64 = (uctx->mcsize == UC_FLAVOR64_VEC_SIZE
+ || uctx->mcsize == UC_FLAVOR64_SIZE);
+ }
+ else if (gprs[0] == 0 && gprs[3] == 184)
+ {
+ int ctxstyle = gprs[5];
+ uctx = (struct gcc_ucontext *) gprs[4];
+ is_vector = (ctxstyle == UC_FLAVOR_VEC || ctxstyle == UC_FLAVOR64_VEC
+ || ctxstyle == UC_TRAD_VEC || ctxstyle == UC_TRAD64_VEC);
+ is_64 = (ctxstyle == UC_FLAVOR64_VEC || ctxstyle == UC_TRAD64_VEC
+ || ctxstyle == UC_FLAVOR64 || ctxstyle == UC_TRAD64);
+ }
+ else
+ return false;
+
+#define set_offset(r, addr) \
+ (fs->regs.reg[r].how = REG_SAVED_OFFSET, \
+ fs->regs.reg[r].loc.offset = (_Unwind_Ptr)(addr) - new_cfa)
+
+ /* Restore even the registers that are not call-saved, since they
+ might be being used in the prologue to save other registers,
+ for instance GPR0 is sometimes used to save LR. */
+
+ /* Handle the GPRs, and produce the information needed to do the rest. */
+ if (is_64)
+ {
+ /* The context is 64-bit, but it doesn't carry any extra information
+ for us because only the low 32 bits of the registers are
+ call-saved. */
+ struct gcc_mcontext64 *m64 = (struct gcc_mcontext64 *)uctx->mcontext;
+ int i;
+
+ float_vector_state = &m64->fvs;
+
+ new_cfa = m64->gpr[1][1];
+
+ set_offset (CR2_REGNO, &m64->cr);
+ for (i = 0; i < 32; i++)
+ set_offset (i, m64->gpr[i] + 1);
+ set_offset (XER_REGNO, m64->xer + 1);
+ set_offset (LINK_REGISTER_REGNUM, m64->lr + 1);
+ set_offset (COUNT_REGISTER_REGNUM, m64->ctr + 1);
+ if (is_vector)
+ set_offset (VRSAVE_REGNO, &m64->vrsave);
+
+ /* Sometimes, srr0 points to the instruction that caused the exception,
+ and sometimes to the next instruction to be executed; we want
+ the latter. */
+ if (m64->exception == 3 || m64->exception == 4
+ || m64->exception == 6
+ || (m64->exception == 7 && !(m64->srr1 & 0x10000)))
+ return_addr = m64->srr0 + 4;
+ else
+ return_addr = m64->srr0;
+ }
+ else
+ {
+ struct gcc_mcontext32 *m = uctx->mcontext;
+ int i;
+
+ float_vector_state = &m->fvs;
+
+ new_cfa = m->gpr[1];
+
+ set_offset (CR2_REGNO, &m->cr);
+ for (i = 0; i < 32; i++)
+ set_offset (i, m->gpr + i);
+ set_offset (XER_REGNO, &m->xer);
+ set_offset (LINK_REGISTER_REGNUM, &m->lr);
+ set_offset (COUNT_REGISTER_REGNUM, &m->ctr);
+
+ if (is_vector)
+ set_offset (VRSAVE_REGNO, &m->vrsave);
+
+ /* Sometimes, srr0 points to the instruction that caused the exception,
+ and sometimes to the next instruction to be executed; we want
+ the latter. */
+ if (m->exception == 3 || m->exception == 4
+ || m->exception == 6
+ || (m->exception == 7 && !(m->srr1 & 0x10000)))
+ return_addr = m->srr0 + 4;
+ else
+ return_addr = m->srr0;
+ }
+
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = STACK_POINTER_REGNUM;
+ fs->cfa_offset = new_cfa - old_cfa;;
+
+ /* The choice of column for the return address is somewhat tricky.
+ Fortunately, the actual choice is private to this file, and
+ the space it's reserved from is the GCC register space, not the
+ DWARF2 numbering. So any free element of the right size is an OK
+ choice. Thus: */
+ fs->retaddr_column = ARG_POINTER_REGNUM;
+ /* FIXME: this should really be done using a DWARF2 location expression,
+ not using a static variable. In fact, this entire file should
+ be implemented in DWARF2 expressions. */
+ set_offset (ARG_POINTER_REGNUM, &return_addr);
+
+ for (i = 0; i < 32; i++)
+ set_offset (32 + i, float_vector_state->fpregs + i);
+ set_offset (SPEFSCR_REGNO, &float_vector_state->fpscr);
+
+ if (is_vector)
+ {
+ for (i = 0; i < 32; i++)
+ set_offset (FIRST_ALTIVEC_REGNO + i, float_vector_state->save_vr + i);
+ set_offset (VSCR_REGNO, float_vector_state->save_vscr);
+ }
+
+ return true;
+}
+
+/* This is also prototyped in rs6000/darwin.h, inside the
+ MD_FALLBACK_FRAME_STATE_FOR macro. */
+extern bool _Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs);
+
+/* Implement the MD_FALLBACK_FRAME_STATE_FOR macro,
+ returning true iff the frame was a sigreturn() frame that we
+ can understand. */
+
+bool
+_Unwind_fallback_frame_state_for (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ reg_unit gprs[32];
+
+ if (!interpret_libc (gprs, context))
+ return false;
+ return handle_syscall (fs, gprs, _Unwind_GetCFA (context));
+}
diff --git a/contrib/gcc/config/rs6000/darwin-fpsave.asm b/contrib/gcc/config/rs6000/darwin-fpsave.asm
new file mode 100644
index 0000000..86d4760
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-fpsave.asm
@@ -0,0 +1,102 @@
+/* This file contains the floating-point save and restore routines.
+ *
+ * Copyright (C) 2004 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 with other programs, and to distribute
+ * those programs 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 another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not 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.
+ */
+
+/* THE SAVE AND RESTORE ROUTINES CAN HAVE ONLY ONE GLOBALLY VISIBLE
+ ENTRY POINT - callers have to jump to "saveFP+60" to save f29..f31,
+ for example. For FP reg saves/restores, it takes one instruction
+ (4 bytes) to do the operation; for Vector regs, 2 instructions are
+ required (8 bytes.)
+
+ MORAL: DO NOT MESS AROUND WITH THESE FUNCTIONS! */
+
+#include "darwin-asm.h"
+
+.text
+ .align 2
+
+/* saveFP saves R0 -- assumed to be the callers LR -- to 8/16(R1). */
+
+.private_extern saveFP
+saveFP:
+ stfd f14,-144(r1)
+ stfd f15,-136(r1)
+ stfd f16,-128(r1)
+ stfd f17,-120(r1)
+ stfd f18,-112(r1)
+ stfd f19,-104(r1)
+ stfd f20,-96(r1)
+ stfd f21,-88(r1)
+ stfd f22,-80(r1)
+ stfd f23,-72(r1)
+ stfd f24,-64(r1)
+ stfd f25,-56(r1)
+ stfd f26,-48(r1)
+ stfd f27,-40(r1)
+ stfd f28,-32(r1)
+ stfd f29,-24(r1)
+ stfd f30,-16(r1)
+ stfd f31,-8(r1)
+ stg r0,SAVED_LR_OFFSET(r1)
+ blr
+
+/* restFP restores the caller`s LR from 8/16(R1). Note that the code for
+ this starts at the offset of F30 restoration, so calling this
+ routine in an attempt to restore only F31 WILL NOT WORK (it would
+ be a stupid thing to do, anyway.) */
+
+.private_extern restFP
+restFP:
+ lfd f14,-144(r1)
+ lfd f15,-136(r1)
+ lfd f16,-128(r1)
+ lfd f17,-120(r1)
+ lfd f18,-112(r1)
+ lfd f19,-104(r1)
+ lfd f20,-96(r1)
+ lfd f21,-88(r1)
+ lfd f22,-80(r1)
+ lfd f23,-72(r1)
+ lfd f24,-64(r1)
+ lfd f25,-56(r1)
+ lfd f26,-48(r1)
+ lfd f27,-40(r1)
+ lfd f28,-32(r1)
+ lfd f29,-24(r1)
+ /* <OFFSET OF F30 RESTORE> restore callers LR */
+ lg r0,SAVED_LR_OFFSET(r1)
+ lfd f30,-16(r1)
+ /* and prepare for return to caller */
+ mtlr r0
+ lfd f31,-8(r1)
+ blr
diff --git a/contrib/gcc/config/rs6000/darwin-ldouble-format b/contrib/gcc/config/rs6000/darwin-ldouble-format
new file mode 100644
index 0000000..0012a33
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-ldouble-format
@@ -0,0 +1,84 @@
+Long double format
+==================
+
+ Each long double is made up of two IEEE doubles. The value of the
+long double is the sum of the values of the two parts (except for
+-0.0). The most significant part is required to be the value of the
+long double rounded to the nearest double, as specified by IEEE. For
+Inf values, the least significant part is required to be one of +0.0
+or -0.0. No other requirements are made; so, for example, 1.0 may be
+represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a NaN
+is don't-care.
+
+Classification
+--------------
+
+A long double can represent any value of the form
+ s * 2^e * sum(k=0...105: f_k * 2^(-k))
+where 's' is +1 or -1, 'e' is between 1022 and -968 inclusive, f_0 is
+1, and f_k for k>0 is 0 or 1. These are the 'normal' long doubles.
+
+A long double can also represent any value of the form
+ s * 2^-968 * sum(k=0...105: f_k * 2^(-k))
+where 's' is +1 or -1, f_0 is 0, and f_k for k>0 is 0 or 1. These are
+the 'subnormal' long doubles.
+
+There are four long doubles that represent zero, two that represent
++0.0 and two that represent -0.0. The sign of the high part is the
+sign of the long double, and the sign of the low part is ignored.
+
+Likewise, there are four long doubles that represent infinities, two
+for +Inf and two for -Inf.
+
+Each NaN, quiet or signalling, that can be represented as a 'double'
+can be represented as a 'long double'. In fact, there are 2^64
+equivalent representations for each one.
+
+There are certain other valid long doubles where both parts are
+nonzero but the low part represents a value which has a bit set below
+2^(e-105). These, together with the subnormal long doubles, make up
+the denormal long doubles.
+
+Many possible long double bit patterns are not valid long doubles.
+These do not represent any value.
+
+Limits
+------
+
+The maximum representable long double is 2^1024-2^918. The smallest
+*normal* positive long double is 2^-968. The smallest denormalised
+positive long double is 2^-1074 (this is the same as for 'double').
+
+Conversions
+-----------
+
+A double can be converted to a long double by adding a zero low part.
+
+A long double can be converted to a double by removing the low part.
+
+Comparisons
+-----------
+
+Two long doubles can be compared by comparing the high parts, and if
+those compare equal, comparing the low parts.
+
+Arithmetic
+----------
+
+The unary negate operation operates by negating the low and high parts.
+
+An absolute or absolute-negate operation must be done by comparing
+against zero and negating if necessary.
+
+Addition and subtraction are performed using library routines. They
+are not at present performed perfectly accurately, the result produced
+will be within 1ulp of the range generated by adding or subtracting
+1ulp from the input values, where a 'ulp' is 2^(e-106) given the
+exponent 'e'. In the presence of cancellation, this may be
+arbitrarily inaccurate. Subtraction is done by negation and addition.
+
+Multiplication is also performed using a library routine. Its result
+will be within 2ulp of the correct result.
+
+Division is also performed using a library routine. Its result will
+be within 3ulp of the correct result.
diff --git a/contrib/gcc/config/rs6000/darwin-ldouble.c b/contrib/gcc/config/rs6000/darwin-ldouble.c
index 210f2d6..c30a98c 100644
--- a/contrib/gcc/config/rs6000/darwin-ldouble.c
+++ b/contrib/gcc/config/rs6000/darwin-ldouble.c
@@ -1,5 +1,6 @@
/* 128-bit long double support routines for Darwin.
- Copyright (C) 1993, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1993, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
This file is part of GCC.
@@ -24,18 +25,18 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* Implementations of floating-point long double basic arithmetic
functions called by the IBM C compiler when generating code for
PowerPC platforms. In particular, the following functions are
- implemented: _xlqadd, _xlqsub, _xlqmul, and _xlqdiv. Double-double
- algorithms are based on the paper "Doubled-Precision IEEE Standard
- 754 Floating-Point Arithmetic" by W. Kahan, February 26, 1987. An
- alternative published reference is "Software for Doubled-Precision
- Floating-Point Computations", by Seppo Linnainmaa, ACM TOMS vol 7
- no 3, September 1961, pages 272-283. */
+ implemented: __gcc_qadd, __gcc_qsub, __gcc_qmul, and __gcc_qdiv.
+ Double-double algorithms are based on the paper "Doubled-Precision
+ IEEE Standard 754 Floating-Point Arithmetic" by W. Kahan, February 26,
+ 1987. An alternative published reference is "Software for
+ Doubled-Precision Floating-Point Computations", by Seppo Linnainmaa,
+ ACM TOMS vol 7 no 3, September 1981, pages 272-283. */
/* Each long double is made up of two IEEE doubles. The value of the
long double is the sum of the values of the two parts. The most
@@ -48,36 +49,48 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
This code currently assumes big-endian. */
-#if !_SOFT_FLOAT && (defined (__MACH__) || defined (__powerpc64__) || defined (_AIX))
+#if ((!defined (__NO_FPRS__) || defined (_SOFT_FLOAT)) \
+ && !defined (__LITTLE_ENDIAN__) \
+ && (defined (__MACH__) || defined (__powerpc__) || defined (_AIX)))
#define fabs(x) __builtin_fabs(x)
+#define isless(x, y) __builtin_isless (x, y)
+#define inf() __builtin_inf()
#define unlikely(x) __builtin_expect ((x), 0)
+#define nonfinite(a) unlikely (! isless (fabs (a), inf ()))
+
+/* Define ALIASNAME as a strong alias for NAME. */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
/* All these routines actually take two long doubles as parameters,
but GCC currently generates poor code when a union is used to turn
a long double into a pair of doubles. */
-extern long double __gcc_qadd (double, double, double, double);
-extern long double __gcc_qsub (double, double, double, double);
-extern long double __gcc_qmul (double, double, double, double);
-extern long double __gcc_qdiv (double, double, double, double);
+long double __gcc_qadd (double, double, double, double);
+long double __gcc_qsub (double, double, double, double);
+long double __gcc_qmul (double, double, double, double);
+long double __gcc_qdiv (double, double, double, double);
-#if defined __ELF__ && defined IN_LIBGCC2_S
-/* Provide definitions of the old symbol names to statisfy apps and
+#if defined __ELF__ && defined SHARED \
+ && (defined __powerpc64__ || !(defined __linux__ || defined __gnu_hurd__))
+/* Provide definitions of the old symbol names to satisfy apps and
shared libs built against an older libgcc. To access the _xlq
symbols an explicit version reference is needed, so these won't
satisfy an unadorned reference like _xlqadd. If dot symbols are
not needed, the assembler will remove the aliases from the symbol
table. */
__asm__ (".symver __gcc_qadd,_xlqadd@GCC_3.4\n\t"
- ".symver __gcc_qsub,_xlqsub@GCC_3.4\n\t"
- ".symver __gcc_qmul,_xlqmul@GCC_3.4\n\t"
- ".symver __gcc_qdiv,_xlqdiv@GCC_3.4\n\t"
- ".symver .__gcc_qadd,._xlqadd@GCC_3.4\n\t"
- ".symver .__gcc_qsub,._xlqsub@GCC_3.4\n\t"
- ".symver .__gcc_qmul,._xlqmul@GCC_3.4\n\t"
- ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4");
+ ".symver __gcc_qsub,_xlqsub@GCC_3.4\n\t"
+ ".symver __gcc_qmul,_xlqmul@GCC_3.4\n\t"
+ ".symver __gcc_qdiv,_xlqdiv@GCC_3.4\n\t"
+ ".symver .__gcc_qadd,._xlqadd@GCC_3.4\n\t"
+ ".symver .__gcc_qsub,._xlqsub@GCC_3.4\n\t"
+ ".symver .__gcc_qmul,._xlqmul@GCC_3.4\n\t"
+ ".symver .__gcc_qdiv,._xlqdiv@GCC_3.4");
#endif
typedef union
@@ -86,66 +99,44 @@ typedef union
double dval[2];
} longDblUnion;
-static const double FPKINF = 1.0/0.0;
-
/* Add two 'long double' values and return the result. */
long double
-__gcc_qadd (double a, double b, double c, double d)
+__gcc_qadd (double a, double aa, double c, double cc)
{
- longDblUnion z;
- double t, tau, u, FPR_zero, FPR_PosInf;
-
- FPR_zero = 0.0;
- FPR_PosInf = FPKINF;
-
- if (unlikely (a != a) || unlikely (c != c))
- return a + c; /* NaN result. */
+ longDblUnion x;
+ double z, q, zz, xh;
- /* Ordered operands are arranged in order of their magnitudes. */
+ z = a + c;
- /* Switch inputs if |(c,d)| > |(a,b)|. */
- if (fabs (c) > fabs (a))
+ if (nonfinite (z))
{
- t = a;
- tau = b;
- a = c;
- b = d;
- c = t;
- d = tau;
+ z = cc + aa + c + a;
+ if (nonfinite (z))
+ return z;
+ x.dval[0] = z; /* Will always be DBL_MAX. */
+ zz = aa + cc;
+ if (fabs(a) > fabs(c))
+ x.dval[1] = a - z + c + zz;
+ else
+ x.dval[1] = c - z + a + zz;
}
-
- /* b <- second largest magnitude double. */
- if (fabs (c) > fabs (b))
- {
- t = b;
- b = c;
- c = t;
- }
-
- /* Thanks to commutivity, sum is invariant w.r.t. the next
- conditional exchange. */
- tau = d + c;
-
- /* Order the smallest magnitude doubles. */
- if (fabs (d) > fabs (c))
+ else
{
- t = c;
- c = d;
- d = t;
- }
+ q = a - z;
+ zz = q + c + (a - (q + z)) + aa + cc;
- t = (tau + b) + a; /* Sum values in ascending magnitude order. */
+ /* Keep -0 result. */
+ if (zz == 0.0)
+ return z;
- /* Infinite or zero result. */
- if (unlikely (t == FPR_zero) || unlikely (fabs (t) == FPR_PosInf))
- return t;
+ xh = z + zz;
+ if (nonfinite (xh))
+ return xh;
- /* Usual case. */
- tau = (((a-t) + b) + c) + d;
- u = t + tau;
- z.dval[0] = u; /* Final fixup for long double result. */
- z.dval[1] = (t - u) + tau;
- return z.ldval;
+ x.dval[0] = xh;
+ x.dval[1] = z - xh + zz;
+ }
+ return x.ldval;
}
long double
@@ -154,32 +145,38 @@ __gcc_qsub (double a, double b, double c, double d)
return __gcc_qadd (a, b, -c, -d);
}
+#ifdef _SOFT_FLOAT
+static double fmsub (double, double, double);
+#endif
+
long double
__gcc_qmul (double a, double b, double c, double d)
{
longDblUnion z;
- double t, tau, u, v, w, FPR_zero, FPR_PosInf;
+ double t, tau, u, v, w;
- FPR_zero = 0.0;
- FPR_PosInf = FPKINF;
-
t = a * c; /* Highest order double term. */
- if (unlikely (t != t) || unlikely (t == FPR_zero)
- || unlikely (fabs (t) == FPR_PosInf))
+ if (unlikely (t == 0) /* Preserve -0. */
+ || nonfinite (t))
return t;
- /* Finite nonzero result requires summing of terms of two highest
- orders. */
+ /* Sum terms of two highest orders. */
- /* Use fused multiply-add to get low part of a * c. */
+ /* Use fused multiply-add to get low part of a * c. */
+#ifndef _SOFT_FLOAT
asm ("fmsub %0,%1,%2,%3" : "=f"(tau) : "f"(a), "f"(c), "f"(t));
+#else
+ tau = fmsub (a, c, t);
+#endif
v = a*d;
w = b*c;
tau += v + w; /* Add in other second-order terms. */
u = t + tau;
/* Construct long double result. */
+ if (nonfinite (u))
+ return u;
z.dval[0] = u;
z.dval[1] = (t - u) + tau;
return z.ldval;
@@ -189,34 +186,253 @@ long double
__gcc_qdiv (double a, double b, double c, double d)
{
longDblUnion z;
- double s, sigma, t, tau, u, v, w, FPR_zero, FPR_PosInf;
-
- FPR_zero = 0.0;
- FPR_PosInf = FPKINF;
+ double s, sigma, t, tau, u, v, w;
t = a / c; /* highest order double term */
- if (unlikely (t != t) || unlikely (t == FPR_zero)
- || unlikely (fabs (t) == FPR_PosInf))
+ if (unlikely (t == 0) /* Preserve -0. */
+ || nonfinite (t))
return t;
/* Finite nonzero result requires corrections to the highest order term. */
- s = c * t; /* (s,sigma) = c*t exactly. */
+ s = c * t; /* (s,sigma) = c*t exactly. */
w = -(-b + d * t); /* Written to get fnmsub for speed, but not
numerically necessary. */
/* Use fused multiply-add to get low part of c * t. */
+#ifndef _SOFT_FLOAT
asm ("fmsub %0,%1,%2,%3" : "=f"(sigma) : "f"(c), "f"(t), "f"(s));
+#else
+ sigma = fmsub (c, t, s);
+#endif
v = a - s;
- tau = ((v-sigma)+w)/c; /* Correction to t. */
+ tau = ((v-sigma)+w)/c; /* Correction to t. */
u = t + tau;
- /* Construct long double result. */
+ /* Construct long double result. */
+ if (nonfinite (u))
+ return u;
z.dval[0] = u;
z.dval[1] = (t - u) + tau;
return z.ldval;
}
+#if defined (_SOFT_FLOAT) && defined (__LONG_DOUBLE_128__)
+
+long double __gcc_qneg (double, double);
+int __gcc_qeq (double, double, double, double);
+int __gcc_qne (double, double, double, double);
+int __gcc_qge (double, double, double, double);
+int __gcc_qle (double, double, double, double);
+int __gcc_qunord (double, double, double, double);
+long double __gcc_stoq (float);
+long double __gcc_dtoq (double);
+float __gcc_qtos (double, double);
+double __gcc_qtod (double, double);
+int __gcc_qtoi (double, double);
+unsigned int __gcc_qtou (double, double);
+long double __gcc_itoq (int);
+long double __gcc_utoq (unsigned int);
+
+extern int __eqdf2 (double, double);
+extern int __ledf2 (double, double);
+extern int __gedf2 (double, double);
+extern int __unorddf2 (double, double);
+
+/* Negate 'long double' value and return the result. */
+long double
+__gcc_qneg (double a, double aa)
+{
+ longDblUnion x;
+
+ x.dval[0] = -a;
+ x.dval[1] = -aa;
+ return x.ldval;
+}
+
+/* Compare two 'long double' values for equality. */
+int
+__gcc_qeq (double a, double aa, double c, double cc)
+{
+ if (__eqdf2 (a, c) == 0)
+ return __eqdf2 (aa, cc);
+ return 1;
+}
+
+strong_alias (__gcc_qeq, __gcc_qne);
+
+/* Compare two 'long double' values for less than or equal. */
+int
+__gcc_qle (double a, double aa, double c, double cc)
+{
+ if (__eqdf2 (a, c) == 0)
+ return __ledf2 (aa, cc);
+ return __ledf2 (a, c);
+}
+
+strong_alias (__gcc_qle, __gcc_qlt);
+
+/* Compare two 'long double' values for greater than or equal. */
+int
+__gcc_qge (double a, double aa, double c, double cc)
+{
+ if (__eqdf2 (a, c) == 0)
+ return __gedf2 (aa, cc);
+ return __gedf2 (a, c);
+}
+
+strong_alias (__gcc_qge, __gcc_qgt);
+
+/* Compare two 'long double' values for unordered. */
+int
+__gcc_qunord (double a, double aa, double c, double cc)
+{
+ if (__eqdf2 (a, c) == 0)
+ return __unorddf2 (aa, cc);
+ return __unorddf2 (a, c);
+}
+
+/* Convert single to long double. */
+long double
+__gcc_stoq (float a)
+{
+ longDblUnion x;
+
+ x.dval[0] = (double) a;
+ x.dval[1] = 0.0;
+
+ return x.ldval;
+}
+
+/* Convert double to long double. */
+long double
+__gcc_dtoq (double a)
+{
+ longDblUnion x;
+
+ x.dval[0] = a;
+ x.dval[1] = 0.0;
+
+ return x.ldval;
+}
+
+/* Convert long double to single. */
+float
+__gcc_qtos (double a, double aa __attribute__ ((__unused__)))
+{
+ return (float) a;
+}
+
+/* Convert long double to double. */
+double
+__gcc_qtod (double a, double aa __attribute__ ((__unused__)))
+{
+ return a;
+}
+
+/* Convert long double to int. */
+int
+__gcc_qtoi (double a, double aa)
+{
+ double z = a + aa;
+ return (int) z;
+}
+
+/* Convert long double to unsigned int. */
+unsigned int
+__gcc_qtou (double a, double aa)
+{
+ double z = a + aa;
+ return (unsigned int) z;
+}
+
+/* Convert int to long double. */
+long double
+__gcc_itoq (int a)
+{
+ return __gcc_dtoq ((double) a);
+}
+
+/* Convert unsigned int to long double. */
+long double
+__gcc_utoq (unsigned int a)
+{
+ return __gcc_dtoq ((double) a);
+}
+
+#include "config/soft-fp/soft-fp.h"
+#include "config/soft-fp/double.h"
+#include "config/soft-fp/quad.h"
+
+/* Compute floating point multiply-subtract with higher (quad) precision. */
+static double
+fmsub (double a, double b, double c)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ FP_DECL_D(B);
+ FP_DECL_D(C);
+ FP_DECL_Q(X);
+ FP_DECL_Q(Y);
+ FP_DECL_Q(Z);
+ FP_DECL_Q(U);
+ FP_DECL_Q(V);
+ FP_DECL_D(R);
+ double r;
+ long double u, v, x, y, z;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_RAW_D (A, a);
+ FP_UNPACK_RAW_D (B, b);
+ FP_UNPACK_RAW_D (C, c);
+
+ /* Extend double to quad. */
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_EXTEND(Q,D,4,2,X,A);
+ FP_EXTEND(Q,D,4,2,Y,B);
+ FP_EXTEND(Q,D,4,2,Z,C);
+#else
+ FP_EXTEND(Q,D,2,1,X,A);
+ FP_EXTEND(Q,D,2,1,Y,B);
+ FP_EXTEND(Q,D,2,1,Z,C);
+#endif
+ FP_PACK_RAW_Q(x,X);
+ FP_PACK_RAW_Q(y,Y);
+ FP_PACK_RAW_Q(z,Z);
+ FP_HANDLE_EXCEPTIONS;
+
+ /* Multiply. */
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_Q(X,x);
+ FP_UNPACK_Q(Y,y);
+ FP_MUL_Q(U,X,Y);
+ FP_PACK_Q(u,U);
+ FP_HANDLE_EXCEPTIONS;
+
+ /* Subtract. */
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(U,u);
+ FP_UNPACK_SEMIRAW_Q(Z,z);
+ FP_SUB_Q(V,U,Z);
+ FP_PACK_SEMIRAW_Q(v,V);
+ FP_HANDLE_EXCEPTIONS;
+
+ /* Truncate quad to double. */
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(V,v);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_TRUNC(D,Q,2,4,R,V);
+#else
+ FP_TRUNC(D,Q,1,2,R,V);
+#endif
+ FP_PACK_SEMIRAW_D(r,R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+#endif
+
#endif
diff --git a/contrib/gcc/config/rs6000/darwin-libgcc.10.4.ver b/contrib/gcc/config/rs6000/darwin-libgcc.10.4.ver
new file mode 100644
index 0000000..019218d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-libgcc.10.4.ver
@@ -0,0 +1,76 @@
+__Unwind_Backtrace
+__Unwind_DeleteException
+__Unwind_FindEnclosingFunction
+__Unwind_Find_FDE
+__Unwind_ForcedUnwind
+__Unwind_GetCFA
+__Unwind_GetDataRelBase
+__Unwind_GetGR
+__Unwind_GetIP
+__Unwind_GetLanguageSpecificData
+__Unwind_GetRegionStart
+__Unwind_GetTextRelBase
+__Unwind_RaiseException
+__Unwind_Resume
+__Unwind_Resume_or_Rethrow
+__Unwind_SetGR
+__Unwind_SetIP
+___absvdi2
+___absvsi2
+___addvdi3
+___addvsi3
+___ashldi3
+___ashrdi3
+___clear_cache
+___clzdi2
+___clzsi2
+___cmpdi2
+___ctzdi2
+___ctzsi2
+___deregister_frame
+___deregister_frame_info
+___deregister_frame_info_bases
+___divdi3
+___enable_execute_stack
+___ffsdi2
+___fixdfdi
+___fixsfdi
+___fixtfdi
+___fixunsdfdi
+___fixunsdfsi
+___fixunssfdi
+___fixunssfsi
+___fixunstfdi
+___floatdidf
+___floatdisf
+___floatditf
+___gcc_personality_v0
+___gcc_qadd
+___gcc_qdiv
+___gcc_qmul
+___gcc_qsub
+___lshrdi3
+___moddi3
+___muldi3
+___mulvdi3
+___mulvsi3
+___negdi2
+___negvdi2
+___negvsi2
+___paritydi2
+___paritysi2
+___popcountdi2
+___popcountsi2
+___register_frame
+___register_frame_info
+___register_frame_info_bases
+___register_frame_info_table
+___register_frame_info_table_bases
+___register_frame_table
+___subvdi3
+___subvsi3
+___trampoline_setup
+___ucmpdi2
+___udivdi3
+___udivmoddi4
+___umoddi3
diff --git a/contrib/gcc/config/rs6000/darwin-libgcc.10.5.ver b/contrib/gcc/config/rs6000/darwin-libgcc.10.5.ver
new file mode 100644
index 0000000..7e0dd52
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-libgcc.10.5.ver
@@ -0,0 +1,89 @@
+__Unwind_Backtrace
+__Unwind_DeleteException
+__Unwind_FindEnclosingFunction
+__Unwind_Find_FDE
+__Unwind_ForcedUnwind
+__Unwind_GetCFA
+__Unwind_GetDataRelBase
+__Unwind_GetGR
+__Unwind_GetIP
+__Unwind_GetIPInfo
+__Unwind_GetLanguageSpecificData
+__Unwind_GetRegionStart
+__Unwind_GetTextRelBase
+__Unwind_RaiseException
+__Unwind_Resume
+__Unwind_Resume_or_Rethrow
+__Unwind_SetGR
+__Unwind_SetIP
+___absvdi2
+___absvsi2
+___addvdi3
+___addvsi3
+___ashldi3
+___ashrdi3
+___clear_cache
+___clzdi2
+___clzsi2
+___cmpdi2
+___ctzdi2
+___ctzsi2
+___deregister_frame
+___deregister_frame_info
+___deregister_frame_info_bases
+___divdc3
+___divdi3
+___divsc3
+___divtc3
+___enable_execute_stack
+___ffsdi2
+___fixdfdi
+___fixsfdi
+___fixtfdi
+___fixunsdfdi
+___fixunsdfsi
+___fixunssfdi
+___fixunssfsi
+___fixunstfdi
+___floatdidf
+___floatdisf
+___floatditf
+___floatundidf
+___floatundisf
+___floatunditf
+___gcc_personality_v0
+___gcc_qadd
+___gcc_qdiv
+___gcc_qmul
+___gcc_qsub
+___lshrdi3
+___moddi3
+___muldc3
+___muldi3
+___mulsc3
+___multc3
+___mulvdi3
+___mulvsi3
+___negdi2
+___negvdi2
+___negvsi2
+___paritydi2
+___paritysi2
+___popcountdi2
+___popcountsi2
+___powidf2
+___powisf2
+___powitf2
+___register_frame
+___register_frame_info
+___register_frame_info_bases
+___register_frame_info_table
+___register_frame_info_table_bases
+___register_frame_table
+___subvdi3
+___subvsi3
+___trampoline_setup
+___ucmpdi2
+___udivdi3
+___udivmoddi4
+___umoddi3
diff --git a/contrib/gcc/config/rs6000/darwin-tramp.asm b/contrib/gcc/config/rs6000/darwin-tramp.asm
index 22ce80a..62522b9 100644
--- a/contrib/gcc/config/rs6000/darwin-tramp.asm
+++ b/contrib/gcc/config/rs6000/darwin-tramp.asm
@@ -1,6 +1,6 @@
/* Special support for trampolines
*
- * Copyright (C) 1996, 1997, 2000 Free Software Foundation, Inc.
+ * Copyright (C) 1996, 1997, 2000, 2004, 2005 Free Software Foundation, Inc.
* Written By Michael Meissner
*
* This file is free software; you can redistribute it and/or modify it
@@ -23,8 +23,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause the
@@ -33,22 +33,24 @@
* executable file might be covered by the GNU General Public License.
*/
+#include "darwin-asm.h"
+
/* Set up trampolines. */
.text
- .align 2
+ .align LOG2_GPR_BYTES
Ltrampoline_initial:
mflr r0
bl 1f
Lfunc = .-Ltrampoline_initial
- .long 0 /* will be replaced with function address */
+ .g_long 0 /* will be replaced with function address */
Lchain = .-Ltrampoline_initial
- .long 0 /* will be replaced with static chain */
+ .g_long 0 /* will be replaced with static chain */
1: mflr r11
- lwz r12,0(r11) /* function address */
+ lg r12,0(r11) /* function address */
mtlr r0
mtctr r12
- lwz r11,4(r11) /* static chain */
+ lg r11,GPR_BYTES(r11) /* static chain */
bctr
trampoline_size = .-Ltrampoline_initial
@@ -65,12 +67,12 @@ ___trampoline_setup:
LCF0:
mflr r11
addis r7,r11,ha16(LTRAMP-LCF0)
- lwz r7,lo16(LTRAMP-LCF0)(r7)
+ lg r7,lo16(LTRAMP-LCF0)(r7)
subi r7,r7,4
li r8,trampoline_size /* verify trampoline big enough */
- cmpw cr1,r8,r4
- srwi r4,r4,2 /* # words to move */
- addi r9,r3,-4 /* adjust pointer for lwzu */
+ cmpg cr1,r8,r4
+ srwi r4,r4,2 /* # words to move (insns always 4-byte) */
+ addi r9,r3,-4 /* adjust pointer for lgu */
mtctr r4
blt cr1,Labort
@@ -83,8 +85,8 @@ Lmove:
bdnz Lmove
/* Store correct function and static chain */
- stw r5,Lfunc(r3)
- stw r6,Lchain(r3)
+ stg r5,Lfunc(r3)
+ stg r6,Lchain(r3)
/* Now flush both caches */
mtctr r4
@@ -94,16 +96,19 @@ Lcache:
addi r3,r3,4
bdnz Lcache
- /* Finally synchronize things & return */
+ /* Ensure cache-flushing has finished. */
sync
isync
- blr
+
+ /* Make stack writeable. */
+ b ___enable_execute_stack
Labort:
#ifdef __DYNAMIC__
bl L_abort$stub
.data
-.picsymbol_stub
+.section __TEXT,__picsymbolstub1,symbol_stubs,pure_instructions,32
+ .align 2
L_abort$stub:
.indirect_symbol _abort
mflr r0
@@ -112,20 +117,19 @@ L0$_abort:
mflr r11
addis r11,r11,ha16(L_abort$lazy_ptr-L0$_abort)
mtlr r0
- lwz r12,lo16(L_abort$lazy_ptr-L0$_abort)(r11)
+ lgu r12,lo16(L_abort$lazy_ptr-L0$_abort)(r11)
mtctr r12
- addi r11,r11,lo16(L_abort$lazy_ptr-L0$_abort)
bctr
.data
.lazy_symbol_pointer
L_abort$lazy_ptr:
.indirect_symbol _abort
- .long dyld_stub_binding_helper
+ .g_long dyld_stub_binding_helper
#else
bl _abort
#endif
.data
- .align 2
+ .align LOG2_GPR_BYTES
LTRAMP:
- .long Ltrampoline_initial
+ .g_long Ltrampoline_initial
diff --git a/contrib/gcc/config/rs6000/darwin-unwind.h b/contrib/gcc/config/rs6000/darwin-unwind.h
new file mode 100644
index 0000000..9218c5a
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-unwind.h
@@ -0,0 +1,35 @@
+/* DWARF2 EH unwinding support for Darwin.
+ Copyright (C) 2004 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 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 combined
+ executable.)
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301, USA. */
+
+extern bool _Unwind_fallback_frame_state_for
+ (struct _Unwind_Context *context, _Unwind_FrameState *fs);
+
+#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS) \
+ (_Unwind_fallback_frame_state_for (CONTEXT, FS) \
+ ? _URC_NO_REASON : _URC_END_OF_STACK)
diff --git a/contrib/gcc/config/rs6000/darwin-vecsave.asm b/contrib/gcc/config/rs6000/darwin-vecsave.asm
new file mode 100644
index 0000000..693879f
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-vecsave.asm
@@ -0,0 +1,165 @@
+/* This file contains the vector save and restore routines.
+ *
+ * Copyright (C) 2004 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 with other programs, and to distribute
+ * those programs 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 another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not 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.
+ */
+
+/* Vector save/restore routines for Darwin. Note that each vector
+ save/restore requires 2 instructions (8 bytes.)
+
+ THE SAVE AND RESTORE ROUTINES CAN HAVE ONLY ONE GLOBALLY VISIBLE
+ ENTRY POINT - callers have to jump to "saveFP+60" to save f29..f31,
+ for example. For FP reg saves/restores, it takes one instruction
+ (4 bytes) to do the operation; for Vector regs, 2 instructions are
+ required (8 bytes.). */
+
+ .machine ppc7400
+.text
+ .align 2
+
+.private_extern saveVEC
+saveVEC:
+ li r11,-192
+ stvx v20,r11,r0
+ li r11,-176
+ stvx v21,r11,r0
+ li r11,-160
+ stvx v22,r11,r0
+ li r11,-144
+ stvx v23,r11,r0
+ li r11,-128
+ stvx v24,r11,r0
+ li r11,-112
+ stvx v25,r11,r0
+ li r11,-96
+ stvx v26,r11,r0
+ li r11,-80
+ stvx v27,r11,r0
+ li r11,-64
+ stvx v28,r11,r0
+ li r11,-48
+ stvx v29,r11,r0
+ li r11,-32
+ stvx v30,r11,r0
+ li r11,-16
+ stvx v31,r11,r0
+ blr
+
+.private_extern restVEC
+restVEC:
+ li r11,-192
+ lvx v20,r11,r0
+ li r11,-176
+ lvx v21,r11,r0
+ li r11,-160
+ lvx v22,r11,r0
+ li r11,-144
+ lvx v23,r11,r0
+ li r11,-128
+ lvx v24,r11,r0
+ li r11,-112
+ lvx v25,r11,r0
+ li r11,-96
+ lvx v26,r11,r0
+ li r11,-80
+ lvx v27,r11,r0
+ li r11,-64
+ lvx v28,r11,r0
+ li r11,-48
+ lvx v29,r11,r0
+ li r11,-32
+ lvx v30,r11,r0
+ li r11,-16
+ lvx v31,r11,r0
+ blr
+
+/* saveVEC_vr11 -- as saveVEC but VRsave is returned in R11. */
+
+.private_extern saveVEC_vr11
+saveVEC_vr11:
+ li r11,-192
+ stvx v20,r11,r0
+ li r11,-176
+ stvx v21,r11,r0
+ li r11,-160
+ stvx v22,r11,r0
+ li r11,-144
+ stvx v23,r11,r0
+ li r11,-128
+ stvx v24,r11,r0
+ li r11,-112
+ stvx v25,r11,r0
+ li r11,-96
+ stvx v26,r11,r0
+ li r11,-80
+ stvx v27,r11,r0
+ li r11,-64
+ stvx v28,r11,r0
+ li r11,-48
+ stvx v29,r11,r0
+ li r11,-32
+ stvx v30,r11,r0
+ li r11,-16
+ stvx v31,r11,r0
+ mfspr r11,VRsave
+ blr
+
+/* As restVec, but the original VRsave value passed in R10. */
+
+.private_extern restVEC_vr10
+restVEC_vr10:
+ li r11,-192
+ lvx v20,r11,r0
+ li r11,-176
+ lvx v21,r11,r0
+ li r11,-160
+ lvx v22,r11,r0
+ li r11,-144
+ lvx v23,r11,r0
+ li r11,-128
+ lvx v24,r11,r0
+ li r11,-112
+ lvx v25,r11,r0
+ li r11,-96
+ lvx v26,r11,r0
+ li r11,-80
+ lvx v27,r11,r0
+ li r11,-64
+ lvx v28,r11,r0
+ li r11,-48
+ lvx v29,r11,r0
+ li r11,-32
+ lvx v30,r11,r0
+ li r11,-16
+ lvx v31,r11,r0
+ /* restore VRsave from R10. */
+ mtspr VRsave,r10
+ blr
diff --git a/contrib/gcc/config/rs6000/darwin-world.asm b/contrib/gcc/config/rs6000/darwin-world.asm
new file mode 100644
index 0000000..7ff51b5
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin-world.asm
@@ -0,0 +1,269 @@
+/* This file contains the exception-handling save_world and
+ * restore_world routines, which need to do a run-time check to see if
+ * they should save and restore the vector registers.
+ *
+ * Copyright (C) 2004 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 with other programs, and to distribute
+ * those programs 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 another program.)
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * As a special exception, if you link this library with files
+ * compiled with GCC to produce an executable, this does not 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.
+ */
+
+ .machine ppc7400
+.data
+ .align 2
+
+#ifdef __DYNAMIC__
+
+.non_lazy_symbol_pointer
+L_has_vec$non_lazy_ptr:
+ .indirect_symbol __cpu_has_altivec
+#ifdef __ppc64__
+ .quad 0
+#else
+ .long 0
+#endif
+
+#else
+
+/* For static, "pretend" we have a non-lazy-pointer. */
+
+L_has_vec$non_lazy_ptr:
+ .long __cpu_has_altivec
+
+#endif
+
+
+.text
+ .align 2
+
+/* save_world and rest_world save/restore F14-F31 and possibly V20-V31
+ (assuming you have a CPU with vector registers; we use a global var
+ provided by the System Framework to determine this.)
+
+ SAVE_WORLD takes R0 (the caller`s caller`s return address) and R11
+ (the stack frame size) as parameters. It returns VRsave in R0 if
+ we`re on a CPU with vector regs.
+
+ With gcc3, we now need to save and restore CR as well, since gcc3's
+ scheduled prologs can cause comparisons to be moved before calls to
+ save_world!
+
+ USES: R0 R11 R12 */
+
+.private_extern save_world
+save_world:
+ stw r0,8(r1)
+ mflr r0
+ bcl 20,31,Ls$pb
+Ls$pb: mflr r12
+ addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Ls$pb)
+ lwz r12,lo16(L_has_vec$non_lazy_ptr-Ls$pb)(r12)
+ mtlr r0
+ lwz r12,0(r12)
+ /* grab CR */
+ mfcr r0
+ /* test HAS_VEC */
+ cmpwi r12,0
+ stfd f14,-144(r1)
+ stfd f15,-136(r1)
+ stfd f16,-128(r1)
+ stfd f17,-120(r1)
+ stfd f18,-112(r1)
+ stfd f19,-104(r1)
+ stfd f20,-96(r1)
+ stfd f21,-88(r1)
+ stfd f22,-80(r1)
+ stfd f23,-72(r1)
+ stfd f24,-64(r1)
+ stfd f25,-56(r1)
+ stfd f26,-48(r1)
+ stfd f27,-40(r1)
+ stfd f28,-32(r1)
+ stfd f29,-24(r1)
+ stfd f30,-16(r1)
+ stfd f31,-8(r1)
+ stmw r13,-220(r1)
+ /* stash CR */
+ stw r0,4(r1)
+ /* set R12 pointing at Vector Reg save area */
+ addi r12,r1,-224
+ /* allocate stack frame */
+ stwux r1,r1,r11
+ /* ...but return if HAS_VEC is zero */
+ bne+ L$saveVMX
+ /* Not forgetting to restore CR. */
+ mtcr r0
+ blr
+
+L$saveVMX:
+ /* We're saving Vector regs too. */
+ /* Restore CR from R0. No More Branches! */
+ mtcr r0
+
+ /* We should really use VRSAVE to figure out which vector regs
+ we actually need to save and restore. Some other time :-/ */
+
+ li r11,-192
+ stvx v20,r11,r12
+ li r11,-176
+ stvx v21,r11,r12
+ li r11,-160
+ stvx v22,r11,r12
+ li r11,-144
+ stvx v23,r11,r12
+ li r11,-128
+ stvx v24,r11,r12
+ li r11,-112
+ stvx v25,r11,r12
+ li r11,-96
+ stvx v26,r11,r12
+ li r11,-80
+ stvx v27,r11,r12
+ li r11,-64
+ stvx v28,r11,r12
+ li r11,-48
+ stvx v29,r11,r12
+ li r11,-32
+ stvx v30,r11,r12
+ mfspr r0,VRsave
+ li r11,-16
+ stvx v31,r11,r12
+ /* VRsave lives at -224(R1) */
+ stw r0,0(r12)
+ blr
+
+
+/* eh_rest_world_r10 is jumped to, not called, so no need to worry about LR.
+ R10 is the C++ EH stack adjust parameter, we return to the caller`s caller.
+
+ USES: R0 R10 R11 R12 and R7 R8
+ RETURNS: C++ EH Data registers (R3 - R6.)
+
+ We now set up R7/R8 and jump to rest_world_eh_r7r8.
+
+ rest_world doesn't use the R10 stack adjust parameter, nor does it
+ pick up the R3-R6 exception handling stuff. */
+
+.private_extern rest_world
+rest_world:
+ /* Pickup previous SP */
+ lwz r11, 0(r1)
+ li r7, 0
+ lwz r8, 8(r11)
+ li r10, 0
+ b rest_world_eh_r7r8
+
+.private_extern eh_rest_world_r10
+eh_rest_world_r10:
+ /* Pickup previous SP */
+ lwz r11, 0(r1)
+ mr r7,r10
+ lwz r8, 8(r11)
+ /* pickup the C++ EH data regs (R3 - R6.) */
+ lwz r6,-420(r11)
+ lwz r5,-424(r11)
+ lwz r4,-428(r11)
+ lwz r3,-432(r11)
+
+ b rest_world_eh_r7r8
+
+/* rest_world_eh_r7r8 is jumped to -- not called! -- when we're doing
+ the exception-handling epilog. R7 contains the offset to add to
+ the SP, and R8 contains the 'real' return address.
+
+ USES: R0 R11 R12 [R7/R8]
+ RETURNS: C++ EH Data registers (R3 - R6.) */
+
+rest_world_eh_r7r8:
+ bcl 20,31,Lr7r8$pb
+Lr7r8$pb: mflr r12
+ lwz r11,0(r1)
+ /* R11 := previous SP */
+ addis r12,r12,ha16(L_has_vec$non_lazy_ptr-Lr7r8$pb)
+ lwz r12,lo16(L_has_vec$non_lazy_ptr-Lr7r8$pb)(r12)
+ lwz r0,4(r11)
+ /* R0 := old CR */
+ lwz r12,0(r12)
+ /* R12 := HAS_VEC */
+ mtcr r0
+ cmpwi r12,0
+ lmw r13,-220(r11)
+ beq L.rest_world_fp_eh
+ /* restore VRsave and V20..V31 */
+ lwz r0,-224(r11)
+ li r12,-416
+ mtspr VRsave,r0
+ lvx v20,r11,r12
+ li r12,-400
+ lvx v21,r11,r12
+ li r12,-384
+ lvx v22,r11,r12
+ li r12,-368
+ lvx v23,r11,r12
+ li r12,-352
+ lvx v24,r11,r12
+ li r12,-336
+ lvx v25,r11,r12
+ li r12,-320
+ lvx v26,r11,r12
+ li r12,-304
+ lvx v27,r11,r12
+ li r12,-288
+ lvx v28,r11,r12
+ li r12,-272
+ lvx v29,r11,r12
+ li r12,-256
+ lvx v30,r11,r12
+ li r12,-240
+ lvx v31,r11,r12
+
+L.rest_world_fp_eh:
+ lfd f14,-144(r11)
+ lfd f15,-136(r11)
+ lfd f16,-128(r11)
+ lfd f17,-120(r11)
+ lfd f18,-112(r11)
+ lfd f19,-104(r11)
+ lfd f20,-96(r11)
+ lfd f21,-88(r11)
+ lfd f22,-80(r11)
+ lfd f23,-72(r11)
+ lfd f24,-64(r11)
+ lfd f25,-56(r11)
+ lfd f26,-48(r11)
+ lfd f27,-40(r11)
+ lfd f28,-32(r11)
+ lfd f29,-24(r11)
+ lfd f30,-16(r11)
+ /* R8 is the exception-handler's address */
+ mtctr r8
+ lfd f31,-8(r11)
+ /* set SP to original value + R7 offset */
+ add r1,r11,r7
+ bctr
diff --git a/contrib/gcc/config/rs6000/darwin.h b/contrib/gcc/config/rs6000/darwin.h
index cae8bac..7bd53fc 100644
--- a/contrib/gcc/config/rs6000/darwin.h
+++ b/contrib/gcc/config/rs6000/darwin.h
@@ -1,5 +1,6 @@
/* Target definitions for PowerPC running Darwin (Mac OS X).
- Copyright (C) 1997, 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Apple Computer Inc.
This file is part of GCC.
@@ -16,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (Darwin/PowerPC)");
@@ -26,106 +27,180 @@
#define DEFAULT_ABI ABI_DARWIN
+#ifdef IN_LIBGCC2
+#undef TARGET_64BIT
+#ifdef __powerpc64__
+#define TARGET_64BIT 1
+#else
+#define TARGET_64BIT 0
+#endif
+#endif
+
/* The object file format is Mach-O. */
#define TARGET_OBJECT_FORMAT OBJECT_MACHO
+/* Size of the Obj-C jump buffer. */
+#define OBJC_JBLEN ((TARGET_64BIT) ? (26*2 + 18*2 + 129 + 1) : (26 + 18*2 + 129 + 1))
+
/* We're not ever going to do TOCs. */
#define TARGET_TOC 0
#define TARGET_NO_TOC 1
-/* Darwin switches. */
-/* Use dynamic-no-pic codegen (no picbase reg; not suitable for shlibs.) */
-#define MASK_MACHO_DYNAMIC_NO_PIC 0x00800000
-
-#define TARGET_DYNAMIC_NO_PIC (target_flags & MASK_MACHO_DYNAMIC_NO_PIC)
-
-/* Handle #pragma weak and #pragma pack. */
-#define HANDLE_SYSV_PRAGMA 1
+/* Override the default rs6000 definition. */
+#undef PTRDIFF_TYPE
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long int" : "int")
+/* Translate config/rs6000/darwin.opt to config/darwin.h. */
+#define TARGET_DYNAMIC_NO_PIC (TARGET_MACHO_DYNAMIC_NO_PIC)
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define ("__ppc__"); \
+ if (!TARGET_64BIT) builtin_define ("__ppc__"); \
+ if (TARGET_64BIT) builtin_define ("__ppc64__"); \
builtin_define ("__POWERPC__"); \
builtin_define ("__NATURAL_ALIGNMENT__"); \
- builtin_define ("__MACH__"); \
- builtin_define ("__APPLE__"); \
+ darwin_cpp_builtins (pfile); \
} \
while (0)
-/* */
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- {"dynamic-no-pic", MASK_MACHO_DYNAMIC_NO_PIC, \
- N_("Generate code suitable for executables (NOT shared libs)")}, \
- {"no-dynamic-no-pic", -MASK_MACHO_DYNAMIC_NO_PIC, ""},
-
-
-/* The Darwin ABI always includes AltiVec, can't be (validly) turned
- off. */
-
-#define SUBTARGET_OVERRIDE_OPTIONS \
+#define SUBTARGET_OVERRIDE_OPTIONS \
do { \
+ /* The Darwin ABI always includes AltiVec, can't be (validly) turned \
+ off. */ \
rs6000_altivec_abi = 1; \
- rs6000_altivec_vrsave = 1; \
+ TARGET_ALTIVEC_VRSAVE = 1; \
if (DEFAULT_ABI == ABI_DARWIN) \
{ \
if (MACHO_DYNAMIC_NO_PIC_P) \
{ \
if (flag_pic) \
- warning ("-mdynamic-no-pic overrides -fpic or -fPIC"); \
+ warning (0, "-mdynamic-no-pic overrides -fpic or -fPIC"); \
flag_pic = 0; \
} \
else if (flag_pic == 1) \
{ \
- /* Darwin doesn't support -fpic. */ \
- warning ("-fpic is not supported; -fPIC assumed"); \
flag_pic = 2; \
} \
} \
-}while(0)
+ if (TARGET_64BIT && ! TARGET_POWERPC64) \
+ { \
+ target_flags |= MASK_POWERPC64; \
+ warning (0, "-m64 requires PowerPC64 architecture, enabling"); \
+ } \
+ if (flag_mkernel) \
+ { \
+ rs6000_default_long_calls = 1; \
+ target_flags |= MASK_SOFT_FLOAT; \
+ } \
+ \
+ /* Make -m64 imply -maltivec. Darwin's 64-bit ABI includes \
+ Altivec. */ \
+ if (!flag_mkernel && !flag_apple_kext \
+ && TARGET_64BIT \
+ && ! (target_flags_explicit & MASK_ALTIVEC)) \
+ target_flags |= MASK_ALTIVEC; \
+ \
+ /* Unless the user (not the configurer) has explicitly overridden \
+ it with -mcpu=G3 or -mno-altivec, then 10.5+ targets default to \
+ G4 unless targetting the kernel. */ \
+ if (!flag_mkernel \
+ && !flag_apple_kext \
+ && darwin_macosx_version_min \
+ && strverscmp (darwin_macosx_version_min, "10.5") >= 0 \
+ && ! (target_flags_explicit & MASK_ALTIVEC) \
+ && ! rs6000_select[1].string) \
+ { \
+ target_flags |= MASK_ALTIVEC; \
+ } \
+} while(0)
+
+#define C_COMMON_OVERRIDE_OPTIONS do { \
+ /* On powerpc, __cxa_get_exception_ptr is available starting in the \
+ 10.4.6 libstdc++.dylib. */ \
+ if ((! darwin_macosx_version_min \
+ || strverscmp (darwin_macosx_version_min, "10.4.6") < 0) \
+ && flag_use_cxa_get_exception_ptr == 2) \
+ flag_use_cxa_get_exception_ptr = 0; \
+ if (flag_mkernel) \
+ flag_no_builtin = 1; \
+ SUBTARGET_C_COMMON_OVERRIDE_OPTIONS; \
+} while (0)
+
+/* Darwin has 128-bit long double support in libc in 10.4 and later.
+ Default to 128-bit long doubles even on earlier platforms for ABI
+ consistency; arithmetic will work even if libc and libm support is
+ not available. */
+
+#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
+
/* We want -fPIC by default, unless we're using -static to compile for
the kernel or some such. */
-
#define CC1_SPEC "\
-%{gused: -feliminate-unused-debug-symbols %<gused }\
-%{static: %{Zdynamic: %e conflicting code gen style switches are used}}\
-%{!static:%{!mdynamic-no-pic:-fPIC}}"
-
-/* It's virtually impossible to predict all the possible combinations
- of -mcpu and -maltivec and whatnot, so just supply
- -force_cpusubtype_ALL if any are seen. Radar 3492132 against the
- assembler is asking for a .machine directive so we could get this
- really right. */
-#define ASM_SPEC "-arch ppc \
- %{Zforce_cpusubtype_ALL:-force_cpusubtype_ALL} \
- %{!Zforce_cpusubtype_ALL:%{maltivec|mcpu=*|mpowerpc64:-force_cpusubtype_ALL}}"
+ %{g: %{!fno-eliminate-unused-debug-symbols: -feliminate-unused-debug-symbols }} \
+ %{static: %{Zdynamic: %e conflicting code gen style switches are used}}\
+ %{!mkernel:%{!static:%{!mdynamic-no-pic:-fPIC}}}"
+
+#define DARWIN_ARCH_SPEC "%{m64:ppc64;:ppc}"
+
+#define DARWIN_SUBARCH_SPEC " \
+ %{m64: ppc64} \
+ %{!m64: \
+ %{mcpu=601:ppc601; \
+ mcpu=603:ppc603; \
+ mcpu=603e:ppc603; \
+ mcpu=604:ppc604; \
+ mcpu=604e:ppc604e; \
+ mcpu=740:ppc750; \
+ mcpu=750:ppc750; \
+ mcpu=G3:ppc750; \
+ mcpu=7400:ppc7400; \
+ mcpu=G4:ppc7400; \
+ mcpu=7450:ppc7450; \
+ mcpu=970:ppc970; \
+ mcpu=power4:ppc970; \
+ mcpu=G5:ppc970; \
+ :ppc}}"
+
+/* crt2.o is at least partially required for 10.3.x and earlier. */
+#define DARWIN_CRT2_SPEC \
+ "%{!m64:%:version-compare(!> 10.4 mmacosx-version-min= crt2.o%s)}"
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
- { "darwin_arch", "ppc" },
-
-/* The "-faltivec" option should have been called "-maltivec" all along. */
-#define SUBTARGET_OPTION_TRANSLATE_TABLE \
- { "-faltivec", "-maltivec -include altivec.h" }, \
- { "-fno-altivec", "-mno-altivec" }, \
- { "-Waltivec-long-deprecated", "-mwarn-altivec-long" }, \
+ { "darwin_arch", DARWIN_ARCH_SPEC }, \
+ { "darwin_crt2", DARWIN_CRT2_SPEC }, \
+ { "darwin_subarch", DARWIN_SUBARCH_SPEC },
+
+/* Output a .machine directive. */
+#undef TARGET_ASM_FILE_START
+#define TARGET_ASM_FILE_START rs6000_darwin_file_start
+
+/* The "-faltivec" option should have been called "-maltivec" all
+ along. -ffix-and-continue and -findirect-data is for compatibility
+ for old compilers. */
+
+#define SUBTARGET_OPTION_TRANSLATE_TABLE \
+ { "-ffix-and-continue", "-mfix-and-continue" }, \
+ { "-findirect-data", "-mfix-and-continue" }, \
+ { "-faltivec", "-maltivec -include altivec.h" }, \
+ { "-fno-altivec", "-mno-altivec" }, \
+ { "-Waltivec-long-deprecated", "-mwarn-altivec-long" }, \
{ "-Wno-altivec-long-deprecated", "-mno-warn-altivec-long" }
-/* Make both r2 and r3 available for allocation. */
+/* Make both r2 and r13 available for allocation. */
#define FIXED_R2 0
#define FIXED_R13 0
/* Base register for access to local variables of the function. */
-#undef FRAME_POINTER_REGNUM
-#define FRAME_POINTER_REGNUM 30
+#undef HARD_FRAME_POINTER_REGNUM
+#define HARD_FRAME_POINTER_REGNUM 30
#undef RS6000_PIC_OFFSET_TABLE_REGNUM
#define RS6000_PIC_OFFSET_TABLE_REGNUM 31
@@ -134,9 +209,10 @@ do { \
#undef STARTING_FRAME_OFFSET
#define STARTING_FRAME_OFFSET \
- (RS6000_ALIGN (current_function_outgoing_args_size, 16) \
- + RS6000_VARARGS_AREA \
- + RS6000_SAVE_AREA)
+ (FRAME_GROWS_DOWNWARD \
+ ? 0 \
+ : (RS6000_ALIGN (current_function_outgoing_args_size, 16) \
+ + RS6000_SAVE_AREA))
#undef STACK_DYNAMIC_OFFSET
#define STACK_DYNAMIC_OFFSET(FUNDECL) \
@@ -146,7 +222,7 @@ do { \
/* These are used by -fbranch-probabilities */
#define HOT_TEXT_SECTION_NAME "__TEXT,__text,regular,pure_instructions"
#define UNLIKELY_EXECUTED_TEXT_SECTION_NAME \
- "__TEXT,__text2,regular,pure_instructions"
+ "__TEXT,__unlikely,regular,pure_instructions"
/* Define cutoff for using external functions to save floating point.
Currently on Darwin, always use inline stores. */
@@ -154,6 +230,10 @@ do { \
#undef FP_SAVE_INLINE
#define FP_SAVE_INLINE(FIRST_REG) ((FIRST_REG) < 64)
+/* Darwin uses a function call if everything needs to be saved/restored. */
+#undef WORLD_SAVE_P
+#define WORLD_SAVE_P(INFO) ((INFO)->world_save_p)
+
/* The assembler wants the alternate register names, but without
leading percent sign. */
#undef REGISTER_NAMES
@@ -175,7 +255,8 @@ do { \
"v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", \
"v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", \
"vrsave", "vscr", \
- "spe_acc", "spefscr" \
+ "spe_acc", "spefscr", \
+ "sfp" \
}
/* This outputs NAME to FILE. */
@@ -199,13 +280,14 @@ do { \
/* This says how to output an assembler line to define a global common
symbol. */
-/* ? */
-#undef ASM_OUTPUT_ALIGNED_COMMON
-#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
- do { fputs (".comm ", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n",\
- (SIZE)); } while (0)
+#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
+ do { \
+ unsigned HOST_WIDE_INT _new_size = SIZE; \
+ fputs (".comm ", (FILE)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
+ if (_new_size == 0) _new_size = 1; \
+ fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED"\n", _new_size); \
+ } while (0)
/* Override the standard rs6000 definition. */
@@ -233,6 +315,19 @@ do { \
fprintf (FILE, "\t.align32 %d,0x60000000\n", (LOG)); \
} while (0)
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+/* This is supported in cctools 465 and later. The macro test
+ above prevents using it in earlier build environments. */
+#define ASM_OUTPUT_MAX_SKIP_ALIGN(FILE,LOG,MAX_SKIP) \
+ if ((LOG) != 0) \
+ { \
+ if ((MAX_SKIP) == 0) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
+#endif
+
/* Generate insns to call the profiler. */
#define PROFILE_HOOK(LABEL) output_profile_hook (LABEL)
@@ -241,10 +336,12 @@ do { \
#define RS6000_MCOUNT "*mcount"
-/* Default processor: a G4. */
+/* Default processor: G4, and G5 for 64-bit. */
#undef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_PPC7400
+#undef PROCESSOR_DEFAULT64
+#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
/* Default target flag settings. Despite the fact that STMW/LMW
serializes, it's still a big code size win to use them. Use FSEL by
@@ -254,9 +351,15 @@ do { \
#define TARGET_DEFAULT (MASK_POWERPC | MASK_MULTIPLE | MASK_NEW_MNEMONICS \
| MASK_PPC_GFXOPT)
+/* Darwin only runs on PowerPC, so short-circuit POWER patterns. */
+#undef TARGET_POWER
+#define TARGET_POWER 0
+#undef TARGET_IEEEQUAD
+#define TARGET_IEEEQUAD 0
+
/* Since Darwin doesn't do TOCs, stub this out. */
-#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) 0
+#define ASM_OUTPUT_SPECIAL_POOL_ENTRY_P(X, MODE) ((void)X, (void)MODE, 0)
/* Unlike most other PowerPC targets, chars are signed, for
consistency with other Darwin architectures. */
@@ -264,11 +367,11 @@ do { \
#undef DEFAULT_SIGNED_CHAR
#define DEFAULT_SIGNED_CHAR (1)
-/* Given an rtx X being reloaded into a reg required to be
- in class CLASS, return the class of reg to actually use.
+/* Given an rtx X being reloaded into a reg required to be
+ in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class.
-
+
On the RS/6000, we have to return NO_REGS when we want to reload a
floating-point CONST_DOUBLE to force it to be copied to memory.
@@ -277,8 +380,8 @@ do { \
#undef PREFERRED_RELOAD_CLASS
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- ((GET_CODE (X) == CONST_DOUBLE \
- && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
+ ((CONSTANT_P (X) \
+ && reg_classes_intersect_p ((CLASS), FLOAT_REGS)) \
? NO_REGS \
: ((GET_CODE (X) == SYMBOL_REF || GET_CODE (X) == HIGH) \
&& reg_class_subset_p (BASE_REGS, (CLASS))) \
@@ -308,23 +411,64 @@ do { \
|| TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
&& TARGET_ALIGN_NATURAL == 0 \
? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED) \
- : (TARGET_ALTIVEC && TREE_CODE (STRUCT) == VECTOR_TYPE) \
+ : (TREE_CODE (STRUCT) == VECTOR_TYPE \
+ && ALTIVEC_VECTOR_MODE (TYPE_MODE (STRUCT))) \
? MAX (MAX ((COMPUTED), (SPECIFIED)), 128) \
: MAX ((COMPUTED), (SPECIFIED)))
+/* Specify padding for the last element of a block move between
+ registers and memory. FIRST is nonzero if this is the only
+ element. */
+#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
+ (!(FIRST) ? upward : FUNCTION_ARG_PADDING (MODE, TYPE))
+
/* XXX: Darwin supports neither .quad, or .llong, but it also doesn't
support 64 bit PowerPC either, so this just keeps things happy. */
#define DOUBLE_INT_ASM_OP "\t.quad\t"
-/* Get HOST_WIDE_INT and CONST_INT to be 32 bits, for compile time
- space/speed. */
-#undef MAX_LONG_TYPE_SIZE
-#define MAX_LONG_TYPE_SIZE 32
-
/* For binary compatibility with 2.95; Darwin C APIs use bool from
- stdbool.h, which was an int-sized enum in 2.95. */
-#define BOOL_TYPE_SIZE INT_TYPE_SIZE
+ stdbool.h, which was an int-sized enum in 2.95. Users can explicitly
+ choose to have sizeof(bool)==1 with the -mone-byte-bool switch. */
+#define BOOL_TYPE_SIZE (darwin_one_byte_bool ? CHAR_TYPE_SIZE : INT_TYPE_SIZE)
#undef REGISTER_TARGET_PRAGMAS
-#define REGISTER_TARGET_PRAGMAS DARWIN_REGISTER_TARGET_PRAGMAS
+#define REGISTER_TARGET_PRAGMAS() \
+ do \
+ { \
+ DARWIN_REGISTER_TARGET_PRAGMAS(); \
+ targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
+ } \
+ while (0)
+
+#ifdef IN_LIBGCC2
+#include <stdbool.h>
+#endif
+
+#define MD_UNWIND_SUPPORT "config/rs6000/darwin-unwind.h"
+
+#define HAS_MD_FALLBACK_FRAME_STATE_FOR 1
+
+/* True, iff we're generating fast turn around debugging code. When
+ true, we arrange for function prologues to start with 5 nops so
+ that gdb may insert code to redirect them, and for data to be
+ accessed indirectly. The runtime uses this indirection to forward
+ references for data to the original instance of that data. */
+
+#define TARGET_FIX_AND_CONTINUE (darwin_fix_and_continue)
+
+/* This is the reserved direct dispatch address for Objective-C. */
+#define OFFS_MSGSEND_FAST 0xFFFEFF00
+
+/* This is the reserved ivar address Objective-C. */
+#define OFFS_ASSIGNIVAR_FAST 0xFFFEFEC0
+
+/* Old versions of Mac OS/Darwin don't have C99 functions available. */
+#undef TARGET_C99_FUNCTIONS
+#define TARGET_C99_FUNCTIONS \
+ (TARGET_64BIT \
+ || (darwin_macosx_version_min \
+ && strverscmp (darwin_macosx_version_min, "10.3") >= 0))
+/* When generating kernel code or kexts, we don't use Altivec by
+ default, as kernel code doesn't save/restore those registers. */
+#define OS_MISSING_ALTIVEC (flag_mkernel || flag_apple_kext)
diff --git a/contrib/gcc/config/rs6000/darwin.md b/contrib/gcc/config/rs6000/darwin.md
new file mode 100644
index 0000000..c8e3287
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin.md
@@ -0,0 +1,440 @@
+/* Machine description patterns for PowerPC running Darwin (Mac OS X).
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by Apple Computer Inc.
+
+This file is part of GCC.
+
+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, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+(define_insn "adddi3_high"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (high:DI (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_64BIT"
+ "{cau|addis} %0,%1,ha16(%2)"
+ [(set_attr "length" "4")])
+
+(define_insn "movdf_low_si"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
+ (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && !TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"lfd %0,lo16(%2)(%1)\";
+ case 1:
+ {
+ if (TARGET_POWERPC64 && TARGET_32BIT)
+ /* Note, old assemblers didn't support relocation here. */
+ return \"ld %0,lo16(%2)(%1)\";
+ else
+ {
+ output_asm_insn (\"{cal|la} %0,lo16(%2)(%1)\", operands);
+ output_asm_insn (\"{l|lwz} %L0,4(%0)\", operands);
+ return (\"{l|lwz} %0,0(%0)\");
+ }
+ }
+ default:
+ gcc_unreachable ();
+ }
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4,12")])
+
+
+(define_insn "movdf_low_di"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
+ (mem:DF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_64BIT"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0:
+ return \"lfd %0,lo16(%2)(%1)\";
+ case 1:
+ return \"ld %0,lo16(%2)(%1)\";
+ default:
+ gcc_unreachable ();
+ }
+}"
+ [(set_attr "type" "load")
+ (set_attr "length" "4,4")])
+
+(define_insn "movdf_low_st_si"
+ [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand 2 "" "")))
+ (match_operand:DF 0 "gpc_reg_operand" "f"))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
+ "stfd %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+(define_insn "movdf_low_st_di"
+ [(set (mem:DF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (match_operand 2 "" "")))
+ (match_operand:DF 0 "gpc_reg_operand" "f"))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_64BIT"
+ "stfd %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+(define_insn "movsf_low_si"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
+ (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
+ "@
+ lfs %0,lo16(%2)(%1)
+ {l|lwz} %0,lo16(%2)(%1)"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn "movsf_low_di"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
+ (mem:SF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_64BIT"
+ "@
+ lfs %0,lo16(%2)(%1)
+ {l|lwz} %0,lo16(%2)(%1)"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn "movsf_low_st_si"
+ [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" "")))
+ (match_operand:SF 0 "gpc_reg_operand" "f,!r"))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
+ "@
+ stfs %0,lo16(%2)(%1)
+ {st|stw} %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+(define_insn "movsf_low_st_di"
+ [(set (mem:SF (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,b")
+ (match_operand 2 "" "")))
+ (match_operand:SF 0 "gpc_reg_operand" "f,!r"))]
+ "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_64BIT"
+ "@
+ stfs %0,lo16(%2)(%1)
+ {st|stw} %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+;; 64-bit MachO load/store support
+(define_insn "movdi_low"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (mem:DI (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (match_operand 2 "" ""))))]
+ "TARGET_MACHO && TARGET_64BIT"
+ "{l|ld} %0,lo16(%2)(%1)"
+ [(set_attr "type" "load")
+ (set_attr "length" "4")])
+
+(define_insn "movsi_low_st"
+ [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (match_operand 2 "" "")))
+ (match_operand:SI 0 "gpc_reg_operand" "r"))]
+ "TARGET_MACHO && ! TARGET_64BIT"
+ "{st|stw} %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+(define_insn "movdi_low_st"
+ [(set (mem:DI (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b")
+ (match_operand 2 "" "")))
+ (match_operand:DI 0 "gpc_reg_operand" "r"))]
+ "TARGET_MACHO && TARGET_64BIT"
+ "{st|std} %0,lo16(%2)(%1)"
+ [(set_attr "type" "store")
+ (set_attr "length" "4")])
+
+;; Mach-O PIC trickery.
+(define_expand "macho_high"
+ [(set (match_operand 0 "" "")
+ (high (match_operand 1 "" "")))]
+ "TARGET_MACHO"
+{
+ if (TARGET_64BIT)
+ emit_insn (gen_macho_high_di (operands[0], operands[1]));
+ else
+ emit_insn (gen_macho_high_si (operands[0], operands[1]));
+
+ DONE;
+})
+
+(define_insn "macho_high_si"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+ (high:SI (match_operand 1 "" "")))]
+ "TARGET_MACHO && ! TARGET_64BIT"
+ "{liu|lis} %0,ha16(%1)")
+
+
+(define_insn "macho_high_di"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b*r")
+ (high:DI (match_operand 1 "" "")))]
+ "TARGET_MACHO && TARGET_64BIT"
+ "{liu|lis} %0,ha16(%1)")
+
+(define_expand "macho_low"
+ [(set (match_operand 0 "" "")
+ (lo_sum (match_operand 1 "" "")
+ (match_operand 2 "" "")))]
+ "TARGET_MACHO"
+{
+ if (TARGET_64BIT)
+ emit_insn (gen_macho_low_di (operands[0], operands[1], operands[2]));
+ else
+ emit_insn (gen_macho_low_si (operands[0], operands[1], operands[2]));
+
+ DONE;
+})
+
+(define_insn "macho_low_si"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand 2 "" "")))]
+ "TARGET_MACHO && ! TARGET_64BIT"
+ "@
+ {cal %0,%a2@l(%1)|la %0,lo16(%2)(%1)}
+ {cal %0,%a2@l(%1)|addic %0,%1,lo16(%2)}")
+
+(define_insn "macho_low_di"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:DI (match_operand:DI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand 2 "" "")))]
+ "TARGET_MACHO && TARGET_64BIT"
+ "@
+ {cal %0,%a2@l(%1)|la %0,lo16(%2)(%1)}
+ {cal %0,%a2@l(%1)|addic %0,%1,lo16(%2)}")
+
+(define_split
+ [(set (mem:V4SI (plus:DI (match_operand:DI 0 "gpc_reg_operand" "")
+ (match_operand:DI 1 "short_cint_operand" "")))
+ (match_operand:V4SI 2 "register_operand" ""))
+ (clobber (match_operand:DI 3 "gpc_reg_operand" ""))]
+ "TARGET_MACHO && TARGET_64BIT"
+ [(set (match_dup 3) (plus:DI (match_dup 0) (match_dup 1)))
+ (set (mem:V4SI (match_dup 3))
+ (match_dup 2))]
+ "")
+
+(define_expand "load_macho_picbase"
+ [(set (match_operand 0 "" "")
+ (unspec [(match_operand 1 "" "")]
+ UNSPEC_LD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
+{
+ if (TARGET_32BIT)
+ emit_insn (gen_load_macho_picbase_si (operands[0], operands[1]));
+ else
+ emit_insn (gen_load_macho_picbase_di (operands[0], operands[1]));
+
+ DONE;
+})
+
+(define_insn "load_macho_picbase_si"
+ [(set (match_operand:SI 0 "register_operand" "=l")
+ (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")
+ (pc)] UNSPEC_LD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
+ "bcl 20,31,%1\\n%1:"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "load_macho_picbase_di"
+ [(set (match_operand:DI 0 "register_operand" "=l")
+ (unspec:DI [(match_operand:DI 1 "immediate_operand" "s")
+ (pc)] UNSPEC_LD_MPIC))]
+ "(DEFAULT_ABI == ABI_DARWIN) && flag_pic && TARGET_64BIT"
+ "bcl 20,31,%1\\n%1:"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_expand "macho_correct_pic"
+ [(set (match_operand 0 "" "")
+ (plus (match_operand 1 "" "")
+ (unspec [(match_operand 2 "" "")
+ (match_operand 3 "" "")]
+ UNSPEC_MPIC_CORRECT)))]
+ "DEFAULT_ABI == ABI_DARWIN"
+{
+ if (TARGET_32BIT)
+ emit_insn (gen_macho_correct_pic_si (operands[0], operands[1], operands[2],
+ operands[3]));
+ else
+ emit_insn (gen_macho_correct_pic_di (operands[0], operands[1], operands[2],
+ operands[3]));
+
+ DONE;
+})
+
+(define_insn "macho_correct_pic_si"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+ (unspec:SI [(match_operand:SI 2 "immediate_operand" "s")
+ (match_operand:SI 3 "immediate_operand" "s")]
+ UNSPEC_MPIC_CORRECT)))]
+ "DEFAULT_ABI == ABI_DARWIN"
+ "addis %0,%1,ha16(%2-%3)\n\taddi %0,%0,lo16(%2-%3)"
+ [(set_attr "length" "8")])
+
+(define_insn "macho_correct_pic_di"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (plus:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (unspec:DI [(match_operand:DI 2 "immediate_operand" "s")
+ (match_operand:DI 3 "immediate_operand" "s")]
+ 16)))]
+ "DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT"
+ "addis %0,%1,ha16(%2-%3)\n\taddi %0,%0,lo16(%2-%3)"
+ [(set_attr "length" "8")])
+
+(define_insn "*call_indirect_nonlocal_darwin64"
+ [(call (mem:SI (match_operand:DI 0 "register_operand" "c,*l,c,*l"))
+ (match_operand 1 "" "g,g,g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
+ (clobber (match_scratch:SI 3 "=l,l,l,l"))]
+ "DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT"
+{
+ return "b%T0l";
+}
+ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+ (set_attr "length" "4,4,8,8")])
+
+(define_insn "*call_nonlocal_darwin64"
+ [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s,s"))
+ (match_operand 1 "" "g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 3 "=l,l"))]
+ "(DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+{
+#if TARGET_MACHO
+ return output_call(insn, operands, 0, 2);
+#else
+ gcc_unreachable ();
+#endif
+}
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*call_value_indirect_nonlocal_darwin64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "register_operand" "c,*l,c,*l"))
+ (match_operand 2 "" "g,g,g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
+ (clobber (match_scratch:SI 4 "=l,l,l,l"))]
+ "DEFAULT_ABI == ABI_DARWIN"
+{
+ return "b%T1l";
+}
+ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+ (set_attr "length" "4,4,8,8")])
+
+(define_insn "*call_value_nonlocal_darwin64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s,s"))
+ (match_operand 2 "" "g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (clobber (match_scratch:SI 4 "=l,l"))]
+ "(DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+{
+#if TARGET_MACHO
+ return output_call(insn, operands, 1, 3);
+#else
+ gcc_unreachable ();
+#endif
+}
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*sibcall_nonlocal_darwin64"
+ [(call (mem:SI (match_operand:DI 0 "symbol_ref_operand" "s,s"))
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "immediate_operand" "O,n"))
+ (use (match_operand:SI 3 "register_operand" "l,l"))
+ (return)]
+ "(DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[2]) & CALL_LONG) == 0"
+{
+ return "b %z0";
+}
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+(define_insn "*sibcall_value_nonlocal_darwin64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "symbol_ref_operand" "s,s"))
+ (match_operand 2 "" "")))
+ (use (match_operand:SI 3 "immediate_operand" "O,n"))
+ (use (match_operand:SI 4 "register_operand" "l,l"))
+ (return)]
+ "(DEFAULT_ABI == ABI_DARWIN)
+ && (INTVAL (operands[3]) & CALL_LONG) == 0"
+ "*
+{
+ return \"b %z1\";
+}"
+ [(set_attr "type" "branch,branch")
+ (set_attr "length" "4,8")])
+
+
+(define_insn "*sibcall_symbolic_64"
+ [(call (mem:SI (match_operand:DI 0 "call_operand" "s,c")) ; 64
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))
+ (use (match_operand:SI 3 "register_operand" "l,l"))
+ (return)]
+ "TARGET_64BIT && DEFAULT_ABI == ABI_DARWIN"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"b %z0\";
+ case 1: return \"b%T0\";
+ default: gcc_unreachable ();
+ }
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
+(define_insn "*sibcall_value_symbolic_64"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:DI 1 "call_operand" "s,c"))
+ (match_operand 2 "" "")))
+ (use (match_operand:SI 3 "" ""))
+ (use (match_operand:SI 4 "register_operand" "l,l"))
+ (return)]
+ "TARGET_64BIT && DEFAULT_ABI == ABI_DARWIN"
+ "*
+{
+ switch (which_alternative)
+ {
+ case 0: return \"b %z1\";
+ case 1: return \"b%T1\";
+ default: gcc_unreachable ();
+ }
+}"
+ [(set_attr "type" "branch")
+ (set_attr "length" "4")])
+
diff --git a/contrib/gcc/config/rs6000/darwin.opt b/contrib/gcc/config/rs6000/darwin.opt
new file mode 100644
index 0000000..99b38ec
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin.opt
@@ -0,0 +1,33 @@
+; Darwin options for PPC port.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+m64
+Target RejectNegative Mask(64BIT)
+Generate 64-bit code
+
+m32
+Target RejectNegative InverseMask(64BIT)
+Generate 32-bit code
+
+mdynamic-no-pic
+Target Report Mask(MACHO_DYNAMIC_NO_PIC)
+Generate code suitable for executables (NOT shared libs)
diff --git a/contrib/gcc/config/rs6000/darwin64.h b/contrib/gcc/config/rs6000/darwin64.h
new file mode 100644
index 0000000..80e802d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin64.h
@@ -0,0 +1,36 @@
+/* Target definitions for PowerPC running Darwin (Mac OS X).
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ Contributed by Apple Computer Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (Darwin/PowerPC64)");
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_POWERPC64 | MASK_64BIT \
+ | MASK_MULTIPLE | MASK_NEW_MNEMONICS | MASK_PPC_GFXOPT)
+
+#undef DARWIN_ARCH_SPEC
+#define DARWIN_ARCH_SPEC "ppc64"
+
+#undef DARWIN_SUBARCH_SPEC
+#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC
+
+#undef DARWIN_CRT2_SPEC
+#define DARWIN_CRT2_SPEC ""
diff --git a/contrib/gcc/config/rs6000/darwin7.h b/contrib/gcc/config/rs6000/darwin7.h
new file mode 100644
index 0000000..4c1cda3
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin7.h
@@ -0,0 +1,31 @@
+/* Target definitions for Darwin 7.x (Mac OS X) systems.
+ Copyright (C) 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Machine dependent libraries. Include libmx when compiling for
+ Darwin 7.0 and above, but before libSystem, since the functions are
+ actually in libSystem but for 7.x compatibility we want them to be
+ looked for in libmx first. Include libmx by default because otherwise
+ libstdc++ isn't usable. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!static:\
+ %:version-compare(!< 10.3 mmacosx-version-min= -lmx)\
+ -lSystem}"
diff --git a/contrib/gcc/config/rs6000/darwin8.h b/contrib/gcc/config/rs6000/darwin8.h
new file mode 100644
index 0000000..ee583a2
--- /dev/null
+++ b/contrib/gcc/config/rs6000/darwin8.h
@@ -0,0 +1,33 @@
+/* Target definitions for Darwin 8.0 and above (Mac OS X) systems.
+ Copyright (C) 2004, 2005
+ Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Machine dependent libraries. Include libmx when compiling on
+ Darwin 7.0 and above, but before libSystem, since the functions are
+ actually in libSystem but for 7.x compatibility we want them to be
+ looked for in libmx first---but only do this if 7.x compatibility
+ is a concern, which it's not in 64-bit mode. Include
+ libSystemStubs when compiling on (not necessarily for) 8.0 and
+ above and not 64-bit long double. */
+
+#undef LIB_SPEC
+#define LIB_SPEC "%{!static:\
+ %{!mlong-double-64:%{pg:-lSystemStubs_profile;:-lSystemStubs}} \
+ %{!m64:%:version-compare(>< 10.3 10.4 mmacosx-version-min= -lmx)} -lSystem}"
diff --git a/contrib/gcc/config/rs6000/default64.h b/contrib/gcc/config/rs6000/default64.h
index c6ed142..10fe09c 100644
--- a/contrib/gcc/config/rs6000/default64.h
+++ b/contrib/gcc/config/rs6000/default64.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for 64 bit powerpc linux defaulting to -m64.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,9 +16,10 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (MASK_POWERPC | MASK_POWERPC64 | MASK_64BIT | MASK_NEW_MNEMONICS)
+ (MASK_POWERPC | MASK_PPC_GFXOPT | \
+ MASK_POWERPC64 | MASK_64BIT | MASK_NEW_MNEMONICS)
diff --git a/contrib/gcc/config/rs6000/e500-double.h b/contrib/gcc/config/rs6000/e500-double.h
new file mode 100644
index 0000000..55587e4
--- /dev/null
+++ b/contrib/gcc/config/rs6000/e500-double.h
@@ -0,0 +1,25 @@
+/* Target definitions for E500 with double precision FP.
+ Copyright (C) 2004, 2006 Free Software Foundation, Inc.
+ Contributed by Aldy Hernandez (aldyh@redhat.com).
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify it
+ under the terms of the GNU General Public License as published
+ by the Free Software Foundation; either version 2, or (at your
+ option) any later version.
+
+ GCC is distributed in the hope that it will be useful, but WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+ License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GCC; see the file COPYING. If not, write to the
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#undef SUB3TARGET_OVERRIDE_OPTIONS
+#define SUB3TARGET_OVERRIDE_OPTIONS \
+ if (!rs6000_explicit_options.float_gprs) \
+ rs6000_float_gprs = 2;
diff --git a/contrib/gcc/config/rs6000/eabi-ci.asm b/contrib/gcc/config/rs6000/eabi-ci.asm
index 447b4e2..d32120f 100644
--- a/contrib/gcc/config/rs6000/eabi-ci.asm
+++ b/contrib/gcc/config/rs6000/eabi-ci.asm
@@ -22,8 +22,8 @@ General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
As a special exception, if you link this library with files
compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/eabi-cn.asm b/contrib/gcc/config/rs6000/eabi-cn.asm
index b2c6095..90a5da7 100644
--- a/contrib/gcc/config/rs6000/eabi-cn.asm
+++ b/contrib/gcc/config/rs6000/eabi-cn.asm
@@ -22,8 +22,8 @@ General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
As a special exception, if you link this library with files
compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/eabi.asm b/contrib/gcc/config/rs6000/eabi.asm
index c7876bc..b5d4505 100644
--- a/contrib/gcc/config/rs6000/eabi.asm
+++ b/contrib/gcc/config/rs6000/eabi.asm
@@ -24,8 +24,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/eabi.h b/contrib/gcc/config/rs6000/eabi.h
index ff8df2c..323e5ad 100644
--- a/contrib/gcc/config/rs6000/eabi.h
+++ b/contrib/gcc/config/rs6000/eabi.h
@@ -1,6 +1,6 @@
/* Core target definitions for GNU compiler
for IBM RS/6000 PowerPC targeted to embedded ELF systems.
- Copyright (C) 1995, 1996, 2000, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2003, 2004 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GCC.
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Add -meabi to target flags. */
#undef TARGET_DEFAULT
@@ -49,9 +49,13 @@
#undef TARGET_E500
#undef TARGET_ISEL
#undef TARGET_FPRS
+#undef TARGET_E500_SINGLE
+#undef TARGET_E500_DOUBLE
#define TARGET_SPE_ABI rs6000_spe_abi
#define TARGET_SPE rs6000_spe
#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
#define TARGET_ISEL rs6000_isel
-#define TARGET_FPRS (!rs6000_float_gprs)
+#define TARGET_FPRS (rs6000_float_gprs == 0)
+#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
+#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
diff --git a/contrib/gcc/config/rs6000/eabialtivec.h b/contrib/gcc/config/rs6000/eabialtivec.h
index e407e3b..437c0c8 100644
--- a/contrib/gcc/config/rs6000/eabialtivec.h
+++ b/contrib/gcc/config/rs6000/eabialtivec.h
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Add -meabi and -maltivec to target flags. */
#undef TARGET_DEFAULT
diff --git a/contrib/gcc/config/rs6000/eabisim.h b/contrib/gcc/config/rs6000/eabisim.h
index 5e0900d..171c791 100644
--- a/contrib/gcc/config/rs6000/eabisim.h
+++ b/contrib/gcc/config/rs6000/eabisim.h
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Simulated)");
diff --git a/contrib/gcc/config/rs6000/eabispe.h b/contrib/gcc/config/rs6000/eabispe.h
index 1551dc1..2a0b923 100644
--- a/contrib/gcc/config/rs6000/eabispe.h
+++ b/contrib/gcc/config/rs6000/eabispe.h
@@ -1,6 +1,6 @@
/* Core target definitions for GNU compiler
for PowerPC embedded targeted systems with SPE support.
- Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Aldy Hernandez (aldyh@redhat.com).
This file is part of GCC.
@@ -17,11 +17,12 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI)
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI \
+ | MASK_STRICT_ALIGN)
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC Embedded SPE)");
@@ -30,17 +31,19 @@
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
if (rs6000_select[1].string == NULL) \
rs6000_cpu = PROCESSOR_PPC8540; \
- if (rs6000_abi_string == NULL) \
+ if (!rs6000_explicit_options.abi) \
rs6000_spe_abi = 1; \
- if (rs6000_float_gprs_string == NULL) \
+ if (!rs6000_explicit_options.float_gprs) \
rs6000_float_gprs = 1; \
/* See note below. */ \
- /*if (rs6000_long_double_size_string == NULL)*/ \
+ /*if (!rs6000_explicit_options.long_double)*/ \
/* rs6000_long_double_type_size = 128;*/ \
- if (rs6000_spe_string == NULL) \
+ if (!rs6000_explicit_options.spe) \
rs6000_spe = 1; \
- if (rs6000_isel_string == NULL) \
- rs6000_isel = 1
+ if (!rs6000_explicit_options.isel) \
+ rs6000_isel = 1; \
+ if (target_flags & MASK_64BIT) \
+ error ("-m64 not supported in this configuration")
/* The e500 ABI says that either long doubles are 128 bits, or if
implemented in any other size, the compiler/linker should error out.
diff --git a/contrib/gcc/config/rs6000/gnu.h b/contrib/gcc/config/rs6000/gnu.h
index 658a6d6..b7ddbfb 100644
--- a/contrib/gcc/config/rs6000/gnu.h
+++ b/contrib/gcc/config/rs6000/gnu.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef CPP_OS_DEFAULT_SPEC
#define CPP_OS_DEFAULT_SPEC "%(cpp_os_gnu)"
diff --git a/contrib/gcc/config/rs6000/host-darwin.c b/contrib/gcc/config/rs6000/host-darwin.c
index d04270c..be0c55f 100644
--- a/contrib/gcc/config/rs6000/host-darwin.c
+++ b/contrib/gcc/config/rs6000/host-darwin.c
@@ -1,5 +1,5 @@
/* Darwin/powerpc host-specific hook definitions.
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,27 +15,37 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
#include "coretypes.h"
#include <signal.h>
#include <sys/ucontext.h>
-#include <sys/mman.h>
#include "hosthooks.h"
#include "hosthooks-def.h"
#include "toplev.h"
#include "diagnostic.h"
+#include "config/host-darwin.h"
static void segv_crash_handler (int);
static void segv_handler (int, siginfo_t *, void *);
static void darwin_rs6000_extra_signals (void);
+#ifndef HAVE_DECL_SIGALTSTACK
/* This doesn't have a prototype in signal.h in 10.2.x and earlier,
fixed in later releases. */
extern int sigaltstack(const struct sigaltstack *, struct sigaltstack *);
+#endif
+
+/* The fields of the mcontext_t type have acquired underscores in later
+ OS versions. */
+#ifdef HAS_MCONTEXT_T_UNDERSCORES
+#define MC_FLD(x) __ ## x
+#else
+#define MC_FLD(x) x
+#endif
#undef HOST_HOOKS_EXTRA_SIGNALS
#define HOST_HOOKS_EXTRA_SIGNALS darwin_rs6000_extra_signals
@@ -58,13 +68,17 @@ segv_handler (int sig ATTRIBUTE_UNUSED,
void *scp)
{
ucontext_t *uc = (ucontext_t *)scp;
+ sigset_t sigset;
unsigned faulting_insn;
/* The fault might have happened when trying to run some instruction, in
which case the next line will segfault _again_. Handle this case. */
signal (SIGSEGV, segv_crash_handler);
+ sigemptyset (&sigset);
+ sigaddset (&sigset, SIGSEGV);
+ sigprocmask (SIG_UNBLOCK, &sigset, NULL);
- faulting_insn = *(unsigned *)uc->uc_mcontext->ss.srr0;
+ faulting_insn = *(unsigned *)uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0);
/* Note that this only has to work for GCC, so we don't have to deal
with all the possible cases (GCC has no AltiVec code, for
@@ -73,7 +87,7 @@ segv_handler (int sig ATTRIBUTE_UNUSED,
this. */
if ((faulting_insn & 0xFFFF8000) == 0x94218000 /* stwu %r1, -xxx(%r1) */
- || (faulting_insn & 0xFFFF03FF) == 0x7C21016E /* stwux %r1, xxx, %r1 */
+ || (faulting_insn & 0xFC1F03FF) == 0x7C01016E /* stwux xxx, %r1, xxx */
|| (faulting_insn & 0xFC1F8000) == 0x90018000 /* stw xxx, -yyy(%r1) */
|| (faulting_insn & 0xFC1F8000) == 0xD8018000 /* stfd xxx, -yyy(%r1) */
|| (faulting_insn & 0xFC1F8000) == 0xBC018000 /* stmw xxx, -yyy(%r1) */)
@@ -101,19 +115,20 @@ segv_handler (int sig ATTRIBUTE_UNUSED,
if (strcmp (shell_commands[i][0], shell_name + 1) == 0)
{
fnotice (stderr,
- "Try running `%s' in the shell to raise its limit.\n",
+ "Try running '%s' in the shell to raise its limit.\n",
shell_commands[i][1]);
}
}
if (global_dc->abort_on_error)
- abort ();
+ fancy_abort (__FILE__, __LINE__, __FUNCTION__);
exit (FATAL_EXIT_CODE);
}
fprintf (stderr, "[address=%08lx pc=%08x]\n",
- uc->uc_mcontext->es.dar, uc->uc_mcontext->ss.srr0);
+ uc->uc_mcontext->MC_FLD(es).MC_FLD(dar),
+ uc->uc_mcontext->MC_FLD(ss).MC_FLD(srr0));
internal_error ("Segmentation Fault");
exit (FATAL_EXIT_CODE);
}
@@ -137,65 +152,5 @@ darwin_rs6000_extra_signals (void)
fatal_error ("While setting up signal handler: %m");
}
-#undef HOST_HOOKS_GT_PCH_GET_ADDRESS
-#define HOST_HOOKS_GT_PCH_GET_ADDRESS darwin_rs6000_gt_pch_get_address
-#undef HOST_HOOKS_GT_PCH_USE_ADDRESS
-#define HOST_HOOKS_GT_PCH_USE_ADDRESS darwin_rs6000_gt_pch_use_address
-
-/* Yes, this is really supposed to work. */
-static char pch_address_space[1024*1024*1024] __attribute__((aligned (4096)));
-
-/* Return the address of the PCH address space, if the PCH will fit in it. */
-
-static void *
-darwin_rs6000_gt_pch_get_address (size_t sz, int fd ATTRIBUTE_UNUSED)
-{
- if (sz <= sizeof (pch_address_space))
- return pch_address_space;
- else
- return NULL;
-}
-
-/* Check ADDR and SZ for validity, and deallocate (using munmap) that part of
- pch_address_space beyond SZ. */
-
-static int
-darwin_rs6000_gt_pch_use_address (void *addr, size_t sz, int fd, size_t off)
-{
- const size_t pagesize = getpagesize();
- void *mmap_result;
- int ret;
-
- if ((size_t)pch_address_space % pagesize != 0
- || sizeof (pch_address_space) % pagesize != 0)
- abort ();
-
- ret = (addr == pch_address_space && sz <= sizeof (pch_address_space));
- if (! ret)
- sz = 0;
-
- /* Round the size to a whole page size. Normally this is a no-op. */
- sz = (sz + pagesize - 1) / pagesize * pagesize;
-
- if (munmap (pch_address_space + sz, sizeof (pch_address_space) - sz) != 0)
- fatal_error ("couldn't unmap pch_address_space: %m\n");
-
- if (ret)
- {
- mmap_result = mmap (addr, sz,
- PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED,
- fd, off);
-
- /* The file might not be mmap-able. */
- ret = mmap_result != (void *) MAP_FAILED;
-
- /* Sanity check for broken MAP_FIXED. */
- if (ret && mmap_result != addr)
- abort ();
- }
-
- return ret;
-}
-
const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/rs6000/host-ppc64-darwin.c b/contrib/gcc/config/rs6000/host-ppc64-darwin.c
new file mode 100644
index 0000000..ec7f9b3
--- /dev/null
+++ b/contrib/gcc/config/rs6000/host-ppc64-darwin.c
@@ -0,0 +1,31 @@
+/* ppc64-darwin host-specific hook definitions.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "hosthooks.h"
+#include "hosthooks-def.h"
+#include "config/host-darwin.h"
+
+/* Darwin doesn't do anything special for ppc64 hosts; this file exists just
+ to include config/host-darwin.h. */
+
+const struct host_hooks host_hooks = HOST_HOOKS_INITIALIZER;
diff --git a/contrib/gcc/config/rs6000/kaos-ppc.h b/contrib/gcc/config/rs6000/kaos-ppc.h
index d6b92e7..eb18541 100644
--- a/contrib/gcc/config/rs6000/kaos-ppc.h
+++ b/contrib/gcc/config/rs6000/kaos-ppc.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fputs (" (PowerPC/kaOS[ELF])", stderr);
diff --git a/contrib/gcc/config/rs6000/libgcc-ppc-glibc.ver b/contrib/gcc/config/rs6000/libgcc-ppc-glibc.ver
new file mode 100644
index 0000000..cf023dd
--- /dev/null
+++ b/contrib/gcc/config/rs6000/libgcc-ppc-glibc.ver
@@ -0,0 +1,52 @@
+%ifndef _SOFT_FLOAT
+%ifndef __powerpc64__
+%exclude {
+ __multc3
+ __divtc3
+ __powitf2
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+}
+
+GCC_4.1.0 {
+ # long double support
+ __multc3
+ __divtc3
+ __powitf2
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+
+%else
+GCC_3.4.4 {
+%endif
+%else
+GCC_4.2.0 {
+%endif
+
+ # long double support
+ __gcc_qadd
+ __gcc_qsub
+ __gcc_qmul
+ __gcc_qdiv
+
+%ifdef _SOFT_FLOAT
+ __gcc_qneg
+ __gcc_qeq
+ __gcc_qne
+ __gcc_qgt
+ __gcc_qge
+ __gcc_qlt
+ __gcc_qle
+ __gcc_qunord
+ __gcc_stoq
+ __gcc_dtoq
+ __gcc_qtos
+ __gcc_qtod
+ __gcc_qtoi
+ __gcc_qtou
+ __gcc_itoq
+ __gcc_utoq
+%endif
+}
diff --git a/contrib/gcc/config/rs6000/linux-unwind.h b/contrib/gcc/config/rs6000/linux-unwind.h
index 842fd10..6a59a54 100644
--- a/contrib/gcc/config/rs6000/linux-unwind.h
+++ b/contrib/gcc/config/rs6000/linux-unwind.h
@@ -1,5 +1,5 @@
/* DWARF2 EH unwinding support for PowerPC and PowerPC64 Linux.
- Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -23,8 +23,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* This file defines our own versions of various kernel and user
structs, so that system headers are not needed, which otherwise
@@ -89,234 +89,260 @@ struct gcc_ucontext
enum { SIGNAL_FRAMESIZE = 128 };
-/* If the current unwind info (FS) does not contain explicit info
- saving R2, then we have to do a minor amount of code reading to
- figure out if it was saved. The big problem here is that the
- code that does the save/restore is generated by the linker, so
- we have no good way to determine at compile time what to do. */
-
-#define MD_FROB_UPDATE_CONTEXT(CTX, FS) \
- do { \
- if ((FS)->regs.reg[2].how == REG_UNSAVED) \
- { \
- unsigned int *insn \
- = (unsigned int *) \
- _Unwind_GetGR ((CTX), LINK_REGISTER_REGNUM); \
- if (*insn == 0xE8410028) \
- _Unwind_SetGRPtr ((CTX), 2, (CTX)->cfa + 40); \
- } \
- } while (0)
-
/* If PC is at a sigreturn trampoline, return a pointer to the
regs. Otherwise return NULL. */
-#define PPC_LINUX_GET_REGS(CONTEXT) \
-({ \
- const unsigned char *pc = (CONTEXT)->ra; \
- struct gcc_regs *regs = NULL; \
- \
- /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */ \
- /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */ \
- if (*(unsigned int *) (pc + 0) != 0x38210000 + SIGNAL_FRAMESIZE \
- || *(unsigned int *) (pc + 8) != 0x44000002) \
- ; \
- else if (*(unsigned int *) (pc + 4) == 0x38000077) \
- { \
- struct sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- unsigned long pad[7]; \
- struct gcc_regs *regs; \
- } *frame = (struct sigframe *) (CONTEXT)->cfa; \
- regs = frame->regs; \
- } \
- else if (*(unsigned int *) (pc + 4) == 0x380000AC) \
- { \
- /* This works for 2.4 kernels, but not for 2.6 kernels with vdso \
- because pc isn't pointing into the stack. Can be removed when \
- no one is running 2.4.19 or 2.4.20, the first two ppc64 \
- kernels released. */ \
- struct rt_sigframe_24 { \
- int tramp[6]; \
- void *pinfo; \
- struct gcc_ucontext *puc; \
- } *frame24 = (struct rt_sigframe_24 *) pc; \
- \
- /* Test for magic value in *puc of vdso. */ \
- if ((long) frame24->puc != -21 * 8) \
- regs = frame24->puc->regs; \
- else \
- { \
- /* This works for 2.4.21 and later kernels. */ \
- struct rt_sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- struct gcc_ucontext uc; \
- unsigned long pad[2]; \
- int tramp[6]; \
- void *pinfo; \
- struct gcc_ucontext *puc; \
- } *frame = (struct rt_sigframe *) (CONTEXT)->cfa; \
- regs = frame->uc.regs; \
- } \
- } \
- regs; \
-})
-
-#define LINUX_HWCAP_DEFAULT 0xc0000000
-
-#define PPC_LINUX_VREGS(REGS) (REGS)->vp
+static struct gcc_regs *
+get_regs (struct _Unwind_Context *context)
+{
+ const unsigned char *pc = context->ra;
+
+ /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
+ /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
+ if (*(unsigned int *) (pc + 0) != 0x38210000 + SIGNAL_FRAMESIZE
+ || *(unsigned int *) (pc + 8) != 0x44000002)
+ return NULL;
+ if (*(unsigned int *) (pc + 4) == 0x38000077)
+ {
+ struct sigframe {
+ char gap[SIGNAL_FRAMESIZE];
+ unsigned long pad[7];
+ struct gcc_regs *regs;
+ } *frame = (struct sigframe *) context->cfa;
+ return frame->regs;
+ }
+ else if (*(unsigned int *) (pc + 4) == 0x380000AC)
+ {
+ /* This works for 2.4 kernels, but not for 2.6 kernels with vdso
+ because pc isn't pointing into the stack. Can be removed when
+ no one is running 2.4.19 or 2.4.20, the first two ppc64
+ kernels released. */
+ struct rt_sigframe_24 {
+ int tramp[6];
+ void *pinfo;
+ struct gcc_ucontext *puc;
+ } *frame24 = (struct rt_sigframe_24 *) pc;
+
+ /* Test for magic value in *puc of vdso. */
+ if ((long) frame24->puc != -21 * 8)
+ return frame24->puc->regs;
+ else
+ {
+ /* This works for 2.4.21 and later kernels. */
+ struct rt_sigframe {
+ char gap[SIGNAL_FRAMESIZE];
+ struct gcc_ucontext uc;
+ unsigned long pad[2];
+ int tramp[6];
+ void *pinfo;
+ struct gcc_ucontext *puc;
+ } *frame = (struct rt_sigframe *) context->cfa;
+ return frame->uc.regs;
+ }
+ }
+ return NULL;
+}
#else /* !__powerpc64__ */
enum { SIGNAL_FRAMESIZE = 64 };
-#define PPC_LINUX_GET_REGS(CONTEXT) \
-({ \
- const unsigned char *pc = (CONTEXT)->ra; \
- struct gcc_regs *regs = NULL; \
- \
- /* li r0, 0x7777; sc (sigreturn old) */ \
- /* li r0, 0x0077; sc (sigreturn new) */ \
- /* li r0, 0x6666; sc (rt_sigreturn old) */ \
- /* li r0, 0x00AC; sc (rt_sigreturn new) */ \
- if (*(unsigned int *) (pc + 4) != 0x44000002) \
- ; \
- else if (*(unsigned int *) (pc + 0) == 0x38007777 \
- || *(unsigned int *) (pc + 0) == 0x38000077) \
- { \
- struct sigframe { \
- char gap[SIGNAL_FRAMESIZE]; \
- unsigned long pad[7]; \
- struct gcc_regs *regs; \
- } *frame = (struct sigframe *) (CONTEXT)->cfa; \
- regs = frame->regs; \
- } \
- else if (*(unsigned int *) (pc + 0) == 0x38006666 \
- || *(unsigned int *) (pc + 0) == 0x380000AC) \
- { \
- struct rt_sigframe { \
- char gap[SIGNAL_FRAMESIZE + 16]; \
- char siginfo[128]; \
- struct gcc_ucontext uc; \
- } *frame = (struct rt_sigframe *) (CONTEXT)->cfa; \
- regs = frame->uc.regs; \
- } \
- regs; \
-})
-
-#define LINUX_HWCAP_DEFAULT 0x80000000
-
-#define PPC_LINUX_VREGS(REGS) &(REGS)->vregs
+static struct gcc_regs *
+get_regs (struct _Unwind_Context *context)
+{
+ const unsigned char *pc = context->ra;
+ /* li r0, 0x7777; sc (sigreturn old) */
+ /* li r0, 0x0077; sc (sigreturn new) */
+ /* li r0, 0x6666; sc (rt_sigreturn old) */
+ /* li r0, 0x00AC; sc (rt_sigreturn new) */
+ if (*(unsigned int *) (pc + 4) != 0x44000002)
+ return NULL;
+ if (*(unsigned int *) (pc + 0) == 0x38007777
+ || *(unsigned int *) (pc + 0) == 0x38000077)
+ {
+ struct sigframe {
+ char gap[SIGNAL_FRAMESIZE];
+ unsigned long pad[7];
+ struct gcc_regs *regs;
+ } *frame = (struct sigframe *) context->cfa;
+ return frame->regs;
+ }
+ else if (*(unsigned int *) (pc + 0) == 0x38006666
+ || *(unsigned int *) (pc + 0) == 0x380000AC)
+ {
+ struct rt_sigframe {
+ char gap[SIGNAL_FRAMESIZE + 16];
+ char siginfo[128];
+ struct gcc_ucontext uc;
+ } *frame = (struct rt_sigframe *) context->cfa;
+ return frame->uc.regs;
+ }
+ return NULL;
+}
#endif
+/* Find an entry in the process auxiliary vector. The canonical way to
+ test for VMX is to look at AT_HWCAP. */
+
+static long
+ppc_linux_aux_vector (long which)
+{
+ /* __libc_stack_end holds the original stack passed to a process. */
+ extern long *__libc_stack_end;
+ long argc;
+ char **argv;
+ char **envp;
+ struct auxv
+ {
+ long a_type;
+ long a_val;
+ } *auxp;
+
+ /* The Linux kernel puts argc first on the stack. */
+ argc = __libc_stack_end[0];
+ /* Followed by argv, NULL terminated. */
+ argv = (char **) __libc_stack_end + 1;
+ /* Followed by environment string pointers, NULL terminated. */
+ envp = argv + argc + 1;
+ while (*envp++)
+ continue;
+ /* Followed by the aux vector, zero terminated. */
+ for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp)
+ if (auxp->a_type == which)
+ return auxp->a_val;
+ return 0;
+}
+
/* Do code reading to identify a signal frame, and set the frame
state data appropriately. See unwind-dw2.c for the structs. */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- static long hwcap = 0; \
- struct gcc_regs *regs = PPC_LINUX_GET_REGS (CONTEXT); \
- long new_cfa; \
- int i; \
- \
- if (regs == NULL) \
- break; \
- \
- new_cfa = 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) &regs->gpr[i] - new_cfa; \
- } \
- \
- (FS)->regs.reg[CR2_REGNO].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[CR2_REGNO].loc.offset \
- = (long) &regs->ccr - new_cfa; \
- \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[LINK_REGISTER_REGNUM].loc.offset \
- = (long) &regs->link - new_cfa; \
- \
- (FS)->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[ARG_POINTER_REGNUM].loc.offset \
- = (long) &regs->nip - new_cfa; \
- (FS)->retaddr_column = ARG_POINTER_REGNUM; \
- \
- if (hwcap == 0) \
- { \
- /* __libc_stack_end holds the original stack passed to a \
- process. */ \
- extern long *__libc_stack_end; \
- long argc; \
- char **argv; \
- char **envp; \
- struct auxv \
- { \
- long a_type; \
- long a_val; \
- } *auxp; \
- \
- /* The Linux kernel puts argc first on the stack. */ \
- argc = __libc_stack_end[0]; \
- /* Followed by argv, NULL terminated. */ \
- argv = (char **) __libc_stack_end + 1; \
- /* Followed by environment string pointers, NULL terminated. */ \
- envp = argv + argc + 1; \
- while (*envp++) \
- continue; \
- /* Followed by the aux vector, zero terminated. */ \
- for (auxp = (struct auxv *) envp; auxp->a_type != 0; ++auxp) \
- if (auxp->a_type == 16) \
- { \
- hwcap = auxp->a_val; \
- break; \
- } \
- \
- /* These will already be set if we found AT_HWCAP. A non-zero \
- value stops us looking again if for some reason we couldn't \
- find AT_HWCAP. */ \
- hwcap |= LINUX_HWCAP_DEFAULT; \
- } \
- \
- /* If we have a FPU... */ \
- if (hwcap & 0x08000000) \
- for (i = 0; i < 32; i++) \
- { \
- (FS)->regs.reg[i + 32].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i + 32].loc.offset \
- = (long) &regs->fpr[i] - new_cfa; \
- } \
- \
- /* If we have a VMX unit... */ \
- if (hwcap & 0x10000000) \
- { \
- struct gcc_vregs *vregs; \
- vregs = PPC_LINUX_VREGS (regs); \
- if (regs->msr & (1 << 25)) \
- { \
- for (i = 0; i < 32; i++) \
- { \
- (FS)->regs.reg[i + FIRST_ALTIVEC_REGNO].how \
- = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i + FIRST_ALTIVEC_REGNO].loc.offset \
- = (long) &vregs[i] - new_cfa; \
- } \
- \
- (FS)->regs.reg[VSCR_REGNO].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[VSCR_REGNO].loc.offset \
- = (long) &vregs->vscr - new_cfa; \
- } \
- \
- (FS)->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[VRSAVE_REGNO].loc.offset \
- = (long) &vregs->vsave - new_cfa; \
- } \
- \
- goto SUCCESS; \
- } while (0)
+#define MD_FALLBACK_FRAME_STATE_FOR ppc_fallback_frame_state
+
+static _Unwind_Reason_Code
+ppc_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ static long hwcap = 0;
+ struct gcc_regs *regs = get_regs (context);
+ long new_cfa;
+ int i;
+
+ if (regs == NULL)
+ return _URC_END_OF_STACK;
+
+ new_cfa = 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) &regs->gpr[i] - new_cfa;
+ }
+
+ fs->regs.reg[CR2_REGNO].how = REG_SAVED_OFFSET;
+ fs->regs.reg[CR2_REGNO].loc.offset = (long) &regs->ccr - new_cfa;
+
+ fs->regs.reg[LINK_REGISTER_REGNUM].how = REG_SAVED_OFFSET;
+ fs->regs.reg[LINK_REGISTER_REGNUM].loc.offset = (long) &regs->link - new_cfa;
+
+ fs->regs.reg[ARG_POINTER_REGNUM].how = REG_SAVED_OFFSET;
+ fs->regs.reg[ARG_POINTER_REGNUM].loc.offset = (long) &regs->nip - new_cfa;
+ fs->retaddr_column = ARG_POINTER_REGNUM;
+ fs->signal_frame = 1;
+
+ if (hwcap == 0)
+ {
+ hwcap = ppc_linux_aux_vector (16);
+ /* These will already be set if we found AT_HWCAP. A nonzero
+ value stops us looking again if for some reason we couldn't
+ find AT_HWCAP. */
+#ifdef __powerpc64__
+ hwcap |= 0xc0000000;
+#else
+ hwcap |= 0x80000000;
+#endif
+ }
+
+ /* If we have a FPU... */
+ if (hwcap & 0x08000000)
+ for (i = 0; i < 32; i++)
+ {
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset = (long) &regs->fpr[i] - new_cfa;
+ }
+
+ /* If we have a VMX unit... */
+ if (hwcap & 0x10000000)
+ {
+ struct gcc_vregs *vregs;
+#ifdef __powerpc64__
+ vregs = regs->vp;
+#else
+ vregs = &regs->vregs;
+#endif
+ if (regs->msr & (1 << 25))
+ {
+ for (i = 0; i < 32; i++)
+ {
+ fs->regs.reg[i + FIRST_ALTIVEC_REGNO].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + FIRST_ALTIVEC_REGNO].loc.offset
+ = (long) &vregs[i] - new_cfa;
+ }
+
+ fs->regs.reg[VSCR_REGNO].how = REG_SAVED_OFFSET;
+ fs->regs.reg[VSCR_REGNO].loc.offset = (long) &vregs->vscr - new_cfa;
+ }
+
+ fs->regs.reg[VRSAVE_REGNO].how = REG_SAVED_OFFSET;
+ fs->regs.reg[VRSAVE_REGNO].loc.offset = (long) &vregs->vsave - new_cfa;
+ }
+
+ return _URC_NO_REASON;
+}
+
+#define MD_FROB_UPDATE_CONTEXT frob_update_context
+
+static void
+frob_update_context (struct _Unwind_Context *context, _Unwind_FrameState *fs ATTRIBUTE_UNUSED)
+{
+ const unsigned int *pc = (const unsigned int *) context->ra;
+
+ /* Fix up for 2.6.12 - 2.6.16 Linux kernels that have vDSO, but don't
+ have S flag in it. */
+#ifdef __powerpc64__
+ /* addi r1, r1, 128; li r0, 0x0077; sc (sigreturn) */
+ /* addi r1, r1, 128; li r0, 0x00AC; sc (rt_sigreturn) */
+ if (pc[0] == 0x38210000 + SIGNAL_FRAMESIZE
+ && (pc[1] == 0x38000077 || pc[1] == 0x380000AC)
+ && pc[2] == 0x44000002)
+ _Unwind_SetSignalFrame (context, 1);
+#else
+ /* li r0, 0x7777; sc (sigreturn old) */
+ /* li r0, 0x0077; sc (sigreturn new) */
+ /* li r0, 0x6666; sc (rt_sigreturn old) */
+ /* li r0, 0x00AC; sc (rt_sigreturn new) */
+ if ((pc[0] == 0x38007777 || pc[0] == 0x38000077
+ || pc[0] == 0x38006666 || pc[0] == 0x380000AC)
+ && pc[1] == 0x44000002)
+ _Unwind_SetSignalFrame (context, 1);
+#endif
+
+#ifdef __powerpc64__
+ if (fs->regs.reg[2].how == REG_UNSAVED)
+ {
+ /* If the current unwind info (FS) does not contain explicit info
+ saving R2, then we have to do a minor amount of code reading to
+ figure out if it was saved. The big problem here is that the
+ code that does the save/restore is generated by the linker, so
+ we have no good way to determine at compile time what to do. */
+ unsigned int *insn
+ = (unsigned int *) _Unwind_GetGR (context, LINK_REGISTER_REGNUM);
+ if (*insn == 0xE8410028)
+ _Unwind_SetGRPtr (context, 2, context->cfa + 40);
+ }
+#endif
+}
diff --git a/contrib/gcc/config/rs6000/linux.h b/contrib/gcc/config/rs6000/linux.h
index 84cdeed..3df356f 100644
--- a/contrib/gcc/config/rs6000/linux.h
+++ b/contrib/gcc/config/rs6000/linux.h
@@ -1,7 +1,7 @@
/* Definitions of target machine for GNU compiler,
for PowerPC machines running Linux.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
+ 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Michael Meissner (meissner@cygnus.com).
This file is part of GCC.
@@ -18,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
@@ -28,20 +28,23 @@
process. */
#define OS_MISSING_POWERPC64 1
+/* We use glibc _mcount for profiling. */
+#define NO_PROFILE_COUNTERS 1
+
/* glibc has float and long double forms of math functions. */
#undef TARGET_C99_FUNCTIONS
-#define TARGET_C99_FUNCTIONS 1
+#define TARGET_C99_FUNCTIONS (OPTION_GLIBC)
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("PPC"); \
- builtin_define_std ("powerpc"); \
- builtin_assert ("cpu=powerpc"); \
- builtin_assert ("machine=powerpc"); \
- TARGET_OS_SYSV_CPP_BUILTINS (); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define_std ("powerpc"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ TARGET_OS_SYSV_CPP_BUILTINS (); \
+ } \
while (0)
#undef CPP_OS_DEFAULT_SPEC
@@ -74,6 +77,11 @@
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC GNU/Linux)");
@@ -102,8 +110,18 @@
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-#define TARGET_HAS_F_SETLKW
+#define TARGET_POSIX_IO
+
+#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* ppc32 glibc provides __stack_chk_guard in -0x7008(2). */
+#define TARGET_THREAD_SSP_OFFSET -0x7008
+#endif
+
+#define POWERPC_LINUX
-#ifdef IN_LIBGCC2
-#include "config/rs6000/linux-unwind.h"
+/* ppc linux has 128-bit long double support in glibc 2.4 and later. */
+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
+#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
#endif
diff --git a/contrib/gcc/config/rs6000/linux64.h b/contrib/gcc/config/rs6000/linux64.h
index 84e13a1..f52b245 100644
--- a/contrib/gcc/config/rs6000/linux64.h
+++ b/contrib/gcc/config/rs6000/linux64.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for 64 bit PowerPC linux.
- Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
This file is part of GCC.
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#ifndef RS6000_BI_ARCH
@@ -50,8 +50,17 @@
#undef TARGET_AIX
#define TARGET_AIX TARGET_64BIT
-#undef PROCESSOR_DEFAULT64
-#define PROCESSOR_DEFAULT64 PROCESSOR_PPC630
+#ifdef HAVE_LD_NO_DOT_SYMS
+/* New ABI uses a local sym for the function entry point. */
+extern int dot_symbols;
+#undef DOT_SYMBOLS
+#define DOT_SYMBOLS dot_symbols
+#endif
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_POWER4
+#undef PROCESSOR_DEFAULT64
+#define PROCESSOR_DEFAULT64 PROCESSOR_POWER4
/* We don't need to generate entries in .fixup, except when
-mrelocatable or -mrelocatable-lib is given. */
@@ -60,7 +69,7 @@
(target_flags & target_flags_explicit & MASK_RELOCATABLE)
#undef RS6000_ABI_NAME
-#define RS6000_ABI_NAME (TARGET_64BIT ? "aixdesc" : "sysv")
+#define RS6000_ABI_NAME "linux"
#define INVALID_64BIT "-m%s not supported in this configuration"
#define INVALID_32BIT INVALID_64BIT
@@ -69,7 +78,7 @@
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
do \
{ \
- if (rs6000_alignment_string == 0) \
+ if (!rs6000_explicit_options.alignment) \
rs6000_alignment_flags = MASK_ALIGN_NATURAL; \
if (TARGET_64BIT) \
{ \
@@ -78,6 +87,7 @@
rs6000_current_abi = ABI_AIX; \
error (INVALID_64BIT, "call"); \
} \
+ dot_symbols = !strcmp (rs6000_abi_name, "aixdesc"); \
if (target_flags & MASK_RELOCATABLE) \
{ \
target_flags &= ~MASK_RELOCATABLE; \
@@ -93,7 +103,7 @@
target_flags &= ~MASK_PROTOTYPE; \
error (INVALID_64BIT, "prototype"); \
} \
- if ((target_flags & MASK_POWERPC64) == 0) \
+ if ((target_flags & MASK_POWERPC64) == 0) \
{ \
target_flags |= MASK_POWERPC64; \
error ("-m64 requires a PowerPC64 cpu"); \
@@ -127,16 +137,16 @@
#ifndef RS6000_BI_ARCH
#define ASM_DEFAULT_SPEC "-mppc64"
-#define ASM_SPEC "%(asm_spec64) %(asm_spec_common)"
+#define ASM_SPEC "%(asm_spec64) %(asm_spec_common)"
#define LINK_OS_LINUX_SPEC "%(link_os_linux_spec64)"
#else
#if DEFAULT_ARCH64_P
#define ASM_DEFAULT_SPEC "-mppc%{!m32:64}"
-#define ASM_SPEC "%{m32:%(asm_spec32)}%{!m32:%(asm_spec64)} %(asm_spec_common)"
+#define ASM_SPEC "%{m32:%(asm_spec32)}%{!m32:%(asm_spec64)} %(asm_spec_common)"
#define LINK_OS_LINUX_SPEC "%{m32:%(link_os_linux_spec32)}%{!m32:%(link_os_linux_spec64)}"
#else
#define ASM_DEFAULT_SPEC "-mppc%{m64:64}"
-#define ASM_SPEC "%{!m64:%(asm_spec32)}%{m64:%(asm_spec64)} %(asm_spec_common)"
+#define ASM_SPEC "%{!m64:%(asm_spec32)}%{m64:%(asm_spec64)} %(asm_spec_common)"
#define LINK_OS_LINUX_SPEC "%{!m64:%(link_os_linux_spec32)}%{m64:%(link_os_linux_spec64)}"
#endif
#endif
@@ -196,24 +206,8 @@
#endif
-#define MASK_PROFILE_KERNEL 0x00100000
-
-/* Non-standard profiling for kernels, which just saves LR then calls
- _mcount without worrying about arg saves. The idea is to change
- the function prologue as little as possible as it isn't easy to
- account for arg save/restore code added just for _mcount. */
-#define TARGET_PROFILE_KERNEL (target_flags & MASK_PROFILE_KERNEL)
-
-/* Override sysv4.h. */
-#undef EXTRA_SUBTARGET_SWITCHES
-#define EXTRA_SUBTARGET_SWITCHES \
- {"profile-kernel", MASK_PROFILE_KERNEL, \
- N_("Call mcount for profiling before a function prologue") }, \
- {"no-profile-kernel", -MASK_PROFILE_KERNEL, \
- N_("Call mcount for profiling after a function prologue") },
-
/* We use glibc _mcount for profiling. */
-#define NO_PROFILE_COUNTERS TARGET_64BIT
+#define NO_PROFILE_COUNTERS 1
#define PROFILE_HOOK(LABEL) \
do { if (TARGET_64BIT) output_profile_hook (LABEL); } while (0)
@@ -234,13 +228,11 @@
the first field is an FP double, only if in power alignment mode. */
#undef ROUND_TYPE_ALIGN
#define ROUND_TYPE_ALIGN(STRUCT, COMPUTED, SPECIFIED) \
- ((TARGET_ALTIVEC && TREE_CODE (STRUCT) == VECTOR_TYPE) \
- ? MAX (MAX ((COMPUTED), (SPECIFIED)), 128) \
- : (TARGET_64BIT \
- && (TREE_CODE (STRUCT) == RECORD_TYPE \
- || TREE_CODE (STRUCT) == UNION_TYPE \
- || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
- && TARGET_ALIGN_NATURAL == 0) \
+ ((TARGET_64BIT \
+ && (TREE_CODE (STRUCT) == RECORD_TYPE \
+ || TREE_CODE (STRUCT) == UNION_TYPE \
+ || TREE_CODE (STRUCT) == QUAL_UNION_TYPE) \
+ && TARGET_ALIGN_NATURAL == 0) \
? rs6000_special_round_type_align (STRUCT, COMPUTED, SPECIFIED) \
: MAX ((COMPUTED), (SPECIFIED)))
@@ -258,7 +250,7 @@
than a doubleword should be padded upward or downward. You could
reasonably assume that they follow the normal rules for structure
layout treating the parameter area as any other block of memory,
- then map the reg param area to registers. ie. pad updard.
+ then map the reg param area to registers. i.e. pad upward.
Setting both of the following defines results in this behavior.
Setting just the first one will result in aggregates that fit in a
doubleword being padded downward, and others being padded upward.
@@ -267,16 +259,6 @@
#define AGGREGATE_PADDING_FIXED TARGET_64BIT
#define AGGREGATES_PAD_UPWARD_ALWAYS 0
-/* We don't want anything in the reg parm area being passed on the
- stack. */
-#define MUST_PASS_IN_STACK(MODE, TYPE) \
- ((TARGET_64BIT \
- && (TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE))) \
- || (!TARGET_64BIT \
- && default_must_pass_in_stack ((MODE), (TYPE))))
-
/* Specify padding for the last element of a block move between
registers and memory. FIRST is nonzero if this is the only
element. */
@@ -301,10 +283,10 @@
/* glibc has float and long double forms of math functions. */
#undef TARGET_C99_FUNCTIONS
-#define TARGET_C99_FUNCTIONS 1
+#define TARGET_C99_FUNCTIONS (OPTION_GLIBC)
#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
+#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
if (TARGET_64BIT) \
@@ -313,7 +295,6 @@
builtin_define ("__PPC64__"); \
builtin_define ("__powerpc__"); \
builtin_define ("__powerpc64__"); \
- builtin_define ("__PIC__"); \
builtin_assert ("cpu=powerpc64"); \
builtin_assert ("machine=powerpc64"); \
} \
@@ -355,13 +336,28 @@
#undef LINK_OS_DEFAULT_SPEC
#define LINK_OS_DEFAULT_SPEC "%(link_os_linux)"
+#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld64.so.1"
+#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#if UCLIBC_DEFAULT
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+#else
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}" U ";:" G "}"
+#endif
+#define LINUX_DYNAMIC_LINKER32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32)
+#define LINUX_DYNAMIC_LINKER64 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64)
+
+
#define LINK_OS_LINUX_SPEC32 "-m elf32ppclinux %{!shared: %{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER32 "}}}"
#define LINK_OS_LINUX_SPEC64 "-m elf64ppc %{!shared: %{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib64/ld64.so.1}}}"
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}}}"
#undef TOC_SECTION_ASM_OP
#define TOC_SECTION_ASM_OP \
@@ -412,11 +408,19 @@
object files, each potentially with a different TOC pointer. For
that reason, place a nop after the call so that the linker can
restore the TOC pointer if a TOC adjusting call stub is needed. */
+#if DOT_SYMBOLS
#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
asm (SECTION_OP "\n" \
" bl ." #FUNC "\n" \
" nop\n" \
" .previous");
+#else
+#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
+ asm (SECTION_OP "\n" \
+" bl " #FUNC "\n" \
+" nop\n" \
+" .previous");
+#endif
#endif
/* FP save and restore routines. */
@@ -441,13 +445,11 @@
if (!flag_inhibit_size_directive) \
{ \
fputs ("\t.size\t", (FILE)); \
- if (TARGET_64BIT) \
+ if (TARGET_64BIT && DOT_SYMBOLS) \
putc ('.', (FILE)); \
assemble_name ((FILE), (FNAME)); \
fputs (",.-", (FILE)); \
- if (TARGET_64BIT) \
- putc ('.', (FILE)); \
- assemble_name ((FILE), (FNAME)); \
+ rs6000_output_function_entry (FILE, FNAME); \
putc ('\n', (FILE)); \
} \
} \
@@ -476,72 +478,14 @@
&& ((TARGET_64BIT \
&& (TARGET_POWERPC64 \
|| TARGET_MINIMAL_TOC \
- || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ || (SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
&& ! TARGET_NO_FP_IN_TOC))) \
|| (!TARGET_64BIT \
&& !TARGET_NO_FP_IN_TOC \
&& !TARGET_RELOCATABLE \
- && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ && SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
&& BITS_PER_WORD == HOST_BITS_PER_INT)))))
-/* This is the same as the dbxelf.h version, except that we need to
- use the function code label, not the function descriptor. */
-#undef ASM_OUTPUT_SOURCE_LINE
-#define ASM_OUTPUT_SOURCE_LINE(FILE, LINE, COUNTER) \
-do \
- { \
- char temp[256]; \
- ASM_GENERATE_INTERNAL_LABEL (temp, "LM", COUNTER); \
- fprintf (FILE, "\t.stabn 68,0,%d,", LINE); \
- assemble_name (FILE, temp); \
- putc ('-', FILE); \
- if (TARGET_64BIT) \
- putc ('.', FILE); \
- assemble_name (FILE, \
- XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0));\
- putc ('\n', FILE); \
- (*targetm.asm_out.internal_label) (FILE, "LM", COUNTER); \
- } \
-while (0)
-
-/* Similarly, we want the function code label here. */
-#define DBX_OUTPUT_BRAC(FILE, NAME, BRAC) \
- do \
- { \
- const char *flab; \
- fprintf (FILE, "%s%d,0,0,", ASM_STABN_OP, BRAC); \
- assemble_name (FILE, NAME); \
- putc ('-', FILE); \
- if (current_function_func_begin_label != NULL_TREE) \
- flab = IDENTIFIER_POINTER (current_function_func_begin_label); \
- else \
- { \
- if (TARGET_64BIT) \
- putc ('.', FILE); \
- flab = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); \
- } \
- assemble_name (FILE, flab); \
- putc ('\n', FILE); \
- } \
- while (0)
-
-#define DBX_OUTPUT_LBRAC(FILE, NAME) DBX_OUTPUT_BRAC (FILE, NAME, N_LBRAC)
-#define DBX_OUTPUT_RBRAC(FILE, NAME) DBX_OUTPUT_BRAC (FILE, NAME, N_RBRAC)
-
-/* Another case where we want the dot name. */
-#define DBX_OUTPUT_NFUN(FILE, LSCOPE, DECL) \
- do \
- { \
- fprintf (FILE, "%s\"\",%d,0,0,", ASM_STABS_OP, N_FUN); \
- assemble_name (FILE, LSCOPE); \
- putc ('-', FILE); \
- if (TARGET_64BIT) \
- putc ('.', FILE); \
- assemble_name (FILE, XSTR (XEXP (DECL_RTL (DECL), 0), 0)); \
- putc ('\n', FILE); \
- } \
- while (0)
-
/* 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. */
@@ -559,11 +503,27 @@ while (0)
#define TARGET_ASM_FILE_END rs6000_elf_end_indicate_exec_stack
-#define TARGET_HAS_F_SETLKW
+#define TARGET_POSIX_IO
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
-#ifdef IN_LIBGCC2
-#include "config/rs6000/linux-unwind.h"
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+#define MD_UNWIND_SUPPORT "config/rs6000/linux-unwind.h"
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* ppc32 glibc provides __stack_chk_guard in -0x7008(2),
+ ppc64 glibc provides it at -0x7010(13). */
+#define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? -0x7010 : -0x7008)
+#endif
+
+#define POWERPC_LINUX
+
+/* ppc{32,64} linux has 128-bit long double support in glibc 2.4 and later. */
+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
+#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
#endif
diff --git a/contrib/gcc/config/rs6000/linux64.opt b/contrib/gcc/config/rs6000/linux64.opt
new file mode 100644
index 0000000..ebd3384
--- /dev/null
+++ b/contrib/gcc/config/rs6000/linux64.opt
@@ -0,0 +1,25 @@
+; Options for 64-bit PowerPC Linux.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mprofile-kernel
+Target Report Mask(PROFILE_KERNEL)
+Call mcount for profiling before a function prologue
diff --git a/contrib/gcc/config/rs6000/linuxaltivec.h b/contrib/gcc/config/rs6000/linuxaltivec.h
index 73ac864..181bb81 100644
--- a/contrib/gcc/config/rs6000/linuxaltivec.h
+++ b/contrib/gcc/config/rs6000/linuxaltivec.h
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC AltiVec GNU/Linux)");
diff --git a/contrib/gcc/config/rs6000/linuxspe.h b/contrib/gcc/config/rs6000/linuxspe.h
index 59eb831..fd7d20e 100644
--- a/contrib/gcc/config/rs6000/linuxspe.h
+++ b/contrib/gcc/config/rs6000/linuxspe.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for PowerPC e500 machines running GNU/Linux.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004 Free Software Foundation, Inc.
Contributed by Aldy Hernandez (aldy@quesejoda.com).
This file is part of GCC.
@@ -17,43 +17,49 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC E500 GNU/Linux)");
/* Override rs6000.h and sysv4.h definition. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS)
+#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_STRICT_ALIGN)
#undef TARGET_SPE_ABI
#undef TARGET_SPE
#undef TARGET_E500
#undef TARGET_ISEL
#undef TARGET_FPRS
+#undef TARGET_E500_SINGLE
+#undef TARGET_E500_DOUBLE
#define TARGET_SPE_ABI rs6000_spe_abi
#define TARGET_SPE rs6000_spe
#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
#define TARGET_ISEL rs6000_isel
-#define TARGET_FPRS (!rs6000_float_gprs)
+#define TARGET_FPRS (rs6000_float_gprs == 0)
+#define TARGET_E500_SINGLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 1)
+#define TARGET_E500_DOUBLE (TARGET_HARD_FLOAT && rs6000_float_gprs == 2)
#undef SUBSUBTARGET_OVERRIDE_OPTIONS
#define SUBSUBTARGET_OVERRIDE_OPTIONS \
if (rs6000_select[1].string == NULL) \
rs6000_cpu = PROCESSOR_PPC8540; \
- if (rs6000_abi_string == NULL || strstr (rs6000_abi_string, "spe") == NULL) \
+ if (!rs6000_explicit_options.abi) \
rs6000_spe_abi = 1; \
- if (rs6000_float_gprs_string == NULL) \
+ if (!rs6000_explicit_options.float_gprs) \
rs6000_float_gprs = 1; \
/* See note below. */ \
- /*if (rs6000_long_double_size_string == NULL)*/ \
+ /*if (!rs6000_explicit_options.long_double)*/ \
/* rs6000_long_double_type_size = 128;*/ \
- if (rs6000_spe_string == NULL) \
+ if (!rs6000_explicit_options.spe) \
rs6000_spe = 1; \
- if (rs6000_isel_string == NULL) \
- rs6000_isel = 1
+ if (!rs6000_explicit_options.isel) \
+ rs6000_isel = 1; \
+ if (target_flags & MASK_64BIT) \
+ error ("-m64 not supported in this configuration")
/* The e500 ABI says that either long doubles are 128 bits, or if
implemented in any other size, the compiler/linker should error out.
diff --git a/contrib/gcc/config/rs6000/lynx.h b/contrib/gcc/config/rs6000/lynx.h
index b32b078..ab2d16f 100644
--- a/contrib/gcc/config/rs6000/lynx.h
+++ b/contrib/gcc/config/rs6000/lynx.h
@@ -1,6 +1,8 @@
/* Definitions for Rs6000 running LynxOS.
- Copyright (C) 1995, 1996, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1995, 1996, 2000, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by David Henkel-Wallace, Cygnus Support (gumby@cygnus.com)
+ Rewritten by Adam Nemet, LynuxWorks Inc.
This file is part of GCC.
@@ -16,72 +18,108 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
-
-/* Print subsidiary information on the compiler version in use. */
-#define TARGET_VERSION fprintf (stderr, " (LynxOS-RS/6000)");
-
-/* LynxOS has signed chars, regardless of what most R/S 6000 systems do */
-#undef DEFAULT_SIGNED_CHAR
-#define DEFAULT_SIGNED_CHAR 1
-
-#undef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_assert ("cpu=rs6000"); \
- builtin_assert ("machine=rs6000"); \
- builtin_assert ("system=lynx"); \
- builtin_assert ("system=unix"); \
- builtin_define_std ("Lynx"); \
- builtin_define ("_IBMR2"); \
- builtin_define_std ("unix"); \
- builtin_define_std ("rs6000"); \
- builtin_define_std ("lynx"); \
- builtin_define_std ("LYNX"); \
- } \
- while (0)
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* Override the definition in sysv4.h. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fputs (" (PowerPC/LynxOS)", stderr);
+
+/* Undefine the definition to enable the LynxOS default from the
+ top-level lynx.h. */
+
+#undef SUBTARGET_EXTRA_SPECS
+
+/* Get rid off the spec definitions from rs6000/sysv4.h. */
-#undef LINK_SPEC
-#define LINK_SPEC "-T0x10001000 -H0x1000 -D0x20000000 -btextro -bhalt:4 -bnodelcsect -bnso -bro -bnoglink %{v} %{b*}"
+#undef CPP_SPEC
+#define CPP_SPEC \
+"%{msoft-float: -D_SOFT_FLOAT} \
+ %(cpp_cpu) \
+ %(cpp_os_lynx)"
-#undef LIB_SPEC
-#define LIB_SPEC "%{mthreads:-L/lib/thread/} \
- %{msystem-v:-lc_v -lm.v} \
- %{!msystem-v:%{mposix:-lc_p} -lc -lm}"
+/* LynxOS only supports big-endian on PPC so we override the
+ definition from sysv4.h. Since the LynxOS 4.0 compiler was set to
+ return every structure in memory regardless of their size we have
+ to emulate the same behavior here with disabling the SVR4 structure
+ returning. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC "%{p:%{mthreads:thread/pinit.o%s}%{!mthreads:pinit.o%s}}%{!p:%{msystem-v:vinit.o%s -e_start}%{!msystem-v:%{mthreads:thread/init.o%s}%{!mthreads:init.o%s}}}"
+#undef CC1_SPEC
+#define CC1_SPEC \
+"%{G*} %{mno-sdata:-msdata=none} \
+ %{maltivec:-mabi=altivec} \
+ -maix-struct-return"
+#undef ASM_SPEC
+#define ASM_SPEC \
+"%(asm_cpu) \
+ %{.s: %{mregnames} %{mno-regnames}} \
+ %{.S: %{mregnames} %{mno-regnames}}"
+
+#undef STARTFILE_SPEC
#undef ENDFILE_SPEC
+#undef LIB_SPEC
+#undef LINK_SPEC
+#define LINK_SPEC \
+"%{!msdata=none:%{G*}} %{msdata=none:-G0} \
+ %(link_os_lynx)"
+
+/* Override the definition from sysv4.h. */
+
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define ("__BIG_ENDIAN__"); \
+ builtin_define ("__powerpc__"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ builtin_define ("__PPC__"); \
+ } \
+ while (0)
+
+/* Override the rs6000.h definition. */
+
+#undef ASM_APP_ON
+#define ASM_APP_ON "#APP\n"
+
+/* Override the rs6000.h definition. */
+
+#undef ASM_APP_OFF
+#define ASM_APP_OFF "#NO_APP\n"
+
+/* LynxOS does not do anything with .fixup plus let's not create
+ writable section for linkonce.r and linkonce.t. */
+
+#undef RELOCATABLE_NEEDS_FIXUP
+
+/* Override these from rs6000.h with the generic definition. */
+
+#undef SIZE_TYPE
+#undef ASM_OUTPUT_ALIGN
+#undef PREFERRED_DEBUGGING_TYPE
+
+/* The file rs6000.c defines TARGET_HAVE_TLS unconditionally to the
+ value of HAVE_AS_TLS. HAVE_AS_TLS is true as gas support for TLS
+ is detected by configure. Override the definition to false. */
+
+#undef HAVE_AS_TLS
+#define HAVE_AS_TLS 0
+
+#ifdef CRT_BEGIN
+/* This function is part of crtbegin*.o which is at the beginning of
+ the link and is called from .fini which is usually toward the end
+ of the executable. Make it longcall so that we don't limit the
+ text size of the executables to 32M. */
+
+static void __do_global_dtors_aux (void) __attribute__ ((longcall));
+#endif /* CRT_BEGIN */
+
+#ifdef CRT_END
+/* Similarly here. This function resides in crtend*.o which is toward
+ to end of the link and is called from .init which is at the
+ beginning. */
-/* This can become more refined as we have more powerpc options. */
-#undef ASM_SPEC
-#define ASM_SPEC "-u %(asm_cpu)"
-
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- {"threads", MASK_THREADS}, \
- {"posix", MASK_POSIX}, \
- {"system-v", MASK_SYSTEM_V},
-
-#undef SUBTARGET_OVERRIDE_OPTIONS
-#define SUBTARGET_OVERRIDE_OPTIONS \
-do { \
- if (TARGET_SYSTEM_V && profile_flag) \
- warning ("-msystem-v and -p are incompatible"); \
- if (TARGET_SYSTEM_V && TARGET_THREADS) \
- warning ("-msystem-v and -mthreads are incompatible"); \
-} while (0)
-
-/* For collect2 */
-#define OBJECT_FORMAT_NONE
-#undef OBJECT_FORMAT_COFF
-#undef MD_EXEC_PREFIX
-#undef REAL_LD_FILE_NAME
-#undef REAL_STRIP_FILE_NAME
-
-/* LynxOS doesn't have mcount. */
-#undef FUNCTION_PROFILER
-#define FUNCTION_PROFILER(file, profile_label_no)
+static void __do_global_ctors_aux (void) __attribute__ ((longcall));
+#endif /* CRT_END */
diff --git a/contrib/gcc/config/rs6000/mpc.md b/contrib/gcc/config/rs6000/mpc.md
index b95bba5..75e4752 100644
--- a/contrib/gcc/config/rs6000/mpc.md
+++ b/contrib/gcc/config/rs6000/mpc.md
@@ -1,5 +1,5 @@
;; Scheduling description for Motorola PowerPC processor cores.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "mpc,mpcfp")
(define_cpu_unit "iu_mpc,mciu_mpc" "mpc")
@@ -27,11 +27,12 @@
;; 505/801/821/823
(define_insn_reservation "mpccore-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,store_c,sync")
(eq_attr "cpu" "mpccore"))
"lsu_mpc")
-(define_insn_reservation "mpccore-store" 1
+(define_insn_reservation "mpccore-store" 2
(and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
(eq_attr "cpu" "mpccore"))
"lsu_mpc")
@@ -46,6 +47,16 @@
(eq_attr "cpu" "mpccore"))
"iu_mpc")
+(define_insn_reservation "mpccore-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "mpccore"))
+ "iu_mpc,iu_mpc")
+
+(define_insn_reservation "mpccore-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "mpccore"))
+ "iu_mpc,iu_mpc,iu_mpc")
+
(define_insn_reservation "mpccore-imul" 2
(and (eq_attr "type" "imul,imul2,imul3,imul_compare")
(eq_attr "cpu" "mpccore"))
@@ -93,7 +104,7 @@
"bpu_mpc")
(define_insn_reservation "mpccore-jmpreg" 1
- (and (eq_attr "type" "jmpreg,branch,cr_logical,delayed_cr,mfcr,mtcr")
+ (and (eq_attr "type" "jmpreg,branch,cr_logical,delayed_cr,mfcr,mtcr,isync")
(eq_attr "cpu" "mpccore"))
"bpu_mpc")
diff --git a/contrib/gcc/config/rs6000/netbsd.h b/contrib/gcc/config/rs6000/netbsd.h
index e0c5196..151c232 100644
--- a/contrib/gcc/config/rs6000/netbsd.h
+++ b/contrib/gcc/config/rs6000/netbsd.h
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_OS_CPP_BUILTINS /* FIXME: sysv4.h should not define this! */
#define TARGET_OS_CPP_BUILTINS() \
diff --git a/contrib/gcc/config/rs6000/power4.md b/contrib/gcc/config/rs6000/power4.md
index fabc1de..53ac066 100644
--- a/contrib/gcc/config/rs6000/power4.md
+++ b/contrib/gcc/config/rs6000/power4.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM Power4 and PowerPC 970 processors.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
;; Sources: IBM Red Book and White Paper on POWER4
@@ -38,38 +38,37 @@
(define_reservation "lsq_power4"
"(du1_power4,lsu1_power4)\
|(du2_power4,lsu2_power4)\
- |(du3_power4,nothing,lsu2_power4)\
- |(du4_power4,nothing,lsu1_power4)")
+ |(du3_power4,lsu2_power4)\
+ |(du4_power4,lsu1_power4)")
(define_reservation "lsuq_power4"
"(du1_power4+du2_power4,lsu1_power4+iu2_power4)\
|(du2_power4+du3_power4,lsu2_power4+iu2_power4)\
|(du3_power4+du4_power4,lsu2_power4+iu1_power4)")
-; |(du2_power4+du3_power4,nothing,lsu2_power4,iu2_power4)
(define_reservation "iq_power4"
"(du1_power4,iu1_power4)\
|(du2_power4,iu2_power4)\
- |(du3_power4,nothing,iu2_power4)\
- |(du4_power4,nothing,iu1_power4)")
+ |(du3_power4,iu2_power4)\
+ |(du4_power4,iu1_power4)")
(define_reservation "fpq_power4"
"(du1_power4,fpu1_power4)\
|(du2_power4,fpu2_power4)\
- |(du3_power4,nothing,fpu2_power4)\
- |(du4_power4,nothing,fpu1_power4)")
+ |(du3_power4,fpu2_power4)\
+ |(du4_power4,fpu1_power4)")
(define_reservation "vq_power4"
"(du1_power4,vec_power4)\
|(du2_power4,vec_power4)\
- |(du3_power4,nothing,vec_power4)\
- |(du4_power4,nothing,vec_power4)")
+ |(du3_power4,vec_power4)\
+ |(du4_power4,vec_power4)")
(define_reservation "vpq_power4"
"(du1_power4,vecperm_power4)\
|(du2_power4,vecperm_power4)\
- |(du3_power4,nothing,vecperm_power4)\
- |(du4_power4,nothing,vecperm_power4)")
+ |(du3_power4,vecperm_power4)\
+ |(du4_power4,vecperm_power4)")
; Dispatch slots are allocated in order conforming to program order.
@@ -130,15 +129,15 @@
(eq_attr "cpu" "power4"))
"lsq_power4")
-(define_insn_reservation "power4-store" 1
+(define_insn_reservation "power4-store" 12
(and (eq_attr "type" "store")
(eq_attr "cpu" "power4"))
"(du1_power4,lsu1_power4,iu1_power4)\
|(du2_power4,lsu2_power4,iu2_power4)\
- |(du3_power4,lsu2_power4,nothing,iu2_power4)\
- |(du4_power4,lsu1_power4,nothing,iu1_power4)")
+ |(du3_power4,lsu2_power4,iu2_power4)\
+ |(du4_power4,lsu1_power4,iu1_power4)")
-(define_insn_reservation "power4-store-update" 1
+(define_insn_reservation "power4-store-update" 12
(and (eq_attr "type" "store_u")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4,lsu1_power4+iu2_power4,iu1_power4)\
@@ -146,35 +145,40 @@
|(du3_power4+du4_power4,lsu2_power4+iu1_power4,iu2_power4)\
|(du3_power4+du4_power4,lsu2_power4,iu1_power4,iu2_power4)")
-(define_insn_reservation "power4-store-update-indexed" 1
+(define_insn_reservation "power4-store-update-indexed" 12
(and (eq_attr "type" "store_ux")
(eq_attr "cpu" "power4"))
"du1_power4+du2_power4+du3_power4+du4_power4,\
iu1_power4,lsu2_power4+iu2_power4,iu2_power4")
-(define_insn_reservation "power4-fpstore" 1
+(define_insn_reservation "power4-fpstore" 12
(and (eq_attr "type" "fpstore")
(eq_attr "cpu" "power4"))
"(du1_power4,lsu1_power4,fpu1_power4)\
|(du2_power4,lsu2_power4,fpu2_power4)\
- |(du3_power4,lsu2_power4,nothing,fpu2_power4)\
- |(du4_power4,lsu1_power4,nothing,fpu1_power4)")
+ |(du3_power4,lsu2_power4,fpu2_power4)\
+ |(du4_power4,lsu1_power4,fpu1_power4)")
-(define_insn_reservation "power4-fpstore-update" 1
+(define_insn_reservation "power4-fpstore-update" 12
(and (eq_attr "type" "fpstore_u,fpstore_ux")
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4,lsu1_power4+iu2_power4,fpu1_power4)\
|(du2_power4+du3_power4,lsu2_power4+iu2_power4,fpu2_power4)\
|(du3_power4+du4_power4,lsu2_power4+iu1_power4,fpu2_power4)")
-; |(du3_power4+du4_power4,nothing,lsu2_power4+iu1_power4,fpu2_power4)")
-(define_insn_reservation "power4-vecstore" 1
+(define_insn_reservation "power4-vecstore" 12
(and (eq_attr "type" "vecstore")
(eq_attr "cpu" "power4"))
"(du1_power4,lsu1_power4,vec_power4)\
|(du2_power4,lsu2_power4,vec_power4)\
- |(du3_power4,lsu2_power4,nothing,vec_power4)\
- |(du4_power4,lsu1_power4,nothing,vec_power4)")
+ |(du3_power4,lsu2_power4,vec_power4)\
+ |(du4_power4,lsu1_power4,vec_power4)")
+
+(define_insn_reservation "power4-llsc" 11
+ (and (eq_attr "type" "load_l,store_c,sync")
+ (eq_attr "cpu" "power4"))
+ "du1_power4+du2_power4+du3_power4+du4_power4,\
+ lsu1_power4")
; Integer latency is 2 cycles
@@ -183,6 +187,26 @@
(eq_attr "cpu" "power4"))
"iq_power4")
+(define_insn_reservation "power4-two" 2
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "power4"))
+ "(du1_power4+du2_power4,iu1_power4,nothing,iu2_power4)\
+ |(du2_power4+du3_power4,iu2_power4,nothing,iu2_power4)\
+ |(du3_power4+du4_power4,iu2_power4,nothing,iu1_power4)\
+ |(du4_power4+du1_power4,iu1_power4,nothing,iu1_power4)")
+
+(define_insn_reservation "power4-three" 2
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "power4"))
+ "(du1_power4+du2_power4+du3_power4,\
+ iu1_power4,nothing,iu2_power4,nothing,iu2_power4)\
+ |(du2_power4+du3_power4+du4_power4,\
+ iu2_power4,nothing,iu2_power4,nothing,iu1_power4)\
+ |(du3_power4+du4_power4+du1_power4,\
+ iu2_power4,nothing,iu1_power4,nothing,iu1_power4)\
+ |(du4_power4+du1_power4+du2_power4,\
+ iu1_power4,nothing,iu2_power4,nothing,iu2_power4)")
+
(define_insn_reservation "power4-insert" 4
(and (eq_attr "type" "insert_word")
(eq_attr "cpu" "power4"))
@@ -200,7 +224,7 @@
(eq_attr "cpu" "power4"))
"(du1_power4+du2_power4,iu1_power4,iu2_power4)\
|(du2_power4+du3_power4,iu2_power4,iu2_power4)\
- |(du3_power4+du4_power4,nothing,iu2_power4,iu1_power4)")
+ |(du3_power4+du4_power4,iu2_power4,iu1_power4)")
(define_bypass 4 "power4-compare" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
@@ -210,7 +234,6 @@
"(du1_power4+du2_power4,iu1_power4*6,iu2_power4)\
|(du2_power4+du3_power4,iu2_power4*6,iu2_power4)\
|(du3_power4+du4_power4,iu2_power4*6,iu1_power4)")
-; |(du3_power4+du4_power4,nothing,iu2_power4*6,iu1_power4)")
(define_bypass 10 "power4-lmul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
@@ -220,7 +243,6 @@
"(du1_power4+du2_power4,iu1_power4*4,iu2_power4)\
|(du2_power4+du3_power4,iu2_power4*4,iu2_power4)\
|(du3_power4+du4_power4,iu2_power4*4,iu1_power4)")
-; |(du3_power4+du4_power4,nothing,iu2_power4*4,iu1_power4)")
(define_bypass 8 "power4-imul-cmp" "power4-branch,power4-crlogical,power4-delayedcr,power4-mfcr,power4-mfcrf")
@@ -230,9 +252,7 @@
"(du1_power4,iu1_power4*6)\
|(du2_power4,iu2_power4*6)\
|(du3_power4,iu2_power4*6)\
- |(du4_power4,iu2_power4*6)")
-; |(du3_power4,nothing,iu2_power4*6)\
-; |(du4_power4,nothing,iu2_power4*6)")
+ |(du4_power4,iu1_power4*6)")
(define_insn_reservation "power4-imul" 5
(and (eq_attr "type" "imul")
@@ -241,8 +261,6 @@
|(du2_power4,iu2_power4*4)\
|(du3_power4,iu2_power4*4)\
|(du4_power4,iu1_power4*4)")
-; |(du3_power4,nothing,iu2_power4*4)\
-; |(du4_power4,nothing,iu1_power4*4)")
(define_insn_reservation "power4-imul3" 4
(and (eq_attr "type" "imul2,imul3")
@@ -251,8 +269,6 @@
|(du2_power4,iu2_power4*3)\
|(du3_power4,iu2_power4*3)\
|(du4_power4,iu1_power4*3)")
-; |(du3_power4,nothing,iu2_power4*3)\
-; |(du4_power4,nothing,iu1_power4*3)")
; SPR move only executes in first IU.
@@ -335,8 +351,6 @@
|(du2_power4,fpu2_power4*28)\
|(du3_power4,fpu2_power4*28)\
|(du4_power4,fpu1_power4*28)")
-; |(du3_power4,nothing,fpu2_power4*28)\
-; |(du4_power4,nothing,fpu1_power4*28)")
(define_insn_reservation "power4-sqrt" 40
(and (eq_attr "type" "ssqrt,dsqrt")
@@ -345,8 +359,12 @@
|(du2_power4,fpu2_power4*35)\
|(du3_power4,fpu2_power4*35)\
|(du4_power4,fpu2_power4*35)")
-; |(du3_power4,nothing,fpu2_power4*35)\
-; |(du4_power4,nothing,fpu2_power4*35)")
+
+(define_insn_reservation "power4-isync" 2
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "power4"))
+ "du1_power4+du2_power4+du3_power4+du4_power4,\
+ lsu1_power4")
; VMX
diff --git a/contrib/gcc/config/rs6000/power5.md b/contrib/gcc/config/rs6000/power5.md
index 59baa79..ce68926 100644
--- a/contrib/gcc/config/rs6000/power5.md
+++ b/contrib/gcc/config/rs6000/power5.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
;; Sources: IBM Red Book and White Paper on POWER5
@@ -37,20 +37,20 @@
(define_reservation "lsq_power5"
"(du1_power5,lsu1_power5)\
|(du2_power5,lsu2_power5)\
- |(du3_power5,nothing,lsu2_power5)\
- |(du4_power5,nothing,lsu1_power5)")
+ |(du3_power5,lsu2_power5)\
+ |(du4_power5,lsu1_power5)")
(define_reservation "iq_power5"
"(du1_power5,iu1_power5)\
|(du2_power5,iu2_power5)\
- |(du3_power5,nothing,iu2_power5)\
- |(du4_power5,nothing,iu1_power5)")
+ |(du3_power5,iu2_power5)\
+ |(du4_power5,iu1_power5)")
(define_reservation "fpq_power5"
"(du1_power5,fpu1_power5)\
|(du2_power5,fpu2_power5)\
- |(du3_power5,nothing,fpu2_power5)\
- |(du4_power5,nothing,fpu1_power5)")
+ |(du3_power5,fpu2_power5)\
+ |(du4_power5,fpu1_power5)")
; Dispatch slots are allocated in order conforming to program order.
(absence_set "du1_power5" "du2_power5,du3_power5,du4_power5,du5_power5")
@@ -103,38 +103,44 @@
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5")
-(define_insn_reservation "power5-store" 1
+(define_insn_reservation "power5-store" 12
(and (eq_attr "type" "store")
(eq_attr "cpu" "power5"))
"(du1_power5,lsu1_power5,iu1_power5)\
|(du2_power5,lsu2_power5,iu2_power5)\
- |(du3_power5,lsu2_power5,nothing,iu2_power5)\
- |(du4_power5,lsu1_power5,nothing,iu1_power5)")
+ |(du3_power5,lsu2_power5,iu2_power5)\
+ |(du4_power5,lsu1_power5,iu1_power5)")
-(define_insn_reservation "power5-store-update" 1
+(define_insn_reservation "power5-store-update" 12
(and (eq_attr "type" "store_u")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5,iu1_power5")
-(define_insn_reservation "power5-store-update-indexed" 1
+(define_insn_reservation "power5-store-update-indexed" 12
(and (eq_attr "type" "store_ux")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5+du3_power5+du4_power5,\
iu1_power5,lsu2_power5+iu2_power5,iu2_power5")
-(define_insn_reservation "power5-fpstore" 1
+(define_insn_reservation "power5-fpstore" 12
(and (eq_attr "type" "fpstore")
(eq_attr "cpu" "power5"))
"(du1_power5,lsu1_power5,fpu1_power5)\
|(du2_power5,lsu2_power5,fpu2_power5)\
- |(du3_power5,lsu2_power5,nothing,fpu2_power5)\
- |(du4_power5,lsu1_power5,nothing,fpu1_power5)")
+ |(du3_power5,lsu2_power5,fpu2_power5)\
+ |(du4_power5,lsu1_power5,fpu1_power5)")
-(define_insn_reservation "power5-fpstore-update" 1
+(define_insn_reservation "power5-fpstore-update" 12
(and (eq_attr "type" "fpstore_u,fpstore_ux")
(eq_attr "cpu" "power5"))
"du1_power5+du2_power5,lsu1_power5+iu2_power5,fpu1_power5")
+(define_insn_reservation "power5-llsc" 11
+ (and (eq_attr "type" "load_l,store_c,sync")
+ (eq_attr "cpu" "power5"))
+ "du1_power5+du2_power5+du3_power5+du4_power5,\
+ lsu1_power5")
+
; Integer latency is 2 cycles
(define_insn_reservation "power5-integer" 2
@@ -142,6 +148,26 @@
(eq_attr "cpu" "power5"))
"iq_power5")
+(define_insn_reservation "power5-two" 2
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "power5"))
+ "(du1_power5+du2_power5,iu1_power5,nothing,iu2_power5)\
+ |(du2_power5+du3_power5,iu2_power5,nothing,iu2_power5)\
+ |(du3_power5+du4_power5,iu2_power5,nothing,iu1_power5)\
+ |(du4_power5+du1_power5,iu1_power5,nothing,iu1_power5)")
+
+(define_insn_reservation "power5-three" 2
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "power5"))
+ "(du1_power5+du2_power5+du3_power5,\
+ iu1_power5,nothing,iu2_power5,nothing,iu2_power5)\
+ |(du2_power5+du3_power5+du4_power5,\
+ iu2_power5,nothing,iu2_power5,nothing,iu1_power5)\
+ |(du3_power5+du4_power5+du1_power5,\
+ iu2_power5,nothing,iu1_power5,nothing,iu1_power5)\
+ |(du4_power5+du1_power5+du2_power5,\
+ iu1_power5,nothing,iu2_power5,nothing,iu2_power5)")
+
(define_insn_reservation "power5-insert" 4
(and (eq_attr "type" "insert_word")
(eq_attr "cpu" "power5"))
@@ -179,9 +205,7 @@
"(du1_power5,iu1_power5*6)\
|(du2_power5,iu2_power5*6)\
|(du3_power5,iu2_power5*6)\
- |(du4_power5,iu2_power5*6)")
-; |(du3_power5,nothing,iu2_power5*6)\
-; |(du4_power5,nothing,iu2_power5*6)")
+ |(du4_power5,iu1_power5*6)")
(define_insn_reservation "power5-imul" 5
(and (eq_attr "type" "imul")
@@ -190,8 +214,6 @@
|(du2_power5,iu2_power5*4)\
|(du3_power5,iu2_power5*4)\
|(du4_power5,iu1_power5*4)")
-; |(du3_power5,nothing,iu2_power5*4)\
-; |(du4_power5,nothing,iu1_power5*4)")
(define_insn_reservation "power5-imul3" 4
(and (eq_attr "type" "imul2,imul3")
@@ -200,8 +222,6 @@
|(du2_power5,iu2_power5*3)\
|(du3_power5,iu2_power5*3)\
|(du4_power5,iu1_power5*3)")
-; |(du3_power5,nothing,iu2_power5*3)\
-; |(du4_power5,nothing,iu1_power5*3)")
; SPR move only executes in first IU.
@@ -284,8 +304,6 @@
|(du2_power5,fpu2_power5*28)\
|(du3_power5,fpu2_power5*28)\
|(du4_power5,fpu1_power5*28)")
-; |(du3_power5,nothing,fpu2_power5*28)\
-; |(du4_power5,nothing,fpu1_power5*28)")
(define_insn_reservation "power5-sqrt" 40
(and (eq_attr "type" "ssqrt,dsqrt")
@@ -294,6 +312,10 @@
|(du2_power5,fpu2_power5*35)\
|(du3_power5,fpu2_power5*35)\
|(du4_power5,fpu2_power5*35)")
-; |(du3_power5,nothing,fpu2_power5*35)\
-; |(du4_power5,nothing,fpu2_power5*35)")
+
+(define_insn_reservation "power5-isync" 2
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "power5"))
+ "du1_power5+du2_power5+du3_power5+du4_power5,\
+ lsu1_power5")
diff --git a/contrib/gcc/config/rs6000/ppc64-fp.c b/contrib/gcc/config/rs6000/ppc64-fp.c
index c736d9a..184f34e 100644
--- a/contrib/gcc/config/rs6000/ppc64-fp.c
+++ b/contrib/gcc/config/rs6000/ppc64-fp.c
@@ -2,7 +2,7 @@
libgcc2.c with macros expanded to force the use of specific types.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2006 Free Software Foundation, Inc.
This file is part of GCC.
@@ -27,10 +27,11 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
-#if defined(__powerpc64__)
+#if defined(__powerpc64__) || defined (__64BIT__) || defined(__ppc64__)
+#define TMODES
#include "config/fp-bit.h"
extern DItype __fixtfdi (TFtype);
@@ -39,8 +40,11 @@ extern DItype __fixsfdi (SFtype);
extern USItype __fixunsdfsi (DFtype);
extern USItype __fixunssfsi (SFtype);
extern TFtype __floatditf (DItype);
+extern TFtype __floatunditf (UDItype);
extern DFtype __floatdidf (DItype);
+extern DFtype __floatundidf (UDItype);
extern SFtype __floatdisf (DItype);
+extern SFtype __floatundisf (UDItype);
extern DItype __fixunstfdi (TFtype);
static DItype local_fixunssfdi (SFtype);
@@ -100,6 +104,18 @@ __floatditf (DItype u)
return (TFtype) dh + (TFtype) dl;
}
+TFtype
+__floatunditf (UDItype u)
+{
+ DFtype dh, dl;
+
+ dh = (USItype) (u >> (sizeof (SItype) * 8));
+ dh *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
+ dl = (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
+
+ return (TFtype) dh + (TFtype) dl;
+}
+
DFtype
__floatdidf (DItype u)
{
@@ -112,6 +128,18 @@ __floatdidf (DItype u)
return d;
}
+DFtype
+__floatundidf (UDItype u)
+{
+ DFtype d;
+
+ d = (USItype) (u >> (sizeof (SItype) * 8));
+ d *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
+ d += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
+
+ return d;
+}
+
SFtype
__floatdisf (DItype u)
{
@@ -137,6 +165,30 @@ __floatdisf (DItype u)
return (SFtype) f;
}
+SFtype
+__floatundisf (UDItype u)
+{
+ DFtype f;
+
+ if (53 < (sizeof (DItype) * 8)
+ && 53 > ((sizeof (DItype) * 8) - 53 + 24))
+ {
+ if (u >= ((UDItype) 1 << 53))
+ {
+ if ((UDItype) u & (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1))
+ {
+ u &= ~ (((UDItype) 1 << ((sizeof (DItype) * 8) - 53)) - 1);
+ u |= ((UDItype) 1 << ((sizeof (DItype) * 8) - 53));
+ }
+ }
+ }
+ f = (USItype) (u >> (sizeof (SItype) * 8));
+ f *= 2.0 * (((UDItype) 1) << ((sizeof (SItype) * 8) - 1));
+ f += (USItype) (u & ((((UDItype) 1) << (sizeof (SItype) * 8)) - 1));
+
+ return (SFtype) f;
+}
+
DItype
__fixunstfdi (TFtype a)
{
diff --git a/contrib/gcc/config/rs6000/predicates.md b/contrib/gcc/config/rs6000/predicates.md
new file mode 100644
index 0000000..6aefe2d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/predicates.md
@@ -0,0 +1,1307 @@
+;; Predicate definitions for POWER and PowerPC.
+;; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Return 1 for anything except PARALLEL.
+(define_predicate "any_operand"
+ (match_code "const_int,const_double,const,symbol_ref,label_ref,subreg,reg,mem"))
+
+;; Return 1 for any PARALLEL.
+(define_predicate "any_parallel_operand"
+ (match_code "parallel"))
+
+;; Return 1 if op is COUNT register.
+(define_predicate "count_register_operand"
+ (and (match_code "reg")
+ (match_test "REGNO (op) == COUNT_REGISTER_REGNUM
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is an Altivec register.
+(define_predicate "altivec_register_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || ALTIVEC_REGNO_P (REGNO (op))
+ || REGNO (op) > LAST_VIRTUAL_REGISTER")))
+
+;; Return 1 if op is XER register.
+(define_predicate "xer_operand"
+ (and (match_code "reg")
+ (match_test "XER_REGNO_P (REGNO (op))")))
+
+;; Return 1 if op is a signed 5-bit constant integer.
+(define_predicate "s5bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= -16 && INTVAL (op) <= 15")))
+
+;; Return 1 if op is a unsigned 5-bit constant integer.
+(define_predicate "u5bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= 0 && INTVAL (op) <= 31")))
+
+;; Return 1 if op is a signed 8-bit constant integer.
+;; Integer multiplication complete more quickly
+(define_predicate "s8bit_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) >= -128 && INTVAL (op) <= 127")))
+
+;; Return 1 if op is a constant integer that can fit in a D field.
+(define_predicate "short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "satisfies_constraint_I (op)")))
+
+;; Return 1 if op is a constant integer that can fit in an unsigned D field.
+(define_predicate "u_short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "satisfies_constraint_K (op)")))
+
+;; Return 1 if op is a constant integer that cannot fit in a signed D field.
+(define_predicate "non_short_cint_operand"
+ (and (match_code "const_int")
+ (match_test "(unsigned HOST_WIDE_INT)
+ (INTVAL (op) + 0x8000) >= 0x10000")))
+
+;; Return 1 if op is a positive constant integer that is an exact power of 2.
+(define_predicate "exact_log2_cint_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) > 0 && exact_log2 (INTVAL (op)) >= 0")))
+
+;; Return 1 if op is a register that is not special.
+(define_predicate "gpc_reg_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "(GET_CODE (op) != REG
+ || (REGNO (op) >= ARG_POINTER_REGNUM
+ && !XER_REGNO_P (REGNO (op)))
+ || REGNO (op) < MQ_REGNO)
+ && !((TARGET_E500_DOUBLE || TARGET_SPE)
+ && invalid_e500_subreg (op, mode))")))
+
+;; Return 1 if op is a register that is a condition register field.
+(define_predicate "cc_reg_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || REGNO (op) > LAST_VIRTUAL_REGISTER
+ || CR_REGNO_P (REGNO (op))")))
+
+;; Return 1 if op is a register that is a condition register field not cr0.
+(define_predicate "cc_reg_not_cr0_operand"
+ (and (match_operand 0 "register_operand")
+ (match_test "GET_CODE (op) != REG
+ || REGNO (op) > LAST_VIRTUAL_REGISTER
+ || CR_REGNO_NOT_CR0_P (REGNO (op))")))
+
+;; Return 1 if op is a constant integer valid for D field
+;; or non-special register register.
+(define_predicate "reg_or_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "short_cint_operand")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid whose negation is valid for
+;; D field or non-special register register.
+;; Do not allow a constant zero because all patterns that call this
+;; predicate use "addic r1,r2,-const" to set carry when r2 is greater than
+;; or equal to const, which does not work for zero.
+(define_predicate "reg_or_neg_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "satisfies_constraint_P (op)
+ && INTVAL (op) != 0")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid for DS field
+;; or non-special register.
+(define_predicate "reg_or_aligned_short_operand"
+ (if_then_else (match_code "const_int")
+ (and (match_operand 0 "short_cint_operand")
+ (match_test "!(INTVAL (op) & 3)"))
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer whose high-order 16 bits are zero
+;; or non-special register.
+(define_predicate "reg_or_u_short_operand"
+ (if_then_else (match_code "const_int")
+ (match_operand 0 "u_short_cint_operand")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is any constant integer
+;; or non-special register.
+(define_predicate "reg_or_cint_operand"
+ (ior (match_code "const_int")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid for addition
+;; or non-special register.
+(define_predicate "reg_or_add_cint_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(HOST_BITS_PER_WIDE_INT == 32
+ && (mode == SImode || INTVAL (op) < 0x7fff8000))
+ || ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80008000)
+ < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is a constant integer valid for subtraction
+;; or non-special register.
+(define_predicate "reg_or_sub_cint_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(HOST_BITS_PER_WIDE_INT == 32
+ && (mode == SImode || - INTVAL (op) < 0x7fff8000))
+ || ((unsigned HOST_WIDE_INT) (- INTVAL (op)
+ + (mode == SImode
+ ? 0x80000000 : 0x80008000))
+ < (unsigned HOST_WIDE_INT) 0x100000000ll)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if op is any 32-bit unsigned constant integer
+;; or non-special register.
+(define_predicate "reg_or_logical_cint_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "(GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
+ && INTVAL (op) >= 0)
+ || ((INTVAL (op) & GET_MODE_MASK (mode)
+ & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0)")
+ (if_then_else (match_code "const_double")
+ (match_test "GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT
+ && mode == DImode
+ && CONST_DOUBLE_HIGH (op) == 0")
+ (match_operand 0 "gpc_reg_operand"))))
+
+;; Return 1 if operand is a CONST_DOUBLE that can be set in a register
+;; with no more than one instruction per word.
+(define_predicate "easy_fp_constant"
+ (match_code "const_double")
+{
+ long k[4];
+ REAL_VALUE_TYPE rv;
+
+ if (GET_MODE (op) != mode
+ || (!SCALAR_FLOAT_MODE_P (mode) && mode != DImode))
+ return 0;
+
+ /* Consider all constants with -msoft-float to be easy. */
+ if ((TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
+ && mode != DImode)
+ return 1;
+
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ return 0;
+
+ /* If we are using V.4 style PIC, consider all constants to be hard. */
+ if (flag_pic && DEFAULT_ABI == ABI_V4)
+ return 0;
+
+#ifdef TARGET_RELOCATABLE
+ /* Similarly if we are using -mrelocatable, consider all constants
+ to be hard. */
+ if (TARGET_RELOCATABLE)
+ return 0;
+#endif
+
+ switch (mode)
+ {
+ case TFmode:
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
+
+ case DFmode:
+ /* Force constants to memory before reload to utilize
+ compress_float_constant.
+ Avoid this when flag_unsafe_math_optimizations is enabled
+ because RDIV division to reciprocal optimization is not able
+ to regenerate the division. */
+ if (TARGET_E500_DOUBLE
+ || (!reload_in_progress && !reload_completed
+ && !flag_unsafe_math_optimizations))
+ return 0;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
+
+ return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
+ && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
+
+ case SFmode:
+ /* The constant 0.f is easy. */
+ if (op == CONST0_RTX (SFmode))
+ return 1;
+
+ /* Force constants to memory before reload to utilize
+ compress_float_constant.
+ Avoid this when flag_unsafe_math_optimizations is enabled
+ because RDIV division to reciprocal optimization is not able
+ to regenerate the division. */
+ if (!reload_in_progress && !reload_completed
+ && !flag_unsafe_math_optimizations)
+ return 0;
+
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, k[0]);
+
+ return num_insns_constant_wide (k[0]) == 1;
+
+ case DImode:
+ return ((TARGET_POWERPC64
+ && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
+ || (num_insns_constant (op, DImode) <= 2));
+
+ case SImode:
+ return 1;
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return 1 if the operand is a CONST_VECTOR and can be loaded into a
+;; vector register without using memory.
+(define_predicate "easy_vector_constant"
+ (match_code "const_vector")
+{
+ if (ALTIVEC_VECTOR_MODE (mode))
+ {
+ if (zero_constant (op, mode))
+ return true;
+ return easy_altivec_constant (op, mode);
+ }
+
+ if (SPE_VECTOR_MODE (mode))
+ {
+ int cst, cst2;
+ if (zero_constant (op, mode))
+ return true;
+ if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
+ return false;
+
+ /* Limit SPE vectors to 15 bits signed. These we can generate with:
+ li r0, CONSTANT1
+ evmergelo r0, r0, r0
+ li r0, CONSTANT2
+
+ I don't know how efficient it would be to allow bigger constants,
+ considering we'll have an extra 'ori' for every 'li'. I doubt 5
+ instructions is better than a 64-bit memory load, but I don't
+ have the e500 timing specs. */
+ if (mode == V2SImode)
+ {
+ cst = INTVAL (CONST_VECTOR_ELT (op, 0));
+ cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
+ return cst >= -0x7fff && cst <= 0x7fff
+ && cst2 >= -0x7fff && cst2 <= 0x7fff;
+ }
+ }
+
+ return false;
+})
+
+;; Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF.
+(define_predicate "easy_vector_constant_add_self"
+ (and (match_code "const_vector")
+ (and (match_test "TARGET_ALTIVEC")
+ (match_test "easy_altivec_constant (op, mode)")))
+{
+ rtx last = CONST_VECTOR_ELT (op, GET_MODE_NUNITS (mode) - 1);
+ HOST_WIDE_INT val = ((INTVAL (last) & 0xff) ^ 0x80) - 0x80;
+ return EASY_VECTOR_15_ADD_SELF (val);
+})
+
+;; Return 1 if operand is constant zero (scalars and vectors).
+(define_predicate "zero_constant"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; Return 1 if operand is 0.0.
+;; or non-special register register field no cr0
+(define_predicate "zero_fp_constant"
+ (and (match_code "const_double")
+ (match_test "SCALAR_FLOAT_MODE_P (mode)
+ && 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 recognize volatile
+;; references where it's safe.
+(define_predicate "volatile_mem_operand"
+ (and (and (match_code "mem")
+ (match_test "MEM_VOLATILE_P (op)"))
+ (if_then_else (match_test "reload_completed")
+ (match_operand 0 "memory_operand")
+ (if_then_else (match_test "reload_in_progress")
+ (match_test "strict_memory_address_p (mode, XEXP (op, 0))")
+ (match_test "memory_address_p (mode, XEXP (op, 0))")))))
+
+;; Return 1 if the operand is an offsettable memory operand.
+(define_predicate "offsettable_mem_operand"
+ (and (match_code "mem")
+ (match_test "offsettable_address_p (reload_completed
+ || reload_in_progress,
+ mode, XEXP (op, 0))")))
+
+;; Return 1 if the operand is a memory operand with an address divisible by 4
+(define_predicate "word_offset_memref_operand"
+ (and (match_operand 0 "memory_operand")
+ (match_test "GET_CODE (XEXP (op, 0)) != PLUS
+ || ! REG_P (XEXP (XEXP (op, 0), 0))
+ || GET_CODE (XEXP (XEXP (op, 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (op, 0), 1)) % 4 == 0")))
+
+;; Return 1 if the operand is an indexed or indirect memory operand.
+(define_predicate "indexed_or_indirect_operand"
+ (match_code "mem")
+{
+ op = XEXP (op, 0);
+ if (TARGET_ALTIVEC
+ && ALTIVEC_VECTOR_MODE (mode)
+ && GET_CODE (op) == AND
+ && GET_CODE (XEXP (op, 1)) == CONST_INT
+ && INTVAL (XEXP (op, 1)) == -16)
+ op = XEXP (op, 0);
+
+ return indexed_or_indirect_address (op, mode);
+})
+
+;; Return 1 if the operand is an indexed or indirect address.
+(define_special_predicate "indexed_or_indirect_address"
+ (and (match_test "REG_P (op)
+ || (GET_CODE (op) == PLUS
+ /* Omit testing REG_P (XEXP (op, 0)). */
+ && REG_P (XEXP (op, 1)))")
+ (match_operand 0 "address_operand")))
+
+;; Used for the destination of the fix_truncdfsi2 expander.
+;; If stfiwx will be used, the result goes to memory; otherwise,
+;; we're going to emit a store and a load of a subreg, so the dest is a
+;; register.
+(define_predicate "fix_trunc_dest_operand"
+ (if_then_else (match_test "! TARGET_E500_DOUBLE && TARGET_PPC_GFXOPT")
+ (match_operand 0 "memory_operand")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if the operand is either a non-special register or can be used
+;; as the operand of a `mode' add insn.
+(define_predicate "add_operand"
+ (if_then_else (match_code "const_int")
+ (match_test "satisfies_constraint_I (op)
+ || satisfies_constraint_L (op)")
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if OP is a constant but not a valid add_operand.
+(define_predicate "non_add_cint_operand"
+ (and (match_code "const_int")
+ (match_test "!satisfies_constraint_I (op)
+ && !satisfies_constraint_L (op)")))
+
+;; Return 1 if the operand is a constant that can be used as the operand
+;; of an OR or XOR.
+(define_predicate "logical_const_operand"
+ (match_code "const_int,const_double")
+{
+ HOST_WIDE_INT opl, oph;
+
+ if (GET_CODE (op) == CONST_INT)
+ {
+ opl = INTVAL (op) & GET_MODE_MASK (mode);
+
+ if (HOST_BITS_PER_WIDE_INT <= 32
+ && GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
+ return 0;
+ }
+ else if (GET_CODE (op) == CONST_DOUBLE)
+ {
+ gcc_assert (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT);
+
+ opl = CONST_DOUBLE_LOW (op);
+ oph = CONST_DOUBLE_HIGH (op);
+ if (oph != 0)
+ return 0;
+ }
+ else
+ return 0;
+
+ return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
+ || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
+})
+
+;; Return 1 if the operand is a non-special register or a constant that
+;; can be used as the operand of an OR or XOR.
+(define_predicate "logical_operand"
+ (ior (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_const_operand")))
+
+;; Return 1 if op is a constant that is not a logical operand, but could
+;; be split into one.
+(define_predicate "non_logical_cint_operand"
+ (and (match_code "const_int,const_double")
+ (and (not (match_operand 0 "logical_operand"))
+ (match_operand 0 "reg_or_logical_cint_operand"))))
+
+;; Return 1 if op is a constant that can be encoded in a 32-bit mask,
+;; suitable for use with rlwinm (no more than two 1->0 or 0->1
+;; transitions). Reject all ones and all zeros, since these should have
+;; been optimized away and confuse the making of MB and ME.
+(define_predicate "mask_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ if (TARGET_POWERPC64)
+ {
+ /* Fail if the mask is not 32-bit. */
+ if (mode == DImode && (c & ~(unsigned HOST_WIDE_INT) 0xffffffff) != 0)
+ return 0;
+
+ /* Fail if the mask wraps around because the upper 32-bits of the
+ mask will all be 1s, contrary to GCC's internal view. */
+ if ((c & 0x80000001) == 0x80000001)
+ return 0;
+ }
+
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
+ /* Reject all zeros or all ones. */
+ if (c == 0)
+ return 0;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a second transition. */
+ c = ~c;
+
+ /* Erase first transition. */
+ c &= -lsb;
+
+ /* Find the second transition (if any). */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Return 1 for the PowerPC64 rlwinm corner case.
+(define_predicate "mask_operand_wrap"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ if ((c & 0x80000001) != 0x80000001)
+ return 0;
+
+ c = ~c;
+ if (c == 0)
+ return 0;
+
+ lsb = c & -c;
+ c = ~c;
+ c &= -lsb;
+ lsb = c & -c;
+ return c == -lsb;
+})
+
+;; Return 1 if the operand is a constant that is a PowerPC64 mask
+;; suitable for use with rldicl or rldicr (no more than one 1->0 or 0->1
+;; transition). Reject all zeros, since zero should have been
+;; optimized away and confuses the making of MB and ME.
+(define_predicate "mask64_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Reject all zeros. */
+ if (c == 0)
+ return 0;
+
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Like mask64_operand, but allow up to three transitions. This
+;; predicate is used by insn patterns that generate two rldicl or
+;; rldicr machine insns.
+(define_predicate "mask64_2_operand"
+ (match_code "const_int")
+{
+ HOST_WIDE_INT c, lsb;
+
+ c = INTVAL (op);
+
+ /* Disallow all zeros. */
+ if (c == 0)
+ return 0;
+
+ /* We don't change the number of transitions by inverting,
+ so make sure we start with the LS bit zero. */
+ if (c & 1)
+ c = ~c;
+
+ /* Find the first transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a second transition. */
+ c = ~c;
+
+ /* Erase first transition. */
+ c &= -lsb;
+
+ /* Find the second transition. */
+ lsb = c & -c;
+
+ /* Invert to look for a third transition. */
+ c = ~c;
+
+ /* Erase second transition. */
+ c &= -lsb;
+
+ /* Find the third transition (if any). */
+ lsb = c & -c;
+
+ /* Match if all the bits above are 1's (or c is zero). */
+ return c == -lsb;
+})
+
+;; Like and_operand, but also match constants that can be implemented
+;; with two rldicl or rldicr insns.
+(define_predicate "and64_2_operand"
+ (ior (match_operand 0 "mask64_2_operand")
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand"))))
+
+;; Return 1 if the operand is either a non-special register or a
+;; constant that can be used as the operand of a logical AND.
+(define_predicate "and_operand"
+ (ior (match_operand 0 "mask_operand")
+ (ior (and (match_test "TARGET_POWERPC64 && mode == DImode")
+ (match_operand 0 "mask64_operand"))
+ (if_then_else (match_test "fixed_regs[CR0_REGNO]")
+ (match_operand 0 "gpc_reg_operand")
+ (match_operand 0 "logical_operand")))))
+
+;; Return 1 if the operand is either a logical operand or a short cint operand.
+(define_predicate "scc_eq_operand"
+ (ior (match_operand 0 "logical_operand")
+ (match_operand 0 "short_cint_operand")))
+
+;; Return 1 if the operand is a general non-special register or memory operand.
+(define_predicate "reg_or_mem_operand"
+ (ior (match_operand 0 "memory_operand")
+ (ior (and (match_code "mem")
+ (match_test "macho_lo_sum_memory_operand (op, mode)"))
+ (ior (match_operand 0 "volatile_mem_operand")
+ (match_operand 0 "gpc_reg_operand")))))
+
+;; Return 1 if the operand is either an easy FP constant or memory or reg.
+(define_predicate "reg_or_none500mem_operand"
+ (if_then_else (match_code "mem")
+ (and (match_test "!TARGET_E500_DOUBLE")
+ (ior (match_operand 0 "memory_operand")
+ (ior (match_test "macho_lo_sum_memory_operand (op, mode)")
+ (match_operand 0 "volatile_mem_operand"))))
+ (match_operand 0 "gpc_reg_operand")))
+
+;; Return 1 if the operand is CONST_DOUBLE 0, register or memory operand.
+(define_predicate "zero_reg_mem_operand"
+ (ior (match_operand 0 "zero_fp_constant")
+ (match_operand 0 "reg_or_mem_operand")))
+
+;; Return 1 if the operand is a general register or memory operand without
+;; pre_inc or pre_dec, which produces invalid form of PowerPC lwa
+;; instruction.
+(define_predicate "lwa_operand"
+ (match_code "reg,subreg,mem")
+{
+ rtx inner = op;
+
+ if (reload_completed && GET_CODE (inner) == SUBREG)
+ inner = SUBREG_REG (inner);
+
+ return gpc_reg_operand (inner, mode)
+ || (memory_operand (inner, mode)
+ && GET_CODE (XEXP (inner, 0)) != PRE_INC
+ && GET_CODE (XEXP (inner, 0)) != PRE_DEC
+ && (GET_CODE (XEXP (inner, 0)) != PLUS
+ || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
+ || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
+})
+
+;; Return 1 if the operand, used inside a MEM, is a SYMBOL_REF.
+(define_predicate "symbol_ref_operand"
+ (and (match_code "symbol_ref")
+ (match_test "(mode == VOIDmode || GET_MODE (op) == mode)
+ && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))")))
+
+;; Return 1 if op is an operand that can be loaded via the GOT.
+;; or non-special register register field no cr0
+(define_predicate "got_operand"
+ (match_code "symbol_ref,const,label_ref"))
+
+;; Return 1 if op is a simple reference that can be loaded via the GOT,
+;; excluding labels involving addition.
+(define_predicate "got_no_const_operand"
+ (match_code "symbol_ref,label_ref"))
+
+;; Return 1 if op is a SYMBOL_REF for a TLS symbol.
+(define_predicate "rs6000_tls_symbol_ref"
+ (and (match_code "symbol_ref")
+ (match_test "RS6000_SYMBOL_REF_TLS_P (op)")))
+
+;; Return 1 if the operand, used inside a MEM, is a valid first argument
+;; to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR.
+(define_predicate "call_operand"
+ (if_then_else (match_code "reg")
+ (match_test "REGNO (op) == LINK_REGISTER_REGNUM
+ || REGNO (op) == COUNT_REGISTER_REGNUM
+ || REGNO (op) >= FIRST_PSEUDO_REGISTER")
+ (match_code "symbol_ref")))
+
+;; Return 1 if the operand is a SYMBOL_REF for a function known to be in
+;; this file.
+(define_predicate "current_file_function_operand"
+ (and (match_code "symbol_ref")
+ (match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
+ && (SYMBOL_REF_LOCAL_P (op)
+ || (op == XEXP (DECL_RTL (current_function_decl),
+ 0)))")))
+
+;; Return 1 if this operand is a valid input for a move insn.
+(define_predicate "input_operand"
+ (match_code "label_ref,symbol_ref,const,high,reg,subreg,mem,
+ const_double,const_vector,const_int,plus")
+{
+ /* Memory is always valid. */
+ if (memory_operand (op, mode))
+ return 1;
+
+ /* For floating-point, easy constants are valid. */
+ if (SCALAR_FLOAT_MODE_P (mode)
+ && CONSTANT_P (op)
+ && easy_fp_constant (op, mode))
+ return 1;
+
+ /* Allow any integer constant. */
+ if (GET_MODE_CLASS (mode) == MODE_INT
+ && (GET_CODE (op) == CONST_INT
+ || GET_CODE (op) == CONST_DOUBLE))
+ return 1;
+
+ /* Allow easy vector constants. */
+ if (GET_CODE (op) == CONST_VECTOR
+ && easy_vector_constant (op, mode))
+ return 1;
+
+ /* Do not allow invalid E500 subregs. */
+ if ((TARGET_E500_DOUBLE || TARGET_SPE)
+ && GET_CODE (op) == SUBREG
+ && invalid_e500_subreg (op, mode))
+ return 0;
+
+ /* For floating-point or multi-word mode, the only remaining valid type
+ is a register. */
+ if (SCALAR_FLOAT_MODE_P (mode)
+ || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
+ return register_operand (op, mode);
+
+ /* The only cases left are integral modes one word or smaller (we
+ do not get called for MODE_CC values). These can be in any
+ register. */
+ if (register_operand (op, mode))
+ return 1;
+
+ /* A SYMBOL_REF referring to the TOC is valid. */
+ if (legitimate_constant_pool_address_p (op))
+ return 1;
+
+ /* A constant pool expression (relative to the TOC) is valid */
+ if (toc_relative_expr_p (op))
+ return 1;
+
+ /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
+ to be valid. */
+ if (DEFAULT_ABI == ABI_V4
+ && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
+ && small_data_operand (op, Pmode))
+ return 1;
+
+ return 0;
+})
+
+;; Return true if OP is an invalid SUBREG operation on the e500.
+(define_predicate "rs6000_nonimmediate_operand"
+ (match_code "reg,subreg,mem")
+{
+ if ((TARGET_E500_DOUBLE || TARGET_SPE)
+ && GET_CODE (op) == SUBREG
+ && invalid_e500_subreg (op, mode))
+ return 0;
+
+ return nonimmediate_operand (op, mode);
+})
+
+;; Return true if operand is boolean operator.
+(define_predicate "boolean_operator"
+ (match_code "and,ior,xor"))
+
+;; Return true if operand is OR-form of boolean operator.
+(define_predicate "boolean_or_operator"
+ (match_code "ior,xor"))
+
+;; Return true if operand is an equality operator.
+(define_special_predicate "equality_operator"
+ (match_code "eq,ne"))
+
+;; Return true if operand is MIN or MAX operator.
+(define_predicate "min_max_operator"
+ (match_code "smin,smax,umin,umax"))
+
+;; Return 1 if OP is a comparison operation that is valid for a branch
+;; instruction. We check the opcode against the mode of the CC value.
+;; validate_condition_mode is an assertion.
+(define_predicate "branch_comparison_operator"
+ (and (match_operand 0 "comparison_operator")
+ (and (match_test "GET_MODE_CLASS (GET_MODE (XEXP (op, 0))) == MODE_CC")
+ (match_test "validate_condition_mode (GET_CODE (op),
+ GET_MODE (XEXP (op, 0))),
+ 1"))))
+
+;; Return 1 if OP is a comparison operation that is valid for an SCC insn --
+;; it must be a positive comparison.
+(define_predicate "scc_comparison_operator"
+ (and (match_operand 0 "branch_comparison_operator")
+ (match_code "eq,lt,gt,ltu,gtu,unordered")))
+
+;; Return 1 if OP is a comparison operation that is valid for a branch
+;; insn, which is true if the corresponding bit in the CC register is set.
+(define_predicate "branch_positive_comparison_operator"
+ (and (match_operand 0 "branch_comparison_operator")
+ (match_code "eq,lt,gt,ltu,gtu,unordered")))
+
+;; Return 1 is OP is a comparison operation that is valid for a trap insn.
+(define_predicate "trap_comparison_operator"
+ (and (match_operand 0 "comparison_operator")
+ (match_code "eq,ne,le,lt,ge,gt,leu,ltu,geu,gtu")))
+
+;; Return 1 if OP is a load multiple operation, known to be a PARALLEL.
+(define_predicate "load_multiple_operation"
+ (match_code "parallel")
+{
+ 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)) != SImode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || 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;
+})
+
+;; Return 1 if OP is a store multiple operation, known to be a PARALLEL.
+;; The second vector element is a CLOBBER.
+(define_predicate "store_multiple_operation"
+ (match_code "parallel")
+{
+ 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 + 1);
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || 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;
+})
+
+;; Return 1 if OP is valid for a save_world call in prologue, known to be
+;; a PARLLEL.
+(define_predicate "save_world_operation"
+ (match_code "parallel")
+{
+ int index;
+ int i;
+ rtx elt;
+ int count = XVECLEN (op, 0);
+
+ if (count != 55)
+ return 0;
+
+ index = 0;
+ if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE)
+ return 0;
+
+ for (i=1; i <= 18; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), DFmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != DFmode)
+ return 0;
+ }
+
+ for (i=1; i <= 12; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != V4SImode)
+ return 0;
+ }
+
+ for (i=1; i <= 19; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), Pmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != Pmode)
+ return 0;
+ }
+
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || ! memory_operand (SET_DEST (elt), Pmode)
+ || GET_CODE (SET_SRC (elt)) != REG
+ || REGNO (SET_SRC (elt)) != CR2_REGNO
+ || GET_MODE (SET_SRC (elt)) != Pmode)
+ return 0;
+
+ if (GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
+ return 0;
+ return 1;
+})
+
+;; Return 1 if OP is valid for a restore_world call in epilogue, known to be
+;; a PARLLEL.
+(define_predicate "restore_world_operation"
+ (match_code "parallel")
+{
+ int index;
+ int i;
+ rtx elt;
+ int count = XVECLEN (op, 0);
+
+ if (count != 59)
+ return 0;
+
+ index = 0;
+ if (GET_CODE (XVECEXP (op, 0, index++)) != RETURN
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER)
+ return 0;
+
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), Pmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || REGNO (SET_DEST (elt)) != CR2_REGNO
+ || GET_MODE (SET_DEST (elt)) != Pmode)
+ return 0;
+
+ for (i=1; i <= 19; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), Pmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != Pmode)
+ return 0;
+ }
+
+ for (i=1; i <= 12; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != V4SImode)
+ return 0;
+ }
+
+ for (i=1; i <= 18; i++)
+ {
+ elt = XVECEXP (op, 0, index++);
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || ! memory_operand (SET_SRC (elt), DFmode)
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != DFmode)
+ return 0;
+ }
+
+ if (GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != CLOBBER
+ || GET_CODE (XVECEXP (op, 0, index++)) != USE)
+ return 0;
+ return 1;
+})
+
+;; Return 1 if OP is valid for a vrsave call, known to be a PARALLEL.
+(define_predicate "vrsave_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno, src_regno;
+ int i;
+
+ 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))) != UNSPEC_VOLATILE
+ || XINT (SET_SRC (XVECEXP (op, 0, 0)), 1) != UNSPECV_SET_VRSAVE)
+ return 0;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_regno = REGNO (XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 1));
+
+ if (dest_regno != VRSAVE_REGNO || src_regno != VRSAVE_REGNO)
+ return 0;
+
+ for (i = 1; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+
+ if (GET_CODE (elt) != CLOBBER
+ && GET_CODE (elt) != SET)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is valid for mfcr insn, known to be a PARALLEL.
+(define_predicate "mfcr_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ 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_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+ || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+ rtx unspec;
+ int maskval;
+ rtx src_reg;
+
+ src_reg = XVECEXP (SET_SRC (exp), 0, 0);
+
+ if (GET_CODE (src_reg) != REG
+ || GET_MODE (src_reg) != CCmode
+ || ! CR_REGNO_P (REGNO (src_reg)))
+ return 0;
+
+ if (GET_CODE (exp) != SET
+ || GET_CODE (SET_DEST (exp)) != REG
+ || GET_MODE (SET_DEST (exp)) != SImode
+ || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
+ return 0;
+ unspec = SET_SRC (exp);
+ maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
+
+ if (GET_CODE (unspec) != UNSPEC
+ || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
+ || XVECLEN (unspec, 0) != 2
+ || XVECEXP (unspec, 0, 0) != src_reg
+ || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ return 0;
+ }
+ return 1;
+})
+
+;; Return 1 if OP is valid for mtcrf insn, known to be a PARALLEL.
+(define_predicate "mtcrf_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ int i;
+ rtx src_reg;
+
+ /* Perform a quick check so we don't blow up below. */
+ if (count < 1
+ || GET_CODE (XVECEXP (op, 0, 0)) != SET
+ || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
+ || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
+ return 0;
+ src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
+
+ if (GET_CODE (src_reg) != REG
+ || GET_MODE (src_reg) != SImode
+ || ! INT_REGNO_P (REGNO (src_reg)))
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx exp = XVECEXP (op, 0, i);
+ rtx unspec;
+ int maskval;
+
+ if (GET_CODE (exp) != SET
+ || GET_CODE (SET_DEST (exp)) != REG
+ || GET_MODE (SET_DEST (exp)) != CCmode
+ || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
+ return 0;
+ unspec = SET_SRC (exp);
+ maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
+
+ if (GET_CODE (unspec) != UNSPEC
+ || XINT (unspec, 1) != UNSPEC_MOVESI_TO_CR
+ || XVECLEN (unspec, 0) != 2
+ || XVECEXP (unspec, 0, 0) != src_reg
+ || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
+ || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
+ return 0;
+ }
+ return 1;
+})
+
+;; Return 1 if OP is valid for lmw insn, known to be a PARALLEL.
+(define_predicate "lmw_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr;
+ unsigned int base_regno;
+ HOST_WIDE_INT offset;
+ 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);
+
+ if (dest_regno > 31
+ || count != 32 - (int) dest_regno)
+ return 0;
+
+ if (legitimate_indirect_address_p (src_addr, 0))
+ {
+ offset = 0;
+ base_regno = REGNO (src_addr);
+ if (base_regno == 0)
+ return 0;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, src_addr, 0))
+ {
+ offset = INTVAL (XEXP (src_addr, 1));
+ base_regno = REGNO (XEXP (src_addr, 0));
+ }
+ else
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+ rtx newaddr;
+ rtx addr_reg;
+ HOST_WIDE_INT newoffset;
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_DEST (elt)) != REG
+ || GET_MODE (SET_DEST (elt)) != SImode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != SImode)
+ return 0;
+ newaddr = XEXP (SET_SRC (elt), 0);
+ if (legitimate_indirect_address_p (newaddr, 0))
+ {
+ newoffset = 0;
+ addr_reg = newaddr;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
+ {
+ addr_reg = XEXP (newaddr, 0);
+ newoffset = INTVAL (XEXP (newaddr, 1));
+ }
+ else
+ return 0;
+ if (REGNO (addr_reg) != base_regno
+ || newoffset != offset + 4 * i)
+ return 0;
+ }
+
+ return 1;
+})
+
+;; Return 1 if OP is valid for stmw insn, known to be a PARALLEL.
+(define_predicate "stmw_operation"
+ (match_code "parallel")
+{
+ int count = XVECLEN (op, 0);
+ unsigned int src_regno;
+ rtx dest_addr;
+ unsigned int base_regno;
+ HOST_WIDE_INT offset;
+ 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);
+
+ if (src_regno > 31
+ || count != 32 - (int) src_regno)
+ return 0;
+
+ if (legitimate_indirect_address_p (dest_addr, 0))
+ {
+ offset = 0;
+ base_regno = REGNO (dest_addr);
+ if (base_regno == 0)
+ return 0;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, dest_addr, 0))
+ {
+ offset = INTVAL (XEXP (dest_addr, 1));
+ base_regno = REGNO (XEXP (dest_addr, 0));
+ }
+ else
+ return 0;
+
+ for (i = 0; i < count; i++)
+ {
+ rtx elt = XVECEXP (op, 0, i);
+ rtx newaddr;
+ rtx addr_reg;
+ HOST_WIDE_INT newoffset;
+
+ if (GET_CODE (elt) != SET
+ || GET_CODE (SET_SRC (elt)) != REG
+ || GET_MODE (SET_SRC (elt)) != SImode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != SImode)
+ return 0;
+ newaddr = XEXP (SET_DEST (elt), 0);
+ if (legitimate_indirect_address_p (newaddr, 0))
+ {
+ newoffset = 0;
+ addr_reg = newaddr;
+ }
+ else if (rs6000_legitimate_offset_address_p (SImode, newaddr, 0))
+ {
+ addr_reg = XEXP (newaddr, 0);
+ newoffset = INTVAL (XEXP (newaddr, 1));
+ }
+ else
+ return 0;
+ if (REGNO (addr_reg) != base_regno
+ || newoffset != offset + 4 * i)
+ return 0;
+ }
+
+ return 1;
+})
diff --git a/contrib/gcc/config/rs6000/rios1.md b/contrib/gcc/config/rs6000/rios1.md
index 5e77a67..59b34c5 100644
--- a/contrib/gcc/config/rs6000/rios1.md
+++ b/contrib/gcc/config/rs6000/rios1.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM POWER processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,8 +15,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "rios1,rios1fp")
(define_cpu_unit "iu_rios1" "rios1")
@@ -26,11 +26,12 @@
;; RIOS1 32-bit IU, FPU, BPU
(define_insn_reservation "rios1-load" 2
- (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u")
+ (and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,\
+ load_l,store_c,sync")
(eq_attr "cpu" "rios1,ppc601"))
"iu_rios1")
-(define_insn_reservation "rios1-store" 1
+(define_insn_reservation "rios1-store" 2
(and (eq_attr "type" "store,store_ux,store_u")
(eq_attr "cpu" "rios1,ppc601"))
"iu_rios1")
@@ -45,7 +46,7 @@
(eq_attr "cpu" "ppc601"))
"iu_rios1")
-(define_insn_reservation "rios1-fpstore" 1
+(define_insn_reservation "rios1-fpstore" 3
(and (eq_attr "type" "fpstore,fpstore_ux,fpstore_u")
(eq_attr "cpu" "rios1,ppc601"))
"iu_rios1+fpu_rios1")
@@ -55,6 +56,16 @@
(eq_attr "cpu" "rios1,ppc601"))
"iu_rios1")
+(define_insn_reservation "rios1-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "rios1,ppc601"))
+ "iu_rios1,iu_rios1")
+
+(define_insn_reservation "rios1-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "rios1,ppc601"))
+ "iu_rios1,iu_rios1,iu_rios1")
+
(define_insn_reservation "rios1-imul" 5
(and (eq_attr "type" "imul,imul_compare")
(eq_attr "cpu" "rios1"))
@@ -173,7 +184,7 @@
"iu_rios1,bpu_rios1")
(define_insn_reservation "rios1-branch" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "rios1,ppc601"))
"bpu_rios1")
diff --git a/contrib/gcc/config/rs6000/rios2.md b/contrib/gcc/config/rs6000/rios2.md
index 36690ac..b2f5cb2 100644
--- a/contrib/gcc/config/rs6000/rios2.md
+++ b/contrib/gcc/config/rs6000/rios2.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM Power2 processor.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,8 +15,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "rios2,rios2fp")
(define_cpu_unit "iu1_rios2,iu2_rios2" "rios2")
@@ -29,11 +29,12 @@
(define_insn_reservation "rios2-load" 2
(and (eq_attr "type" "load,load_ext,load_ext_u,load_ext_ux,\
- load_ux,load_u,fpload,fpload_ux,fpload_u")
+ load_ux,load_u,fpload,fpload_ux,fpload_u,\
+ load_l,store_c,sync")
(eq_attr "cpu" "rios2"))
"iu1_rios2|iu2_rios2")
-(define_insn_reservation "rios2-store" 1
+(define_insn_reservation "rios2-store" 2
(and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
(eq_attr "cpu" "rios2"))
"iu1_rios2|iu2_rios2")
@@ -43,6 +44,16 @@
(eq_attr "cpu" "rios2"))
"iu1_rios2|iu2_rios2")
+(define_insn_reservation "rios2-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "rios2"))
+ "iu1_rios2|iu2_rios2,iu1_rios2|iu2_rios2")
+
+(define_insn_reservation "rios2-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "rios2"))
+ "iu1_rios2|iu2_rios2,iu1_rios2|iu2_rios2,iu1_rios2|iu2_rios2")
+
(define_insn_reservation "rios2-imul" 2
(and (eq_attr "type" "imul,imul2,imul3,imul_compare")
(eq_attr "cpu" "rios2"))
@@ -111,7 +122,7 @@
"iu1_rios2,bpu_rios2")
(define_insn_reservation "rios2-branch" 1
- (and (eq_attr "type" "jmpreg,branch")
+ (and (eq_attr "type" "jmpreg,branch,isync")
(eq_attr "cpu" "rios2"))
"bpu_rios2")
diff --git a/contrib/gcc/config/rs6000/rs6000-c.c b/contrib/gcc/config/rs6000/rs6000-c.c
index 13d0ca6..5c6abd10 100644
--- a/contrib/gcc/config/rs6000/rs6000-c.c
+++ b/contrib/gcc/config/rs6000/rs6000-c.c
@@ -1,8 +1,9 @@
/* Subroutines for the C front end on the POWER and PowerPC architectures.
- Copyright (C) 2002, 2003
+ Copyright (C) 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Zack Weinberg <zack@codesourcery.com>
+ and Paolo Bonzini <bonzini@gnu.org>
This file is part of GCC.
@@ -18,8 +19,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -27,9 +28,15 @@
#include "tm.h"
#include "cpplib.h"
#include "tree.h"
+#include "c-common.h"
#include "c-pragma.h"
-#include "errors.h"
+#include "c-tree.h"
+#include "toplev.h"
#include "tm_p.h"
+#include "target.h"
+#include "langhooks.h"
+
+
/* Handle the machine specific pragma longcall. Its syntax is
@@ -41,10 +48,10 @@
whether or not new function declarations receive a longcall
attribute by default. */
-#define SYNTAX_ERROR(msgid) do { \
- warning (msgid); \
- warning ("ignoring malformed #pragma longcall"); \
- return; \
+#define SYNTAX_ERROR(gmsgid) do { \
+ warning (OPT_Wpragmas, gmsgid); \
+ warning (OPT_Wpragmas, "ignoring malformed #pragma longcall"); \
+ return; \
} while (0)
void
@@ -55,20 +62,20 @@ rs6000_pragma_longcall (cpp_reader *pfile ATTRIBUTE_UNUSED)
/* If we get here, generic code has already scanned the directive
leader and the word "longcall". */
- if (c_lex (&x) != CPP_OPEN_PAREN)
+ if (pragma_lex (&x) != CPP_OPEN_PAREN)
SYNTAX_ERROR ("missing open paren");
- if (c_lex (&n) != CPP_NUMBER)
+ if (pragma_lex (&n) != CPP_NUMBER)
SYNTAX_ERROR ("missing number");
- if (c_lex (&x) != CPP_CLOSE_PAREN)
+ if (pragma_lex (&x) != CPP_CLOSE_PAREN)
SYNTAX_ERROR ("missing close paren");
- if (!integer_zerop (n) && !integer_onep (n))
+ if (n != integer_zero_node && n != integer_one_node)
SYNTAX_ERROR ("number must be 0 or 1");
- if (c_lex (&x) != CPP_EOF)
- warning ("junk at end of #pragma longcall");
+ if (pragma_lex (&x) != CPP_EOF)
+ warning (OPT_Wpragmas, "junk at end of #pragma longcall");
- rs6000_default_long_calls = integer_onep (n);
+ rs6000_default_long_calls = (n == integer_one_node);
}
/* Handle defining many CPP flags based on TARGET_xxx. As a general
@@ -87,8 +94,18 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
builtin_define ("_ARCH_PWR");
if (TARGET_POWERPC)
builtin_define ("_ARCH_PPC");
+ if (TARGET_PPC_GPOPT)
+ builtin_define ("_ARCH_PPCSQ");
+ if (TARGET_PPC_GFXOPT)
+ builtin_define ("_ARCH_PPCGR");
if (TARGET_POWERPC64)
builtin_define ("_ARCH_PPC64");
+ if (TARGET_MFCRF)
+ builtin_define ("_ARCH_PWR4");
+ if (TARGET_POPCNTB)
+ builtin_define ("_ARCH_PWR5");
+ if (TARGET_FPRND)
+ builtin_define ("_ARCH_PWR5X");
if (! TARGET_POWER && ! TARGET_POWER2 && ! TARGET_POWERPC)
builtin_define ("_ARCH_COM");
if (TARGET_ALTIVEC)
@@ -108,6 +125,9 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
/* Used by lwarx/stwcx. errata work-around. */
if (rs6000_cpu == PROCESSOR_PPC405)
builtin_define ("__PPC405__");
+ /* Used by libstdc++. */
+ if (TARGET_NO_LWSYNC)
+ builtin_define ("__NO_LWSYNC__");
/* May be overridden by target configuration. */
RS6000_CPU_CPP_ENDIAN_BUILTINS();
@@ -130,4 +150,2430 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
default:
break;
}
+
+ /* Let the compiled code know if 'f' class registers will not be available. */
+ if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ builtin_define ("__NO_FPRS__");
+}
+
+
+struct altivec_builtin_types
+{
+ enum rs6000_builtins code;
+ enum rs6000_builtins overloaded_code;
+ signed char ret_type;
+ signed char op1;
+ signed char op2;
+ signed char op3;
+};
+
+const struct altivec_builtin_types altivec_overloaded_builtins[] = {
+ /* Unary AltiVec builtins. */
+ { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABS, ALTIVEC_BUILTIN_ABS_V4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABSS, ALTIVEC_BUILTIN_ABSS_V16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABSS, ALTIVEC_BUILTIN_ABSS_V8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ABSS, ALTIVEC_BUILTIN_ABSS_V4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_CEIL, ALTIVEC_BUILTIN_VRFIP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_EXPTE, ALTIVEC_BUILTIN_VEXPTEFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_FLOOR, ALTIVEC_BUILTIN_VRFIM,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_LOGE, ALTIVEC_BUILTIN_VLOGEFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_MTVSCR, ALTIVEC_BUILTIN_MTVSCR,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_RE, ALTIVEC_BUILTIN_VREFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_ROUND, ALTIVEC_BUILTIN_VRFIN,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_RSQRTE, ALTIVEC_BUILTIN_VRSQRTEFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_TRUNC, ALTIVEC_BUILTIN_VRFIZ,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSB,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHSH,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKH, ALTIVEC_BUILTIN_VUPKHPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_pixel_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHSH, ALTIVEC_BUILTIN_VUPKHSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHSH, ALTIVEC_BUILTIN_VUPKHSH,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHPX, ALTIVEC_BUILTIN_VUPKHPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHPX, ALTIVEC_BUILTIN_VUPKHPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_pixel_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHSB, ALTIVEC_BUILTIN_VUPKHSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKHSB, ALTIVEC_BUILTIN_VUPKHSB,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKL, ALTIVEC_BUILTIN_VUPKLSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKL, ALTIVEC_BUILTIN_VUPKLSB,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKL, ALTIVEC_BUILTIN_VUPKLPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_pixel_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKL, ALTIVEC_BUILTIN_VUPKLSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_UNPACKL, ALTIVEC_BUILTIN_VUPKLSH,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLPX, ALTIVEC_BUILTIN_VUPKLPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLPX, ALTIVEC_BUILTIN_VUPKLPX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_pixel_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLSH, ALTIVEC_BUILTIN_VUPKLSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLSH, ALTIVEC_BUILTIN_VUPKLSH,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V8HI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0, 0 },
+ { ALTIVEC_BUILTIN_VEC_VUPKLSB, ALTIVEC_BUILTIN_VUPKLSB,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V16QI, 0, 0 },
+
+ /* Binary AltiVec builtins. */
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADD, ALTIVEC_BUILTIN_VADDFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDFP, ALTIVEC_BUILTIN_VADDFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWM, ALTIVEC_BUILTIN_VADDUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHM, ALTIVEC_BUILTIN_VADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBM, ALTIVEC_BUILTIN_VADDUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDC, ALTIVEC_BUILTIN_VADDCUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ADDS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSWS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSWS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSWS, ALTIVEC_BUILTIN_VADDSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUWS, ALTIVEC_BUILTIN_VADDUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSHS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSHS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSHS, ALTIVEC_BUILTIN_VADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUHS, ALTIVEC_BUILTIN_VADDUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSBS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSBS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDSBS, ALTIVEC_BUILTIN_VADDSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VADDUBS, ALTIVEC_BUILTIN_VADDUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_AVG, ALTIVEC_BUILTIN_VAVGSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGSW, ALTIVEC_BUILTIN_VAVGSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGUW, ALTIVEC_BUILTIN_VAVGUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGSH, ALTIVEC_BUILTIN_VAVGSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGUH, ALTIVEC_BUILTIN_VAVGUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGSB, ALTIVEC_BUILTIN_VAVGSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VAVGUB, ALTIVEC_BUILTIN_VAVGUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPB, ALTIVEC_BUILTIN_VCMPBFP,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPEQ, ALTIVEC_BUILTIN_VCMPEQFP,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQFP, ALTIVEC_BUILTIN_VCMPEQFP,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUW, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUW, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUW, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUW, ALTIVEC_BUILTIN_VCMPEQUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUH, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUH, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUH, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUH, ALTIVEC_BUILTIN_VCMPEQUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUB, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUB, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUB, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPEQUB, ALTIVEC_BUILTIN_VCMPEQUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGE, ALTIVEC_BUILTIN_VCMPGEFP,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTSB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTSH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTSW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPGT, ALTIVEC_BUILTIN_VCMPGTFP,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTFP, ALTIVEC_BUILTIN_VCMPGTFP,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSW, ALTIVEC_BUILTIN_VCMPGTSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSW, ALTIVEC_BUILTIN_VCMPGTSW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUW, ALTIVEC_BUILTIN_VCMPGTUW,
+ RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUW, ALTIVEC_BUILTIN_VCMPGTUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSH, ALTIVEC_BUILTIN_VCMPGTSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSH, ALTIVEC_BUILTIN_VCMPGTSH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUH, ALTIVEC_BUILTIN_VCMPGTUH,
+ RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUH, ALTIVEC_BUILTIN_VCMPGTUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSB, ALTIVEC_BUILTIN_VCMPGTSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTSB, ALTIVEC_BUILTIN_VCMPGTSB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUB, ALTIVEC_BUILTIN_VCMPGTUB,
+ RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCMPGTUB, ALTIVEC_BUILTIN_VCMPGTUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLE, ALTIVEC_BUILTIN_VCMPGEFP,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTUB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTSB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTUH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTSH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTUW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTSW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CMPLT, ALTIVEC_BUILTIN_VCMPGTFP,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_CTF, ALTIVEC_BUILTIN_VCFUX,
+ RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CTF, ALTIVEC_BUILTIN_VCFSX,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCFSX, ALTIVEC_BUILTIN_VCFSX,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VCFUX, ALTIVEC_BUILTIN_VCFUX,
+ RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CTS, ALTIVEC_BUILTIN_VCTSXS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_CTU, ALTIVEC_BUILTIN_VCTUXS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEBX,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEBX,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEHX,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEHX,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDE, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEWX, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEWX, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEWX, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEWX, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEWX, ALTIVEC_BUILTIN_LVEWX,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEHX, ALTIVEC_BUILTIN_LVEHX,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEHX, ALTIVEC_BUILTIN_LVEHX,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEBX, ALTIVEC_BUILTIN_LVEBX,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVEBX, ALTIVEC_BUILTIN_LVEBX,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LDL, ALTIVEC_BUILTIN_LVXL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSL, ALTIVEC_BUILTIN_LVSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_long, 0 },
+ { ALTIVEC_BUILTIN_VEC_LVSR, ALTIVEC_BUILTIN_LVSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_float, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MAX, ALTIVEC_BUILTIN_VMAXFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXFP, ALTIVEC_BUILTIN_VMAXFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSW, ALTIVEC_BUILTIN_VMAXSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUW, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUW, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUW, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUW, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUW, ALTIVEC_BUILTIN_VMAXUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSH, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSH, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSH, ALTIVEC_BUILTIN_VMAXSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUH, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUH, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUH, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUH, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUH, ALTIVEC_BUILTIN_VMAXUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSB, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSB, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXSB, ALTIVEC_BUILTIN_VMAXSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUB, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUB, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUB, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUB, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMAXUB, ALTIVEC_BUILTIN_VMAXUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEH, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHH, ALTIVEC_BUILTIN_VMRGHH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHB, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHB, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGHB, ALTIVEC_BUILTIN_VMRGHB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MERGEL, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLH, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLH, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLH, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLH, ALTIVEC_BUILTIN_VMRGLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLB, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLB, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMRGLB, ALTIVEC_BUILTIN_VMRGLB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MIN, ALTIVEC_BUILTIN_VMINFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINFP, ALTIVEC_BUILTIN_VMINFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSW, ALTIVEC_BUILTIN_VMINSW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUW, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUW, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUW, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUW, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUW, ALTIVEC_BUILTIN_VMINUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSH, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSH, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSH, ALTIVEC_BUILTIN_VMINSH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSB, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSB, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINSB, ALTIVEC_BUILTIN_VMINSB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUH, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUH, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUH, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUH, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUH, ALTIVEC_BUILTIN_VMINUH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMINUB, ALTIVEC_BUILTIN_VMINUB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULEUB,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULESB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULEUH,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULESH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULEUB, ALTIVEC_BUILTIN_VMULEUB,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULESB, ALTIVEC_BUILTIN_VMULESB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULEUH, ALTIVEC_BUILTIN_VMULEUH,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULESH, ALTIVEC_BUILTIN_VMULESH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULO, ALTIVEC_BUILTIN_VMULOUB,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULO, ALTIVEC_BUILTIN_VMULOSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULO, ALTIVEC_BUILTIN_VMULOUH,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_MULO, ALTIVEC_BUILTIN_VMULOSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULOSH, ALTIVEC_BUILTIN_VMULOSH,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULOUH, ALTIVEC_BUILTIN_VMULOUH,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULOSB, ALTIVEC_BUILTIN_VMULOSB,
+ RS6000_BTI_V8HI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VMULOUB, ALTIVEC_BUILTIN_VMULOUB,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACK, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUWUM, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUWUM, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUWUM, ALTIVEC_BUILTIN_VPKUWUM,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUHUM, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUHUM, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUHUM, ALTIVEC_BUILTIN_VPKUHUM,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKPX, ALTIVEC_BUILTIN_VPKPX,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKS, ALTIVEC_BUILTIN_VPKUHUS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKS, ALTIVEC_BUILTIN_VPKSHSS,
+ RS6000_BTI_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKS, ALTIVEC_BUILTIN_VPKUWUS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKS, ALTIVEC_BUILTIN_VPKSWSS,
+ RS6000_BTI_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKSWSS, ALTIVEC_BUILTIN_VPKSWSS,
+ RS6000_BTI_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUWUS, ALTIVEC_BUILTIN_VPKUWUS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKSHSS, ALTIVEC_BUILTIN_VPKSHSS,
+ RS6000_BTI_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKUHUS, ALTIVEC_BUILTIN_VPKUHUS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKSU, ALTIVEC_BUILTIN_VPKUHUS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKSU, ALTIVEC_BUILTIN_VPKSHUS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKSU, ALTIVEC_BUILTIN_VPKUWUS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_PACKSU, ALTIVEC_BUILTIN_VPKSWUS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKSWUS, ALTIVEC_BUILTIN_VPKSWUS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VPKSHUS, ALTIVEC_BUILTIN_VPKSHUS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_RL, ALTIVEC_BUILTIN_VRLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLW, ALTIVEC_BUILTIN_VRLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLW, ALTIVEC_BUILTIN_VRLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLH, ALTIVEC_BUILTIN_VRLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLH, ALTIVEC_BUILTIN_VRLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLB, ALTIVEC_BUILTIN_VRLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VRLB, ALTIVEC_BUILTIN_VRLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SL, ALTIVEC_BUILTIN_VSLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLW, ALTIVEC_BUILTIN_VSLW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLW, ALTIVEC_BUILTIN_VSLW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLH, ALTIVEC_BUILTIN_VSLH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLH, ALTIVEC_BUILTIN_VSLH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLB, ALTIVEC_BUILTIN_VSLB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSLB, ALTIVEC_BUILTIN_VSLB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLL, ALTIVEC_BUILTIN_VSL,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SLO, ALTIVEC_BUILTIN_VSLO,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTH, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTH, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTH, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTH, ALTIVEC_BUILTIN_VSPLTH,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTB, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTB, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSPLTB, ALTIVEC_BUILTIN_VSPLTB,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SR, ALTIVEC_BUILTIN_VSRW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRW, ALTIVEC_BUILTIN_VSRW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRW, ALTIVEC_BUILTIN_VSRW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRH, ALTIVEC_BUILTIN_VSRH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRH, ALTIVEC_BUILTIN_VSRH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRB, ALTIVEC_BUILTIN_VSRB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRB, ALTIVEC_BUILTIN_VSRB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRA, ALTIVEC_BUILTIN_VSRAW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAW, ALTIVEC_BUILTIN_VSRAW,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAW, ALTIVEC_BUILTIN_VSRAW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAH, ALTIVEC_BUILTIN_VSRAH,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAH, ALTIVEC_BUILTIN_VSRAH,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAB, ALTIVEC_BUILTIN_VSRAB,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSRAB, ALTIVEC_BUILTIN_VSRAB,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRL, ALTIVEC_BUILTIN_VSR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SRO, ALTIVEC_BUILTIN_VSRO,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUB, ALTIVEC_BUILTIN_VSUBFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBFP, ALTIVEC_BUILTIN_VSUBFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWM, ALTIVEC_BUILTIN_VSUBUWM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHM, ALTIVEC_BUILTIN_VSUBUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBM, ALTIVEC_BUILTIN_VSUBUBM,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBC, ALTIVEC_BUILTIN_VSUBCUW,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUBS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSWS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSWS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSWS, ALTIVEC_BUILTIN_VSUBSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUWS, ALTIVEC_BUILTIN_VSUBUWS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSHS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSHS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSHS, ALTIVEC_BUILTIN_VSUBSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUHS, ALTIVEC_BUILTIN_VSUBUHS,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBSBS, ALTIVEC_BUILTIN_VSUBSBS,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUBUBS, ALTIVEC_BUILTIN_VSUBUBS,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUM4S, ALTIVEC_BUILTIN_VSUM4UBS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUM4S, ALTIVEC_BUILTIN_VSUM4SBS,
+ RS6000_BTI_V4SI, RS6000_BTI_V16QI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUM4S, ALTIVEC_BUILTIN_VSUM4SHS,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUM4SHS, ALTIVEC_BUILTIN_VSUM4SHS,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUM4SBS, ALTIVEC_BUILTIN_VSUM4SBS,
+ RS6000_BTI_V4SI, RS6000_BTI_V16QI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_VSUM4UBS, ALTIVEC_BUILTIN_VSUM4UBS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUM2S, ALTIVEC_BUILTIN_VSUM2SWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_SUMS, ALTIVEC_BUILTIN_VSUMSWS,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SF, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI, 0 },
+ { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 },
+
+ /* Ternary AltiVec builtins. */
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_V4SF, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_INTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_INTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DST, ALTIVEC_BUILTIN_DST,
+ RS6000_BTI_void, ~RS6000_BTI_float, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_V4SF, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_INTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_INTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_UINTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTST, ALTIVEC_BUILTIN_DSTST,
+ RS6000_BTI_void, ~RS6000_BTI_float, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V4SF, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTSTT, ALTIVEC_BUILTIN_DSTSTT,
+ RS6000_BTI_void, ~RS6000_BTI_float, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_V4SF, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTQI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTHI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_UINTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_unsigned_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_long, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_DSTT, ALTIVEC_BUILTIN_DSTT,
+ RS6000_BTI_void, ~RS6000_BTI_float, RS6000_BTI_INTSI, RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_MADD, ALTIVEC_BUILTIN_VMADDFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_MADDS, ALTIVEC_BUILTIN_VMHADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM,
+ RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MLADD, ALTIVEC_BUILTIN_VMLADDUHM,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MRADDS, ALTIVEC_BUILTIN_VMHRADDSHS,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMUBM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMMBM,
+ RS6000_BTI_V4SI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMUHM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_MSUM, ALTIVEC_BUILTIN_VMSUMSHM,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMSHM, ALTIVEC_BUILTIN_VMSUMSHM,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMUHM, ALTIVEC_BUILTIN_VMSUMUHM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMMBM, ALTIVEC_BUILTIN_VMSUMMBM,
+ RS6000_BTI_V4SI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMUBM, ALTIVEC_BUILTIN_VMSUMUBM,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_MSUMS, ALTIVEC_BUILTIN_VMSUMUHS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_MSUMS, ALTIVEC_BUILTIN_VMSUMSHS,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMSHS, ALTIVEC_BUILTIN_VMSUMSHS,
+ RS6000_BTI_V4SI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_VMSUMUHS, ALTIVEC_BUILTIN_VMSUMUHS,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_NMSUB, ALTIVEC_BUILTIN_VNMSUBFP,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_8HI,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_4SF,
+ RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_4SI,
+ RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_4SI,
+ RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_4SI,
+ RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_8HI,
+ RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_8HI,
+ RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_8HI,
+ RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_8HI,
+ RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_16QI,
+ RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_16QI,
+ RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_SLD, ALTIVEC_BUILTIN_VSLDOI_16QI,
+ RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI, RS6000_BTI_NOT_OPAQUE },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_ST, ALTIVEC_BUILTIN_STVX,
+ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STE, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEWX, ALTIVEC_BUILTIN_STVEWX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEHX, ALTIVEC_BUILTIN_STVEHX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STVEBX, ALTIVEC_BUILTIN_STVEBX,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_void },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_V4SF },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V4SF, RS6000_BTI_INTSI, ~RS6000_BTI_float },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTSI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, ~RS6000_BTI_INTSI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTHI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_INTHI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_unsigned_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_UINTQI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_bool_V16QI, RS6000_BTI_INTSI, ~RS6000_BTI_INTQI },
+ { ALTIVEC_BUILTIN_VEC_STL, ALTIVEC_BUILTIN_STVXL,
+ RS6000_BTI_void, RS6000_BTI_pixel_V8HI, RS6000_BTI_INTSI, ~RS6000_BTI_pixel_V8HI },
+
+ /* Predicates. */
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTFP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+
+
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_pixel_V8HI, RS6000_BTI_pixel_V8HI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPEQ_P, ALTIVEC_BUILTIN_VCMPEQFP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+
+
+ /* cmpge is the same as cmpgt for all cases except floating point.
+ There is further code to deal with this special case in
+ altivec_build_resolved_builtin. */
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_bool_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSB_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V16QI, RS6000_BTI_V16QI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V8HI, RS6000_BTI_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSH_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V8HI, RS6000_BTI_bool_V8HI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTUW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGTSW_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI },
+ { ALTIVEC_BUILTIN_VCMPGE_P, ALTIVEC_BUILTIN_VCMPGEFP_P,
+ RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF },
+
+ { 0, 0, 0, 0, 0, 0 }
+};
+
+
+/* Convert a type stored into a struct altivec_builtin_types as ID,
+ into a tree. The types are in rs6000_builtin_types: negative values
+ create a pointer type for the type associated to ~ID. Note it is
+ a logical NOT, rather than a negation, otherwise you cannot represent
+ a pointer type for ID 0. */
+
+static inline tree
+rs6000_builtin_type (int id)
+{
+ tree t;
+ t = rs6000_builtin_types[id < 0 ? ~id : id];
+ return id < 0 ? build_pointer_type (t) : t;
+}
+
+/* Check whether the type of an argument, T, is compatible with a
+ type ID stored into a struct altivec_builtin_types. Integer
+ types are considered compatible; otherwise, the language hook
+ lang_hooks.types_compatible_p makes the decision. */
+
+static inline bool
+rs6000_builtin_type_compatible (tree t, int id)
+{
+ tree builtin_type;
+ builtin_type = rs6000_builtin_type (id);
+ if (INTEGRAL_TYPE_P (t) && INTEGRAL_TYPE_P (builtin_type))
+ return true;
+ else
+ return lang_hooks.types_compatible_p (t, builtin_type);
}
+
+
+/* Build a tree for a function call to an Altivec non-overloaded builtin.
+ The overloaded builtin that matched the types and args is described
+ by DESC. The N arguments are given in ARGS, respectively.
+
+ Actually the only thing it does is calling fold_convert on ARGS, with
+ a small exception for vec_{all,any}_{ge,le} predicates. */
+
+static tree
+altivec_build_resolved_builtin (tree *args, int n,
+ const struct altivec_builtin_types *desc)
+{
+ tree impl_fndecl = rs6000_builtin_decls[desc->overloaded_code];
+ tree ret_type = rs6000_builtin_type (desc->ret_type);
+ tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (impl_fndecl));
+ tree arglist = NULL_TREE, arg_type[3];
+
+ int i;
+ for (i = 0; i < n; i++)
+ arg_type[i] = TREE_VALUE (argtypes), argtypes = TREE_CHAIN (argtypes);
+
+ /* The AltiVec overloading implementation is overall gross, but this
+ is particularly disgusting. The vec_{all,any}_{ge,le} builtins
+ are completely different for floating-point vs. integer vector
+ types, because the former has vcmpgefp, but the latter should use
+ vcmpgtXX.
+
+ In practice, the second and third arguments are swapped, and the
+ condition (LT vs. EQ, which is recognizable by bit 1 of the first
+ argument) is reversed. Patch the arguments here before building
+ the resolved CALL_EXPR. */
+ if (desc->code == ALTIVEC_BUILTIN_VCMPGE_P
+ && desc->overloaded_code != ALTIVEC_BUILTIN_VCMPGEFP_P)
+ {
+ tree t;
+ t = args[2], args[2] = args[1], args[1] = t;
+ t = arg_type[2], arg_type[2] = arg_type[1], arg_type[1] = t;
+
+ args[0] = fold_build2 (BIT_XOR_EXPR, TREE_TYPE (args[0]), args[0],
+ build_int_cst (NULL_TREE, 2));
+ }
+
+ while (--n >= 0)
+ arglist = tree_cons (NULL_TREE,
+ fold_convert (arg_type[n], args[n]),
+ arglist);
+
+ return fold_convert (ret_type,
+ build_function_call_expr (impl_fndecl, arglist));
+}
+
+/* Implementation of the resolve_overloaded_builtin target hook, to
+ support Altivec's overloaded builtins. */
+
+tree
+altivec_resolve_overloaded_builtin (tree fndecl, tree arglist)
+{
+ unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ tree fnargs = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ tree types[3], args[3];
+ const struct altivec_builtin_types *desc;
+ int n;
+
+ if (fcode < ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ || fcode > ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ return NULL_TREE;
+
+ for (n = 0;
+ !VOID_TYPE_P (TREE_VALUE (fnargs)) && arglist;
+ fnargs = TREE_CHAIN (fnargs), arglist = TREE_CHAIN (arglist), n++)
+ {
+ tree decl_type = TREE_VALUE (fnargs);
+ tree arg = TREE_VALUE (arglist);
+ tree type;
+
+ if (arg == error_mark_node)
+ return error_mark_node;
+
+ if (n >= 3)
+ abort ();
+
+ arg = default_conversion (arg);
+
+ /* The C++ front-end converts float * to const void * using
+ NOP_EXPR<const void *> (NOP_EXPR<void *> (x)). */
+ type = TREE_TYPE (arg);
+ if (POINTER_TYPE_P (type)
+ && TREE_CODE (arg) == NOP_EXPR
+ && lang_hooks.types_compatible_p (TREE_TYPE (arg),
+ const_ptr_type_node)
+ && lang_hooks.types_compatible_p (TREE_TYPE (TREE_OPERAND (arg, 0)),
+ ptr_type_node))
+ {
+ arg = TREE_OPERAND (arg, 0);
+ type = TREE_TYPE (arg);
+ }
+
+ /* Remove the const from the pointers to simplify the overload
+ matching further down. */
+ if (POINTER_TYPE_P (decl_type)
+ && POINTER_TYPE_P (type)
+ && TYPE_QUALS (TREE_TYPE (type)) != 0)
+ {
+ if (TYPE_READONLY (TREE_TYPE (type))
+ && !TYPE_READONLY (TREE_TYPE (decl_type)))
+ warning (0, "passing arg %d of %qE discards qualifiers from"
+ "pointer target type", n + 1, fndecl);
+ type = build_pointer_type (build_qualified_type (TREE_TYPE (type),
+ 0));
+ arg = fold_convert (type, arg);
+ }
+
+ args[n] = arg;
+ types[n] = type;
+ }
+
+ /* If the number of arguments did not match the prototype, return NULL
+ and the generic code will issue the appropriate error message. */
+ if (!VOID_TYPE_P (TREE_VALUE (fnargs)) || arglist)
+ return NULL;
+
+ if (n == 0)
+ abort ();
+
+ if (fcode == ALTIVEC_BUILTIN_VEC_STEP)
+ {
+ if (TREE_CODE (types[0]) != VECTOR_TYPE)
+ goto bad;
+
+ return build_int_cst (NULL_TREE, TYPE_VECTOR_SUBPARTS (types[0]));
+ }
+
+ for (desc = altivec_overloaded_builtins;
+ desc->code && desc->code != fcode; desc++)
+ continue;
+
+ /* For arguments after the last, we have RS6000_BTI_NOT_OPAQUE in
+ the opX fields. */
+ for (; desc->code == fcode; desc++)
+ if ((desc->op1 == RS6000_BTI_NOT_OPAQUE
+ || rs6000_builtin_type_compatible (types[0], desc->op1))
+ && (desc->op2 == RS6000_BTI_NOT_OPAQUE
+ || rs6000_builtin_type_compatible (types[1], desc->op2))
+ && (desc->op3 == RS6000_BTI_NOT_OPAQUE
+ || rs6000_builtin_type_compatible (types[2], desc->op3)))
+ return altivec_build_resolved_builtin (args, n, desc);
+
+ bad:
+ error ("invalid parameter combination for AltiVec intrinsic");
+ return error_mark_node;
+}
+
diff --git a/contrib/gcc/config/rs6000/rs6000-modes.def b/contrib/gcc/config/rs6000/rs6000-modes.def
index 6f17f1a..c0599b3 100644
--- a/contrib/gcc/config/rs6000/rs6000-modes.def
+++ b/contrib/gcc/config/rs6000/rs6000-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* 128-bit floating point. ABI_V4 uses IEEE quad, AIX/Darwin
adjust this in rs6000_override_options. */
@@ -38,3 +38,10 @@ PARTIAL_INT_MODE (SI);
CC_MODE (CCUNS);
CC_MODE (CCFP);
CC_MODE (CCEQ);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 16); /* V16QI V8HI V4SI V2DI */
+VECTOR_MODE (INT, DI, 1);
+VECTOR_MODES (FLOAT, 8); /* V4HF V2SF */
+VECTOR_MODES (FLOAT, 16); /* V8HF V4SF V2DF */
diff --git a/contrib/gcc/config/rs6000/rs6000-protos.h b/contrib/gcc/config/rs6000/rs6000-protos.h
index 3303ecd..0cb5a50 100644
--- a/contrib/gcc/config/rs6000/rs6000-protos.h
+++ b/contrib/gcc/config/rs6000/rs6000-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
- Copyright (C) 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#ifndef GCC_RS6000_PROTOS_H
#define GCC_RS6000_PROTOS_H
@@ -32,83 +32,42 @@ extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, int, int, int);
extern void rs6000_va_start (tree, rtx);
#endif /* TREE_CODE */
-extern struct rtx_def *rs6000_got_register (rtx);
-extern struct rtx_def *find_addr_reg (rtx);
-extern int any_operand (rtx, enum machine_mode);
-extern int short_cint_operand (rtx, enum machine_mode);
-extern int u_short_cint_operand (rtx, enum machine_mode);
-extern int non_short_cint_operand (rtx, enum machine_mode);
-extern int exact_log2_cint_operand (rtx, enum machine_mode);
-extern int gpc_reg_operand (rtx, enum machine_mode);
-extern int cc_reg_operand (rtx, enum machine_mode);
-extern int cc_reg_not_cr0_operand (rtx, enum machine_mode);
-extern int reg_or_short_operand (rtx, enum machine_mode);
-extern int reg_or_neg_short_operand (rtx, enum machine_mode);
-extern int reg_or_aligned_short_operand (rtx, enum machine_mode);
-extern int reg_or_u_short_operand (rtx, enum machine_mode);
-extern int reg_or_cint_operand (rtx, enum machine_mode);
-extern int reg_or_arith_cint_operand (rtx, enum machine_mode);
-extern int reg_or_add_cint64_operand (rtx, enum machine_mode);
-extern int reg_or_sub_cint64_operand (rtx, enum machine_mode);
-extern int reg_or_logical_cint_operand (rtx, enum machine_mode);
-extern int got_operand (rtx, enum machine_mode);
-extern int word_offset_memref_operand (rtx, enum machine_mode);
-extern int got_no_const_operand (rtx, enum machine_mode);
+extern bool easy_altivec_constant (rtx, enum machine_mode);
+extern bool macho_lo_sum_memory_operand (rtx, enum machine_mode);
extern int num_insns_constant (rtx, enum machine_mode);
-extern int easy_fp_constant (rtx, enum machine_mode);
-extern int easy_vector_constant (rtx, enum machine_mode);
-extern rtx gen_easy_vector_constant_add_self (rtx);
-extern const char *output_vec_const_move (rtx *);
-extern int zero_fp_constant (rtx, enum machine_mode);
-extern int zero_constant (rtx, enum machine_mode);
-extern int volatile_mem_operand (rtx, enum machine_mode);
-extern int offsettable_mem_operand (rtx, enum machine_mode);
-extern int mem_or_easy_const_operand (rtx, enum machine_mode);
-extern int add_operand (rtx, enum machine_mode);
-extern int non_add_cint_operand (rtx, enum machine_mode);
-extern int non_logical_cint_operand (rtx, enum machine_mode);
-extern int logical_operand (rtx, enum machine_mode);
-extern int mask_operand (rtx, enum machine_mode);
-extern int mask_operand_wrap (rtx, enum machine_mode);
-extern int mask64_operand (rtx, enum machine_mode);
-extern int mask64_2_operand (rtx, enum machine_mode);
-extern void build_mask64_2_operands (rtx, rtx *);
-extern int and64_operand (rtx, enum machine_mode);
-extern int and64_2_operand (rtx, enum machine_mode);
-extern int and_operand (rtx, enum machine_mode);
-extern int count_register_operand (rtx, enum machine_mode);
-extern int xer_operand (rtx, enum machine_mode);
-extern int reg_or_mem_operand (rtx, enum machine_mode);
-extern int lwa_operand (rtx, enum machine_mode);
-extern int call_operand (rtx, enum machine_mode);
-extern int current_file_function_operand (rtx, enum machine_mode);
-extern int input_operand (rtx, enum machine_mode);
+extern int num_insns_constant_wide (HOST_WIDE_INT);
extern int small_data_operand (rtx, enum machine_mode);
-extern int s8bit_cint_operand (rtx, enum machine_mode);
+extern bool toc_relative_expr_p (rtx);
+extern bool invalid_e500_subreg (rtx, enum machine_mode);
+extern void validate_condition_mode (enum rtx_code, enum machine_mode);
extern bool legitimate_constant_pool_address_p (rtx);
+extern bool legitimate_indirect_address_p (rtx, int);
+
+extern rtx rs6000_got_register (rtx);
+extern rtx find_addr_reg (rtx);
+extern rtx gen_easy_altivec_constant (rtx);
+extern const char *output_vec_const_move (rtx *);
+extern void rs6000_expand_vector_init (rtx, rtx);
+extern void rs6000_expand_vector_set (rtx, rtx, int);
+extern void rs6000_expand_vector_extract (rtx, rtx, int);
+extern void build_mask64_2_operands (rtx, rtx *);
+extern int expand_block_clear (rtx[]);
extern int expand_block_move (rtx[]);
-extern int load_multiple_operation (rtx, enum machine_mode);
extern const char * rs6000_output_load_multiple (rtx[]);
-extern int store_multiple_operation (rtx, enum machine_mode);
-extern int branch_comparison_operator (rtx, enum machine_mode);
-extern int branch_positive_comparison_operator (rtx, enum machine_mode);
-extern int scc_comparison_operator (rtx, enum machine_mode);
-extern int trap_comparison_operator (rtx, enum machine_mode);
-extern int boolean_operator (rtx, enum machine_mode);
-extern int boolean_or_operator (rtx, enum machine_mode);
-extern int min_max_operator (rtx, enum machine_mode);
extern int includes_lshift_p (rtx, rtx);
extern int includes_rshift_p (rtx, rtx);
extern int includes_rldic_lshift_p (rtx, rtx);
extern int includes_rldicr_lshift_p (rtx, rtx);
+extern int insvdi_rshift_rlwimi_p (rtx, rtx, rtx);
extern int registers_ok_for_quad_peep (rtx, rtx);
-extern int addrs_ok_for_quad_peep (rtx, rtx);
+extern int mems_ok_for_quad_peep (rtx, rtx);
extern bool gpr_or_gpr_p (rtx, rtx);
-extern enum reg_class secondary_reload_class (enum reg_class,
- enum machine_mode, rtx);
+extern enum reg_class rs6000_secondary_reload_class (enum reg_class,
+ enum machine_mode, rtx);
extern int ccr_bit (rtx, int);
extern int extract_MB (rtx);
extern int extract_ME (rtx);
+extern void rs6000_output_function_entry (FILE *, const char *);
extern void print_operand (FILE *, rtx, int);
extern void print_operand_address (FILE *, rtx);
extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
@@ -116,52 +75,56 @@ extern enum rtx_code rs6000_reverse_condition (enum machine_mode,
extern void rs6000_emit_sCOND (enum rtx_code, rtx);
extern void rs6000_emit_cbranch (enum rtx_code, rtx);
extern char * output_cbranch (rtx, const char *, int, rtx);
-extern char * output_e500_flip_eq_bit (rtx, rtx);
+extern char * output_e500_flip_gt_bit (rtx, rtx);
extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
+extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
extern void rs6000_emit_minmax (rtx, enum rtx_code, rtx, rtx);
+extern void rs6000_emit_sync (enum rtx_code, enum machine_mode,
+ rtx, rtx, rtx, rtx, bool);
+extern void rs6000_split_atomic_op (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+extern void rs6000_split_compare_and_swap (rtx, rtx, rtx, rtx, rtx);
+extern void rs6000_expand_compare_and_swapqhi (rtx, rtx, rtx, rtx);
+extern void rs6000_split_compare_and_swapqhi (rtx, rtx, rtx, rtx, rtx, rtx);
+extern void rs6000_split_lock_test_and_set (rtx, rtx, rtx, rtx);
+extern void rs6000_emit_swdivsf (rtx, rtx, rtx);
+extern void rs6000_emit_swdivdf (rtx, rtx, rtx);
extern void output_toc (FILE *, rtx, int, enum machine_mode);
extern void rs6000_initialize_trampoline (rtx, rtx, rtx);
-extern struct rtx_def *rs6000_longcall_ref (rtx);
+extern rtx rs6000_longcall_ref (rtx);
extern void rs6000_fatal_bad_address (rtx);
-extern int stmw_operation (rtx, enum machine_mode);
-extern int mfcr_operation (rtx, enum machine_mode);
-extern int mtcrf_operation (rtx, enum machine_mode);
-extern int lmw_operation (rtx, enum machine_mode);
-extern struct rtx_def *create_TOC_reference (rtx);
+extern rtx create_TOC_reference (rtx);
extern void rs6000_split_multireg_move (rtx, rtx);
extern void rs6000_emit_move (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_address (rtx, rtx, enum machine_mode);
extern rtx rs6000_legitimize_reload_address (rtx, enum machine_mode,
- int, int, int, int *);
+ int, int, int, int *);
extern int rs6000_legitimate_address (enum machine_mode, rtx, int);
+extern bool rs6000_legitimate_offset_address_p (enum machine_mode, rtx, int);
extern bool rs6000_mode_dependent_address (rtx);
+extern bool rs6000_offsettable_memref_p (rtx);
extern rtx rs6000_return_addr (int, rtx);
extern void rs6000_output_symbol_ref (FILE*, rtx);
extern HOST_WIDE_INT rs6000_initial_elimination_offset (int, int);
-extern rtx rs6000_machopic_legitimize_pic_address (rtx orig,
- enum machine_mode mode, rtx reg);
-
+extern rtx rs6000_machopic_legitimize_pic_address (rtx, enum machine_mode,
+ rtx);
#endif /* RTX_CODE */
#ifdef TREE_CODE
-extern unsigned int rs6000_special_round_type_align (tree, int, int);
+extern unsigned int rs6000_special_round_type_align (tree, unsigned int,
+ unsigned int);
extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
- tree, int);
+ tree, int, int);
extern int function_arg_boundary (enum machine_mode, tree);
-extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern int function_arg_pass_by_reference (CUMULATIVE_ARGS *,
- enum machine_mode,
- tree, int);
+extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern tree altivec_resolve_overloaded_builtin (tree, tree);
extern rtx rs6000_function_value (tree, tree);
extern rtx rs6000_libcall_value (enum machine_mode);
-extern struct rtx_def *rs6000_va_arg (tree, tree);
+extern rtx rs6000_va_arg (tree, tree);
extern int function_ok_for_sibcall (tree);
extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
+extern bool rs6000_elf_in_small_data_p (tree);
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
extern enum direction function_arg_padding (enum machine_mode, tree);
@@ -179,13 +142,6 @@ extern void rs6000_gen_section_name (char **, const char *, const char *);
extern void output_function_profiler (FILE *, int);
extern void output_profile_hook (int);
extern int rs6000_trampoline_size (void);
-extern void toc_section (void);
-extern void sdata_section (void);
-extern void sdata2_section (void);
-extern void sbss_section (void);
-extern void private_data_section (void);
-extern void read_only_data_section (void);
-extern void read_only_private_data_section (void);
extern int get_TOC_alias_set (void);
extern void rs6000_emit_prologue (void);
extern void rs6000_emit_load_toc_table (int);
@@ -194,13 +150,12 @@ extern unsigned int rs6000_dbx_register_number (unsigned int);
extern void rs6000_emit_epilogue (int);
extern void rs6000_emit_eh_reg_restore (rtx, rtx);
extern const char * output_isel (rtx *);
-extern int vrsave_operation (rtx, enum machine_mode);
extern int rs6000_register_move_cost (enum machine_mode,
- enum reg_class, enum reg_class);
+ enum reg_class, enum reg_class);
extern int rs6000_memory_move_cost (enum machine_mode, enum reg_class, int);
extern bool rs6000_tls_referenced_p (rtx);
-extern int rs6000_tls_symbol_ref (rtx, enum machine_mode);
-extern void rs6000_output_dwarf_dtprel (FILE*, int, rtx);
+extern int rs6000_hard_regno_nregs (int, enum machine_mode);
+extern void rs6000_conditional_register_usage (void);
/* Declare functions in rs6000-c.c */
@@ -211,4 +166,5 @@ extern void rs6000_cpu_cpp_builtins (struct cpp_reader *);
char *output_call (rtx, rtx *, int, int);
#endif
+extern bool rs6000_hard_regno_mode_ok_p[][FIRST_PSEUDO_REGISTER];
#endif /* rs6000-protos.h */
diff --git a/contrib/gcc/config/rs6000/rs6000.c b/contrib/gcc/config/rs6000/rs6000.c
index ea35843..5e9d0fe 100644
--- a/contrib/gcc/config/rs6000/rs6000.c
+++ b/contrib/gcc/config/rs6000/rs6000.c
@@ -1,6 +1,7 @@
/* Subroutines used for code generation on IBM RS/6000.
- Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -52,18 +53,21 @@
#include "reload.h"
#include "cfglayout.h"
#include "sched-int.h"
+#include "tree-gimple.h"
+#include "intl.h"
+#include "params.h"
+#include "tm-constrs.h"
#if TARGET_XCOFF
#include "xcoffout.h" /* get declarations of xcoff_*_section_name */
#endif
+#if TARGET_MACHO
+#include "gstab.h" /* for N_SLINE */
+#endif
#ifndef TARGET_NO_PROTOTYPE
#define TARGET_NO_PROTOTYPE 0
#endif
-#define EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
-#define EASY_VECTOR_15_ADD_SELF(n) ((n) >= 0x10 && (n) <= 0x1e \
- && !((n) & 1))
-
#define min(A,B) ((A) < (B) ? (A) : (B))
#define max(A,B) ((A) > (B) ? (A) : (B))
@@ -75,9 +79,10 @@ typedef struct rs6000_stack {
int lr_save_p; /* true if the link reg needs to be saved */
int cr_save_p; /* true if the CR reg needs to be saved */
unsigned int vrsave_mask; /* mask of vec registers to save */
- int toc_save_p; /* true if the TOC needs to be saved */
int push_p; /* true if we need to allocate stack space */
int calls_p; /* true if the function makes any calls */
+ int world_save_p; /* true if we're saving *everything*:
+ r13-r31, cr, f14-f31, vrsave, v20-v31 */
enum rs6000_abi abi; /* which ABI to use */
int gp_save_offset; /* offset to save GP regs from initial SP */
int fp_save_offset; /* offset to save FP regs from initial SP */
@@ -86,11 +91,9 @@ typedef struct rs6000_stack {
int cr_save_offset; /* offset to save CR from initial SP */
int vrsave_save_offset; /* offset to save VRSAVE from initial SP */
int spe_gp_save_offset; /* offset to save spe 64-bit gprs */
- 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 */
HOST_WIDE_INT vars_size; /* variable save area size */
int parm_size; /* outgoing parameter size */
int save_size; /* save area size */
@@ -99,17 +102,32 @@ typedef struct rs6000_stack {
int fp_size; /* size of saved FP registers */
int altivec_size; /* size of saved AltiVec registers */
int cr_size; /* size to hold CR if not in save_size */
- int lr_size; /* size to hold LR if not in save_size */
int vrsave_size; /* size to hold VRSAVE if not in save_size */
int altivec_padding_size; /* size of altivec alignment padding if
not in save_size */
int spe_gp_size; /* size of 64-bit GPR save size for SPE */
int spe_padding_size;
- int toc_size; /* size to hold TOC if not in save_size */
HOST_WIDE_INT total_size; /* total bytes allocated for stack */
int spe_64bit_regs_used;
} rs6000_stack_t;
+/* A C structure for machine-specific, per-function data.
+ This is added to the cfun structure. */
+typedef struct machine_function GTY(())
+{
+ /* Flags if __builtin_return_address (n) with n >= 1 was used. */
+ int ra_needs_full_frame;
+ /* Some local-dynamic symbol. */
+ const char *some_ld_name;
+ /* Whether the instruction chain has been scanned already. */
+ int insn_chain_scanned_p;
+ /* Flags if __builtin_return_address (0) was used. */
+ int ra_need_lr;
+ /* Offset from virtual_stack_vars_rtx to the start of the ABI_V4
+ varargs save area. */
+ HOST_WIDE_INT varargs_save_offset;
+} machine_function;
+
/* Target cpu type */
enum processor_type rs6000_cpu;
@@ -127,11 +145,6 @@ static GTY(()) bool rs6000_always_hint;
/* Schedule instructions for group formation. */
static GTY(()) bool rs6000_sched_groups;
-/* Support adjust_priority scheduler hook
- and -mprioritize-restricted-insns= option. */
-const char *rs6000_sched_restricted_insns_priority_str;
-int rs6000_sched_restricted_insns_priority;
-
/* Support for -msched-costly-dep option. */
const char *rs6000_sched_costly_dep_str;
enum rs6000_dependence_cost rs6000_sched_costly_dep;
@@ -140,39 +153,26 @@ enum rs6000_dependence_cost rs6000_sched_costly_dep;
const char *rs6000_sched_insert_nops_str;
enum rs6000_nop_insertion rs6000_sched_insert_nops;
-/* Size of long double */
-const char *rs6000_long_double_size_string;
-int rs6000_long_double_type_size;
+/* Support targetm.vectorize.builtin_mask_for_load. */
+static GTY(()) tree altivec_builtin_mask_for_load;
-/* Whether -mabi=altivec has appeared */
-int rs6000_altivec_abi;
+/* Size of long double. */
+int rs6000_long_double_type_size;
-/* Whether VRSAVE instructions should be generated. */
-int rs6000_altivec_vrsave;
+/* IEEE quad extended precision long double. */
+int rs6000_ieeequad;
-/* String from -mvrsave= option. */
-const char *rs6000_altivec_vrsave_string;
+/* Whether -mabi=altivec has appeared. */
+int rs6000_altivec_abi;
/* Nonzero if we want SPE ABI extensions. */
int rs6000_spe_abi;
-/* Whether isel instructions should be generated. */
-int rs6000_isel;
-
-/* Whether SPE simd instructions should be generated. */
-int rs6000_spe;
-
/* Nonzero if floating point operations are done in the GPRs. */
int rs6000_float_gprs = 0;
-/* String from -mfloat-gprs=. */
-const char *rs6000_float_gprs_string;
-
-/* String from -misel=. */
-const char *rs6000_isel_string;
-
-/* String from -mspe=. */
-const char *rs6000_spe_string;
+/* Nonzero if we want Darwin's struct-by-value-in-regs ABI. */
+int rs6000_darwin64_abi;
/* Set to nonzero once AIX common-mode calls have been defined. */
static GTY(()) int common_mode_defined;
@@ -207,32 +207,21 @@ const char *rs6000_tls_size_string;
/* ABI enumeration available for subtarget to use. */
enum rs6000_abi rs6000_current_abi;
-/* ABI string from -mabi= option. */
-const char *rs6000_abi_string;
+/* Whether to use variant of AIX ABI for PowerPC64 Linux. */
+int dot_symbols;
/* Debug flags */
const char *rs6000_debug_name;
int rs6000_debug_stack; /* debug stack applications */
int rs6000_debug_arg; /* debug argument handling */
-/* Opaque types. */
-static GTY(()) tree opaque_V2SI_type_node;
-static GTY(()) tree opaque_V2SF_type_node;
-static GTY(()) tree opaque_p_V2SI_type_node;
-
-/* AltiVec requires a few more basic types in addition to the vector
- types already defined in tree.c. */
-static GTY(()) tree bool_char_type_node; /* __bool char */
-static GTY(()) tree bool_short_type_node; /* __bool short */
-static GTY(()) tree bool_int_type_node; /* __bool int */
-static GTY(()) tree pixel_type_node; /* __pixel */
-static GTY(()) tree bool_V16QI_type_node; /* __vector __bool char */
-static GTY(()) tree bool_V8HI_type_node; /* __vector __bool short */
-static GTY(()) tree bool_V4SI_type_node; /* __vector __bool int */
-static GTY(()) tree pixel_V8HI_type_node; /* __vector __pixel */
-
-int rs6000_warn_altivec_long = 1; /* On by default. */
-const char *rs6000_warn_altivec_long_switch;
+/* Value is TRUE if register/mode pair is acceptable. */
+bool rs6000_hard_regno_mode_ok_p[NUM_MACHINE_MODES][FIRST_PSEUDO_REGISTER];
+
+/* Built in types. */
+
+tree rs6000_builtin_types[RS6000_BTI_MAX];
+tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
const char *rs6000_traceback_name;
static enum {
@@ -246,22 +235,28 @@ static enum {
int toc_initialized;
char toc_label_name[10];
-/* Alias set for saves and restores from the rs6000 stack. */
-static GTY(()) int rs6000_sr_alias_set;
-
-/* Call distance, overridden by -mlongcall and #pragma longcall(1).
- The only place that looks at this is rs6000_set_default_type_attributes;
- everywhere else should rely on the presence or absence of a longcall
- attribute on the function declaration. Exception: init_cumulative_args
- looks at it too, for libcalls. */
-int rs6000_default_long_calls;
-const char *rs6000_longcall_switch;
+static GTY(()) section *read_only_data_section;
+static GTY(()) section *private_data_section;
+static GTY(()) section *read_only_private_data_section;
+static GTY(()) section *sdata2_section;
+static GTY(()) section *toc_section;
/* Control alignment for fields within structures. */
/* String from -malign-XXXXX. */
-const char *rs6000_alignment_string;
int rs6000_alignment_flags;
+/* True for any options that were explicitly set. */
+struct {
+ bool aix_struct_ret; /* True if -maix-struct-ret was used. */
+ bool alignment; /* True if -malign- was used. */
+ bool abi; /* True if -mabi=spe/nospe was used. */
+ bool spe; /* True if -mspe= was used. */
+ bool float_gprs; /* True if -mfloat-gprs= was used. */
+ bool isel; /* True if -misel was used. */
+ bool long_double; /* True if -mlong-double- was used. */
+ bool ieee; /* True if -mabi=ieee/ibmlongdouble used. */
+} rs6000_explicit_options;
+
struct builtin_description
{
/* mask is not const because we're going to alter it below. This
@@ -272,10 +267,314 @@ struct builtin_description
const char *const name;
const enum rs6000_builtins code;
};
+
+/* Target cpu costs. */
+
+struct processor_costs {
+ const int mulsi; /* cost of SImode multiplication. */
+ const int mulsi_const; /* cost of SImode multiplication by constant. */
+ const int mulsi_const9; /* cost of SImode mult by short constant. */
+ const int muldi; /* cost of DImode multiplication. */
+ const int divsi; /* cost of SImode division. */
+ const int divdi; /* cost of DImode division. */
+ const int fp; /* cost of simple SFmode and DFmode insns. */
+ const int dmul; /* cost of DFmode multiplication (and fmadd). */
+ const int sdiv; /* cost of SFmode division (fdivs). */
+ const int ddiv; /* cost of DFmode division (fdiv). */
+};
+
+const struct processor_costs *rs6000_cost;
+
+/* Processor costs (relative to an add) */
+
+/* Instruction size costs on 32bit processors. */
+static const
+struct processor_costs size32_cost = {
+ COSTS_N_INSNS (1), /* mulsi */
+ COSTS_N_INSNS (1), /* mulsi_const */
+ COSTS_N_INSNS (1), /* mulsi_const9 */
+ COSTS_N_INSNS (1), /* muldi */
+ COSTS_N_INSNS (1), /* divsi */
+ COSTS_N_INSNS (1), /* divdi */
+ COSTS_N_INSNS (1), /* fp */
+ COSTS_N_INSNS (1), /* dmul */
+ COSTS_N_INSNS (1), /* sdiv */
+ COSTS_N_INSNS (1), /* ddiv */
+};
+
+/* Instruction size costs on 64bit processors. */
+static const
+struct processor_costs size64_cost = {
+ COSTS_N_INSNS (1), /* mulsi */
+ COSTS_N_INSNS (1), /* mulsi_const */
+ COSTS_N_INSNS (1), /* mulsi_const9 */
+ COSTS_N_INSNS (1), /* muldi */
+ COSTS_N_INSNS (1), /* divsi */
+ COSTS_N_INSNS (1), /* divdi */
+ COSTS_N_INSNS (1), /* fp */
+ COSTS_N_INSNS (1), /* dmul */
+ COSTS_N_INSNS (1), /* sdiv */
+ COSTS_N_INSNS (1), /* ddiv */
+};
+
+/* Instruction costs on RIOS1 processors. */
+static const
+struct processor_costs rios1_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (5), /* muldi */
+ COSTS_N_INSNS (19), /* divsi */
+ COSTS_N_INSNS (19), /* divdi */
+ COSTS_N_INSNS (2), /* fp */
+ COSTS_N_INSNS (2), /* dmul */
+ COSTS_N_INSNS (19), /* sdiv */
+ COSTS_N_INSNS (19), /* ddiv */
+};
+
+/* Instruction costs on RIOS2 processors. */
+static const
+struct processor_costs rios2_cost = {
+ COSTS_N_INSNS (2), /* mulsi */
+ COSTS_N_INSNS (2), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (2), /* muldi */
+ COSTS_N_INSNS (13), /* divsi */
+ COSTS_N_INSNS (13), /* divdi */
+ COSTS_N_INSNS (2), /* fp */
+ COSTS_N_INSNS (2), /* dmul */
+ COSTS_N_INSNS (17), /* sdiv */
+ COSTS_N_INSNS (17), /* ddiv */
+};
+
+/* Instruction costs on RS64A processors. */
+static const
+struct processor_costs rs64a_cost = {
+ COSTS_N_INSNS (20), /* mulsi */
+ COSTS_N_INSNS (12), /* mulsi_const */
+ COSTS_N_INSNS (8), /* mulsi_const9 */
+ COSTS_N_INSNS (34), /* muldi */
+ COSTS_N_INSNS (65), /* divsi */
+ COSTS_N_INSNS (67), /* divdi */
+ COSTS_N_INSNS (4), /* fp */
+ COSTS_N_INSNS (4), /* dmul */
+ COSTS_N_INSNS (31), /* sdiv */
+ COSTS_N_INSNS (31), /* ddiv */
+};
+
+/* Instruction costs on MPCCORE processors. */
+static const
+struct processor_costs mpccore_cost = {
+ COSTS_N_INSNS (2), /* mulsi */
+ COSTS_N_INSNS (2), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (2), /* muldi */
+ COSTS_N_INSNS (6), /* divsi */
+ COSTS_N_INSNS (6), /* divdi */
+ COSTS_N_INSNS (4), /* fp */
+ COSTS_N_INSNS (5), /* dmul */
+ COSTS_N_INSNS (10), /* sdiv */
+ COSTS_N_INSNS (17), /* ddiv */
+};
+
+/* Instruction costs on PPC403 processors. */
+static const
+struct processor_costs ppc403_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (4), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (33), /* divsi */
+ COSTS_N_INSNS (33), /* divdi */
+ COSTS_N_INSNS (11), /* fp */
+ COSTS_N_INSNS (11), /* dmul */
+ COSTS_N_INSNS (11), /* sdiv */
+ COSTS_N_INSNS (11), /* ddiv */
+};
+
+/* Instruction costs on PPC405 processors. */
+static const
+struct processor_costs ppc405_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (5), /* muldi */
+ COSTS_N_INSNS (35), /* divsi */
+ COSTS_N_INSNS (35), /* divdi */
+ COSTS_N_INSNS (11), /* fp */
+ COSTS_N_INSNS (11), /* dmul */
+ COSTS_N_INSNS (11), /* sdiv */
+ COSTS_N_INSNS (11), /* ddiv */
+};
+
+/* Instruction costs on PPC440 processors. */
+static const
+struct processor_costs ppc440_cost = {
+ COSTS_N_INSNS (3), /* mulsi */
+ COSTS_N_INSNS (2), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (3), /* muldi */
+ COSTS_N_INSNS (34), /* divsi */
+ COSTS_N_INSNS (34), /* divdi */
+ COSTS_N_INSNS (5), /* fp */
+ COSTS_N_INSNS (5), /* dmul */
+ COSTS_N_INSNS (19), /* sdiv */
+ COSTS_N_INSNS (33), /* ddiv */
+};
+
+/* Instruction costs on PPC601 processors. */
+static const
+struct processor_costs ppc601_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (5), /* mulsi_const */
+ COSTS_N_INSNS (5), /* mulsi_const9 */
+ COSTS_N_INSNS (5), /* muldi */
+ COSTS_N_INSNS (36), /* divsi */
+ COSTS_N_INSNS (36), /* divdi */
+ COSTS_N_INSNS (4), /* fp */
+ COSTS_N_INSNS (5), /* dmul */
+ COSTS_N_INSNS (17), /* sdiv */
+ COSTS_N_INSNS (31), /* ddiv */
+};
+
+/* Instruction costs on PPC603 processors. */
+static const
+struct processor_costs ppc603_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (3), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (5), /* muldi */
+ COSTS_N_INSNS (37), /* divsi */
+ COSTS_N_INSNS (37), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (4), /* dmul */
+ COSTS_N_INSNS (18), /* sdiv */
+ COSTS_N_INSNS (33), /* ddiv */
+};
+
+/* Instruction costs on PPC604 processors. */
+static const
+struct processor_costs ppc604_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (4), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (20), /* divsi */
+ COSTS_N_INSNS (20), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (18), /* sdiv */
+ COSTS_N_INSNS (32), /* ddiv */
+};
+
+/* Instruction costs on PPC604e processors. */
+static const
+struct processor_costs ppc604e_cost = {
+ COSTS_N_INSNS (2), /* mulsi */
+ COSTS_N_INSNS (2), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (2), /* muldi */
+ COSTS_N_INSNS (20), /* divsi */
+ COSTS_N_INSNS (20), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (18), /* sdiv */
+ COSTS_N_INSNS (32), /* ddiv */
+};
+
+/* Instruction costs on PPC620 processors. */
+static const
+struct processor_costs ppc620_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (7), /* muldi */
+ COSTS_N_INSNS (21), /* divsi */
+ COSTS_N_INSNS (37), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (18), /* sdiv */
+ COSTS_N_INSNS (32), /* ddiv */
+};
+
+/* Instruction costs on PPC630 processors. */
+static const
+struct processor_costs ppc630_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (7), /* muldi */
+ COSTS_N_INSNS (21), /* divsi */
+ COSTS_N_INSNS (37), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (17), /* sdiv */
+ COSTS_N_INSNS (21), /* ddiv */
+};
+
+/* Instruction costs on PPC750 and PPC7400 processors. */
+static const
+struct processor_costs ppc750_cost = {
+ COSTS_N_INSNS (5), /* mulsi */
+ COSTS_N_INSNS (3), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (5), /* muldi */
+ COSTS_N_INSNS (17), /* divsi */
+ COSTS_N_INSNS (17), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (17), /* sdiv */
+ COSTS_N_INSNS (31), /* ddiv */
+};
+
+/* Instruction costs on PPC7450 processors. */
+static const
+struct processor_costs ppc7450_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (3), /* mulsi_const */
+ COSTS_N_INSNS (3), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (23), /* divsi */
+ COSTS_N_INSNS (23), /* divdi */
+ COSTS_N_INSNS (5), /* fp */
+ COSTS_N_INSNS (5), /* dmul */
+ COSTS_N_INSNS (21), /* sdiv */
+ COSTS_N_INSNS (35), /* ddiv */
+};
+
+/* Instruction costs on PPC8540 processors. */
+static const
+struct processor_costs ppc8540_cost = {
+ COSTS_N_INSNS (4), /* mulsi */
+ COSTS_N_INSNS (4), /* mulsi_const */
+ COSTS_N_INSNS (4), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (19), /* divsi */
+ COSTS_N_INSNS (19), /* divdi */
+ COSTS_N_INSNS (4), /* fp */
+ COSTS_N_INSNS (4), /* dmul */
+ COSTS_N_INSNS (29), /* sdiv */
+ COSTS_N_INSNS (29), /* ddiv */
+};
+
+/* Instruction costs on POWER4 and POWER5 processors. */
+static const
+struct processor_costs power4_cost = {
+ COSTS_N_INSNS (3), /* mulsi */
+ COSTS_N_INSNS (2), /* mulsi_const */
+ COSTS_N_INSNS (2), /* mulsi_const9 */
+ COSTS_N_INSNS (4), /* muldi */
+ COSTS_N_INSNS (18), /* divsi */
+ COSTS_N_INSNS (34), /* divdi */
+ COSTS_N_INSNS (3), /* fp */
+ COSTS_N_INSNS (3), /* dmul */
+ COSTS_N_INSNS (17), /* sdiv */
+ COSTS_N_INSNS (17), /* ddiv */
+};
+
static bool rs6000_function_ok_for_sibcall (tree, tree);
-static int num_insns_constant_wide (HOST_WIDE_INT);
-static void validate_condition_mode (enum rtx_code, enum machine_mode);
+static const char *rs6000_invalid_within_doloop (rtx);
static rtx rs6000_generate_compare (enum rtx_code);
static void rs6000_maybe_dead (rtx);
static void rs6000_emit_stack_tie (void);
@@ -291,21 +590,21 @@ static unsigned toc_hash_function (const void *);
static int toc_hash_eq (const void *, const void *);
static int constant_pool_expr_1 (rtx, int *, int *);
static bool constant_pool_expr_p (rtx);
-static bool toc_relative_expr_p (rtx);
static bool legitimate_small_data_p (enum machine_mode, rtx);
-static bool legitimate_offset_address_p (enum machine_mode, rtx, int);
static bool legitimate_indexed_address_p (rtx, int);
-static bool legitimate_indirect_address_p (rtx, int);
-static bool macho_lo_sum_memory_operand (rtx x, enum machine_mode mode);
static bool legitimate_lo_sum_address_p (enum machine_mode, rtx, int);
static struct machine_function * rs6000_init_machine_status (void);
static bool rs6000_assemble_integer (rtx, unsigned int, int);
+static bool no_global_regs_above (int);
#ifdef HAVE_GAS_HIDDEN
static void rs6000_assemble_visibility (tree, int);
#endif
static int rs6000_ra_ever_killed (void);
static tree rs6000_handle_longcall_attribute (tree *, tree, tree, int, bool *);
static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *);
+static bool rs6000_ms_bitfield_layout_p (tree);
+static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *);
+static void rs6000_eliminate_indexed_memrefs (rtx operands[2]);
static const char *rs6000_mangle_fundamental_type (tree);
extern const struct attribute_spec rs6000_attribute_table[];
static void rs6000_set_default_type_attributes (tree);
@@ -317,34 +616,33 @@ static rtx rs6000_emit_set_long_const (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
static bool rs6000_return_in_memory (tree, tree);
static void rs6000_file_start (void);
#if TARGET_ELF
-static unsigned int rs6000_elf_section_type_flags (tree, const char *, int);
+static int rs6000_elf_reloc_rw_mask (void);
static void rs6000_elf_asm_out_constructor (rtx, int);
static void rs6000_elf_asm_out_destructor (rtx, int);
static void rs6000_elf_end_indicate_exec_stack (void) ATTRIBUTE_UNUSED;
-static void rs6000_elf_select_section (tree, int, unsigned HOST_WIDE_INT);
-static void rs6000_elf_unique_section (tree, int);
-static void rs6000_elf_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
+static void rs6000_elf_asm_init_sections (void);
+static section *rs6000_elf_select_rtx_section (enum machine_mode, rtx,
+ unsigned HOST_WIDE_INT);
static void rs6000_elf_encode_section_info (tree, rtx, int)
ATTRIBUTE_UNUSED;
-static bool rs6000_elf_in_small_data_p (tree);
#endif
+static bool rs6000_use_blocks_for_constant_p (enum machine_mode, rtx);
#if TARGET_XCOFF
+static void rs6000_xcoff_asm_output_anchor (rtx);
static void rs6000_xcoff_asm_globalize_label (FILE *, const char *);
-static void rs6000_xcoff_asm_named_section (const char *, unsigned int);
-static void rs6000_xcoff_select_section (tree, int, unsigned HOST_WIDE_INT);
-static void rs6000_xcoff_unique_section (tree, int);
-static void rs6000_xcoff_select_rtx_section (enum machine_mode, rtx,
+static void rs6000_xcoff_asm_init_sections (void);
+static int rs6000_xcoff_reloc_rw_mask (void);
+static void rs6000_xcoff_asm_named_section (const char *, unsigned int, tree);
+static section *rs6000_xcoff_select_section (tree, int,
unsigned HOST_WIDE_INT);
+static void rs6000_xcoff_unique_section (tree, int);
+static section *rs6000_xcoff_select_rtx_section
+ (enum machine_mode, rtx, unsigned HOST_WIDE_INT);
static const char * rs6000_xcoff_strip_name_encoding (const char *);
static unsigned int rs6000_xcoff_section_type_flags (tree, const char *, int);
static void rs6000_xcoff_file_start (void);
static void rs6000_xcoff_file_end (void);
#endif
-#if TARGET_MACHO
-static bool rs6000_binds_local_p (tree);
-#endif
-static int rs6000_use_dfa_pipeline_interface (void);
static int rs6000_variable_issue (FILE *, int, rtx, int);
static bool rs6000_rtx_costs (rtx, int, int, int *);
static int rs6000_adjust_cost (rtx, rtx, rtx, int);
@@ -363,7 +661,9 @@ static int redefine_groups (FILE *, int, rtx, rtx);
static int pad_groups (FILE *, int, rtx, rtx);
static void rs6000_sched_finish (FILE *, int);
static int rs6000_use_sched_lookahead (void);
+static tree rs6000_builtin_mask_for_load (void);
+static void def_builtin (int, const char *, tree, int);
static void rs6000_init_builtins (void);
static rtx rs6000_expand_unop_builtin (enum insn_code, tree, rtx);
static rtx rs6000_expand_binop_builtin (enum insn_code, tree, rtx);
@@ -376,6 +676,7 @@ static void rs6000_init_libfuncs (void);
static void enable_mask_for_builtins (struct builtin_description *, int,
enum rs6000_builtins,
enum rs6000_builtins);
+static tree build_opaque_vector_type (tree, int);
static void spe_init_builtins (void);
static rtx spe_expand_builtin (tree, rtx, bool *);
static rtx spe_expand_stv_builtin (enum insn_code, tree);
@@ -390,45 +691,78 @@ static rtx altivec_expand_ld_builtin (tree, rtx, bool *);
static rtx altivec_expand_st_builtin (tree, rtx, bool *);
static rtx altivec_expand_dst_builtin (tree, rtx, bool *);
static rtx altivec_expand_abs_builtin (enum insn_code, tree, rtx);
-static rtx altivec_expand_predicate_builtin (enum insn_code,
- const char *, tree, rtx);
+static rtx altivec_expand_predicate_builtin (enum insn_code,
+ const char *, tree, rtx);
static rtx altivec_expand_lv_builtin (enum insn_code, tree, rtx);
static rtx altivec_expand_stv_builtin (enum insn_code, tree);
-static void rs6000_parse_abi_options (void);
-static void rs6000_parse_alignment_option (void);
+static rtx altivec_expand_vec_init_builtin (tree, tree, rtx);
+static rtx altivec_expand_vec_set_builtin (tree);
+static rtx altivec_expand_vec_ext_builtin (tree, rtx);
+static int get_element_number (tree, tree);
+static bool rs6000_handle_option (size_t, const char *, int);
static void rs6000_parse_tls_size_option (void);
static void rs6000_parse_yes_no_option (const char *, const char *, int *);
static int first_altivec_reg_to_save (void);
static unsigned int compute_vrsave_mask (void);
+static void compute_save_world_info (rs6000_stack_t *info_ptr);
static void is_altivec_return_reg (rtx, void *);
static rtx generate_set_vrsave (rtx, rs6000_stack_t *, int);
int easy_vector_constant (rtx, enum machine_mode);
-static int easy_vector_same (rtx, enum machine_mode);
-static int easy_vector_splat_const (int, enum machine_mode);
-static bool is_ev64_opaque_type (tree);
+static bool rs6000_is_opaque_type (tree);
static rtx rs6000_dwarf_register_span (rtx);
static rtx rs6000_legitimize_tls_address (rtx, enum tls_model);
+static void rs6000_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
static rtx rs6000_tls_get_addr (void);
static rtx rs6000_got_sym (void);
-static inline int rs6000_tls_symbol_ref_1 (rtx *, void *);
+static int rs6000_tls_symbol_ref_1 (rtx *, void *);
static const char *rs6000_get_some_local_dynamic_name (void);
static int rs6000_get_some_local_dynamic_name_1 (rtx *, void *);
static rtx rs6000_complex_function_value (enum machine_mode);
static rtx rs6000_spe_function_arg (CUMULATIVE_ARGS *,
enum machine_mode, tree);
+static void rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *,
+ HOST_WIDE_INT);
+static void rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *,
+ tree, HOST_WIDE_INT);
+static void rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *,
+ HOST_WIDE_INT,
+ rtx[], int *);
+static void rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *,
+ tree, HOST_WIDE_INT,
+ rtx[], int *);
+static rtx rs6000_darwin64_record_arg (CUMULATIVE_ARGS *, tree, int, bool);
static rtx rs6000_mixed_function_arg (enum machine_mode, tree, int);
static void rs6000_move_block_from_reg (int regno, rtx x, int nregs);
static void setup_incoming_varargs (CUMULATIVE_ARGS *,
enum machine_mode, tree,
int *, int);
+static bool rs6000_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
+static int rs6000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
+ tree, bool);
+static const char *invalid_arg_for_unprototyped_fn (tree, tree, tree);
#if TARGET_MACHO
static void macho_branch_islands (void);
-static void add_compiler_branch_island (tree, tree, int);
static int no_previous_def (tree function_name);
static tree get_prev_label (tree function_name);
+static void rs6000_darwin_file_start (void);
#endif
static tree rs6000_build_builtin_va_list (void);
+static tree rs6000_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool rs6000_must_pass_in_stack (enum machine_mode, tree);
+static bool rs6000_scalar_mode_supported_p (enum machine_mode);
+static bool rs6000_vector_mode_supported_p (enum machine_mode);
+static int get_vec_cmp_insn (enum rtx_code, enum machine_mode,
+ enum machine_mode);
+static rtx rs6000_emit_vector_compare (enum rtx_code, rtx, rtx,
+ enum machine_mode);
+static int get_vsel_insn (enum machine_mode);
+static void rs6000_emit_vector_select (rtx, rtx, rtx, rtx);
+static tree rs6000_stack_protect_fail (void);
+
+const int INSN_NOT_AVAILABLE = -1;
+static enum machine_mode rs6000_eh_return_filter_mode (void);
/* Hash table stuff for keeping track of TOC entries. */
@@ -464,7 +798,9 @@ char rs6000_reg_names[][8] =
"24", "25", "26", "27", "28", "29", "30", "31",
"vrsave", "vscr",
/* SPE registers. */
- "spe_acc", "spefscr"
+ "spe_acc", "spefscr",
+ /* Soft frame pointer. */
+ "sfp"
};
#ifdef TARGET_REGNAMES
@@ -488,7 +824,9 @@ static const char alt_reg_names[][8] =
"%v24", "%v25", "%v26", "%v27", "%v28", "%v29", "%v30", "%v31",
"vrsave", "vscr",
/* SPE registers. */
- "spe_acc", "spefscr"
+ "spe_acc", "spefscr",
+ /* Soft frame pointer. */
+ "sfp"
};
#endif
@@ -501,10 +839,6 @@ static const char alt_reg_names[][8] =
/* The VRSAVE bitmask puts bit %v0 as the most significant bit. */
#define ALTIVEC_REG_BIT(REGNO) (0x80000000 >> ((REGNO) - FIRST_ALTIVEC_REGNO))
-
-/* Return 1 for a symbol ref for a thread-local storage symbol. */
-#define RS6000_SYMBOL_REF_TLS_P(RTX) \
- (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -533,6 +867,10 @@ static const char alt_reg_names[][8] =
#define TARGET_ASM_UNALIGNED_HI_OP "\t.short\t"
#undef TARGET_ASM_UNALIGNED_SI_OP
#define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
+#undef TARGET_ASM_UNALIGNED_DI_OP
+#define TARGET_ASM_UNALIGNED_DI_OP "\t.quad\t"
+#undef TARGET_ASM_ALIGNED_DI_OP
+#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
#endif
#endif
@@ -557,8 +895,6 @@ static const char alt_reg_names[][8] =
#undef TARGET_ASM_FUNCTION_EPILOGUE
#define TARGET_ASM_FUNCTION_EPILOGUE rs6000_output_function_epilogue
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE rs6000_use_dfa_pipeline_interface
#undef TARGET_SCHED_VARIABLE_ISSUE
#define TARGET_SCHED_VARIABLE_ISSUE rs6000_variable_issue
@@ -568,7 +904,7 @@ static const char alt_reg_names[][8] =
#define TARGET_SCHED_ADJUST_COST rs6000_adjust_cost
#undef TARGET_SCHED_ADJUST_PRIORITY
#define TARGET_SCHED_ADJUST_PRIORITY rs6000_adjust_priority
-#undef TARGET_SCHED_IS_COSTLY_DEPENDENCE
+#undef TARGET_SCHED_IS_COSTLY_DEPENDENCE
#define TARGET_SCHED_IS_COSTLY_DEPENDENCE rs6000_is_costly_dependence
#undef TARGET_SCHED_FINISH
#define TARGET_SCHED_FINISH rs6000_sched_finish
@@ -576,6 +912,9 @@ static const char alt_reg_names[][8] =
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD rs6000_use_sched_lookahead
+#undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
+#define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD rs6000_builtin_mask_for_load
+
#undef TARGET_INIT_BUILTINS
#define TARGET_INIT_BUILTINS rs6000_init_builtins
@@ -590,9 +929,12 @@ static const char alt_reg_names[][8] =
#if TARGET_MACHO
#undef TARGET_BINDS_LOCAL_P
-#define TARGET_BINDS_LOCAL_P rs6000_binds_local_p
+#define TARGET_BINDS_LOCAL_P darwin_binds_local_p
#endif
+#undef TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P rs6000_ms_bitfield_layout_p
+
#undef TARGET_ASM_OUTPUT_MI_THUNK
#define TARGET_ASM_OUTPUT_MI_THUNK rs6000_output_mi_thunk
@@ -602,13 +944,16 @@ static const char alt_reg_names[][8] =
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
#define TARGET_FUNCTION_OK_FOR_SIBCALL rs6000_function_ok_for_sibcall
+#undef TARGET_INVALID_WITHIN_DOLOOP
+#define TARGET_INVALID_WITHIN_DOLOOP rs6000_invalid_within_doloop
+
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS rs6000_rtx_costs
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST hook_int_rtx_0
#undef TARGET_VECTOR_OPAQUE_P
-#define TARGET_VECTOR_OPAQUE_P is_ev64_opaque_type
+#define TARGET_VECTOR_OPAQUE_P rs6000_is_opaque_type
#undef TARGET_DWARF_REGISTER_SPAN
#define TARGET_DWARF_REGISTER_SPAN rs6000_dwarf_register_span
@@ -620,10 +965,6 @@ static const char alt_reg_names[][8] =
#undef TARGET_PROMOTE_FUNCTION_RETURN
#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
-/* Structure return values are passed as an extra parameter. */
-#undef TARGET_STRUCT_VALUE_RTX
-#define TARGET_STRUCT_VALUE_RTX hook_rtx_tree_int_null
-
#undef TARGET_RETURN_IN_MEMORY
#define TARGET_RETURN_IN_MEMORY rs6000_return_in_memory
@@ -637,12 +978,134 @@ static const char alt_reg_names[][8] =
#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED hook_bool_CUMULATIVE_ARGS_true
#undef TARGET_SPLIT_COMPLEX_ARG
#define TARGET_SPLIT_COMPLEX_ARG hook_bool_tree_true
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK rs6000_must_pass_in_stack
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE rs6000_pass_by_reference
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES rs6000_arg_partial_bytes
#undef TARGET_BUILD_BUILTIN_VA_LIST
#define TARGET_BUILD_BUILTIN_VA_LIST rs6000_build_builtin_va_list
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR rs6000_gimplify_va_arg
+
+#undef TARGET_EH_RETURN_FILTER_MODE
+#define TARGET_EH_RETURN_FILTER_MODE rs6000_eh_return_filter_mode
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P rs6000_scalar_mode_supported_p
+
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P rs6000_vector_mode_supported_p
+
+#undef TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN
+#define TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN invalid_arg_for_unprototyped_fn
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION rs6000_handle_option
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS \
+ (TARGET_DEFAULT)
+
+#undef TARGET_STACK_PROTECT_FAIL
+#define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail
+
+/* MPC604EUM 3.5.2 Weak Consistency between Multiple Processors
+ The PowerPC architecture requires only weak consistency among
+ processors--that is, memory accesses between processors need not be
+ sequentially consistent and memory accesses among processors can occur
+ in any order. The ability to order memory accesses weakly provides
+ opportunities for more efficient use of the system bus. Unless a
+ dependency exists, the 604e allows read operations to precede store
+ operations. */
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING true
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL rs6000_output_dwarf_dtprel
+#endif
+
+/* Use a 32-bit anchor range. This leads to sequences like:
+
+ addis tmp,anchor,high
+ add dest,tmp,low
+
+ where tmp itself acts as an anchor, and can be shared between
+ accesses to the same 64k page. */
+#undef TARGET_MIN_ANCHOR_OFFSET
+#define TARGET_MIN_ANCHOR_OFFSET -0x7fffffff - 1
+#undef TARGET_MAX_ANCHOR_OFFSET
+#define TARGET_MAX_ANCHOR_OFFSET 0x7fffffff
+#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P
+#define TARGET_USE_BLOCKS_FOR_CONSTANT_P rs6000_use_blocks_for_constant_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
+
+/* Value is 1 if hard register REGNO can hold a value of machine-mode
+ MODE. */
+static int
+rs6000_hard_regno_mode_ok (int regno, enum machine_mode mode)
+{
+ /* The GPRs can hold any mode, but values bigger than one register
+ cannot go past R31. */
+ if (INT_REGNO_P (regno))
+ return INT_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1);
+
+ /* The float registers can only hold floating modes and DImode.
+ This also excludes decimal float modes. */
+ if (FP_REGNO_P (regno))
+ return
+ (SCALAR_FLOAT_MODE_P (mode)
+ && !DECIMAL_FLOAT_MODE_P (mode)
+ && FP_REGNO_P (regno + HARD_REGNO_NREGS (regno, mode) - 1))
+ || (GET_MODE_CLASS (mode) == MODE_INT
+ && GET_MODE_SIZE (mode) == UNITS_PER_FP_WORD);
+
+ /* The CR register can only hold CC modes. */
+ if (CR_REGNO_P (regno))
+ return GET_MODE_CLASS (mode) == MODE_CC;
+
+ if (XER_REGNO_P (regno))
+ return mode == PSImode;
+
+ /* AltiVec only in AldyVec registers. */
+ if (ALTIVEC_REGNO_P (regno))
+ return ALTIVEC_VECTOR_MODE (mode);
+
+ /* ...but GPRs can hold SIMD data on the SPE in one register. */
+ if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return 1;
+
+ /* We cannot put TImode anywhere except general register and it must be
+ able to fit within the register set. */
+
+ return GET_MODE_SIZE (mode) <= UNITS_PER_WORD;
+}
+
+/* Initialize rs6000_hard_regno_mode_ok_p table. */
+static void
+rs6000_init_hard_regno_mode_ok (void)
+{
+ int r, m;
+
+ for (r = 0; r < FIRST_PSEUDO_REGISTER; ++r)
+ for (m = 0; m < NUM_MACHINE_MODES; ++m)
+ if (rs6000_hard_regno_mode_ok (r, m))
+ rs6000_hard_regno_mode_ok_p[m][r] = true;
+}
+
+/* If not otherwise specified by a target, make 'long double' equivalent to
+ 'double'. */
+
+#ifndef RS6000_DEFAULT_LONG_DOUBLE_SIZE
+#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 64
+#endif
+
/* Override command line options. Mostly we process the processor
type and sometimes adjust other TARGET_ options. */
@@ -663,7 +1126,7 @@ rs6000_override_options (const char *default_cpu)
/* This table occasionally claims that a processor does not support
a particular feature even though it does, but the feature is slower
than the alternative. Thus, it shouldn't be relied on as a
- complete description of the processor's support.
+ complete description of the processor's support.
Please keep this list in order, and don't forget to update the
documentation in invoke.texi when adding a new processor or
@@ -677,10 +1140,14 @@ rs6000_override_options (const char *default_cpu)
= {{"401", PROCESSOR_PPC403, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"403", PROCESSOR_PPC403,
POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_STRICT_ALIGN},
- {"405", PROCESSOR_PPC405, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"405fp", PROCESSOR_PPC405, POWERPC_BASE_MASK},
- {"440", PROCESSOR_PPC440, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"440fp", PROCESSOR_PPC440, POWERPC_BASE_MASK},
+ {"405", PROCESSOR_PPC405,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+ {"405fp", PROCESSOR_PPC405,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
+ {"440", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_SOFT_FLOAT | MASK_MULHW | MASK_DLMZB},
+ {"440fp", PROCESSOR_PPC440,
+ POWERPC_BASE_MASK | MASK_MULHW | MASK_DLMZB},
{"505", PROCESSOR_MPCCORE, POWERPC_BASE_MASK},
{"601", PROCESSOR_PPC601,
MASK_POWER | POWERPC_BASE_MASK | MASK_MULTIPLE | MASK_STRING},
@@ -700,7 +1167,11 @@ rs6000_override_options (const char *default_cpu)
{"801", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"821", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"823", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
- {"8540", PROCESSOR_PPC8540, POWERPC_BASE_MASK | MASK_PPC_GFXOPT},
+ {"8540", PROCESSOR_PPC8540,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_STRICT_ALIGN},
+ /* 8548 has a dummy entry for now. */
+ {"8548", PROCESSOR_PPC8540,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_STRICT_ALIGN},
{"860", PROCESSOR_MPCCORE, POWERPC_BASE_MASK | MASK_SOFT_FLOAT},
{"970", PROCESSOR_POWER4,
POWERPC_7400_MASK | MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64},
@@ -718,17 +1189,25 @@ rs6000_override_options (const char *default_cpu)
{"power4", PROCESSOR_POWER4,
POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POWERPC64},
{"power5", PROCESSOR_POWER5,
- POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_MFCRF | MASK_POWERPC64},
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB},
+ {"power5+", PROCESSOR_POWER5,
+ POWERPC_BASE_MASK | MASK_POWERPC64 | MASK_PPC_GFXOPT
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND},
+ {"power6", PROCESSOR_POWER5,
+ POWERPC_7400_MASK | MASK_POWERPC64 | MASK_MFCRF | MASK_POPCNTB
+ | MASK_FPRND},
{"powerpc", PROCESSOR_POWERPC, POWERPC_BASE_MASK},
{"powerpc64", PROCESSOR_POWERPC64,
- POWERPC_BASE_MASK | MASK_POWERPC64},
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64},
{"rios", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
{"rios1", PROCESSOR_RIOS1, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
{"rios2", PROCESSOR_RIOS2,
MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING},
{"rsc", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
{"rsc1", PROCESSOR_PPC601, MASK_POWER | MASK_MULTIPLE | MASK_STRING},
- {"rs64a", PROCESSOR_RS64A, POWERPC_BASE_MASK | MASK_POWERPC64},
+ {"rs64", PROCESSOR_RS64A,
+ POWERPC_BASE_MASK | MASK_PPC_GFXOPT | MASK_POWERPC64}
};
const size_t ptt_size = ARRAY_SIZE (processor_target_table);
@@ -741,11 +1220,15 @@ rs6000_override_options (const char *default_cpu)
enum {
POWER_MASKS = MASK_POWER | MASK_POWER2 | MASK_MULTIPLE | MASK_STRING,
- POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT
+ POWERPC_MASKS = (POWERPC_BASE_MASK | MASK_PPC_GPOPT | MASK_STRICT_ALIGN
| MASK_PPC_GFXOPT | MASK_POWERPC64 | MASK_ALTIVEC
- | MASK_MFCRF)
+ | MASK_MFCRF | MASK_POPCNTB | MASK_FPRND | MASK_MULHW
+ | MASK_DLMZB)
};
- set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
+
+ rs6000_init_hard_regno_mode_ok ();
+
+ set_masks = POWER_MASKS | POWERPC_MASKS | MASK_SOFT_FLOAT;
#ifdef OS_MISSING_POWERPC64
if (OS_MISSING_POWERPC64)
set_masks &= ~MASK_POWERPC64;
@@ -807,14 +1290,14 @@ rs6000_override_options (const char *default_cpu)
{
target_flags &= ~MASK_MULTIPLE;
if ((target_flags_explicit & MASK_MULTIPLE) != 0)
- warning ("-mmultiple is not supported on little endian systems");
+ warning (0, "-mmultiple is not supported on little endian systems");
}
if (TARGET_STRING)
{
target_flags &= ~MASK_STRING;
if ((target_flags_explicit & MASK_STRING) != 0)
- warning ("-mstring is not supported on little endian systems");
+ warning (0, "-mstring is not supported on little endian systems");
}
}
@@ -840,44 +1323,40 @@ rs6000_override_options (const char *default_cpu)
else if (! strncmp (rs6000_traceback_name, "no", 2))
rs6000_traceback = traceback_none;
else
- error ("unknown -mtraceback arg `%s'; expecting `full', `partial' or `none'",
+ error ("unknown -mtraceback arg %qs; expecting %<full%>, %<partial%> or %<none%>",
rs6000_traceback_name);
}
- /* Set size of long double */
- rs6000_long_double_type_size = 64;
- if (rs6000_long_double_size_string)
- {
- char *tail;
- int size = strtol (rs6000_long_double_size_string, &tail, 10);
- if (*tail != '\0' || (size != 64 && size != 128))
- error ("Unknown switch -mlong-double-%s",
- rs6000_long_double_size_string);
- else
- rs6000_long_double_type_size = size;
- }
+ if (!rs6000_explicit_options.long_double)
+ rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+
+#ifndef POWERPC_LINUX
+ if (!rs6000_explicit_options.ieee)
+ rs6000_ieeequad = 1;
+#endif
/* Set Altivec ABI as default for powerpc64 linux. */
if (TARGET_ELF && TARGET_64BIT)
{
rs6000_altivec_abi = 1;
- rs6000_altivec_vrsave = 1;
+ TARGET_ALTIVEC_VRSAVE = 1;
}
- /* Handle -mabi= options. */
- rs6000_parse_abi_options ();
-
- /* Handle -malign-XXXXX option. */
- rs6000_parse_alignment_option ();
+ /* Set the Darwin64 ABI as default for 64-bit Darwin. */
+ if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
+ {
+ rs6000_darwin64_abi = 1;
+#if TARGET_MACHO
+ darwin_one_byte_bool = 1;
+#endif
+ /* Default to natural alignment, for better performance. */
+ rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+ }
- /* Handle generic -mFOO=YES/NO options. */
- rs6000_parse_yes_no_option ("vrsave", rs6000_altivec_vrsave_string,
- &rs6000_altivec_vrsave);
- rs6000_parse_yes_no_option ("isel", rs6000_isel_string,
- &rs6000_isel);
- rs6000_parse_yes_no_option ("spe", rs6000_spe_string, &rs6000_spe);
- rs6000_parse_yes_no_option ("float-gprs", rs6000_float_gprs_string,
- &rs6000_float_gprs);
+ /* Place FP constants in the constant pool instead of TOC
+ if section anchors enabled. */
+ if (flag_section_anchors)
+ TARGET_NO_FP_IN_TOC = 1;
/* Handle -mtls-size option. */
rs6000_parse_tls_size_option ();
@@ -888,37 +1367,35 @@ rs6000_override_options (const char *default_cpu)
#ifdef SUBSUBTARGET_OVERRIDE_OPTIONS
SUBSUBTARGET_OVERRIDE_OPTIONS;
#endif
+#ifdef SUB3TARGET_OVERRIDE_OPTIONS
+ SUB3TARGET_OVERRIDE_OPTIONS;
+#endif
if (TARGET_E500)
{
if (TARGET_ALTIVEC)
- error ("AltiVec and E500 instructions cannot coexist");
+ error ("AltiVec and E500 instructions cannot coexist");
/* The e500 does not have string instructions, and we set
MASK_STRING above when optimizing for size. */
if ((target_flags & MASK_STRING) != 0)
target_flags = target_flags & ~MASK_STRING;
-
- /* No SPE means 64-bit long doubles, even if an E500. */
- if (rs6000_spe_string != 0
- && !strcmp (rs6000_spe_string, "no"))
- rs6000_long_double_type_size = 64;
}
else if (rs6000_select[1].string != NULL)
{
/* For the powerpc-eabispe configuration, we set all these by
default, so let's unset them if we manually set another
CPU that is not the E500. */
- if (rs6000_abi_string == 0)
+ if (!rs6000_explicit_options.abi)
rs6000_spe_abi = 0;
- if (rs6000_spe_string == 0)
+ if (!rs6000_explicit_options.spe)
rs6000_spe = 0;
- if (rs6000_float_gprs_string == 0)
+ if (!rs6000_explicit_options.float_gprs)
rs6000_float_gprs = 0;
- if (rs6000_isel_string == 0)
+ if (!rs6000_explicit_options.isel)
rs6000_isel = 0;
- if (rs6000_long_double_size_string == 0)
- rs6000_long_double_type_size = 64;
+ if (!rs6000_explicit_options.long_double)
+ rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
}
rs6000_always_hint = (rs6000_cpu != PROCESSOR_POWER4
@@ -926,70 +1403,41 @@ rs6000_override_options (const char *default_cpu)
rs6000_sched_groups = (rs6000_cpu == PROCESSOR_POWER4
|| rs6000_cpu == PROCESSOR_POWER5);
- /* Handle -m(no-)longcall option. This is a bit of a cheap hack,
- using TARGET_OPTIONS to handle a toggle switch, but we're out of
- bits in target_flags so TARGET_SWITCHES cannot be used.
- Assumption here is that rs6000_longcall_switch points into the
- text of the complete option, rather than being a copy, so we can
- scan back for the presence or absence of the no- modifier. */
- if (rs6000_longcall_switch)
- {
- const char *base = rs6000_longcall_switch;
- while (base[-1] != 'm') base--;
-
- if (*rs6000_longcall_switch != '\0')
- error ("invalid option `%s'", base);
- rs6000_default_long_calls = (base[0] != 'n');
- }
-
- /* Handle -m(no-)warn-altivec-long similarly. */
- if (rs6000_warn_altivec_long_switch)
- {
- const char *base = rs6000_warn_altivec_long_switch;
- while (base[-1] != 'm') base--;
-
- if (*rs6000_warn_altivec_long_switch != '\0')
- error ("invalid option `%s'", base);
- rs6000_warn_altivec_long = (base[0] != 'n');
- }
-
- /* Handle -mprioritize-restricted-insns option. */
rs6000_sched_restricted_insns_priority
= (rs6000_sched_groups ? 1 : 0);
- if (rs6000_sched_restricted_insns_priority_str)
- rs6000_sched_restricted_insns_priority =
- atoi (rs6000_sched_restricted_insns_priority_str);
/* Handle -msched-costly-dep option. */
rs6000_sched_costly_dep
= (rs6000_sched_groups ? store_to_load_dep_costly : no_dep_costly);
+
if (rs6000_sched_costly_dep_str)
{
- if (! strcmp (rs6000_sched_costly_dep_str, "no"))
- rs6000_sched_costly_dep = no_dep_costly;
+ if (! strcmp (rs6000_sched_costly_dep_str, "no"))
+ rs6000_sched_costly_dep = no_dep_costly;
else if (! strcmp (rs6000_sched_costly_dep_str, "all"))
- rs6000_sched_costly_dep = all_deps_costly;
+ rs6000_sched_costly_dep = all_deps_costly;
else if (! strcmp (rs6000_sched_costly_dep_str, "true_store_to_load"))
- rs6000_sched_costly_dep = true_store_to_load_dep_costly;
+ rs6000_sched_costly_dep = true_store_to_load_dep_costly;
else if (! strcmp (rs6000_sched_costly_dep_str, "store_to_load"))
- rs6000_sched_costly_dep = store_to_load_dep_costly;
- else
- rs6000_sched_costly_dep = atoi (rs6000_sched_costly_dep_str);
+ rs6000_sched_costly_dep = store_to_load_dep_costly;
+ else
+ rs6000_sched_costly_dep = atoi (rs6000_sched_costly_dep_str);
}
/* Handle -minsert-sched-nops option. */
rs6000_sched_insert_nops
= (rs6000_sched_groups ? sched_finish_regroup_exact : sched_finish_none);
+
if (rs6000_sched_insert_nops_str)
{
if (! strcmp (rs6000_sched_insert_nops_str, "no"))
- rs6000_sched_insert_nops = sched_finish_none;
+ rs6000_sched_insert_nops = sched_finish_none;
else if (! strcmp (rs6000_sched_insert_nops_str, "pad"))
- rs6000_sched_insert_nops = sched_finish_pad_groups;
+ rs6000_sched_insert_nops = sched_finish_pad_groups;
else if (! strcmp (rs6000_sched_insert_nops_str, "regroup_exact"))
- rs6000_sched_insert_nops = sched_finish_regroup_exact;
+ rs6000_sched_insert_nops = sched_finish_regroup_exact;
else
- rs6000_sched_insert_nops = atoi (rs6000_sched_insert_nops_str);
+ rs6000_sched_insert_nops = atoi (rs6000_sched_insert_nops_str);
}
#ifdef TARGET_REGNAMES
@@ -999,25 +1447,16 @@ rs6000_override_options (const char *default_cpu)
memcpy (rs6000_reg_names, alt_reg_names, sizeof (rs6000_reg_names));
#endif
- /* Set TARGET_AIX_STRUCT_RET last, after the ABI is determined.
+ /* Set aix_struct_return last, after the ABI is determined.
If -maix-struct-return or -msvr4-struct-return was explicitly
used, don't override with the ABI default. */
- if ((target_flags_explicit & MASK_AIX_STRUCT_RET) == 0)
- {
- if (DEFAULT_ABI == ABI_V4 && !DRAFT_V4_STRUCT_RET)
- target_flags = (target_flags & ~MASK_AIX_STRUCT_RET);
- else
- target_flags |= MASK_AIX_STRUCT_RET;
- }
+ if (!rs6000_explicit_options.aix_struct_ret)
+ aix_struct_return = (DEFAULT_ABI != ABI_V4 || DRAFT_V4_STRUCT_RET);
- if (TARGET_LONG_DOUBLE_128
- && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN))
+ if (TARGET_LONG_DOUBLE_128 && !TARGET_IEEEQUAD)
REAL_MODE_FORMAT (TFmode) = &ibm_extended_format;
- /* Allocate an alias set for register saves & restores from stack. */
- rs6000_sr_alias_set = new_alias_set ();
-
- if (TARGET_TOC)
+ if (TARGET_TOC)
ASM_GENERATE_INTERNAL_LABEL (toc_label_name, "LCTOC", 1);
/* We can only guarantee the availability of DI pseudo-ops when
@@ -1028,9 +1467,23 @@ rs6000_override_options (const char *default_cpu)
targetm.asm_out.unaligned_op.di = NULL;
}
- /* Set maximum branch target alignment at two instructions, eight bytes. */
- align_jumps_max_skip = 8;
- align_loops_max_skip = 8;
+ /* Set branch target alignment, if not optimizing for size. */
+ if (!optimize_size)
+ {
+ if (rs6000_sched_groups)
+ {
+ if (align_functions <= 0)
+ align_functions = 16;
+ if (align_jumps <= 0)
+ align_jumps = 16;
+ if (align_loops <= 0)
+ align_loops = 16;
+ }
+ if (align_jumps_max_skip <= 0)
+ align_jumps_max_skip = 15;
+ if (align_loops_max_skip <= 0)
+ align_loops_max_skip = 15;
+ }
/* Arrange to save and restore machine status around nested functions. */
init_machine_status = rs6000_init_machine_status;
@@ -1039,6 +1492,96 @@ rs6000_override_options (const char *default_cpu)
Linux and Darwin ABIs at the moment. For now, only AIX is fixed. */
if (DEFAULT_ABI != ABI_AIX)
targetm.calls.split_complex_arg = NULL;
+
+ /* Initialize rs6000_cost with the appropriate target costs. */
+ if (optimize_size)
+ rs6000_cost = TARGET_POWERPC64 ? &size64_cost : &size32_cost;
+ else
+ switch (rs6000_cpu)
+ {
+ case PROCESSOR_RIOS1:
+ rs6000_cost = &rios1_cost;
+ break;
+
+ case PROCESSOR_RIOS2:
+ rs6000_cost = &rios2_cost;
+ break;
+
+ case PROCESSOR_RS64A:
+ rs6000_cost = &rs64a_cost;
+ break;
+
+ case PROCESSOR_MPCCORE:
+ rs6000_cost = &mpccore_cost;
+ break;
+
+ case PROCESSOR_PPC403:
+ rs6000_cost = &ppc403_cost;
+ break;
+
+ case PROCESSOR_PPC405:
+ rs6000_cost = &ppc405_cost;
+ break;
+
+ case PROCESSOR_PPC440:
+ rs6000_cost = &ppc440_cost;
+ break;
+
+ case PROCESSOR_PPC601:
+ rs6000_cost = &ppc601_cost;
+ break;
+
+ case PROCESSOR_PPC603:
+ rs6000_cost = &ppc603_cost;
+ break;
+
+ case PROCESSOR_PPC604:
+ rs6000_cost = &ppc604_cost;
+ break;
+
+ case PROCESSOR_PPC604e:
+ rs6000_cost = &ppc604e_cost;
+ break;
+
+ case PROCESSOR_PPC620:
+ rs6000_cost = &ppc620_cost;
+ break;
+
+ case PROCESSOR_PPC630:
+ rs6000_cost = &ppc630_cost;
+ break;
+
+ case PROCESSOR_PPC750:
+ case PROCESSOR_PPC7400:
+ rs6000_cost = &ppc750_cost;
+ break;
+
+ case PROCESSOR_PPC7450:
+ rs6000_cost = &ppc7450_cost;
+ break;
+
+ case PROCESSOR_PPC8540:
+ rs6000_cost = &ppc8540_cost;
+ break;
+
+ case PROCESSOR_POWER4:
+ case PROCESSOR_POWER5:
+ rs6000_cost = &power4_cost;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Implement targetm.vectorize.builtin_mask_for_load. */
+static tree
+rs6000_builtin_mask_for_load (void)
+{
+ if (TARGET_ALTIVEC)
+ return altivec_builtin_mask_for_load;
+ else
+ return 0;
}
/* Handle generic options of the form -mfoo=yes/no.
@@ -1059,48 +1602,6 @@ rs6000_parse_yes_no_option (const char *name, const char *value, int *flag)
error ("unknown -m%s= option specified: '%s'", name, value);
}
-/* Handle -mabi= options. */
-static void
-rs6000_parse_abi_options (void)
-{
- if (rs6000_abi_string == 0)
- return;
- else if (! strcmp (rs6000_abi_string, "altivec"))
- {
- rs6000_altivec_abi = 1;
- rs6000_spe_abi = 0;
- }
- else if (! strcmp (rs6000_abi_string, "no-altivec"))
- rs6000_altivec_abi = 0;
- else if (! strcmp (rs6000_abi_string, "spe"))
- {
- rs6000_spe_abi = 1;
- rs6000_altivec_abi = 0;
- if (!TARGET_SPE_ABI)
- error ("not configured for ABI: '%s'", rs6000_abi_string);
- }
-
- else if (! strcmp (rs6000_abi_string, "no-spe"))
- rs6000_spe_abi = 0;
- else
- error ("unknown ABI specified: '%s'", rs6000_abi_string);
-}
-
-/* Handle -malign-XXXXXX options. */
-static void
-rs6000_parse_alignment_option (void)
-{
- if (rs6000_alignment_string == 0)
- return;
- else if (! strcmp (rs6000_alignment_string, "power"))
- rs6000_alignment_flags = MASK_ALIGN_POWER;
- else if (! strcmp (rs6000_alignment_string, "natural"))
- rs6000_alignment_flags = MASK_ALIGN_NATURAL;
- else
- error ("unknown -malign-XXXXX option specified: '%s'",
- rs6000_alignment_string);
-}
-
/* Validate and record the size specified with the -mtls-size option. */
static void
@@ -1115,12 +1616,313 @@ rs6000_parse_tls_size_option (void)
else if (strcmp (rs6000_tls_size_string, "64") == 0)
rs6000_tls_size = 64;
else
- error ("bad value `%s' for -mtls-size switch", rs6000_tls_size_string);
+ error ("bad value %qs for -mtls-size switch", rs6000_tls_size_string);
}
void
optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
{
+ if (DEFAULT_ABI == ABI_DARWIN)
+ /* The Darwin libraries never set errno, so we might as well
+ avoid calling them when that's the only reason we would. */
+ flag_errno_math = 0;
+
+ /* Double growth factor to counter reduced min jump length. */
+ set_param_value ("max-grow-copy-bb-insns", 16);
+
+ /* Enable section anchors by default.
+ Skip section anchors for Objective C and Objective C++
+ until front-ends fixed. */
+ if (!TARGET_MACHO && lang_hooks.name[4] != 'O')
+ flag_section_anchors = 1;
+}
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+rs6000_handle_option (size_t code, const char *arg, int value)
+{
+ switch (code)
+ {
+ case OPT_mno_power:
+ target_flags &= ~(MASK_POWER | MASK_POWER2
+ | MASK_MULTIPLE | MASK_STRING);
+ target_flags_explicit |= (MASK_POWER | MASK_POWER2
+ | MASK_MULTIPLE | MASK_STRING);
+ break;
+ case OPT_mno_powerpc:
+ target_flags &= ~(MASK_POWERPC | MASK_PPC_GPOPT
+ | MASK_PPC_GFXOPT | MASK_POWERPC64);
+ target_flags_explicit |= (MASK_POWERPC | MASK_PPC_GPOPT
+ | MASK_PPC_GFXOPT | MASK_POWERPC64);
+ break;
+ case OPT_mfull_toc:
+ target_flags &= ~MASK_MINIMAL_TOC;
+ TARGET_NO_FP_IN_TOC = 0;
+ TARGET_NO_SUM_IN_TOC = 0;
+ target_flags_explicit |= MASK_MINIMAL_TOC;
+#ifdef TARGET_USES_SYSV4_OPT
+ /* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be
+ just the same as -mminimal-toc. */
+ target_flags |= MASK_MINIMAL_TOC;
+ target_flags_explicit |= MASK_MINIMAL_TOC;
+#endif
+ break;
+
+#ifdef TARGET_USES_SYSV4_OPT
+ case OPT_mtoc:
+ /* Make -mtoc behave like -mminimal-toc. */
+ target_flags |= MASK_MINIMAL_TOC;
+ target_flags_explicit |= MASK_MINIMAL_TOC;
+ break;
+#endif
+
+#ifdef TARGET_USES_AIX64_OPT
+ case OPT_maix64:
+#else
+ case OPT_m64:
+#endif
+ target_flags |= MASK_POWERPC64 | MASK_POWERPC;
+ target_flags |= ~target_flags_explicit & MASK_PPC_GFXOPT;
+ target_flags_explicit |= MASK_POWERPC64 | MASK_POWERPC;
+ break;
+
+#ifdef TARGET_USES_AIX64_OPT
+ case OPT_maix32:
+#else
+ case OPT_m32:
+#endif
+ target_flags &= ~MASK_POWERPC64;
+ target_flags_explicit |= MASK_POWERPC64;
+ break;
+
+ case OPT_minsert_sched_nops_:
+ rs6000_sched_insert_nops_str = arg;
+ break;
+
+ case OPT_mminimal_toc:
+ if (value == 1)
+ {
+ TARGET_NO_FP_IN_TOC = 0;
+ TARGET_NO_SUM_IN_TOC = 0;
+ }
+ break;
+
+ case OPT_mpower:
+ if (value == 1)
+ {
+ target_flags |= (MASK_MULTIPLE | MASK_STRING);
+ target_flags_explicit |= (MASK_MULTIPLE | MASK_STRING);
+ }
+ break;
+
+ case OPT_mpower2:
+ if (value == 1)
+ {
+ target_flags |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
+ target_flags_explicit |= (MASK_POWER | MASK_MULTIPLE | MASK_STRING);
+ }
+ break;
+
+ case OPT_mpowerpc_gpopt:
+ case OPT_mpowerpc_gfxopt:
+ if (value == 1)
+ {
+ target_flags |= MASK_POWERPC;
+ target_flags_explicit |= MASK_POWERPC;
+ }
+ break;
+
+ case OPT_maix_struct_return:
+ case OPT_msvr4_struct_return:
+ rs6000_explicit_options.aix_struct_ret = true;
+ break;
+
+ case OPT_mvrsave_:
+ rs6000_parse_yes_no_option ("vrsave", arg, &(TARGET_ALTIVEC_VRSAVE));
+ break;
+
+ case OPT_misel_:
+ rs6000_explicit_options.isel = true;
+ rs6000_parse_yes_no_option ("isel", arg, &(rs6000_isel));
+ break;
+
+ case OPT_mspe_:
+ rs6000_explicit_options.spe = true;
+ rs6000_parse_yes_no_option ("spe", arg, &(rs6000_spe));
+ /* No SPE means 64-bit long doubles, even if an E500. */
+ if (!rs6000_spe)
+ rs6000_long_double_type_size = 64;
+ break;
+
+ case OPT_mdebug_:
+ rs6000_debug_name = arg;
+ break;
+
+#ifdef TARGET_USES_SYSV4_OPT
+ case OPT_mcall_:
+ rs6000_abi_name = arg;
+ break;
+
+ case OPT_msdata_:
+ rs6000_sdata_name = arg;
+ break;
+
+ case OPT_mtls_size_:
+ rs6000_tls_size_string = arg;
+ break;
+
+ case OPT_mrelocatable:
+ if (value == 1)
+ {
+ target_flags |= MASK_MINIMAL_TOC;
+ target_flags_explicit |= MASK_MINIMAL_TOC;
+ TARGET_NO_FP_IN_TOC = 1;
+ }
+ break;
+
+ case OPT_mrelocatable_lib:
+ if (value == 1)
+ {
+ target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
+ target_flags_explicit |= MASK_RELOCATABLE | MASK_MINIMAL_TOC;
+ TARGET_NO_FP_IN_TOC = 1;
+ }
+ else
+ {
+ target_flags &= ~MASK_RELOCATABLE;
+ target_flags_explicit |= MASK_RELOCATABLE;
+ }
+ break;
+#endif
+
+ case OPT_mabi_:
+ if (!strcmp (arg, "altivec"))
+ {
+ rs6000_explicit_options.abi = true;
+ rs6000_altivec_abi = 1;
+ rs6000_spe_abi = 0;
+ }
+ else if (! strcmp (arg, "no-altivec"))
+ {
+ /* ??? Don't set rs6000_explicit_options.abi here, to allow
+ the default for rs6000_spe_abi to be chosen later. */
+ rs6000_altivec_abi = 0;
+ }
+ else if (! strcmp (arg, "spe"))
+ {
+ rs6000_explicit_options.abi = true;
+ rs6000_spe_abi = 1;
+ rs6000_altivec_abi = 0;
+ if (!TARGET_SPE_ABI)
+ error ("not configured for ABI: '%s'", arg);
+ }
+ else if (! strcmp (arg, "no-spe"))
+ {
+ rs6000_explicit_options.abi = true;
+ rs6000_spe_abi = 0;
+ }
+
+ /* These are here for testing during development only, do not
+ document in the manual please. */
+ else if (! strcmp (arg, "d64"))
+ {
+ rs6000_darwin64_abi = 1;
+ warning (0, "Using darwin64 ABI");
+ }
+ else if (! strcmp (arg, "d32"))
+ {
+ rs6000_darwin64_abi = 0;
+ warning (0, "Using old darwin ABI");
+ }
+
+ else if (! strcmp (arg, "ibmlongdouble"))
+ {
+ rs6000_explicit_options.ieee = true;
+ rs6000_ieeequad = 0;
+ warning (0, "Using IBM extended precision long double");
+ }
+ else if (! strcmp (arg, "ieeelongdouble"))
+ {
+ rs6000_explicit_options.ieee = true;
+ rs6000_ieeequad = 1;
+ warning (0, "Using IEEE extended precision long double");
+ }
+
+ else
+ {
+ error ("unknown ABI specified: '%s'", arg);
+ return false;
+ }
+ break;
+
+ case OPT_mcpu_:
+ rs6000_select[1].string = arg;
+ break;
+
+ case OPT_mtune_:
+ rs6000_select[2].string = arg;
+ break;
+
+ case OPT_mtraceback_:
+ rs6000_traceback_name = arg;
+ break;
+
+ case OPT_mfloat_gprs_:
+ rs6000_explicit_options.float_gprs = true;
+ if (! strcmp (arg, "yes") || ! strcmp (arg, "single"))
+ rs6000_float_gprs = 1;
+ else if (! strcmp (arg, "double"))
+ rs6000_float_gprs = 2;
+ else if (! strcmp (arg, "no"))
+ rs6000_float_gprs = 0;
+ else
+ {
+ error ("invalid option for -mfloat-gprs: '%s'", arg);
+ return false;
+ }
+ break;
+
+ case OPT_mlong_double_:
+ rs6000_explicit_options.long_double = true;
+ rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+ if (value != 64 && value != 128)
+ {
+ error ("Unknown switch -mlong-double-%s", arg);
+ rs6000_long_double_type_size = RS6000_DEFAULT_LONG_DOUBLE_SIZE;
+ return false;
+ }
+ else
+ rs6000_long_double_type_size = value;
+ break;
+
+ case OPT_msched_costly_dep_:
+ rs6000_sched_costly_dep_str = arg;
+ break;
+
+ case OPT_malign_:
+ rs6000_explicit_options.alignment = true;
+ if (! strcmp (arg, "power"))
+ {
+ /* On 64-bit Darwin, power alignment is ABI-incompatible with
+ some C library functions, so warn about it. The flag may be
+ useful for performance studies from time to time though, so
+ don't disable it entirely. */
+ if (DEFAULT_ABI == ABI_DARWIN && TARGET_64BIT)
+ warning (0, "-malign-power is not supported for 64-bit Darwin;"
+ " it is incompatible with the installed C and C++ libraries");
+ rs6000_alignment_flags = MASK_ALIGN_POWER;
+ }
+ else if (! strcmp (arg, "natural"))
+ rs6000_alignment_flags = MASK_ALIGN_NATURAL;
+ else
+ {
+ error ("unknown -malign-XXXXX option specified: '%s'", arg);
+ return false;
+ }
+ break;
+ }
+ return true;
}
/* Do anything needed at the start of the asm file. */
@@ -1157,6 +1959,12 @@ rs6000_file_start (void)
}
}
+ if (PPC405_ERRATUM77)
+ {
+ fprintf (file, "%s PPC405CR_ERRATUM77", start);
+ start = "";
+ }
+
#ifdef USING_ELFOS_H
switch (rs6000_sdata)
{
@@ -1177,7 +1985,14 @@ rs6000_file_start (void)
if (*start == '\0')
putc ('\n', file);
}
+
+ if (DEFAULT_ABI == ABI_AIX || (TARGET_ELF && flag_pic == 2))
+ {
+ switch_to_section (toc_section);
+ switch_to_section (text_section);
+ }
}
+
/* Return nonzero if this function is known to have a null epilogue. */
@@ -1201,310 +2016,19 @@ direct_return (void)
return 0;
}
-/* Returns 1 always. */
-
-int
-any_operand (rtx op ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return 1;
-}
-
-/* Returns 1 if op is the count register. */
-int
-count_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != REG)
- return 0;
-
- if (REGNO (op) == COUNT_REGISTER_REGNUM)
- return 1;
-
- if (REGNO (op) > FIRST_PSEUDO_REGISTER)
- return 1;
-
- return 0;
-}
-
-/* Returns 1 if op is an altivec register. */
-int
-altivec_register_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) > FIRST_PSEUDO_REGISTER
- || ALTIVEC_REGNO_P (REGNO (op))));
-}
-
-int
-xer_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != REG)
- return 0;
-
- if (XER_REGNO_P (REGNO (op)))
- return 1;
-
- return 0;
-}
-
-/* Return 1 if OP is a signed 8-bit constant. Int multiplication
- by such constants completes more quickly. */
-
-int
-s8bit_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ( GET_CODE (op) == CONST_INT
- && (INTVAL (op) >= -128 && INTVAL (op) <= 127));
-}
-
-/* Return 1 if OP is a constant that can fit in a D field. */
-
-int
-short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op), 'I'));
-}
-
-/* Similar for an unsigned D field. */
-
-int
-u_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_LETTER_P (INTVAL (op) & GET_MODE_MASK (mode), 'K'));
-}
-
-/* Return 1 if OP is a CONST_INT that cannot fit in a signed D field. */
-
-int
-non_short_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x8000) >= 0x10000);
-}
-
-/* Returns 1 if OP is a CONST_INT that is a positive value
- and an exact power of 2. */
-
-int
-exact_log2_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && INTVAL (op) > 0
- && exact_log2 (INTVAL (op)) >= 0);
-}
-
-/* Returns 1 if OP is a register that is not special (i.e., not MQ,
- ctr, or lr). */
-
-int
-gpc_reg_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || (REGNO (op) >= ARG_POINTER_REGNUM
- && !XER_REGNO_P (REGNO (op)))
- || REGNO (op) < MQ_REGNO));
-}
-
-/* Returns 1 if OP is either a pseudo-register or a register denoting a
- CR field. */
-
-int
-cc_reg_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) >= FIRST_PSEUDO_REGISTER
- || CR_REGNO_P (REGNO (op))));
-}
-
-/* Returns 1 if OP is either a pseudo-register or a register denoting a
- CR field that isn't CR0. */
-
-int
-cc_reg_not_cr0_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- && (GET_CODE (op) != REG
- || REGNO (op) >= FIRST_PSEUDO_REGISTER
- || CR_REGNO_NOT_CR0_P (REGNO (op))));
-}
-
-/* Returns 1 if OP is either a constant integer valid for a D-field or
- a non-special register. If a register, it must be in the proper
- mode unless MODE is VOIDmode. */
-
-int
-reg_or_short_operand (rtx op, enum machine_mode mode)
-{
- return short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
-}
-
-/* Similar, except check if the negation of the constant would be
- valid for a D-field. Don't allow a constant zero, since all the
- patterns that call this predicate use "addic r1,r2,-constant" on
- a constant value to set a carry when r2 is greater or equal to
- "constant". That doesn't work for zero. */
-
-int
-reg_or_neg_short_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- return CONST_OK_FOR_LETTER_P (INTVAL (op), 'P') && INTVAL (op) != 0;
-
- return gpc_reg_operand (op, mode);
-}
-
-/* Returns 1 if OP is either a constant integer valid for a DS-field or
- a non-special register. If a register, it must be in the proper
- mode unless MODE is VOIDmode. */
-
-int
-reg_or_aligned_short_operand (rtx op, enum machine_mode mode)
-{
- if (gpc_reg_operand (op, mode))
- return 1;
- else if (short_cint_operand (op, mode) && !(INTVAL (op) & 3))
- return 1;
-
- return 0;
-}
-
-
-/* Return 1 if the operand is either a register or an integer whose
- high-order 16 bits are zero. */
-
-int
-reg_or_u_short_operand (rtx op, enum machine_mode mode)
-{
- return u_short_cint_operand (op, mode) || gpc_reg_operand (op, mode);
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- constant integer. */
-
-int
-reg_or_cint_operand (rtx op, enum machine_mode mode)
-{
- return (GET_CODE (op) == CONST_INT || gpc_reg_operand (op, mode));
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- 32-bit signed constant integer. */
-
-int
-reg_or_arith_cint_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT != 32
- && ((unsigned HOST_WIDE_INT) (INTVAL (op) + 0x80000000)
- < (unsigned HOST_WIDE_INT) 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 (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT == 32
- && INTVAL (op) < 0x7fff8000
-#else
- && ((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 (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || (GET_CODE (op) == CONST_INT
-#if HOST_BITS_PER_WIDE_INT == 32
- && (- INTVAL (op)) < 0x7fff8000
-#else
- && ((unsigned HOST_WIDE_INT) ((- INTVAL (op)) + 0x80008000)
- < 0x100000000ll)
-#endif
- ));
-}
-
-/* Return 1 is the operand is either a non-special register or ANY
- 32-bit unsigned constant integer. */
-
-int
-reg_or_logical_cint_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- {
- if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT)
- {
- if (GET_MODE_BITSIZE (mode) <= 32)
- abort ();
-
- if (INTVAL (op) < 0)
- return 0;
- }
-
- return ((INTVAL (op) & GET_MODE_MASK (mode)
- & (~ (unsigned HOST_WIDE_INT) 0xffffffff)) == 0);
- }
- else if (GET_CODE (op) == CONST_DOUBLE)
- {
- if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
- || mode != DImode)
- abort ();
-
- return CONST_DOUBLE_HIGH (op) == 0;
- }
- else
- return gpc_reg_operand (op, mode);
-}
-
-/* Return 1 if the operand is an operand that can be loaded via the GOT. */
-
-int
-got_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF
- || GET_CODE (op) == CONST
- || GET_CODE (op) == LABEL_REF);
-}
-
-/* Return 1 if the operand is a simple references that can be loaded via
- the GOT (labels involving addition aren't allowed). */
-
-int
-got_no_const_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF);
-}
-
/* Return the number of instructions it takes to form a constant in an
integer register. */
-static int
+int
num_insns_constant_wide (HOST_WIDE_INT value)
{
/* signed constant loadable with {cal|addi} */
- if (CONST_OK_FOR_LETTER_P (value, 'I'))
+ if ((unsigned HOST_WIDE_INT) (value + 0x8000) < 0x10000)
return 1;
/* constant loadable with {cau|addis} */
- else if (CONST_OK_FOR_LETTER_P (value, 'L'))
+ else if ((value & 0xffff) == 0
+ && (value >> 31 == -1 || value >> 31 == 0))
return 1;
#if HOST_BITS_PER_WIDE_INT == 64
@@ -1533,285 +2057,228 @@ num_insns_constant_wide (HOST_WIDE_INT value)
int
num_insns_constant (rtx op, enum machine_mode mode)
{
- if (GET_CODE (op) == CONST_INT)
+ HOST_WIDE_INT low, high;
+
+ switch (GET_CODE (op))
{
+ case CONST_INT:
#if HOST_BITS_PER_WIDE_INT == 64
if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1
&& mask64_operand (op, mode))
- return 2;
+ return 2;
else
#endif
return num_insns_constant_wide (INTVAL (op));
- }
-
- else if (GET_CODE (op) == CONST_DOUBLE && mode == SFmode)
- {
- long l;
- REAL_VALUE_TYPE rv;
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_SINGLE (rv, l);
- return num_insns_constant_wide ((HOST_WIDE_INT) l);
- }
+ case CONST_DOUBLE:
+ if (mode == SFmode)
+ {
+ long l;
+ REAL_VALUE_TYPE rv;
- else if (GET_CODE (op) == CONST_DOUBLE)
- {
- HOST_WIDE_INT low;
- HOST_WIDE_INT high;
- long l[2];
- REAL_VALUE_TYPE rv;
- int endian = (WORDS_BIG_ENDIAN == 0);
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ return num_insns_constant_wide ((HOST_WIDE_INT) l);
+ }
- if (mode == VOIDmode || mode == DImode)
- {
- high = CONST_DOUBLE_HIGH (op);
- low = CONST_DOUBLE_LOW (op);
- }
- else
- {
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
- high = l[endian];
- low = l[1 - endian];
- }
+ if (mode == VOIDmode || mode == DImode)
+ {
+ high = CONST_DOUBLE_HIGH (op);
+ low = CONST_DOUBLE_LOW (op);
+ }
+ else
+ {
+ long l[2];
+ REAL_VALUE_TYPE rv;
- if (TARGET_32BIT)
- return (num_insns_constant_wide (low)
- + num_insns_constant_wide (high));
+ REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
+ high = l[WORDS_BIG_ENDIAN == 0];
+ low = l[WORDS_BIG_ENDIAN != 0];
+ }
- else
- {
- if (high == 0 && low >= 0)
- return num_insns_constant_wide (low);
+ if (TARGET_32BIT)
+ return (num_insns_constant_wide (low)
+ + num_insns_constant_wide (high));
+ else
+ {
+ if ((high == 0 && low >= 0)
+ || (high == -1 && low < 0))
+ return num_insns_constant_wide (low);
- else if (high == -1 && low < 0)
- return num_insns_constant_wide (low);
+ else if (mask64_operand (op, mode))
+ return 2;
- else if (mask64_operand (op, mode))
- return 2;
+ else if (low == 0)
+ return num_insns_constant_wide (high) + 1;
- else if (low == 0)
- return num_insns_constant_wide (high) + 1;
+ else
+ return (num_insns_constant_wide (high)
+ + num_insns_constant_wide (low) + 1);
+ }
- else
- return (num_insns_constant_wide (high)
- + num_insns_constant_wide (low) + 1);
- }
+ default:
+ gcc_unreachable ();
}
-
- else
- abort ();
}
-/* Return 1 if the operand is a CONST_DOUBLE and it can be put into a
- register with one instruction per word. We only do this if we can
- safely read CONST_DOUBLE_{LOW,HIGH}. */
+/* Interpret element ELT of the CONST_VECTOR OP as an integer value.
+ If the mode of OP is MODE_VECTOR_INT, this simply returns the
+ corresponding element of the vector, but for V4SFmode and V2SFmode,
+ the corresponding "float" is interpreted as an SImode integer. */
-int
-easy_fp_constant (rtx op, enum machine_mode mode)
+static HOST_WIDE_INT
+const_vector_elt_as_int (rtx op, unsigned int elt)
{
- if (GET_CODE (op) != CONST_DOUBLE
- || GET_MODE (op) != mode
- || (GET_MODE_CLASS (mode) != MODE_FLOAT && mode != DImode))
- return 0;
-
- /* Consider all constants with -msoft-float to be easy. */
- if ((TARGET_SOFT_FLOAT || !TARGET_FPRS)
- && mode != DImode)
- return 1;
-
- /* If we are using V.4 style PIC, consider all constants to be hard. */
- if (flag_pic && DEFAULT_ABI == ABI_V4)
- return 0;
+ rtx tmp = CONST_VECTOR_ELT (op, elt);
+ if (GET_MODE (op) == V4SFmode
+ || GET_MODE (op) == V2SFmode)
+ tmp = gen_lowpart (SImode, tmp);
+ return INTVAL (tmp);
+}
-#ifdef TARGET_RELOCATABLE
- /* Similarly if we are using -mrelocatable, consider all constants
- to be hard. */
- if (TARGET_RELOCATABLE)
- return 0;
-#endif
+/* Return true if OP can be synthesized with a particular vspltisb, vspltish
+ or vspltisw instruction. OP is a CONST_VECTOR. Which instruction is used
+ depends on STEP and COPIES, one of which will be 1. If COPIES > 1,
+ all items are set to the same value and contain COPIES replicas of the
+ vsplt's operand; if STEP > 1, one in STEP elements is set to the vsplt's
+ operand and the others are set to the value of the operand's msb. */
- if (mode == TFmode)
- {
- long k[4];
- REAL_VALUE_TYPE rv;
+static bool
+vspltis_constant (rtx op, unsigned step, unsigned copies)
+{
+ enum machine_mode mode = GET_MODE (op);
+ enum machine_mode inner = GET_MODE_INNER (mode);
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+ unsigned i;
+ unsigned nunits = GET_MODE_NUNITS (mode);
+ unsigned bitsize = GET_MODE_BITSIZE (inner);
+ unsigned mask = GET_MODE_MASK (inner);
- return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[2]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[3]) == 1);
- }
+ HOST_WIDE_INT val = const_vector_elt_as_int (op, nunits - 1);
+ HOST_WIDE_INT splat_val = val;
+ HOST_WIDE_INT msb_val = val > 0 ? 0 : -1;
- else if (mode == DFmode)
+ /* Construct the value to be splatted, if possible. If not, return 0. */
+ for (i = 2; i <= copies; i *= 2)
{
- long k[2];
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
-
- return (num_insns_constant_wide ((HOST_WIDE_INT) k[0]) == 1
- && num_insns_constant_wide ((HOST_WIDE_INT) k[1]) == 1);
+ HOST_WIDE_INT small_val;
+ bitsize /= 2;
+ small_val = splat_val >> bitsize;
+ mask >>= bitsize;
+ if (splat_val != ((small_val << bitsize) | (small_val & mask)))
+ return false;
+ splat_val = small_val;
}
- else if (mode == SFmode)
- {
- long l;
- REAL_VALUE_TYPE rv;
-
- REAL_VALUE_FROM_CONST_DOUBLE (rv, op);
- REAL_VALUE_TO_TARGET_SINGLE (rv, l);
-
- return num_insns_constant_wide (l) == 1;
- }
+ /* Check if SPLAT_VAL can really be the operand of a vspltis[bhw]. */
+ if (EASY_VECTOR_15 (splat_val))
+ ;
- else if (mode == DImode)
- return ((TARGET_POWERPC64
- && GET_CODE (op) == CONST_DOUBLE && CONST_DOUBLE_LOW (op) == 0)
- || (num_insns_constant (op, DImode) <= 2));
+ /* Also check if we can splat, and then add the result to itself. Do so if
+ the value is positive, of if the splat instruction is using OP's mode;
+ for splat_val < 0, the splat and the add should use the same mode. */
+ else if (EASY_VECTOR_15_ADD_SELF (splat_val)
+ && (splat_val >= 0 || (step == 1 && copies == 1)))
+ ;
- else if (mode == SImode)
- return 1;
else
- abort ();
-}
-
-/* Returns the constant for the splat instrunction, if exists. */
+ return false;
-static int
-easy_vector_splat_const (int cst, enum machine_mode mode)
-{
- switch (mode)
+ /* Check if VAL is present in every STEP-th element, and the
+ other elements are filled with its most significant bit. */
+ for (i = 0; i < nunits - 1; ++i)
{
- case V4SImode:
- if (EASY_VECTOR_15 (cst)
- || EASY_VECTOR_15_ADD_SELF (cst))
- return cst;
- if ((cst & 0xffff) != ((cst >> 16) & 0xffff))
- break;
- cst = cst >> 16;
- case V8HImode:
- if (EASY_VECTOR_15 (cst)
- || EASY_VECTOR_15_ADD_SELF (cst))
- return cst;
- if ((cst & 0xff) != ((cst >> 8) & 0xff))
- break;
- cst = cst >> 8;
- case V16QImode:
- if (EASY_VECTOR_15 (cst)
- || EASY_VECTOR_15_ADD_SELF (cst))
- return cst;
- default:
- break;
+ HOST_WIDE_INT desired_val;
+ if (((i + 1) & (step - 1)) == 0)
+ desired_val = val;
+ else
+ desired_val = msb_val;
+
+ if (desired_val != const_vector_elt_as_int (op, i))
+ return false;
}
- return 0;
+
+ return true;
}
-/* Return nonzero if all elements of a vector have the same value. */
+/* Return true if OP is of the given MODE and can be synthesized
+ with a vspltisb, vspltish or vspltisw. */
-static int
-easy_vector_same (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+bool
+easy_altivec_constant (rtx op, enum machine_mode mode)
{
- int units, i, cst;
-
- units = CONST_VECTOR_NUNITS (op);
-
- cst = INTVAL (CONST_VECTOR_ELT (op, 0));
- for (i = 1; i < units; ++i)
- if (INTVAL (CONST_VECTOR_ELT (op, i)) != cst)
- break;
- if (i == units && easy_vector_splat_const (cst, mode))
- return 1;
- return 0;
-}
+ unsigned step, copies;
-/* Return 1 if the operand is a CONST_INT and can be put into a
- register without using memory. */
+ if (mode == VOIDmode)
+ mode = GET_MODE (op);
+ else if (mode != GET_MODE (op))
+ return false;
-int
-easy_vector_constant (rtx op, enum machine_mode mode)
-{
- int cst, cst2;
+ /* Start with a vspltisw. */
+ step = GET_MODE_NUNITS (mode) / 4;
+ copies = 1;
- if (GET_CODE (op) != CONST_VECTOR
- || (!TARGET_ALTIVEC
- && !TARGET_SPE))
- return 0;
+ if (vspltis_constant (op, step, copies))
+ return true;
- if (zero_constant (op, mode)
- && ((TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
- || (TARGET_SPE && SPE_VECTOR_MODE (mode))))
- return 1;
+ /* Then try with a vspltish. */
+ if (step == 1)
+ copies <<= 1;
+ else
+ step >>= 1;
- if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
- return 0;
+ if (vspltis_constant (op, step, copies))
+ return true;
- if (TARGET_SPE && mode == V1DImode)
- return 0;
+ /* And finally a vspltisb. */
+ if (step == 1)
+ copies <<= 1;
+ else
+ step >>= 1;
- cst = INTVAL (CONST_VECTOR_ELT (op, 0));
- cst2 = INTVAL (CONST_VECTOR_ELT (op, 1));
-
- /* Limit SPE vectors to 15 bits signed. These we can generate with:
- li r0, CONSTANT1
- evmergelo r0, r0, r0
- li r0, CONSTANT2
-
- I don't know how efficient it would be to allow bigger constants,
- considering we'll have an extra 'ori' for every 'li'. I doubt 5
- instructions is better than a 64-bit memory load, but I don't
- have the e500 timing specs. */
- if (TARGET_SPE && mode == V2SImode
- && cst >= -0x7fff && cst <= 0x7fff
- && cst2 >= -0x7fff && cst2 <= 0x7fff)
- return 1;
+ if (vspltis_constant (op, step, copies))
+ return true;
- if (TARGET_ALTIVEC
- && easy_vector_same (op, mode))
- {
- cst = easy_vector_splat_const (cst, mode);
- if (EASY_VECTOR_15_ADD_SELF (cst)
- || EASY_VECTOR_15 (cst))
- return 1;
- }
- return 0;
+ return false;
}
-/* Same as easy_vector_constant but only for EASY_VECTOR_15_ADD_SELF. */
+/* Generate a VEC_DUPLICATE representing a vspltis[bhw] instruction whose
+ result is OP. Abort if it is not possible. */
-int
-easy_vector_constant_add_self (rtx op, enum machine_mode mode)
+rtx
+gen_easy_altivec_constant (rtx op)
{
- int cst;
- if (TARGET_ALTIVEC
- && GET_CODE (op) == CONST_VECTOR
- && easy_vector_same (op, mode))
- {
- cst = easy_vector_splat_const (INTVAL (CONST_VECTOR_ELT (op, 0)), mode);
- if (EASY_VECTOR_15_ADD_SELF (cst))
- return 1;
- }
- return 0;
-}
+ enum machine_mode mode = GET_MODE (op);
+ int nunits = GET_MODE_NUNITS (mode);
+ rtx last = CONST_VECTOR_ELT (op, nunits - 1);
+ unsigned step = nunits / 4;
+ unsigned copies = 1;
-/* Generate easy_vector_constant out of a easy_vector_constant_add_self. */
+ /* Start with a vspltisw. */
+ if (vspltis_constant (op, step, copies))
+ return gen_rtx_VEC_DUPLICATE (V4SImode, gen_lowpart (SImode, last));
-rtx
-gen_easy_vector_constant_add_self (rtx op)
-{
- int i, units;
- rtvec v;
- units = GET_MODE_NUNITS (GET_MODE (op));
- v = rtvec_alloc (units);
+ /* Then try with a vspltish. */
+ if (step == 1)
+ copies <<= 1;
+ else
+ step >>= 1;
+
+ if (vspltis_constant (op, step, copies))
+ return gen_rtx_VEC_DUPLICATE (V8HImode, gen_lowpart (HImode, last));
- for (i = 0; i < units; i++)
- RTVEC_ELT (v, i) =
- GEN_INT (INTVAL (CONST_VECTOR_ELT (op, i)) >> 1);
- return gen_rtx_raw_CONST_VECTOR (GET_MODE (op), v);
+ /* And finally a vspltisb. */
+ if (step == 1)
+ copies <<= 1;
+ else
+ step >>= 1;
+
+ if (vspltis_constant (op, step, copies))
+ return gen_rtx_VEC_DUPLICATE (V16QImode, gen_lowpart (QImode, last));
+
+ gcc_unreachable ();
}
const char *
@@ -1823,354 +2290,214 @@ output_vec_const_move (rtx *operands)
dest = operands[0];
vec = operands[1];
-
- cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
- cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
mode = GET_MODE (dest);
if (TARGET_ALTIVEC)
{
+ rtx splat_vec;
if (zero_constant (vec, mode))
return "vxor %0,%0,%0";
- else if (easy_vector_constant (vec, mode))
- {
- operands[1] = GEN_INT (cst);
- switch (mode)
- {
- case V4SImode:
- if (EASY_VECTOR_15 (cst))
- {
- operands[1] = GEN_INT (cst);
- return "vspltisw %0,%1";
- }
- else if (EASY_VECTOR_15_ADD_SELF (cst))
- return "#";
- cst = cst >> 16;
- case V8HImode:
- if (EASY_VECTOR_15 (cst))
- {
- operands[1] = GEN_INT (cst);
- return "vspltish %0,%1";
- }
- else if (EASY_VECTOR_15_ADD_SELF (cst))
- return "#";
- cst = cst >> 8;
- case V16QImode:
- if (EASY_VECTOR_15 (cst))
- {
- operands[1] = GEN_INT (cst);
- return "vspltisb %0,%1";
- }
- else if (EASY_VECTOR_15_ADD_SELF (cst))
- return "#";
- default:
- abort ();
- }
- }
- else
- abort ();
- }
-
- if (TARGET_SPE)
- {
- /* Vector constant 0 is handled as a splitter of V2SI, and in the
- pattern of V1DI, V4HI, and V2SF.
-
- FIXME: We should probably return # and add post reload
- splitters for these, but this way is so easy ;-).
- */
- operands[1] = GEN_INT (cst);
- operands[2] = GEN_INT (cst2);
- if (cst == cst2)
- return "li %0,%1\n\tevmergelo %0,%0,%0";
- else
- return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
- }
-
- abort ();
-}
-/* Return 1 if the operand is the constant 0. This works for scalars
- as well as vectors. */
-int
-zero_constant (rtx op, enum machine_mode mode)
-{
- return op == CONST0_RTX (mode);
-}
+ splat_vec = gen_easy_altivec_constant (vec);
+ gcc_assert (GET_CODE (splat_vec) == VEC_DUPLICATE);
+ operands[1] = XEXP (splat_vec, 0);
+ if (!EASY_VECTOR_15 (INTVAL (operands[1])))
+ return "#";
-/* Return 1 if the operand is 0.0. */
-int
-zero_fp_constant (rtx op, 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
- recognize volatile references where its safe. */
-
-int
-volatile_mem_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM)
- return 0;
-
- if (!MEM_VOLATILE_P (op))
- return 0;
-
- if (mode != GET_MODE (op))
- return 0;
-
- if (reload_completed)
- return memory_operand (op, mode);
-
- if (reload_in_progress)
- return strict_memory_address_p (mode, XEXP (op, 0));
-
- return memory_address_p (mode, XEXP (op, 0));
-}
-
-/* Return 1 if the operand is an offsettable memory operand. */
-
-int
-offsettable_mem_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == MEM)
- && offsettable_address_p (reload_completed || reload_in_progress,
- mode, XEXP (op, 0)));
-}
-
-/* Return 1 if the operand is either an easy FP constant (see above) or
- memory. */
+ switch (GET_MODE (splat_vec))
+ {
+ case V4SImode:
+ return "vspltisw %0,%1";
-int
-mem_or_easy_const_operand (rtx op, enum machine_mode mode)
-{
- return memory_operand (op, mode) || easy_fp_constant (op, mode);
-}
+ case V8HImode:
+ return "vspltish %0,%1";
-/* Return 1 if the operand is either a non-special register or an item
- that can be used as the operand of a `mode' add insn. */
+ case V16QImode:
+ return "vspltisb %0,%1";
-int
-add_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == CONST_INT)
- return (CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
- || CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
+ default:
+ gcc_unreachable ();
+ }
+ }
- return gpc_reg_operand (op, mode);
-}
+ gcc_assert (TARGET_SPE);
-/* Return 1 if OP is a constant but not a valid add_operand. */
+ /* Vector constant 0 is handled as a splitter of V2SI, and in the
+ pattern of V1DI, V4HI, and V2SF.
-int
-non_add_cint_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT
- && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'I')
- && !CONST_OK_FOR_LETTER_P (INTVAL (op), 'L'));
+ FIXME: We should probably return # and add post reload
+ splitters for these, but this way is so easy ;-). */
+ cst = INTVAL (CONST_VECTOR_ELT (vec, 0));
+ cst2 = INTVAL (CONST_VECTOR_ELT (vec, 1));
+ operands[1] = CONST_VECTOR_ELT (vec, 0);
+ operands[2] = CONST_VECTOR_ELT (vec, 1);
+ if (cst == cst2)
+ return "li %0,%1\n\tevmergelo %0,%0,%0";
+ else
+ return "li %0,%1\n\tevmergelo %0,%0,%0\n\tli %0,%2";
}
-/* Return 1 if the operand is a non-special register or a constant that
- can be used as the operand of an OR or XOR insn on the RS/6000. */
-
-int
-logical_operand (rtx op, enum machine_mode mode)
-{
- HOST_WIDE_INT opl, oph;
+/* Initialize vector TARGET to VALS. */
- if (gpc_reg_operand (op, mode))
- return 1;
+void
+rs6000_expand_vector_init (rtx target, rtx vals)
+{
+ enum machine_mode mode = GET_MODE (target);
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ int n_elts = GET_MODE_NUNITS (mode);
+ int n_var = 0, one_var = -1;
+ bool all_same = true, all_const_zero = true;
+ rtx x, mem;
+ int i;
- if (GET_CODE (op) == CONST_INT)
+ for (i = 0; i < n_elts; ++i)
{
- opl = INTVAL (op) & GET_MODE_MASK (mode);
+ x = XVECEXP (vals, 0, i);
+ if (!CONSTANT_P (x))
+ ++n_var, one_var = i;
+ else if (x != CONST0_RTX (inner_mode))
+ all_const_zero = false;
-#if HOST_BITS_PER_WIDE_INT <= 32
- if (GET_MODE_BITSIZE (mode) > HOST_BITS_PER_WIDE_INT && opl < 0)
- return 0;
-#endif
+ if (i > 0 && !rtx_equal_p (x, XVECEXP (vals, 0, 0)))
+ all_same = false;
}
- else if (GET_CODE (op) == CONST_DOUBLE)
- {
- if (GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
- abort ();
- opl = CONST_DOUBLE_LOW (op);
- oph = CONST_DOUBLE_HIGH (op);
- if (oph != 0)
- return 0;
+ if (n_var == 0)
+ {
+ if (mode != V4SFmode && all_const_zero)
+ {
+ /* Zero register. */
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_XOR (mode, target, target)));
+ return;
+ }
+ else if (mode != V4SFmode && easy_vector_constant (vals, mode))
+ {
+ /* Splat immediate. */
+ emit_insn (gen_rtx_SET (VOIDmode, target, vals));
+ return;
+ }
+ else if (all_same)
+ ; /* Splat vector element. */
+ else
+ {
+ /* Load from constant pool. */
+ emit_move_insn (target, gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
+ return;
+ }
}
- else
- return 0;
-
- return ((opl & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0
- || (opl & ~ (unsigned HOST_WIDE_INT) 0xffff0000) == 0);
-}
-
-/* Return 1 if C is a constant that is not a logical operand (as
- above), but could be split into one. */
-
-int
-non_logical_cint_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE)
- && ! logical_operand (op, mode)
- && reg_or_logical_cint_operand (op, mode));
-}
-
-/* Return 1 if C is a constant that can be encoded in a 32-bit mask on the
- RS/6000. It is if there are no more than two 1->0 or 0->1 transitions.
- Reject all ones and all zeros, since these should have been optimized
- away and confuse the making of MB and ME. */
-int
-mask_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT c, lsb;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- c = INTVAL (op);
-
- /* Fail in 64-bit mode if the mask wraps around because the upper
- 32-bits of the mask will all be 1s, contrary to GCC's internal view. */
- if (TARGET_POWERPC64 && (c & 0x80000001) == 0x80000001)
- return 0;
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Reject all zeros or all ones. */
- if (c == 0)
- return 0;
-
- /* Find the first transition. */
- lsb = c & -c;
-
- /* Invert to look for a second transition. */
- c = ~c;
-
- /* Erase first transition. */
- c &= -lsb;
-
- /* Find the second transition (if any). */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
-}
-
-/* Return 1 for the PowerPC64 rlwinm corner case. */
-
-int
-mask_operand_wrap (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- HOST_WIDE_INT c, lsb;
-
- if (GET_CODE (op) != CONST_INT)
- return 0;
-
- c = INTVAL (op);
-
- if ((c & 0x80000001) != 0x80000001)
- return 0;
-
- c = ~c;
- if (c == 0)
- return 0;
-
- lsb = c & -c;
- c = ~c;
- c &= -lsb;
- lsb = c & -c;
- return c == -lsb;
-}
-
-/* Return 1 if the operand is a constant that is a PowerPC64 mask.
- It is if there are no more than one 1->0 or 0->1 transitions.
- Reject all zeros, since zero should have been optimized away and
- confuses the making of MB and ME. */
+ /* Store value to stack temp. Load vector element. Splat. */
+ if (all_same)
+ {
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
+ emit_move_insn (adjust_address_nv (mem, inner_mode, 0),
+ XVECEXP (vals, 0, 0));
+ x = gen_rtx_UNSPEC (VOIDmode,
+ gen_rtvec (1, const0_rtx), UNSPEC_LVE);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode,
+ target, mem),
+ x)));
+ x = gen_rtx_VEC_SELECT (inner_mode, target,
+ gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (1, const0_rtx)));
+ emit_insn (gen_rtx_SET (VOIDmode, target,
+ gen_rtx_VEC_DUPLICATE (mode, x)));
+ return;
+ }
-int
-mask64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == CONST_INT)
+ /* One field is non-constant. Load constant then overwrite
+ varying field. */
+ if (n_var == 1)
{
- HOST_WIDE_INT c, lsb;
+ rtx copy = copy_rtx (vals);
- c = INTVAL (op);
+ /* Load constant part of vector, substitute neighboring value for
+ varying element. */
+ XVECEXP (copy, 0, one_var) = XVECEXP (vals, 0, (one_var + 1) % n_elts);
+ rs6000_expand_vector_init (target, copy);
- /* Reject all zeros. */
- if (c == 0)
- return 0;
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Find the transition, and check that all bits above are 1's. */
- lsb = c & -c;
-
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
+ /* Insert variable. */
+ rs6000_expand_vector_set (target, XVECEXP (vals, 0, one_var), one_var);
+ return;
}
- return 0;
+
+ /* Construct the vector in memory one field at a time
+ and load the whole vector. */
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
+ for (i = 0; i < n_elts; i++)
+ emit_move_insn (adjust_address_nv (mem, inner_mode,
+ i * GET_MODE_SIZE (inner_mode)),
+ XVECEXP (vals, 0, i));
+ emit_move_insn (target, mem);
}
-/* Like mask64_operand, but allow up to three transitions. This
- predicate is used by insn patterns that generate two rldicl or
- rldicr machine insns. */
+/* Set field ELT of TARGET to VAL. */
-int
-mask64_2_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+void
+rs6000_expand_vector_set (rtx target, rtx val, int elt)
{
- if (GET_CODE (op) == CONST_INT)
- {
- HOST_WIDE_INT c, lsb;
-
- c = INTVAL (op);
-
- /* Disallow all zeros. */
- if (c == 0)
- return 0;
-
- /* We don't change the number of transitions by inverting,
- so make sure we start with the LS bit zero. */
- if (c & 1)
- c = ~c;
-
- /* Find the first transition. */
- lsb = c & -c;
-
- /* Invert to look for a second transition. */
- c = ~c;
-
- /* Erase first transition. */
- c &= -lsb;
+ enum machine_mode mode = GET_MODE (target);
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ rtx reg = gen_reg_rtx (mode);
+ rtx mask, mem, x;
+ int width = GET_MODE_SIZE (inner_mode);
+ int i;
- /* Find the second transition. */
- lsb = c & -c;
+ /* Load single variable value. */
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (inner_mode), 0);
+ emit_move_insn (adjust_address_nv (mem, inner_mode, 0), val);
+ x = gen_rtx_UNSPEC (VOIDmode,
+ gen_rtvec (1, const0_rtx), UNSPEC_LVE);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode,
+ reg, mem),
+ x)));
+
+ /* Linear sequence. */
+ mask = gen_rtx_PARALLEL (V16QImode, rtvec_alloc (16));
+ for (i = 0; i < 16; ++i)
+ XVECEXP (mask, 0, i) = GEN_INT (i);
+
+ /* Set permute mask to insert element into target. */
+ for (i = 0; i < width; ++i)
+ XVECEXP (mask, 0, elt*width + i)
+ = GEN_INT (i + 0x10);
+ x = gen_rtx_CONST_VECTOR (V16QImode, XVEC (mask, 0));
+ x = gen_rtx_UNSPEC (mode,
+ gen_rtvec (3, target, reg,
+ force_reg (V16QImode, x)),
+ UNSPEC_VPERM);
+ emit_insn (gen_rtx_SET (VOIDmode, target, x));
+}
+
+/* Extract field ELT from VEC into TARGET. */
- /* Invert to look for a third transition. */
- c = ~c;
+void
+rs6000_expand_vector_extract (rtx target, rtx vec, int elt)
+{
+ enum machine_mode mode = GET_MODE (vec);
+ enum machine_mode inner_mode = GET_MODE_INNER (mode);
+ rtx mem, x;
- /* Erase second transition. */
- c &= -lsb;
+ /* Allocate mode-sized buffer. */
+ mem = assign_stack_temp (mode, GET_MODE_SIZE (mode), 0);
- /* Find the third transition (if any). */
- lsb = c & -c;
+ /* Add offset to field within buffer matching vector element. */
+ mem = adjust_address_nv (mem, mode, elt * GET_MODE_SIZE (inner_mode));
- /* Match if all the bits above are 1's (or c is zero). */
- return c == -lsb;
- }
- return 0;
+ /* Store single field into mode-sized buffer. */
+ x = gen_rtx_UNSPEC (VOIDmode,
+ gen_rtvec (1, const0_rtx), UNSPEC_STVE);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (2,
+ gen_rtx_SET (VOIDmode,
+ mem, vec),
+ x)));
+ emit_move_insn (target, adjust_address_nv (mem, inner_mode, 0));
}
/* Generates shifts and masks for a pair of rldicl or rldicr insns to
@@ -2182,8 +2509,7 @@ build_mask64_2_operands (rtx in, rtx *out)
unsigned HOST_WIDE_INT c, lsb, m1, m2;
int shift;
- if (GET_CODE (in) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (in) == CONST_INT);
c = INTVAL (in);
if (c & 1)
@@ -2239,203 +2565,73 @@ build_mask64_2_operands (rtx in, rtx *out)
#else
(void)in;
(void)out;
- abort ();
+ gcc_unreachable ();
#endif
}
-/* Return 1 if the operand is either a non-special register or a constant
- that can be used as the operand of a PowerPC64 logical AND insn. */
-
-int
-and64_operand (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return (gpc_reg_operand (op, mode) || mask64_operand (op, mode));
-
- return (logical_operand (op, mode) || mask64_operand (op, mode));
-}
-
-/* Like the above, but also match constants that can be implemented
- with two rldicl or rldicr insns. */
-
-int
-and64_2_operand (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return gpc_reg_operand (op, mode) || mask64_2_operand (op, mode);
-
- return logical_operand (op, mode) || mask64_2_operand (op, mode);
-}
-
-/* Return 1 if the operand is either a non-special register or a
- constant that can be used as the operand of an RS/6000 logical AND insn. */
-
-int
-and_operand (rtx op, enum machine_mode mode)
-{
- if (fixed_regs[CR0_REGNO]) /* CR0 not available, don't do andi./andis. */
- return (gpc_reg_operand (op, mode) || mask_operand (op, mode));
-
- return (logical_operand (op, mode) || mask_operand (op, mode));
-}
-
-/* Return 1 if the operand is a general register or memory operand. */
-
-int
-reg_or_mem_operand (rtx op, enum machine_mode mode)
-{
- return (gpc_reg_operand (op, mode)
- || memory_operand (op, mode)
- || macho_lo_sum_memory_operand (op, mode)
- || volatile_mem_operand (op, mode));
-}
-
-/* Return 1 if the operand is a general register or memory operand without
- pre_inc or pre_dec which produces invalid form of PowerPC lwa
- instruction. */
-
-int
-lwa_operand (rtx op, enum machine_mode mode)
-{
- rtx inner = op;
-
- if (reload_completed && GET_CODE (inner) == SUBREG)
- inner = SUBREG_REG (inner);
-
- return gpc_reg_operand (inner, mode)
- || (memory_operand (inner, mode)
- && GET_CODE (XEXP (inner, 0)) != PRE_INC
- && GET_CODE (XEXP (inner, 0)) != PRE_DEC
- && (GET_CODE (XEXP (inner, 0)) != PLUS
- || GET_CODE (XEXP (XEXP (inner, 0), 1)) != CONST_INT
- || INTVAL (XEXP (XEXP (inner, 0), 1)) % 4 == 0));
-}
-
-/* Return 1 if the operand, used inside a MEM, is a SYMBOL_REF. */
-
-int
-symbol_ref_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF
- && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op)));
-}
-
-/* Return 1 if the operand, used inside a MEM, is a valid first argument
- to CALL. This is a SYMBOL_REF, a pseudo-register, LR or CTR. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && GET_MODE (op) != mode)
- return 0;
-
- return (GET_CODE (op) == SYMBOL_REF
- || (GET_CODE (op) == REG
- && (REGNO (op) == LINK_REGISTER_REGNUM
- || REGNO (op) == COUNT_REGISTER_REGNUM
- || REGNO (op) >= FIRST_PSEUDO_REGISTER)));
-}
-
-/* Return 1 if the operand is a SYMBOL_REF for a function known to be in
- this file. */
-
-int
-current_file_function_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == SYMBOL_REF
- && (DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
- && (SYMBOL_REF_LOCAL_P (op)
- || (op == XEXP (DECL_RTL (current_function_decl), 0))));
-}
-
-/* Return 1 if this operand is a valid input for a move insn. */
+/* Return TRUE if OP is an invalid SUBREG operation on the e500. */
-int
-input_operand (rtx op, enum machine_mode mode)
+bool
+invalid_e500_subreg (rtx op, enum machine_mode mode)
{
- /* Memory is always valid. */
- if (memory_operand (op, mode))
- return 1;
-
- /* Only a tiny bit of handling for CONSTANT_P_RTX is necessary. */
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
-
- /* For floating-point, easy constants are valid. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && CONSTANT_P (op)
- && easy_fp_constant (op, mode))
- return 1;
-
- /* Allow any integer constant. */
- if (GET_MODE_CLASS (mode) == MODE_INT
- && (GET_CODE (op) == CONST_INT
- || GET_CODE (op) == CONST_DOUBLE))
- return 1;
-
- /* Allow easy vector constants. */
- if (GET_CODE (op) == CONST_VECTOR
- && easy_vector_constant (op, mode))
- return 1;
-
- /* For floating-point or multi-word mode, the only remaining valid type
- is a register. */
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || GET_MODE_SIZE (mode) > UNITS_PER_WORD)
- return register_operand (op, mode);
-
- /* The only cases left are integral modes one word or smaller (we
- do not get called for MODE_CC values). These can be in any
- register. */
- if (register_operand (op, mode))
- return 1;
-
- /* A SYMBOL_REF referring to the TOC is valid. */
- if (legitimate_constant_pool_address_p (op))
- return 1;
+ if (TARGET_E500_DOUBLE)
+ {
+ /* Reject (subreg:SI (reg:DF)). */
+ if (GET_CODE (op) == SUBREG
+ && mode == SImode
+ && REG_P (SUBREG_REG (op))
+ && GET_MODE (SUBREG_REG (op)) == DFmode)
+ return true;
- /* A constant pool expression (relative to the TOC) is valid */
- if (toc_relative_expr_p (op))
- return 1;
+ /* Reject (subreg:DF (reg:DI)). */
+ if (GET_CODE (op) == SUBREG
+ && mode == DFmode
+ && REG_P (SUBREG_REG (op))
+ && GET_MODE (SUBREG_REG (op)) == DImode)
+ return true;
+ }
- /* V.4 allows SYMBOL_REFs and CONSTs that are in the small data region
- to be valid. */
- if (DEFAULT_ABI == ABI_V4
- && (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == CONST)
- && small_data_operand (op, Pmode))
- return 1;
+ if (TARGET_SPE
+ && GET_CODE (op) == SUBREG
+ && mode == SImode
+ && REG_P (SUBREG_REG (op))
+ && SPE_VECTOR_MODE (GET_MODE (SUBREG_REG (op))))
+ return true;
- return 0;
+ return false;
}
-
/* Darwin, AIX increases natural record alignment to doubleword if the first
field is an FP double while the FP fields remain word aligned. */
unsigned int
-rs6000_special_round_type_align (tree type, int computed, int specified)
+rs6000_special_round_type_align (tree type, unsigned int computed,
+ unsigned int specified)
{
+ unsigned int align = MAX (computed, specified);
tree field = TYPE_FIELDS (type);
- /* Skip all the static variables only if ABI is greater than
- 1 or equal to 0. */
- while (field != NULL && TREE_CODE (field) == VAR_DECL)
+ /* Skip all non field decls */
+ while (field != NULL && TREE_CODE (field) != FIELD_DECL)
field = TREE_CHAIN (field);
- if (field == NULL || field == type || DECL_MODE (field) != DFmode)
- return MAX (computed, specified);
+ if (field != NULL && field != type)
+ {
+ type = TREE_TYPE (field);
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
- return MAX (MAX (computed, specified), 64);
+ if (type != error_mark_node && TYPE_MODE (type) == DFmode)
+ align = MAX (align, 64);
+ }
+
+ return align;
}
/* Return 1 for an operand in small memory on V.4/eabi. */
int
-small_data_operand (rtx op ATTRIBUTE_UNUSED,
+small_data_operand (rtx op ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED)
{
#if TARGET_ELF
@@ -2462,10 +2658,10 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED,
HOST_WIDE_INT summand;
/* We have to be careful here, because it is the referenced address
- that must be 32k from _SDA_BASE_, not just the symbol. */
+ that must be 32k from _SDA_BASE_, not just the symbol. */
summand = INTVAL (XEXP (sum, 1));
if (summand < 0 || (unsigned HOST_WIDE_INT) summand > g_switch_value)
- return 0;
+ return 0;
sym_ref = XEXP (sum, 0);
}
@@ -2476,27 +2672,6 @@ small_data_operand (rtx op ATTRIBUTE_UNUSED,
#endif
}
-/* Return true, if operand is a memory operand and has a
- displacement divisible by 4. */
-
-int
-word_offset_memref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- rtx addr;
- int off = 0;
-
- if (!memory_operand (op, mode))
- return 0;
-
- addr = XEXP (op, 0);
- if (GET_CODE (addr) == PLUS
- && GET_CODE (XEXP (addr, 0)) == REG
- && GET_CODE (XEXP (addr, 1)) == CONST_INT)
- off = INTVAL (XEXP (addr, 1));
-
- return (off % 4) == 0;
-}
-
/* Return true if either operand is a general purpose register. */
bool
@@ -2509,10 +2684,10 @@ gpr_or_gpr_p (rtx op0, rtx op1)
/* Subroutines of rs6000_legitimize_address and rs6000_legitimate_address. */
-static int
-constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc)
+static int
+constant_pool_expr_1 (rtx op, int *have_sym, int *have_toc)
{
- switch (GET_CODE(op))
+ switch (GET_CODE (op))
{
case SYMBOL_REF:
if (RS6000_SYMBOL_REF_TLS_P (op))
@@ -2555,7 +2730,7 @@ constant_pool_expr_p (rtx op)
return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_sym;
}
-static bool
+bool
toc_relative_expr_p (rtx op)
{
int have_sym = 0;
@@ -2563,9 +2738,6 @@ toc_relative_expr_p (rtx op)
return constant_pool_expr_1 (op, &have_sym, &have_toc) && have_toc;
}
-/* SPE offset addressing is limited to 5-bits worth of double words. */
-#define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
-
bool
legitimate_constant_pool_address_p (rtx x)
{
@@ -2585,8 +2757,11 @@ legitimate_small_data_p (enum machine_mode mode, rtx x)
&& small_data_operand (x, mode));
}
-static bool
-legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
+/* SPE offset addressing is limited to 5-bits worth of double words. */
+#define SPE_CONST_OFFSET_OK(x) (((x) & ~0xf8) == 0)
+
+bool
+rs6000_legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
{
unsigned HOST_WIDE_INT offset, extra;
@@ -2596,6 +2771,8 @@ legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
return false;
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
return false;
+ if (legitimate_constant_pool_address_p (x))
+ return true;
if (GET_CODE (XEXP (x, 1)) != CONST_INT)
return false;
@@ -2607,10 +2784,10 @@ legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
case V8HImode:
case V4SFmode:
case V4SImode:
- /* AltiVec vector modes. Only reg+reg addressing is valid here,
- which leaves the only valid constant offset of zero, which by
- canonicalization rules is also invalid. */
- return false;
+ /* AltiVec vector modes. Only reg+reg addressing is valid and
+ constant offset zero should not occur due to canonicalization.
+ Allow any offset when not strict before reload. */
+ return !strict;
case V4HImode:
case V2SImode:
@@ -2620,7 +2797,18 @@ legitimate_offset_address_p (enum machine_mode mode, rtx x, int strict)
return SPE_CONST_OFFSET_OK (offset);
case DFmode:
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
case DImode:
+ /* On e500v2, we may have:
+
+ (subreg:DF (mem:DI (plus (reg) (const_int))) 0).
+
+ Which gets addressed with evldd instructions. */
+ if (TARGET_E500_DOUBLE)
+ return SPE_CONST_OFFSET_OK (offset);
+
if (mode == DFmode || !TARGET_POWERPC64)
extra = 4;
else if (offset & 3)
@@ -2652,31 +2840,38 @@ legitimate_indexed_address_p (rtx x, int strict)
if (GET_CODE (x) != PLUS)
return false;
+
op0 = XEXP (x, 0);
op1 = XEXP (x, 1);
- if (!REG_P (op0) || !REG_P (op1))
- return false;
+ /* Recognize the rtl generated by reload which we know will later be
+ replaced with proper base and index regs. */
+ if (!strict
+ && reload_in_progress
+ && (REG_P (op0) || GET_CODE (op0) == PLUS)
+ && REG_P (op1))
+ return true;
- return ((INT_REG_OK_FOR_BASE_P (op0, strict)
- && INT_REG_OK_FOR_INDEX_P (op1, strict))
- || (INT_REG_OK_FOR_BASE_P (op1, strict)
- && INT_REG_OK_FOR_INDEX_P (op0, strict)));
+ return (REG_P (op0) && REG_P (op1)
+ && ((INT_REG_OK_FOR_BASE_P (op0, strict)
+ && INT_REG_OK_FOR_INDEX_P (op1, strict))
+ || (INT_REG_OK_FOR_BASE_P (op1, strict)
+ && INT_REG_OK_FOR_INDEX_P (op0, strict))));
}
-static inline bool
+inline bool
legitimate_indirect_address_p (rtx x, int strict)
{
return GET_CODE (x) == REG && INT_REG_OK_FOR_BASE_P (x, strict);
}
-static bool
+bool
macho_lo_sum_memory_operand (rtx x, enum machine_mode mode)
{
- if (!TARGET_MACHO || !flag_pic
- || mode != SImode || GET_CODE(x) != MEM)
- return false;
- x = XEXP (x, 0);
+ if (!TARGET_MACHO || !flag_pic
+ || mode != SImode || GET_CODE (x) != MEM)
+ return false;
+ x = XEXP (x, 0);
if (GET_CODE (x) != LO_SUM)
return false;
@@ -2698,6 +2893,9 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
return false;
if (!INT_REG_OK_FOR_BASE_P (XEXP (x, 0), strict))
return false;
+ /* Restrict addressing for DI because of our SUBREG hackery. */
+ if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
+ return false;
x = XEXP (x, 1);
if (TARGET_ELF || TARGET_MACHO)
@@ -2708,8 +2906,9 @@ legitimate_lo_sum_address_p (enum machine_mode mode, rtx x, int strict)
return false;
if (GET_MODE_NUNITS (mode) != 1)
return false;
- if (GET_MODE_BITSIZE (mode) > 32
- && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode))
+ if (GET_MODE_BITSIZE (mode) > 64
+ || (GET_MODE_BITSIZE (mode) > 32 && !TARGET_POWERPC64
+ && !(TARGET_HARD_FLOAT && TARGET_FPRS && mode == DFmode)))
return false;
return CONSTANT_P (x);
@@ -2753,11 +2952,11 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return rs6000_legitimize_tls_address (x, model);
}
- if (GET_CODE (x) == PLUS
+ if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& (unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1)) + 0x8000) >= 0x10000)
- {
+ {
HOST_WIDE_INT high_int, low_int;
rtx sum;
low_int = ((INTVAL (XEXP (x, 1)) & 0xffff) ^ 0x8000) - 0x8000;
@@ -2766,13 +2965,14 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
GEN_INT (high_int)), 0);
return gen_rtx_PLUS (Pmode, sum, GEN_INT (low_int));
}
- else if (GET_CODE (x) == PLUS
+ else if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == REG
&& GET_CODE (XEXP (x, 1)) != CONST_INT
&& GET_MODE_NUNITS (mode) == 1
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || (((mode != DImode && mode != DFmode) || TARGET_E500_DOUBLE)
+ && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& mode != TImode)
{
@@ -2791,24 +2991,28 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
reg = force_reg (Pmode, x);
return reg;
}
- else if (SPE_VECTOR_MODE (mode))
+ else if (SPE_VECTOR_MODE (mode)
+ || (TARGET_E500_DOUBLE && (mode == DFmode
+ || mode == DImode)))
{
+ if (mode == DImode)
+ return NULL_RTX;
/* We accept [reg + reg] and [reg + OFFSET]. */
if (GET_CODE (x) == PLUS)
- {
- rtx op1 = XEXP (x, 0);
- rtx op2 = XEXP (x, 1);
+ {
+ rtx op1 = XEXP (x, 0);
+ rtx op2 = XEXP (x, 1);
- op1 = force_reg (Pmode, op1);
+ op1 = force_reg (Pmode, op1);
- if (GET_CODE (op2) != REG
- && (GET_CODE (op2) != CONST_INT
- || !SPE_CONST_OFFSET_OK (INTVAL (op2))))
- op2 = force_reg (Pmode, op2);
+ if (GET_CODE (op2) != REG
+ && (GET_CODE (op2) != CONST_INT
+ || !SPE_CONST_OFFSET_OK (INTVAL (op2))))
+ op2 = force_reg (Pmode, op2);
- return gen_rtx_PLUS (Pmode, op1, op2);
- }
+ return gen_rtx_PLUS (Pmode, op1, op2);
+ }
return force_reg (Pmode, x);
}
@@ -2817,7 +3021,7 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& TARGET_NO_TOC
&& ! flag_pic
&& GET_CODE (x) != CONST_INT
- && GET_CODE (x) != CONST_DOUBLE
+ && GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
&& GET_MODE_NUNITS (mode) == 1
&& (GET_MODE_BITSIZE (mode) <= 32
@@ -2833,17 +3037,17 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
&& ! MACHO_DYNAMIC_NO_PIC_P
#endif
&& GET_CODE (x) != CONST_INT
- && GET_CODE (x) != CONST_DOUBLE
+ && GET_CODE (x) != CONST_DOUBLE
&& CONSTANT_P (x)
&& ((TARGET_HARD_FLOAT && TARGET_FPRS) || mode != DFmode)
- && mode != DImode
+ && mode != DImode
&& mode != TImode)
{
rtx reg = gen_reg_rtx (Pmode);
emit_insn (gen_macho_high (reg, x));
return gen_rtx_LO_SUM (Pmode, reg, x);
}
- else if (TARGET_TOC
+ else if (TARGET_TOC
&& constant_pool_expr_p (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), Pmode))
{
@@ -2853,10 +3057,10 @@ rs6000_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return NULL_RTX;
}
-/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
-void
+static void
rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
switch (size)
@@ -2868,7 +3072,7 @@ rs6000_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs (DOUBLE_INT_ASM_OP, file);
break;
default:
- abort ();
+ gcc_unreachable ();
}
output_addr_const (file, x);
fputs ("@dtprel+0x8000", file);
@@ -2897,7 +3101,7 @@ rs6000_got_sym (void)
rs6000_got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_LOCAL;
SYMBOL_REF_FLAGS (rs6000_got_symbol) |= SYMBOL_FLAG_EXTERNAL;
- }
+ }
return rs6000_got_symbol;
}
@@ -2953,6 +3157,11 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
{
rtx r3, got, tga, tmp1, tmp2, eqv;
+ /* We currently use relocations like @got@tlsgd for tls, which
+ means the linker will handle allocation of tls entries, placing
+ them in the .got section. So use a pointer to the .got section,
+ not one to secondary TOC sections used by 64-bit -mminimal-toc,
+ or to secondary GOT sections used by 32-bit -fPIC. */
if (TARGET_64BIT)
got = gen_rtx_REG (Pmode, 2);
else
@@ -2974,8 +3183,7 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
tmp1 = gen_reg_rtx (Pmode);
tmp2 = gen_reg_rtx (Pmode);
tmp3 = gen_reg_rtx (Pmode);
- mem = gen_rtx_MEM (Pmode, tmp1);
- RTX_UNCHANGING_P (mem) = 1;
+ mem = gen_const_mem (Pmode, tmp1);
first = emit_insn (gen_load_toc_v4_PIC_1b (tempLR, gsym));
emit_move_insn (tmp1, tempLR);
@@ -3083,15 +3291,6 @@ rs6000_legitimize_tls_address (rtx addr, enum tls_model model)
return dest;
}
-/* Return 1 if X is a SYMBOL_REF for a TLS symbol. This is used in
- instruction definitions. */
-
-int
-rs6000_tls_symbol_ref (rtx x, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return RS6000_SYMBOL_REF_TLS_P (x);
-}
-
/* Return 1 if X contains a thread-local symbol. */
bool
@@ -3106,7 +3305,7 @@ rs6000_tls_referenced_p (rtx x)
/* Return 1 if *X is a thread-local symbol. This is the same as
rs6000_tls_symbol_ref except for the type of the unused argument. */
-static inline int
+static int
rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
{
return RS6000_SYMBOL_REF_TLS_P (*x);
@@ -3133,10 +3332,11 @@ rs6000_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
The Darwin code is inside #if TARGET_MACHO because only then is
machopic_function_base_name() defined. */
rtx
-rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
- int opnum, int type, int ind_levels ATTRIBUTE_UNUSED, int *win)
+rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
+ int opnum, int type,
+ int ind_levels ATTRIBUTE_UNUSED, int *win)
{
- /* We must recognize output that we have already generated ourselves. */
+ /* We must recognize output that we have already generated ourselves. */
if (GET_CODE (x) == PLUS
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
@@ -3144,8 +3344,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
{
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
*win = 1;
return x;
}
@@ -3165,8 +3365,8 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
/* Result of previous invocation of this function on Darwin
floating point constant. */
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
*win = 1;
return x;
}
@@ -3180,6 +3380,7 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& (INTVAL (XEXP (x, 1)) & 3) != 0
+ && !ALTIVEC_VECTOR_MODE (mode)
&& GET_MODE_SIZE (mode) >= UNITS_PER_WORD
&& TARGET_POWERPC64)
{
@@ -3197,56 +3398,69 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
&& REG_MODE_OK_FOR_BASE_P (XEXP (x, 0), mode)
&& GET_CODE (XEXP (x, 1)) == CONST_INT
&& !SPE_VECTOR_MODE (mode)
+ && !(TARGET_E500_DOUBLE && (mode == DFmode
+ || mode == DImode))
&& !ALTIVEC_VECTOR_MODE (mode))
{
HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT high
- = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
+ = (((val - low) & 0xffffffff) ^ 0x80000000) - 0x80000000;
/* Check for 32-bit overflow. */
if (high + low != val)
- {
+ {
*win = 0;
return x;
}
/* Reload the high part into a base reg; leave the low part
- in the mem directly. */
+ in the mem directly. */
x = gen_rtx_PLUS (GET_MODE (x),
- gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
- GEN_INT (high)),
- GEN_INT (low));
+ gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0),
+ GEN_INT (high)),
+ GEN_INT (low));
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
- BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
- opnum, (enum reload_type)type);
+ BASE_REG_CLASS, GET_MODE (x), VOIDmode, 0, 0,
+ opnum, (enum reload_type)type);
*win = 1;
return x;
}
-#if TARGET_MACHO
if (GET_CODE (x) == SYMBOL_REF
- && DEFAULT_ABI == ABI_DARWIN
&& !ALTIVEC_VECTOR_MODE (mode)
+ && !SPE_VECTOR_MODE (mode)
+#if TARGET_MACHO
+ && DEFAULT_ABI == ABI_DARWIN
&& (flag_pic || MACHO_DYNAMIC_NO_PIC_P)
- /* Don't do this for TFmode, since the result isn't offsettable. */
- && mode != TFmode)
+#else
+ && DEFAULT_ABI == ABI_V4
+ && !flag_pic
+#endif
+ /* Don't do this for TFmode, since the result isn't offsettable.
+ The same goes for DImode without 64-bit gprs and DFmode
+ without fprs. */
+ && mode != TFmode
+ && (mode != DImode || TARGET_POWERPC64)
+ && (mode != DFmode || TARGET_POWERPC64
+ || (TARGET_FPRS && TARGET_HARD_FLOAT)))
{
+#if TARGET_MACHO
if (flag_pic)
{
rtx offset = gen_rtx_CONST (Pmode,
gen_rtx_MINUS (Pmode, x,
- gen_rtx_SYMBOL_REF (Pmode,
- machopic_function_base_name ())));
+ machopic_function_base_sym ()));
x = gen_rtx_LO_SUM (GET_MODE (x),
gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
gen_rtx_HIGH (Pmode, offset)), offset);
}
else
+#endif
x = gen_rtx_LO_SUM (GET_MODE (x),
- gen_rtx_HIGH (Pmode, x), x);
+ gen_rtx_HIGH (Pmode, x), x);
push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
@@ -3254,19 +3468,35 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
*win = 1;
return x;
}
-#endif
+
+ /* Reload an offset address wrapped by an AND that represents the
+ masking of the lower bits. Strip the outer AND and let reload
+ convert the offset address into an indirect address. */
+ if (TARGET_ALTIVEC
+ && ALTIVEC_VECTOR_MODE (mode)
+ && GET_CODE (x) == AND
+ && GET_CODE (XEXP (x, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) == -16)
+ {
+ x = XEXP (x, 0);
+ *win = 1;
+ return x;
+ }
if (TARGET_TOC
&& constant_pool_expr_p (x)
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (get_pool_constant (x), mode))
{
- (x) = create_TOC_reference (x);
+ x = create_TOC_reference (x);
*win = 1;
return x;
}
*win = 0;
return x;
-}
+}
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression
that is a valid memory address for an instruction.
@@ -3282,12 +3512,20 @@ rs6000_legitimize_reload_address (rtx x, enum machine_mode mode,
word aligned.
For modes spanning multiple registers (DFmode in 32-bit GPRs,
- 32-bit DImode, TImode), indexed addressing cannot be used because
+ 32-bit DImode, TImode, TFmode), indexed addressing cannot be used because
adjacent memory cells are accessed by adding word-sized offsets
during assembly output. */
int
rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
{
+ /* If this is an unaligned stvx/ldvx type address, discard the outer AND. */
+ if (TARGET_ALTIVEC
+ && ALTIVEC_VECTOR_MODE (mode)
+ && GET_CODE (x) == AND
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && INTVAL (XEXP (x, 1)) == -16)
+ x = XEXP (x, 0);
+
if (RS6000_SYMBOL_REF_TLS_P (x))
return 0;
if (legitimate_indirect_address_p (x, reg_ok_strict))
@@ -3295,6 +3533,9 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
if ((GET_CODE (x) == PRE_INC || GET_CODE (x) == PRE_DEC)
&& !ALTIVEC_VECTOR_MODE (mode)
&& !SPE_VECTOR_MODE (mode)
+ && mode != TFmode
+ /* Restrict addressing for DI because of our SUBREG hackery. */
+ && !(TARGET_E500_DOUBLE && (mode == DFmode || mode == DImode))
&& TARGET_UPDATE
&& legitimate_indirect_address_p (XEXP (x, 0), reg_ok_strict))
return 1;
@@ -3310,12 +3551,13 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
|| XEXP (x, 0) == arg_pointer_rtx)
&& GET_CODE (XEXP (x, 1)) == CONST_INT)
return 1;
- if (legitimate_offset_address_p (mode, x, reg_ok_strict))
+ if (rs6000_legitimate_offset_address_p (mode, x, reg_ok_strict))
return 1;
if (mode != TImode
+ && mode != TFmode
&& ((TARGET_HARD_FLOAT && TARGET_FPRS)
|| TARGET_POWERPC64
- || (mode != DFmode && mode != TFmode))
+ || ((mode != DFmode || TARGET_E500_DOUBLE) && mode != TFmode))
&& (TARGET_POWERPC64 || mode != DImode)
&& legitimate_indexed_address_p (x, reg_ok_strict))
return 1;
@@ -3332,7 +3574,7 @@ rs6000_legitimate_address (enum machine_mode mode, rtx x, int reg_ok_strict)
??? Except that due to conceptual problems in offsettable_address_p
we can't really report the problems of integral offsets. So leave
- this assuming that the adjustable offset must be valid for the
+ this assuming that the adjustable offset must be valid for the
sub-words of a TFmode operand, which is what we had before. */
bool
@@ -3361,6 +3603,142 @@ rs6000_mode_dependent_address (rtx addr)
return false;
}
+
+/* More elaborate version of recog's offsettable_memref_p predicate
+ that works around the ??? note of rs6000_mode_dependent_address.
+ In particular it accepts
+
+ (mem:DI (plus:SI (reg/f:SI 31 31) (const_int 32760 [0x7ff8])))
+
+ in 32-bit mode, that the recog predicate rejects. */
+
+bool
+rs6000_offsettable_memref_p (rtx op)
+{
+ if (!MEM_P (op))
+ return false;
+
+ /* First mimic offsettable_memref_p. */
+ if (offsettable_address_p (1, GET_MODE (op), XEXP (op, 0)))
+ return true;
+
+ /* offsettable_address_p invokes rs6000_mode_dependent_address, but
+ the latter predicate knows nothing about the mode of the memory
+ reference and, therefore, assumes that it is the largest supported
+ mode (TFmode). As a consequence, legitimate offsettable memory
+ references are rejected. rs6000_legitimate_offset_address_p contains
+ the correct logic for the PLUS case of rs6000_mode_dependent_address. */
+ return rs6000_legitimate_offset_address_p (GET_MODE (op), XEXP (op, 0), 1);
+}
+
+/* Return number of consecutive hard regs needed starting at reg REGNO
+ to hold something of mode MODE.
+ This is ordinarily the length in words of a value of mode MODE
+ but can be less for certain modes in special long registers.
+
+ For the SPE, GPRs are 64 bits but only 32 bits are visible in
+ scalar instructions. The upper 32 bits are only available to the
+ SIMD instructions.
+
+ POWER and PowerPC GPRs hold 32 bits worth;
+ PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
+
+int
+rs6000_hard_regno_nregs (int regno, enum machine_mode mode)
+{
+ if (FP_REGNO_P (regno))
+ return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+
+ if (SPE_SIMD_REGNO_P (regno) && TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return (GET_MODE_SIZE (mode) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD;
+
+ if (ALTIVEC_REGNO_P (regno))
+ return
+ (GET_MODE_SIZE (mode) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD;
+
+ /* The value returned for SCmode in the E500 double case is 2 for
+ ABI compatibility; storing an SCmode value in a single register
+ would require function_arg and rs6000_spe_function_arg to handle
+ SCmode so as to pass the value correctly in a pair of
+ registers. */
+ if (TARGET_E500_DOUBLE && FLOAT_MODE_P (mode) && mode != SCmode)
+ return (GET_MODE_SIZE (mode) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD;
+
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
+
+/* Change register usage conditional on target flags. */
+void
+rs6000_conditional_register_usage (void)
+{
+ int i;
+
+ /* Set MQ register fixed (already call_used) if not POWER
+ architecture (RIOS1, RIOS2, RSC, and PPC601) so that it will not
+ be allocated. */
+ if (! TARGET_POWER)
+ fixed_regs[64] = 1;
+
+ /* 64-bit AIX and Linux reserve GPR13 for thread-private data. */
+ if (TARGET_64BIT)
+ fixed_regs[13] = call_used_regs[13]
+ = call_really_used_regs[13] = 1;
+
+ /* Conditionally disable FPRs. */
+ if (TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ for (i = 32; i < 64; i++)
+ fixed_regs[i] = call_used_regs[i]
+ = call_really_used_regs[i] = 1;
+
+ /* The TOC register is not killed across calls in a way that is
+ visible to the compiler. */
+ if (DEFAULT_ABI == ABI_AIX)
+ call_really_used_regs[2] = 0;
+
+ if (DEFAULT_ABI == ABI_V4
+ && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+ && flag_pic == 2)
+ fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ if (DEFAULT_ABI == ABI_V4
+ && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM
+ && flag_pic == 1)
+ fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
+ = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
+ = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ if (DEFAULT_ABI == ABI_DARWIN
+ && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM)
+ fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
+ = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
+ = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ if (TARGET_TOC && TARGET_MINIMAL_TOC)
+ fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM]
+ = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1;
+
+ if (TARGET_ALTIVEC)
+ global_regs[VSCR_REGNO] = 1;
+
+ if (TARGET_SPE)
+ {
+ global_regs[SPEFSCR_REGNO] = 1;
+ fixed_regs[FIXED_SCRATCH]
+ = call_used_regs[FIXED_SCRATCH]
+ = call_really_used_regs[FIXED_SCRATCH] = 1;
+ }
+
+ if (! TARGET_ALTIVEC)
+ {
+ for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
+ fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1;
+ call_really_used_regs[VRSAVE_REGNO] = 1;
+ }
+
+ if (TARGET_ALTIVEC_ABI)
+ for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i)
+ call_used_regs[i] = call_really_used_regs[i] = 1;
+}
/* Try to output insns to set TARGET equal to the constant C if it can
be done in less than N insns. Do all computations in MODE.
@@ -3369,21 +3747,22 @@ rs6000_mode_dependent_address (rtx addr)
insns, zero is returned and no insns and emitted. */
rtx
-rs6000_emit_set_const (rtx dest, enum machine_mode mode,
+rs6000_emit_set_const (rtx dest, enum machine_mode mode,
rtx source, int n ATTRIBUTE_UNUSED)
{
rtx result, insn, set;
HOST_WIDE_INT c0, c1;
- if (mode == QImode || mode == HImode)
+ switch (mode)
{
+ case QImode:
+ case HImode:
if (dest == NULL)
- dest = gen_reg_rtx (mode);
+ dest = gen_reg_rtx (mode);
emit_insn (gen_rtx_SET (VOIDmode, dest, source));
return dest;
- }
- else if (mode == SImode)
- {
+
+ case SImode:
result = no_new_pseudos ? dest : gen_reg_rtx (SImode);
emit_insn (gen_rtx_SET (VOIDmode, result,
@@ -3393,16 +3772,17 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode,
gen_rtx_IOR (SImode, result,
GEN_INT (INTVAL (source) & 0xffff))));
result = dest;
- }
- else if (mode == DImode)
- {
- if (GET_CODE (source) == CONST_INT)
+ break;
+
+ case DImode:
+ switch (GET_CODE (source))
{
+ case CONST_INT:
c0 = INTVAL (source);
c1 = -(c0 < 0);
- }
- else if (GET_CODE (source) == CONST_DOUBLE)
- {
+ break;
+
+ case CONST_DOUBLE:
#if HOST_BITS_PER_WIDE_INT >= 64
c0 = CONST_DOUBLE_LOW (source);
c1 = -(c0 < 0);
@@ -3410,14 +3790,18 @@ rs6000_emit_set_const (rtx dest, enum machine_mode mode,
c0 = CONST_DOUBLE_LOW (source);
c1 = CONST_DOUBLE_HIGH (source);
#endif
+ break;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
result = rs6000_emit_set_long_const (dest, c0, c1);
+ break;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
insn = get_last_insn ();
set = single_set (insn);
@@ -3457,7 +3841,7 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
ud3 = c2 & 0xffff;
ud4 = (c2 & 0xffff0000) >> 16;
- if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
+ if ((ud4 == 0xffff && ud3 == 0xffff && ud2 == 0xffff && (ud1 & 0x8000))
|| (ud4 == 0 && ud3 == 0 && ud2 == 0 && ! (ud1 & 0x8000)))
{
if (ud1 & 0x8000)
@@ -3466,22 +3850,22 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
emit_move_insn (dest, GEN_INT (ud1));
}
- else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
+ else if ((ud4 == 0xffff && ud3 == 0xffff && (ud2 & 0x8000))
|| (ud4 == 0 && ud3 == 0 && ! (ud2 & 0x8000)))
{
if (ud2 & 0x8000)
- emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
+ emit_move_insn (dest, GEN_INT (((ud2 << 16) ^ 0x80000000)
- 0x80000000));
else
emit_move_insn (dest, GEN_INT (ud2 << 16));
if (ud1 != 0)
emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
}
- else if ((ud4 == 0xffff && (ud3 & 0x8000))
+ else if ((ud4 == 0xffff && (ud3 & 0x8000))
|| (ud4 == 0 && ! (ud3 & 0x8000)))
{
if (ud3 & 0x8000)
- emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
+ emit_move_insn (dest, GEN_INT (((ud3 << 16) ^ 0x80000000)
- 0x80000000));
else
emit_move_insn (dest, GEN_INT (ud3 << 16));
@@ -3492,10 +3876,10 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
if (ud1 != 0)
emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
}
- else
+ else
{
if (ud4 & 0x8000)
- emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
+ emit_move_insn (dest, GEN_INT (((ud4 << 16) ^ 0x80000000)
- 0x80000000));
else
emit_move_insn (dest, GEN_INT (ud4 << 16));
@@ -3505,8 +3889,8 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
emit_move_insn (dest, gen_rtx_ASHIFT (DImode, dest, GEN_INT (32)));
if (ud2 != 0)
- emit_move_insn (dest, gen_rtx_IOR (DImode, dest,
- GEN_INT (ud2 << 16)));
+ emit_move_insn (dest, gen_rtx_IOR (DImode, dest,
+ GEN_INT (ud2 << 16)));
if (ud1 != 0)
emit_move_insn (dest, gen_rtx_IOR (DImode, dest, GEN_INT (ud1)));
}
@@ -3514,6 +3898,29 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c1, HOST_WIDE_INT c2)
return dest;
}
+/* Helper for the following. Get rid of [r+r] memory refs
+ in cases where it won't work (TImode, TFmode). */
+
+static void
+rs6000_eliminate_indexed_memrefs (rtx operands[2])
+{
+ if (GET_CODE (operands[0]) == MEM
+ && GET_CODE (XEXP (operands[0], 0)) != REG
+ && ! legitimate_constant_pool_address_p (XEXP (operands[0], 0))
+ && ! reload_in_progress)
+ operands[0]
+ = replace_equiv_address (operands[0],
+ copy_addr_to_reg (XEXP (operands[0], 0)));
+
+ if (GET_CODE (operands[1]) == MEM
+ && GET_CODE (XEXP (operands[1], 0)) != REG
+ && ! legitimate_constant_pool_address_p (XEXP (operands[1], 0))
+ && ! reload_in_progress)
+ operands[1]
+ = replace_equiv_address (operands[1],
+ copy_addr_to_reg (XEXP (operands[1], 0)));
+}
+
/* Emit a move from SOURCE to DEST in mode MODE. */
void
rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
@@ -3521,7 +3928,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
rtx operands[2];
operands[0] = dest;
operands[1] = source;
-
+
/* Sanity checks. Check that we get CONST_DOUBLE only when we should. */
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& ! FLOAT_MODE_P (mode)
@@ -3532,13 +3939,12 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
to a CONST_INT. */
operands[1] = gen_int_mode (CONST_DOUBLE_LOW (operands[1]), mode);
}
- if (GET_CODE (operands[1]) == CONST_DOUBLE
- && ! FLOAT_MODE_P (mode)
- && ((CONST_DOUBLE_HIGH (operands[1]) == 0
- && CONST_DOUBLE_LOW (operands[1]) >= 0)
- || (CONST_DOUBLE_HIGH (operands[1]) == -1
- && CONST_DOUBLE_LOW (operands[1]) < 0)))
- abort ();
+ gcc_assert (GET_CODE (operands[1]) != CONST_DOUBLE
+ || FLOAT_MODE_P (mode)
+ || ((CONST_DOUBLE_HIGH (operands[1]) != 0
+ || CONST_DOUBLE_LOW (operands[1]) < 0)
+ && (CONST_DOUBLE_HIGH (operands[1]) != -1
+ || CONST_DOUBLE_LOW (operands[1]) >= 0)));
/* Check if GCC is setting up a block move that will end up using FP
registers as temporaries. We must make sure this is acceptable. */
@@ -3550,7 +3956,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
&& ! (SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[0]) > 32
? 32 : MEM_ALIGN (operands[0])))
|| SLOW_UNALIGNED_ACCESS (SImode, (MEM_ALIGN (operands[1]) > 32
- ? 32
+ ? 32
: MEM_ALIGN (operands[1]))))
&& ! MEM_VOLATILE_P (operands [0])
&& ! MEM_VOLATILE_P (operands [1]))
@@ -3561,23 +3967,10 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
adjust_address (operands[1], SImode, 4));
return;
}
-
- if (!no_new_pseudos)
- {
- if (GET_CODE (operands[1]) == MEM && optimize > 0
- && (mode == QImode || mode == HImode || mode == SImode)
- && GET_MODE_SIZE (mode) < GET_MODE_SIZE (word_mode))
- {
- rtx reg = gen_reg_rtx (word_mode);
- emit_insn (gen_rtx_SET (word_mode, reg,
- gen_rtx_ZERO_EXTEND (word_mode,
- operands[1])));
- operands[1] = gen_lowpart (mode, reg);
- }
- if (GET_CODE (operands[0]) != REG)
- operands[1] = force_reg (mode, operands[1]);
- }
+ if (!no_new_pseudos && GET_CODE (operands[0]) == MEM
+ && !gpc_reg_operand (operands[1], mode))
+ operands[1] = force_reg (mode, operands[1]);
if (mode == SFmode && ! TARGET_POWERPC
&& TARGET_HARD_FLOAT && TARGET_FPRS
@@ -3591,7 +3984,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
regnum = REGNO (operands[1]);
else
regnum = -1;
-
+
/* If operands[1] is a register, on POWER it may have
double-precision data in it, so truncate it to single
precision. */
@@ -3606,11 +3999,29 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
/* Recognize the case where operand[1] is a reference to thread-local
data and load its address to a register. */
- if (GET_CODE (operands[1]) == SYMBOL_REF)
+ if (rs6000_tls_referenced_p (operands[1]))
{
- enum tls_model model = SYMBOL_REF_TLS_MODEL (operands[1]);
- if (model != 0)
- operands[1] = rs6000_legitimize_tls_address (operands[1], model);
+ enum tls_model model;
+ rtx tmp = operands[1];
+ rtx addend = NULL;
+
+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (tmp, 0), 1);
+ tmp = XEXP (XEXP (tmp, 0), 0);
+ }
+
+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+ model = SYMBOL_REF_TLS_MODEL (tmp);
+ gcc_assert (model != 0);
+
+ tmp = rs6000_legitimize_tls_address (tmp, model);
+ if (addend)
+ {
+ tmp = gen_rtx_PLUS (mode, tmp, addend);
+ tmp = force_operand (tmp, operands[0]);
+ }
+ operands[1] = tmp;
}
/* Handle the case where reload calls us with an invalid address. */
@@ -3619,14 +4030,9 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
|| ! nonimmediate_operand (operands[0], mode)))
goto emit_set;
- /* Handle the case of CONSTANT_P_RTX. */
- if (GET_CODE (operands[1]) == CONSTANT_P_RTX)
- goto emit_set;
-
/* 128-bit constant floating-point values on Darwin should really be
loaded as two parts. */
- if ((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
+ if (!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128
&& mode == TFmode && GET_CODE (operands[1]) == CONST_DOUBLE)
{
/* DImode is used, not DFmode, because simplify_gen_subreg doesn't
@@ -3655,13 +4061,16 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
break;
case TFmode:
+ rs6000_eliminate_indexed_memrefs (operands);
+ /* fall through */
+
case DFmode:
case SFmode:
- if (CONSTANT_P (operands[1])
+ if (CONSTANT_P (operands[1])
&& ! easy_fp_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
break;
-
+
case V16QImode:
case V8HImode:
case V4SFmode:
@@ -3674,14 +4083,14 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
&& !easy_vector_constant (operands[1], mode))
operands[1] = force_const_mem (mode, operands[1]);
break;
-
+
case SImode:
case DImode:
/* Use default pattern for address of ELF small data */
if (TARGET_ELF
&& mode == Pmode
&& DEFAULT_ABI == ABI_V4
- && (GET_CODE (operands[1]) == SYMBOL_REF
+ && (GET_CODE (operands[1]) == SYMBOL_REF
|| GET_CODE (operands[1]) == CONST)
&& small_data_operand (operands[1], mode))
{
@@ -3722,7 +4131,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
= CONSTANT_POOL_ADDRESS_P (operands[1]);
SYMBOL_REF_FLAGS (new_ref) = SYMBOL_REF_FLAGS (operands[1]);
SYMBOL_REF_USED (new_ref) = SYMBOL_REF_USED (operands[1]);
- SYMBOL_REF_DECL (new_ref) = SYMBOL_REF_DECL (operands[1]);
+ SYMBOL_REF_DATA (new_ref) = SYMBOL_REF_DATA (operands[1]);
operands[1] = new_ref;
}
@@ -3736,7 +4145,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
operands[1], mode, operands[0]);
if (operands[0] != operands[1])
emit_insn (gen_rtx_SET (VOIDmode,
- operands[0], operands[1]));
+ operands[0], operands[1]));
return;
}
#endif
@@ -3821,35 +4230,23 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
operands[1] = force_const_mem (mode, operands[1]);
- if (TARGET_TOC
+ if (TARGET_TOC
&& constant_pool_expr_p (XEXP (operands[1], 0))
&& ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (
get_pool_constant (XEXP (operands[1], 0)),
get_pool_mode (XEXP (operands[1], 0))))
{
operands[1]
- = gen_rtx_MEM (mode,
- create_TOC_reference (XEXP (operands[1], 0)));
+ = gen_const_mem (mode,
+ create_TOC_reference (XEXP (operands[1], 0)));
set_mem_alias_set (operands[1], get_TOC_alias_set ());
- RTX_UNCHANGING_P (operands[1]) = 1;
}
}
break;
case TImode:
- if (GET_CODE (operands[0]) == MEM
- && GET_CODE (XEXP (operands[0], 0)) != REG
- && ! reload_in_progress)
- operands[0]
- = replace_equiv_address (operands[0],
- copy_addr_to_reg (XEXP (operands[0], 0)));
-
- if (GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) != REG
- && ! reload_in_progress)
- operands[1]
- = replace_equiv_address (operands[1],
- copy_addr_to_reg (XEXP (operands[1], 0)));
+ rs6000_eliminate_indexed_memrefs (operands);
+
if (TARGET_POWER)
{
emit_insn (gen_rtx_PARALLEL (VOIDmode,
@@ -3863,7 +4260,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Above, we may have called force_const_mem which may have returned
@@ -3878,7 +4275,8 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
/* Nonzero if we can use a floating-point register to pass this arg. */
#define USE_FP_FOR_ARG_P(CUM,MODE,TYPE) \
- (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ (SCALAR_FLOAT_MODE_P (MODE) \
+ && !DECIMAL_FLOAT_MODE_P (MODE) \
&& (CUM)->fregno <= FP_ARG_MAX_REG \
&& TARGET_HARD_FLOAT && TARGET_FPRS)
@@ -3898,7 +4296,7 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
returned in memory. The Darwin ABI does the same. The SVR4 ABI
specifies that structures <= 8 bytes are returned in r3/r4, but a
draft put them in memory, and GCC used to implement the draft
- instead of the final standard. Therefore, TARGET_AIX_STRUCT_RET
+ instead of the final standard. Therefore, aix_struct_return
controls this instead of DEFAULT_ABI; V.4 targets needing backward
compatibility can change DRAFT_V4_STRUCT_RET to override the
default, and -m switches get the final word. See
@@ -3913,12 +4311,54 @@ rs6000_emit_move (rtx dest, rtx source, enum machine_mode mode)
static bool
rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
{
+ /* In the darwin64 abi, try to use registers for larger structs
+ if possible. */
+ if (rs6000_darwin64_abi
+ && TREE_CODE (type) == RECORD_TYPE
+ && int_size_in_bytes (type) > 0)
+ {
+ CUMULATIVE_ARGS valcum;
+ rtx valret;
+
+ valcum.words = 0;
+ valcum.fregno = FP_ARG_MIN_REG;
+ valcum.vregno = ALTIVEC_ARG_MIN_REG;
+ /* Do a trial code generation as if this were going to be passed
+ as an argument; if any part goes in memory, we return NULL. */
+ valret = rs6000_darwin64_record_arg (&valcum, type, 1, true);
+ if (valret)
+ return false;
+ /* Otherwise fall through to more conventional ABI rules. */
+ }
+
if (AGGREGATE_TYPE_P (type)
- && (TARGET_AIX_STRUCT_RET
+ && (aix_struct_return
|| (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8))
return true;
- if (DEFAULT_ABI == ABI_V4 && TYPE_MODE (type) == TFmode)
+
+ /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector
+ modes only exist for GCC vector types if -maltivec. */
+ if (TARGET_32BIT && !TARGET_ALTIVEC_ABI
+ && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
+ return false;
+
+ /* Return synthetic vectors in memory. */
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
+ {
+ static bool warned_for_return_big_vectors = false;
+ if (!warned_for_return_big_vectors)
+ {
+ warning (0, "GCC vector returned by reference: "
+ "non-standard ABI extension with no compatibility guarantee");
+ warned_for_return_big_vectors = true;
+ }
+ return true;
+ }
+
+ if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && TYPE_MODE (type) == TFmode)
return true;
+
return false;
}
@@ -3930,7 +4370,7 @@ rs6000_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
so we never return a PARALLEL. */
void
-init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
+init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
rtx libname ATTRIBUTE_UNUSED, int incoming,
int libcall, int n_named_args)
{
@@ -3976,18 +4416,29 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
fprintf (stderr, " proto = %d, nargs = %d\n",
cum->prototype, cum->nargs_prototype);
}
-
- if (fntype
- && !TARGET_ALTIVEC
- && TARGET_ALTIVEC_ABI
- && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
- {
- error ("Cannot return value in vector register because"
- " altivec instructions are disabled, use -maltivec"
- " to enable them.");
- }
+
+ if (fntype
+ && !TARGET_ALTIVEC
+ && TARGET_ALTIVEC_ABI
+ && ALTIVEC_VECTOR_MODE (TYPE_MODE (TREE_TYPE (fntype))))
+ {
+ error ("cannot return value in vector register because"
+ " altivec instructions are disabled, use -maltivec"
+ " to enable them");
+ }
}
+/* Return true if TYPE must be passed on the stack and not in registers. */
+
+static bool
+rs6000_must_pass_in_stack (enum machine_mode mode, tree type)
+{
+ if (DEFAULT_ABI == ABI_AIX || TARGET_64BIT)
+ return must_pass_in_stack_var_size (mode, type);
+ else
+ return must_pass_in_stack_var_size_or_pad (mode, type);
+}
+
/* If defined, a C expression which determines whether, and in which
direction, to pad out an argument with extra space. The value
should be of type `enum direction': either `upward' to pad above
@@ -4011,7 +4462,7 @@ function_arg_padding (enum machine_mode mode, tree type)
{
/* GCC used to pass structures of the same size as integer types as
if they were in fact integers, ignoring FUNCTION_ARG_PADDING.
- ie. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
+ i.e. Structures of size 1 or 2 (or 4 when TARGET_64BIT) were
passed padded downward, except that -mstrict-align further
muddied the water in that multi-component structures of 2 and 4
bytes in size were passed padded upward.
@@ -4047,24 +4498,58 @@ function_arg_padding (enum machine_mode mode, tree type)
}
/* If defined, a C expression that gives the alignment boundary, in bits,
- of an argument with the specified mode and type. If it is not defined,
+ of an argument with the specified mode and type. If it is not defined,
PARM_BOUNDARY is used for all arguments.
-
- V.4 wants long longs to be double word aligned. */
+
+ V.4 wants long longs and doubles to be double word aligned. Just
+ testing the mode size is a boneheaded way to do this as it means
+ that other types such as complex int are also double word aligned.
+ However, we're stuck with this because changing the ABI might break
+ existing library interfaces.
+
+ Doubleword align SPE vectors.
+ Quadword align Altivec vectors.
+ Quadword align large synthetic vector types. */
int
-function_arg_boundary (enum machine_mode mode, tree type ATTRIBUTE_UNUSED)
+function_arg_boundary (enum machine_mode mode, tree type)
{
- if (DEFAULT_ABI == ABI_V4 && GET_MODE_SIZE (mode) == 8)
+ if (DEFAULT_ABI == ABI_V4
+ && (GET_MODE_SIZE (mode) == 8
+ || (TARGET_HARD_FLOAT
+ && TARGET_FPRS
+ && mode == TFmode)))
return 64;
- else if (SPE_VECTOR_MODE (mode))
+ else if (SPE_VECTOR_MODE (mode)
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) >= 8
+ && int_size_in_bytes (type) < 16))
return 64;
- else if (ALTIVEC_VECTOR_MODE (mode))
+ else if (ALTIVEC_VECTOR_MODE (mode)
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) >= 16))
+ return 128;
+ else if (rs6000_darwin64_abi && mode == BLKmode
+ && type && TYPE_ALIGN (type) > 64)
return 128;
else
return PARM_BOUNDARY;
}
+/* For a function parm of MODE and TYPE, return the starting word in
+ the parameter area. NWORDS of the parameter area are already used. */
+
+static unsigned int
+rs6000_parm_start (enum machine_mode mode, tree type, unsigned int nwords)
+{
+ unsigned int align;
+ unsigned int parm_offset;
+
+ align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
+ parm_offset = DEFAULT_ABI == ABI_V4 ? 2 : 6;
+ return nwords + (-(parm_offset + nwords) & align);
+}
+
/* Compute the size (in words) of a function argument. */
static unsigned long
@@ -4083,6 +4568,89 @@ rs6000_arg_size (enum machine_mode mode, tree type)
return (size + 7) >> 3;
}
+/* Use this to flush pending int fields. */
+
+static void
+rs6000_darwin64_record_arg_advance_flush (CUMULATIVE_ARGS *cum,
+ HOST_WIDE_INT bitpos)
+{
+ unsigned int startbit, endbit;
+ int intregs, intoffset;
+ enum machine_mode mode;
+
+ if (cum->intoffset == -1)
+ return;
+
+ intoffset = cum->intoffset;
+ cum->intoffset = -1;
+
+ if (intoffset % BITS_PER_WORD != 0)
+ {
+ mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
+ MODE_INT, 0);
+ if (mode == BLKmode)
+ {
+ /* We couldn't find an appropriate mode, which happens,
+ e.g., in packed structs when there are 3 bytes to load.
+ Back intoffset back to the beginning of the word in this
+ case. */
+ intoffset = intoffset & -BITS_PER_WORD;
+ }
+ }
+
+ startbit = intoffset & -BITS_PER_WORD;
+ endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+ intregs = (endbit - startbit) / BITS_PER_WORD;
+ cum->words += intregs;
+}
+
+/* The darwin64 ABI calls for us to recurse down through structs,
+ looking for elements passed in registers. Unfortunately, we have
+ to track int register count here also because of misalignments
+ in powerpc alignment mode. */
+
+static void
+rs6000_darwin64_record_arg_advance_recurse (CUMULATIVE_ARGS *cum,
+ tree type,
+ HOST_WIDE_INT startbitpos)
+{
+ tree f;
+
+ for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
+ if (TREE_CODE (f) == FIELD_DECL)
+ {
+ HOST_WIDE_INT bitpos = startbitpos;
+ tree ftype = TREE_TYPE (f);
+ enum machine_mode mode;
+ if (ftype == error_mark_node)
+ continue;
+ mode = TYPE_MODE (ftype);
+
+ if (DECL_SIZE (f) != 0
+ && host_integerp (bit_position (f), 1))
+ bitpos += int_bit_position (f);
+
+ /* ??? FIXME: else assume zero offset. */
+
+ if (TREE_CODE (ftype) == RECORD_TYPE)
+ rs6000_darwin64_record_arg_advance_recurse (cum, ftype, bitpos);
+ else if (USE_FP_FOR_ARG_P (cum, mode, ftype))
+ {
+ rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
+ cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
+ cum->words += (GET_MODE_SIZE (mode) + 7) >> 3;
+ }
+ else if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, 1))
+ {
+ rs6000_darwin64_record_arg_advance_flush (cum, bitpos);
+ cum->vregno++;
+ cum->words += 2;
+ }
+ else if (cum->intoffset == -1)
+ cum->intoffset = bitpos;
+ }
+}
+
/* 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.)
@@ -4092,25 +4660,32 @@ rs6000_arg_size (enum machine_mode mode, tree type)
itself. */
void
-function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named)
+function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int named, int depth)
{
- cum->nargs_prototype--;
+ int size;
+
+ /* Only tick off an argument if we're not recursing. */
+ if (depth == 0)
+ cum->nargs_prototype--;
- if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ if (TARGET_ALTIVEC_ABI
+ && (ALTIVEC_VECTOR_MODE (mode)
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
{
bool stack = false;
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
- {
+ {
cum->vregno++;
if (!TARGET_ALTIVEC)
- error ("Cannot pass argument in vector register because"
+ error ("cannot pass argument in vector register because"
" altivec instructions are disabled, use -maltivec"
- " to enable them.");
+ " to enable them");
/* PowerPC64 Linux and AIX allocate GPRs for a vector argument
- even if it is going to be passed in a vector register.
+ even if it is going to be passed in a vector register.
Darwin does the same for variable-argument functions. */
if ((DEFAULT_ABI == ABI_AIX && TARGET_64BIT)
|| (cum->stdarg && DEFAULT_ABI != ABI_V4))
@@ -4120,9 +4695,9 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
stack = true;
if (stack)
- {
+ {
int align;
-
+
/* Vector parameters must be 16-byte aligned. This places
them at 2 mod 4 in terms of words in 32-bit mode, since
the parameter save area starts at offset 24 from the
@@ -4135,13 +4710,13 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
else
align = cum->words & 1;
cum->words += align + rs6000_arg_size (mode, type);
-
+
if (TARGET_DEBUG_ARG)
{
- fprintf (stderr, "function_adv: words = %2d, align=%d, ",
+ fprintf (stderr, "function_adv: words = %2d, align=%d, ",
cum->words, align);
fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s\n",
- cum->nargs_prototype, cum->prototype,
+ cum->nargs_prototype, cum->prototype,
GET_MODE_NAME (mode));
}
}
@@ -4150,17 +4725,46 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
&& !cum->stdarg
&& cum->sysv_gregno <= GP_ARG_MAX_REG)
cum->sysv_gregno++;
+
+ else if (rs6000_darwin64_abi
+ && mode == BLKmode
+ && TREE_CODE (type) == RECORD_TYPE
+ && (size = int_size_in_bytes (type)) > 0)
+ {
+ /* Variable sized types have size == -1 and are
+ treated as if consisting entirely of ints.
+ Pad to 16 byte boundary if needed. */
+ if (TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
+ && (cum->words % 2) != 0)
+ cum->words++;
+ /* For varargs, we can just go up by the size of the struct. */
+ if (!named)
+ cum->words += (size + 7) / 8;
+ else
+ {
+ /* It is tempting to say int register count just goes up by
+ sizeof(type)/8, but this is wrong in a case such as
+ { int; double; int; } [powerpc alignment]. We have to
+ grovel through the fields for these too. */
+ cum->intoffset = 0;
+ rs6000_darwin64_record_arg_advance_recurse (cum, type, 0);
+ rs6000_darwin64_record_arg_advance_flush (cum,
+ size * BITS_PER_UNIT);
+ }
+ }
else if (DEFAULT_ABI == ABI_V4)
{
if (TARGET_HARD_FLOAT && TARGET_FPRS
- && (mode == SFmode || mode == DFmode))
+ && (mode == SFmode || mode == DFmode
+ || (mode == TFmode && !TARGET_IEEEQUAD)))
{
- if (cum->fregno <= FP_ARG_V4_MAX_REG)
- cum->fregno++;
+ if (cum->fregno + (mode == TFmode ? 1 : 0) <= FP_ARG_V4_MAX_REG)
+ cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
else
{
- if (mode == DFmode)
- cum->words += cum->words & 1;
+ cum->fregno = FP_ARG_V4_MAX_REG + 1;
+ if (mode == DFmode || mode == TFmode)
+ cum->words += cum->words & 1;
cum->words += rs6000_arg_size (mode, type);
}
}
@@ -4205,17 +4809,13 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
else
{
int n_words = rs6000_arg_size (mode, type);
- int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
+ int start_words = cum->words;
+ int align_words = rs6000_parm_start (mode, type, start_words);
- /* The simple alignment calculation here works because
- function_arg_boundary / PARM_BOUNDARY will only be 1 or 2.
- If we ever want to handle alignments larger than 8 bytes for
- 32-bit or 16 bytes for 64-bit, then we'll need to take into
- account the offset to the start of the parm save area. */
- align &= cum->words;
- cum->words += align + n_words;
+ cum->words = align_words + n_words;
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ if (SCALAR_FLOAT_MODE_P (mode)
+ && !DECIMAL_FLOAT_MODE_P (mode)
&& TARGET_HARD_FLOAT && TARGET_FPRS)
cum->fregno += (GET_MODE_SIZE (mode) + 7) >> 3;
@@ -4225,20 +4825,61 @@ function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->words, cum->fregno);
fprintf (stderr, "nargs = %4d, proto = %d, mode = %4s, ",
cum->nargs_prototype, cum->prototype, GET_MODE_NAME (mode));
- fprintf (stderr, "named = %d, align = %d\n", named, align);
+ fprintf (stderr, "named = %d, align = %d, depth = %d\n",
+ named, align_words - start_words, depth);
}
}
}
-/* Determine where to put a SIMD argument on the SPE. */
+static rtx
+spe_build_register_parallel (enum machine_mode mode, int gregno)
+{
+ rtx r1, r3;
+
+ switch (mode)
+ {
+ case DFmode:
+ r1 = gen_rtx_REG (DImode, gregno);
+ r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
+ return gen_rtx_PARALLEL (mode, gen_rtvec (1, r1));
+
+ case DCmode:
+ r1 = gen_rtx_REG (DImode, gregno);
+ r1 = gen_rtx_EXPR_LIST (VOIDmode, r1, const0_rtx);
+ r3 = gen_rtx_REG (DImode, gregno + 2);
+ r3 = gen_rtx_EXPR_LIST (VOIDmode, r3, GEN_INT (8));
+ return gen_rtx_PARALLEL (mode, gen_rtvec (2, r1, r3));
+
+ default:
+ gcc_unreachable ();
+ }
+}
+/* Determine where to put a SIMD argument on the SPE. */
static rtx
-rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type)
{
+ int gregno = cum->sysv_gregno;
+
+ /* On E500 v2, double arithmetic is done on the full 64-bit GPR, but
+ are passed and returned in a pair of GPRs for ABI compatibility. */
+ if (TARGET_E500_DOUBLE && (mode == DFmode || mode == DCmode))
+ {
+ int n_words = rs6000_arg_size (mode, type);
+
+ /* Doubles go in an odd/even register pair (r5/r6, etc). */
+ if (mode == DFmode)
+ gregno += (1 - gregno) & 1;
+
+ /* Multi-reg args are not split between registers and stack. */
+ if (gregno + n_words - 1 > GP_ARG_MAX_REG)
+ return NULL_RTX;
+
+ return spe_build_register_parallel (mode, gregno);
+ }
if (cum->stdarg)
{
- int gregno = cum->sysv_gregno;
int n_words = rs6000_arg_size (mode, type);
/* SPE vectors are put in odd registers. */
@@ -4261,13 +4902,198 @@ rs6000_spe_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- if (cum->sysv_gregno <= GP_ARG_MAX_REG)
- return gen_rtx_REG (mode, cum->sysv_gregno);
+ if (gregno <= GP_ARG_MAX_REG)
+ return gen_rtx_REG (mode, gregno);
else
return NULL_RTX;
}
}
+/* A subroutine of rs6000_darwin64_record_arg. Assign the bits of the
+ structure between cum->intoffset and bitpos to integer registers. */
+
+static void
+rs6000_darwin64_record_arg_flush (CUMULATIVE_ARGS *cum,
+ HOST_WIDE_INT bitpos, rtx rvec[], int *k)
+{
+ enum machine_mode mode;
+ unsigned int regno;
+ unsigned int startbit, endbit;
+ int this_regno, intregs, intoffset;
+ rtx reg;
+
+ if (cum->intoffset == -1)
+ return;
+
+ intoffset = cum->intoffset;
+ cum->intoffset = -1;
+
+ /* If this is the trailing part of a word, try to only load that
+ much into the register. Otherwise load the whole register. Note
+ that in the latter case we may pick up unwanted bits. It's not a
+ problem at the moment but may wish to revisit. */
+
+ if (intoffset % BITS_PER_WORD != 0)
+ {
+ mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
+ MODE_INT, 0);
+ if (mode == BLKmode)
+ {
+ /* We couldn't find an appropriate mode, which happens,
+ e.g., in packed structs when there are 3 bytes to load.
+ Back intoffset back to the beginning of the word in this
+ case. */
+ intoffset = intoffset & -BITS_PER_WORD;
+ mode = word_mode;
+ }
+ }
+ else
+ mode = word_mode;
+
+ startbit = intoffset & -BITS_PER_WORD;
+ endbit = (bitpos + BITS_PER_WORD - 1) & -BITS_PER_WORD;
+ intregs = (endbit - startbit) / BITS_PER_WORD;
+ this_regno = cum->words + intoffset / BITS_PER_WORD;
+
+ if (intregs > 0 && intregs > GP_ARG_NUM_REG - this_regno)
+ cum->use_stack = 1;
+
+ intregs = MIN (intregs, GP_ARG_NUM_REG - this_regno);
+ if (intregs <= 0)
+ return;
+
+ intoffset /= BITS_PER_UNIT;
+ do
+ {
+ regno = GP_ARG_MIN_REG + this_regno;
+ reg = gen_rtx_REG (mode, regno);
+ rvec[(*k)++] =
+ gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (intoffset));
+
+ this_regno += 1;
+ intoffset = (intoffset | (UNITS_PER_WORD-1)) + 1;
+ mode = word_mode;
+ intregs -= 1;
+ }
+ while (intregs > 0);
+}
+
+/* Recursive workhorse for the following. */
+
+static void
+rs6000_darwin64_record_arg_recurse (CUMULATIVE_ARGS *cum, tree type,
+ HOST_WIDE_INT startbitpos, rtx rvec[],
+ int *k)
+{
+ tree f;
+
+ for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
+ if (TREE_CODE (f) == FIELD_DECL)
+ {
+ HOST_WIDE_INT bitpos = startbitpos;
+ tree ftype = TREE_TYPE (f);
+ enum machine_mode mode;
+ if (ftype == error_mark_node)
+ continue;
+ mode = TYPE_MODE (ftype);
+
+ if (DECL_SIZE (f) != 0
+ && host_integerp (bit_position (f), 1))
+ bitpos += int_bit_position (f);
+
+ /* ??? FIXME: else assume zero offset. */
+
+ if (TREE_CODE (ftype) == RECORD_TYPE)
+ rs6000_darwin64_record_arg_recurse (cum, ftype, bitpos, rvec, k);
+ else if (cum->named && USE_FP_FOR_ARG_P (cum, mode, ftype))
+ {
+#if 0
+ switch (mode)
+ {
+ case SCmode: mode = SFmode; break;
+ case DCmode: mode = DFmode; break;
+ case TCmode: mode = TFmode; break;
+ default: break;
+ }
+#endif
+ rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
+ rvec[(*k)++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, cum->fregno++),
+ GEN_INT (bitpos / BITS_PER_UNIT));
+ if (mode == TFmode)
+ cum->fregno++;
+ }
+ else if (cum->named && USE_ALTIVEC_FOR_ARG_P (cum, mode, ftype, 1))
+ {
+ rs6000_darwin64_record_arg_flush (cum, bitpos, rvec, k);
+ rvec[(*k)++]
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, cum->vregno++),
+ GEN_INT (bitpos / BITS_PER_UNIT));
+ }
+ else if (cum->intoffset == -1)
+ cum->intoffset = bitpos;
+ }
+}
+
+/* For the darwin64 ABI, we want to construct a PARALLEL consisting of
+ the register(s) to be used for each field and subfield of a struct
+ being passed by value, along with the offset of where the
+ register's value may be found in the block. FP fields go in FP
+ register, vector fields go in vector registers, and everything
+ else goes in int registers, packed as in memory.
+
+ This code is also used for function return values. RETVAL indicates
+ whether this is the case.
+
+ Much of this is taken from the SPARC V9 port, which has a similar
+ calling convention. */
+
+static rtx
+rs6000_darwin64_record_arg (CUMULATIVE_ARGS *orig_cum, tree type,
+ int named, bool retval)
+{
+ rtx rvec[FIRST_PSEUDO_REGISTER];
+ int k = 1, kbase = 1;
+ HOST_WIDE_INT typesize = int_size_in_bytes (type);
+ /* This is a copy; modifications are not visible to our caller. */
+ CUMULATIVE_ARGS copy_cum = *orig_cum;
+ CUMULATIVE_ARGS *cum = &copy_cum;
+
+ /* Pad to 16 byte boundary if needed. */
+ if (!retval && TYPE_ALIGN (type) >= 2 * BITS_PER_WORD
+ && (cum->words % 2) != 0)
+ cum->words++;
+
+ cum->intoffset = 0;
+ cum->use_stack = 0;
+ cum->named = named;
+
+ /* Put entries into rvec[] for individual FP and vector fields, and
+ for the chunks of memory that go in int regs. Note we start at
+ element 1; 0 is reserved for an indication of using memory, and
+ may or may not be filled in below. */
+ rs6000_darwin64_record_arg_recurse (cum, type, 0, rvec, &k);
+ rs6000_darwin64_record_arg_flush (cum, typesize * BITS_PER_UNIT, rvec, &k);
+
+ /* If any part of the struct went on the stack put all of it there.
+ This hack is because the generic code for
+ FUNCTION_ARG_PARTIAL_NREGS cannot handle cases where the register
+ parts of the struct are not at the beginning. */
+ if (cum->use_stack)
+ {
+ if (retval)
+ return NULL_RTX; /* doesn't go in registers at all */
+ kbase = 0;
+ rvec[0] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
+ }
+ if (k > 1 || cum->use_stack)
+ return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (k - kbase, &rvec[kbase]));
+ else
+ return NULL_RTX;
+}
+
/* Determine where to place an argument in 64-bit mode with 32-bit ABI. */
static rtx
@@ -4293,15 +5119,13 @@ rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
if (align_words + n_units > GP_ARG_NUM_REG)
/* Not all of the arg fits in gprs. Say that it goes in memory too,
using a magic NULL_RTX component.
- FIXME: This is not strictly correct. Only some of the arg
- belongs in memory, not all of it. However, there isn't any way
- to do this currently, apart from building rtx descriptions for
- the pieces of memory we want stored. Due to bugs in the generic
- code we can't use the normal function_arg_partial_nregs scheme
- with the PARALLEL arg description we emit here.
- In any case, the code to store the whole arg to memory is often
- more efficient than code to store pieces, and we know that space
- is available in the right place for the whole arg. */
+ This is not strictly correct. Only some of the arg belongs in
+ memory, not all of it. However, the normal scheme using
+ function_arg_partial_nregs can result in unusual subregs, eg.
+ (subreg:SI (reg:DF) 4), which are not handled well. The code to
+ store the whole arg to memory is often more efficient than code
+ to store pieces, and we know that space is available in the right
+ place for the whole arg. */
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX, const0_rtx);
i = 0;
@@ -4325,7 +5149,8 @@ rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
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.
+ the preceding args and about the function being called. It is
+ not modified in this routine.
NAMED is nonzero if this argument is a named parameter
(otherwise it is an extra parameter matching an ellipsis).
@@ -4343,8 +5168,8 @@ rs6000_mixed_function_arg (enum machine_mode mode, tree type, int align_words)
with MODE and TYPE set to that of the pointer to the arg, not the arg
itself. */
-struct rtx_def *
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+rtx
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named)
{
enum rs6000_abi abi = DEFAULT_ABI;
@@ -4374,34 +5199,46 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return GEN_INT (cum->call_cookie);
}
+ if (rs6000_darwin64_abi && mode == BLKmode
+ && TREE_CODE (type) == RECORD_TYPE)
+ {
+ rtx rslt = rs6000_darwin64_record_arg (cum, type, named, false);
+ if (rslt != NULL_RTX)
+ return rslt;
+ /* Else fall through to usual handling. */
+ }
+
if (USE_ALTIVEC_FOR_ARG_P (cum, mode, type, named))
if (TARGET_64BIT && ! cum->prototype)
{
- /* Vector parameters get passed in vector register
- and also in GPRs or memory, in absence of prototype. */
- int align_words;
- rtx slot;
- align_words = (cum->words + 1) & ~1;
-
- if (align_words >= GP_ARG_NUM_REG)
- {
- slot = NULL_RTX;
- }
- else
- {
- slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
- }
- return gen_rtx_PARALLEL (mode,
- gen_rtvec (2,
- gen_rtx_EXPR_LIST (VOIDmode,
- slot, const0_rtx),
- gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (mode, cum->vregno),
- const0_rtx)));
+ /* Vector parameters get passed in vector register
+ and also in GPRs or memory, in absence of prototype. */
+ int align_words;
+ rtx slot;
+ align_words = (cum->words + 1) & ~1;
+
+ if (align_words >= GP_ARG_NUM_REG)
+ {
+ slot = NULL_RTX;
+ }
+ else
+ {
+ slot = gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
+ }
+ return gen_rtx_PARALLEL (mode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ slot, const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (mode, cum->vregno),
+ const0_rtx)));
}
else
return gen_rtx_REG (mode, cum->vregno);
- else if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ else if (TARGET_ALTIVEC_ABI
+ && (ALTIVEC_VECTOR_MODE (mode)
+ || (type && TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) == 16)))
{
if (named || abi == ABI_V4)
return NULL_RTX;
@@ -4442,14 +5279,19 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
return gen_rtx_REG (part_mode, GP_ARG_MIN_REG + align_words);
}
}
- else if (TARGET_SPE_ABI && TARGET_SPE && SPE_VECTOR_MODE (mode))
+ else if (TARGET_SPE_ABI && TARGET_SPE
+ && (SPE_VECTOR_MODE (mode)
+ || (TARGET_E500_DOUBLE && (mode == DFmode
+ || mode == DCmode))))
return rs6000_spe_function_arg (cum, mode, type);
+
else if (abi == ABI_V4)
{
if (TARGET_HARD_FLOAT && TARGET_FPRS
- && (mode == SFmode || mode == DFmode))
+ && (mode == SFmode || mode == DFmode
+ || (mode == TFmode && !TARGET_IEEEQUAD)))
{
- if (cum->fregno <= FP_ARG_V4_MAX_REG)
+ if (cum->fregno + (mode == TFmode ? 1 : 0) <= FP_ARG_V4_MAX_REG)
return gen_rtx_REG (mode, cum->fregno);
else
return NULL_RTX;
@@ -4477,8 +5319,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
else
{
- int align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
- int align_words = cum->words + (cum->words & align);
+ int align_words = rs6000_parm_start (mode, type, cum->words);
if (USE_FP_FOR_ARG_P (cum, mode, type))
{
@@ -4493,8 +5334,7 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
{
/* Currently, we only ever need one reg here because complex
doubles are split. */
- if (cum->fregno != FP_ARG_MAX_REG || fmode != TFmode)
- abort ();
+ gcc_assert (cum->fregno == FP_ARG_MAX_REG && fmode == TFmode);
/* Long double split over regs and memory. */
fmode = DFmode;
@@ -4527,11 +5367,21 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
include the portion actually in registers here. */
enum machine_mode rmode = TARGET_32BIT ? SImode : DImode;
rtx off;
+ int i = 0;
+ if (align_words + n_words > GP_ARG_NUM_REG)
+ /* Not all of the arg fits in gprs. Say that it
+ goes in memory too, using a magic NULL_RTX
+ component. Also see comment in
+ rs6000_mixed_function_arg for why the normal
+ function_arg_partial_nregs scheme doesn't work
+ in this case. */
+ rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, NULL_RTX,
+ const0_rtx);
do
{
r = gen_rtx_REG (rmode,
GP_ARG_MIN_REG + align_words);
- off = GEN_INT (k * GET_MODE_SIZE (rmode));
+ off = GEN_INT (i++ * GET_MODE_SIZE (rmode));
rvec[k++] = gen_rtx_EXPR_LIST (VOIDmode, r, off);
}
while (++align_words < GP_ARG_NUM_REG && --n_words != 0);
@@ -4559,6 +5409,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
if (TARGET_32BIT && TARGET_POWERPC64)
return rs6000_mixed_function_arg (mode, type, align_words);
+ if (mode == BLKmode)
+ mode = Pmode;
+
return gen_rtx_REG (mode, GP_ARG_MIN_REG + align_words);
}
else
@@ -4567,18 +5420,16 @@ function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode,
}
/* 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. When an arg is described by a PARALLEL,
- perhaps using more than one register type, this function returns the
- number of registers used by the first element of the PARALLEL. */
+ the number of bytes passed in registers. For args passed entirely in
+ registers or entirely in memory, zero. When an arg is described by a
+ PARALLEL, perhaps using more than one register type, this function
+ returns the number of bytes used by the first element of the PARALLEL. */
-int
-function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int named)
+static int
+rs6000_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, bool named)
{
int ret = 0;
- int align;
- int parm_offset;
int align_words;
if (DEFAULT_ABI == ABI_V4)
@@ -4588,32 +5439,39 @@ function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
&& cum->nargs_prototype >= 0)
return 0;
- align = function_arg_boundary (mode, type) / PARM_BOUNDARY - 1;
- parm_offset = TARGET_32BIT ? 2 : 0;
- align_words = cum->words + ((parm_offset - cum->words) & align);
-
- if (USE_FP_FOR_ARG_P (cum, mode, type)
- /* If we are passing this arg in gprs as well, then this function
- should return the number of gprs (or memory) partially passed,
- *not* the number of fprs. */
- && !(type
- && (cum->nargs_prototype <= 0
- || (DEFAULT_ABI == ABI_AIX
- && TARGET_XL_COMPAT
- && align_words >= GP_ARG_NUM_REG))))
- {
- if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3) > FP_ARG_MAX_REG + 1)
- ret = FP_ARG_MAX_REG + 1 - cum->fregno;
+ /* In this complicated case we just disable the partial_nregs code. */
+ if (rs6000_darwin64_abi && mode == BLKmode
+ && TREE_CODE (type) == RECORD_TYPE
+ && int_size_in_bytes (type) > 0)
+ return 0;
+
+ align_words = rs6000_parm_start (mode, type, cum->words);
+
+ if (USE_FP_FOR_ARG_P (cum, mode, type))
+ {
+ /* If we are passing this arg in the fixed parameter save area
+ (gprs or memory) as well as fprs, then this function should
+ return the number of partial bytes passed in the parameter
+ save area rather than partial bytes passed in fprs. */
+ if (type
+ && (cum->nargs_prototype <= 0
+ || (DEFAULT_ABI == ABI_AIX
+ && TARGET_XL_COMPAT
+ && align_words >= GP_ARG_NUM_REG)))
+ return 0;
+ else if (cum->fregno + ((GET_MODE_SIZE (mode) + 7) >> 3)
+ > FP_ARG_MAX_REG + 1)
+ ret = (FP_ARG_MAX_REG + 1 - cum->fregno) * 8;
else if (cum->nargs_prototype >= 0)
return 0;
}
if (align_words < GP_ARG_NUM_REG
&& GP_ARG_NUM_REG < align_words + rs6000_arg_size (mode, type))
- ret = GP_ARG_NUM_REG - align_words;
+ ret = (GP_ARG_NUM_REG - align_words) * (TARGET_32BIT ? 4 : 8);
if (ret != 0 && TARGET_DEBUG_ARG)
- fprintf (stderr, "function_arg_partial_nregs: %d\n", ret);
+ fprintf (stderr, "rs6000_arg_partial_bytes: %d\n", ret);
return ret;
}
@@ -4632,22 +5490,60 @@ function_arg_partial_nregs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
As an extension to all ABIs, variable sized types are passed by
reference. */
-int
-function_arg_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- tree type, int named ATTRIBUTE_UNUSED)
+static bool
+rs6000_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
{
- if ((DEFAULT_ABI == ABI_V4
- && ((type && AGGREGATE_TYPE_P (type))
- || mode == TFmode))
- || (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
- || (type && int_size_in_bytes (type) < 0))
+ if (DEFAULT_ABI == ABI_V4 && TARGET_IEEEQUAD && mode == TFmode)
{
if (TARGET_DEBUG_ARG)
- fprintf (stderr, "function_arg_pass_by_reference\n");
+ fprintf (stderr, "function_arg_pass_by_reference: V4 long double\n");
+ return 1;
+ }
+ if (!type)
+ return 0;
+
+ if (DEFAULT_ABI == ABI_V4 && AGGREGATE_TYPE_P (type))
+ {
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference: V4 aggregate\n");
+ return 1;
+ }
+
+ if (int_size_in_bytes (type) < 0)
+ {
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference: variable size\n");
+ return 1;
+ }
+
+ /* Allow -maltivec -mabi=no-altivec without warning. Altivec vector
+ modes only exist for GCC vector types if -maltivec. */
+ if (TARGET_32BIT && !TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ {
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference: AltiVec\n");
+ return 1;
+ }
+
+ /* Pass synthetic vectors in memory. */
+ if (TREE_CODE (type) == VECTOR_TYPE
+ && int_size_in_bytes (type) > (TARGET_ALTIVEC_ABI ? 16 : 8))
+ {
+ static bool warned_for_pass_big_vectors = false;
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "function_arg_pass_by_reference: synthetic vector\n");
+ if (!warned_for_pass_big_vectors)
+ {
+ warning (0, "GCC vector passed by reference: "
+ "non-standard ABI extension with no compatibility guarantee");
+ warned_for_pass_big_vectors = true;
+ }
return 1;
}
+
return 0;
}
@@ -4660,30 +5556,28 @@ rs6000_move_block_from_reg (int regno, rtx x, int nregs)
if (nregs == 0)
return;
- for (i = 0; i < nregs; i++)
+ for (i = 0; i < nregs; i++)
{
- rtx tem = adjust_address_nv (x, reg_mode, i*GET_MODE_SIZE(reg_mode));
+ rtx tem = adjust_address_nv (x, reg_mode, i * GET_MODE_SIZE (reg_mode));
if (reload_completed)
- {
- if (! strict_memory_address_p (reg_mode, XEXP (tem, 0)))
- tem = NULL_RTX;
- else
- tem = simplify_gen_subreg (reg_mode, x, BLKmode,
- i * GET_MODE_SIZE(reg_mode));
- }
+ {
+ if (! strict_memory_address_p (reg_mode, XEXP (tem, 0)))
+ tem = NULL_RTX;
+ else
+ tem = simplify_gen_subreg (reg_mode, x, BLKmode,
+ i * GET_MODE_SIZE (reg_mode));
+ }
else
tem = replace_equiv_address (tem, XEXP (tem, 0));
- if (tem == NULL_RTX)
- abort ();
+ gcc_assert (tem);
emit_move_insn (tem, gen_rtx_REG (reg_mode, regno + i));
}
}
-
/* Perform any needed actions needed for a function that is receiving a
- variable number of arguments.
+ variable number of arguments.
CUM is as above.
@@ -4697,8 +5591,9 @@ rs6000_move_block_from_reg (int regno, rtx x, int nregs)
stack and set PRETEND_SIZE to the length of the registers pushed. */
static void
-setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- tree type, int *pretend_size ATTRIBUTE_UNUSED, int no_rtl)
+setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, int *pretend_size ATTRIBUTE_UNUSED,
+ int no_rtl)
{
CUMULATIVE_ARGS next_cum;
int reg_size = TARGET_32BIT ? 4 : 8;
@@ -4707,68 +5602,145 @@ setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
/* Skip the last named argument. */
next_cum = *cum;
- function_arg_advance (&next_cum, mode, type, 1);
+ function_arg_advance (&next_cum, mode, type, 1, 0);
if (DEFAULT_ABI == ABI_V4)
{
- /* Indicate to allocate space on the stack for varargs save area. */
- cfun->machine->sysv_varargs_p = 1;
+ first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
+
if (! no_rtl)
- save_area = plus_constant (virtual_stack_vars_rtx,
- - RS6000_VARARGS_SIZE);
+ {
+ int gpr_reg_num = 0, gpr_size = 0, fpr_size = 0;
+ HOST_WIDE_INT offset = 0;
+
+ /* Try to optimize the size of the varargs save area.
+ The ABI requires that ap.reg_save_area is doubleword
+ aligned, but we don't need to allocate space for all
+ the bytes, only those to which we actually will save
+ anything. */
+ if (cfun->va_list_gpr_size && first_reg_offset < GP_ARG_NUM_REG)
+ gpr_reg_num = GP_ARG_NUM_REG - first_reg_offset;
+ if (TARGET_HARD_FLOAT && TARGET_FPRS
+ && next_cum.fregno <= FP_ARG_V4_MAX_REG
+ && cfun->va_list_fpr_size)
+ {
+ if (gpr_reg_num)
+ fpr_size = (next_cum.fregno - FP_ARG_MIN_REG)
+ * UNITS_PER_FP_WORD;
+ if (cfun->va_list_fpr_size
+ < FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
+ fpr_size += cfun->va_list_fpr_size * UNITS_PER_FP_WORD;
+ else
+ fpr_size += (FP_ARG_V4_MAX_REG + 1 - next_cum.fregno)
+ * UNITS_PER_FP_WORD;
+ }
+ if (gpr_reg_num)
+ {
+ offset = -((first_reg_offset * reg_size) & ~7);
+ if (!fpr_size && gpr_reg_num > cfun->va_list_gpr_size)
+ {
+ gpr_reg_num = cfun->va_list_gpr_size;
+ if (reg_size == 4 && (first_reg_offset & 1))
+ gpr_reg_num++;
+ }
+ gpr_size = (gpr_reg_num * reg_size + 7) & ~7;
+ }
+ else if (fpr_size)
+ offset = - (int) (next_cum.fregno - FP_ARG_MIN_REG)
+ * UNITS_PER_FP_WORD
+ - (int) (GP_ARG_NUM_REG * reg_size);
- first_reg_offset = next_cum.sysv_gregno - GP_ARG_MIN_REG;
+ if (gpr_size + fpr_size)
+ {
+ rtx reg_save_area
+ = assign_stack_local (BLKmode, gpr_size + fpr_size, 64);
+ gcc_assert (GET_CODE (reg_save_area) == MEM);
+ reg_save_area = XEXP (reg_save_area, 0);
+ if (GET_CODE (reg_save_area) == PLUS)
+ {
+ gcc_assert (XEXP (reg_save_area, 0)
+ == virtual_stack_vars_rtx);
+ gcc_assert (GET_CODE (XEXP (reg_save_area, 1)) == CONST_INT);
+ offset += INTVAL (XEXP (reg_save_area, 1));
+ }
+ else
+ gcc_assert (reg_save_area == virtual_stack_vars_rtx);
+ }
+
+ cfun->machine->varargs_save_offset = offset;
+ save_area = plus_constant (virtual_stack_vars_rtx, offset);
+ }
}
else
{
first_reg_offset = next_cum.words;
save_area = virtual_incoming_args_rtx;
- cfun->machine->sysv_varargs_p = 0;
- if (MUST_PASS_IN_STACK (mode, type))
+ if (targetm.calls.must_pass_in_stack (mode, type))
first_reg_offset += rs6000_arg_size (TYPE_MODE (type), type);
}
set = get_varargs_alias_set ();
- if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG)
+ if (! no_rtl && first_reg_offset < GP_ARG_NUM_REG
+ && cfun->va_list_gpr_size)
{
+ int nregs = GP_ARG_NUM_REG - first_reg_offset;
+
+ if (va_list_gpr_counter_field)
+ {
+ /* V4 va_list_gpr_size counts number of registers needed. */
+ if (nregs > cfun->va_list_gpr_size)
+ nregs = cfun->va_list_gpr_size;
+ }
+ else
+ {
+ /* char * va_list instead counts number of bytes needed. */
+ if (nregs > cfun->va_list_gpr_size / reg_size)
+ nregs = cfun->va_list_gpr_size / reg_size;
+ }
+
mem = gen_rtx_MEM (BLKmode,
- plus_constant (save_area,
- first_reg_offset * reg_size)),
+ plus_constant (save_area,
+ first_reg_offset * reg_size));
+ MEM_NOTRAP_P (mem) = 1;
set_mem_alias_set (mem, set);
set_mem_align (mem, BITS_PER_WORD);
- rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
- GP_ARG_NUM_REG - first_reg_offset);
+ rs6000_move_block_from_reg (GP_ARG_MIN_REG + first_reg_offset, mem,
+ nregs);
}
/* Save FP registers if needed. */
if (DEFAULT_ABI == ABI_V4
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& ! no_rtl
- && next_cum.fregno <= FP_ARG_V4_MAX_REG)
+ && next_cum.fregno <= FP_ARG_V4_MAX_REG
+ && cfun->va_list_fpr_size)
{
- int fregno = next_cum.fregno;
+ int fregno = next_cum.fregno, nregs;
rtx cr1 = gen_rtx_REG (CCmode, CR1_REGNO);
rtx lab = gen_label_rtx ();
- int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG) * 8);
+ int off = (GP_ARG_NUM_REG * reg_size) + ((fregno - FP_ARG_MIN_REG)
+ * UNITS_PER_FP_WORD);
- emit_jump_insn (gen_rtx_SET (VOIDmode,
- pc_rtx,
- gen_rtx_IF_THEN_ELSE (VOIDmode,
+ emit_jump_insn
+ (gen_rtx_SET (VOIDmode,
+ pc_rtx,
+ gen_rtx_IF_THEN_ELSE (VOIDmode,
gen_rtx_NE (VOIDmode, cr1,
- const0_rtx),
+ const0_rtx),
gen_rtx_LABEL_REF (VOIDmode, lab),
pc_rtx)));
- while (fregno <= FP_ARG_V4_MAX_REG)
+ for (nregs = 0;
+ fregno <= FP_ARG_V4_MAX_REG && nregs < cfun->va_list_fpr_size;
+ fregno++, off += UNITS_PER_FP_WORD, nregs++)
{
mem = gen_rtx_MEM (DFmode, plus_constant (save_area, off));
- set_mem_alias_set (mem, set);
+ MEM_NOTRAP_P (mem) = 1;
+ set_mem_alias_set (mem, set);
set_mem_align (mem, GET_MODE_ALIGNMENT (DFmode));
emit_move_insn (mem, gen_rtx_REG (DFmode, fregno));
- fregno++;
- off += 8;
}
emit_label (lab);
@@ -4790,9 +5762,9 @@ rs6000_build_builtin_va_list (void)
record = (*lang_hooks.types.make_type) (RECORD_TYPE);
type_decl = build_decl (TYPE_DECL, get_identifier ("__va_list_tag"), record);
- f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
+ f_gpr = build_decl (FIELD_DECL, get_identifier ("gpr"),
unsigned_char_type_node);
- f_fpr = build_decl (FIELD_DECL, get_identifier ("fpr"),
+ f_fpr = build_decl (FIELD_DECL, get_identifier ("fpr"),
unsigned_char_type_node);
/* Give the two bytes of padding a name, so that -Wpadded won't warn on
every user file. */
@@ -4803,6 +5775,9 @@ rs6000_build_builtin_va_list (void)
f_sav = build_decl (FIELD_DECL, get_identifier ("reg_save_area"),
ptr_type_node);
+ va_list_gpr_counter_field = f_gpr;
+ va_list_fpr_counter_field = f_fpr;
+
DECL_FIELD_CONTEXT (f_gpr) = record;
DECL_FIELD_CONTEXT (f_fpr) = record;
DECL_FIELD_CONTEXT (f_res) = record;
@@ -4845,85 +5820,88 @@ rs6000_va_start (tree valist, rtx nextarg)
f_ovf = TREE_CHAIN (f_res);
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);
+ valist = build_va_arg_indirect_ref (valist);
+ gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+ fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+ ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+ sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
/* Count number of gp and fp argument registers used. */
words = current_function_args_info.words;
- n_gpr = current_function_args_info.sysv_gregno - GP_ARG_MIN_REG;
- n_fpr = current_function_args_info.fregno - FP_ARG_MIN_REG;
+ n_gpr = MIN (current_function_args_info.sysv_gregno - GP_ARG_MIN_REG,
+ GP_ARG_NUM_REG);
+ n_fpr = MIN (current_function_args_info.fregno - FP_ARG_MIN_REG,
+ FP_ARG_NUM_REG);
if (TARGET_DEBUG_ARG)
fprintf (stderr, "va_start: words = "HOST_WIDE_INT_PRINT_DEC", n_gpr = "
HOST_WIDE_INT_PRINT_DEC", n_fpr = "HOST_WIDE_INT_PRINT_DEC"\n",
words, n_gpr, n_fpr);
- 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);
+ if (cfun->va_list_gpr_size)
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
+ build_int_cst (NULL_TREE, n_gpr));
+ 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);
+ if (cfun->va_list_fpr_size)
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
+ build_int_cst (NULL_TREE, n_fpr));
+ 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);
if (words != 0)
- t = build (PLUS_EXPR, TREE_TYPE (ovf), t,
- build_int_2 (words * UNITS_PER_WORD, 0));
- t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t,
+ build_int_cst (NULL_TREE, words * UNITS_PER_WORD));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ /* If there were no va_arg invocations, don't set up the register
+ save area. */
+ if (!cfun->va_list_gpr_size
+ && !cfun->va_list_fpr_size
+ && n_gpr < GP_ARG_NUM_REG
+ && n_fpr < FP_ARG_V4_MAX_REG)
+ return;
+
/* Find the register save area. */
t = make_tree (TREE_TYPE (sav), virtual_stack_vars_rtx);
- t = build (PLUS_EXPR, TREE_TYPE (sav), t,
- build_int_2 (-RS6000_VARARGS_SIZE, -1));
- t = build (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
+ if (cfun->machine->varargs_save_offset)
+ t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
+ build_int_cst (NULL_TREE, cfun->machine->varargs_save_offset));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
}
/* Implement va_arg. */
-rtx
-rs6000_va_arg (tree valist, tree type)
+tree
+rs6000_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{
tree f_gpr, f_fpr, f_res, f_ovf, f_sav;
tree gpr, fpr, ovf, sav, reg, t, u;
- int indirect_p, size, rsize, n_reg, sav_ofs, sav_scale;
- rtx lab_false, lab_over, addr_rtx, r;
+ int size, rsize, n_reg, sav_ofs, sav_scale;
+ tree lab_false, lab_over, addr;
int align;
+ tree ptrtype = build_pointer_type (type);
- if (DEFAULT_ABI != ABI_V4)
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
- /* Variable sized types are passed by reference, as are AltiVec
- vectors when 32-bit and not using the AltiVec ABI extension. */
- if (int_size_in_bytes (type) < 0
- || (TARGET_32BIT
- && !TARGET_ALTIVEC_ABI
- && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))))
- {
- u = build_pointer_type (type);
-
- /* Args grow upward. */
- t = build (POSTINCREMENT_EXPR, TREE_TYPE (valist), valist,
- build_int_2 (POINTER_SIZE / BITS_PER_UNIT, 0));
- TREE_SIDE_EFFECTS (t) = 1;
-
- t = build1 (NOP_EXPR, build_pointer_type (u), t);
- TREE_SIDE_EFFECTS (t) = 1;
-
- t = build1 (INDIRECT_REF, u, t);
- TREE_SIDE_EFFECTS (t) = 1;
+ t = rs6000_gimplify_va_arg (valist, ptrtype, pre_p, post_p);
+ return build_va_arg_indirect_ref (t);
+ }
- return expand_expr (t, NULL_RTX, VOIDmode, EXPAND_NORMAL);
- }
- if (targetm.calls.split_complex_arg
- && TREE_CODE (type) == COMPLEX_TYPE)
+ if (DEFAULT_ABI != ABI_V4)
+ {
+ if (targetm.calls.split_complex_arg && TREE_CODE (type) == COMPLEX_TYPE)
{
tree elem_type = TREE_TYPE (type);
enum machine_mode elem_mode = TYPE_MODE (elem_type);
@@ -4931,33 +5909,24 @@ rs6000_va_arg (tree valist, tree type)
if (elem_size < UNITS_PER_WORD)
{
- rtx real_part, imag_part, dest_real, rr;
-
- real_part = rs6000_va_arg (valist, elem_type);
- imag_part = rs6000_va_arg (valist, elem_type);
+ tree real_part, imag_part;
+ tree post = NULL_TREE;
- /* We're not returning the value here, but the address.
- real_part and imag_part are not contiguous, and we know
- there is space available to pack real_part next to
- imag_part. float _Complex is not promoted to
- double _Complex by the default promotion rules that
- promote float to double. */
- if (2 * elem_size > UNITS_PER_WORD)
- abort ();
+ real_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
+ &post);
+ /* Copy the value into a temporary, lest the formal temporary
+ be reused out from under us. */
+ real_part = get_initialized_tmp_var (real_part, pre_p, &post);
+ append_to_statement_list (post, pre_p);
- real_part = gen_rtx_MEM (elem_mode, real_part);
- imag_part = gen_rtx_MEM (elem_mode, imag_part);
+ imag_part = rs6000_gimplify_va_arg (valist, elem_type, pre_p,
+ post_p);
- dest_real = adjust_address (imag_part, elem_mode, -elem_size);
- rr = gen_reg_rtx (elem_mode);
- emit_move_insn (rr, real_part);
- emit_move_insn (dest_real, rr);
-
- return XEXP (dest_real, 0);
+ return build2 (COMPLEX_EXPR, type, real_part, imag_part);
}
}
- return std_expand_builtin_va_arg (valist, type);
+ return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
}
f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
@@ -4966,46 +5935,32 @@ rs6000_va_arg (tree valist, tree type)
f_ovf = TREE_CHAIN (f_res);
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);
+ valist = build_va_arg_indirect_ref (valist);
+ gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+ fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+ ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+ sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
size = int_size_in_bytes (type);
rsize = (size + 3) / 4;
align = 1;
- if (AGGREGATE_TYPE_P (type)
- || TYPE_MODE (type) == TFmode
- || (!TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type))))
- {
- /* Aggregates, long doubles, and AltiVec vectors are passed by
- reference. */
- indirect_p = 1;
- reg = gpr;
- n_reg = 1;
- sav_ofs = 0;
- sav_scale = 4;
- size = 4;
- rsize = 1;
- }
- else if (TARGET_HARD_FLOAT && TARGET_FPRS
- && (TYPE_MODE (type) == SFmode || TYPE_MODE (type) == DFmode))
+ if (TARGET_HARD_FLOAT && TARGET_FPRS
+ && (TYPE_MODE (type) == SFmode
+ || TYPE_MODE (type) == DFmode
+ || TYPE_MODE (type) == TFmode))
{
/* FP args go in FP registers, if present. */
- indirect_p = 0;
reg = fpr;
- n_reg = 1;
+ n_reg = (size + 7) / 8;
sav_ofs = 8*4;
sav_scale = 8;
- if (TYPE_MODE (type) == DFmode)
+ if (TYPE_MODE (type) != SFmode)
align = 8;
}
else
{
/* Otherwise into GP registers. */
- indirect_p = 0;
reg = gpr;
n_reg = rsize;
sav_ofs = 0;
@@ -5016,66 +5971,59 @@ rs6000_va_arg (tree valist, tree type)
/* Pull the value out of the saved registers.... */
- lab_over = NULL_RTX;
- addr_rtx = gen_reg_rtx (Pmode);
+ lab_over = NULL;
+ addr = create_tmp_var (ptr_type_node, "addr");
+ DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
/* AltiVec vectors never go in registers when -mabi=altivec. */
if (TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (TYPE_MODE (type)))
align = 16;
else
{
- lab_false = gen_label_rtx ();
- lab_over = gen_label_rtx ();
+ lab_false = create_artificial_label ();
+ lab_over = create_artificial_label ();
/* Long long and SPE vectors are aligned in the registers.
As are any other 2 gpr item such as complex int due to a
historical mistake. */
u = reg;
- if (n_reg == 2)
+ if (n_reg == 2 && reg == gpr)
{
- u = build (BIT_AND_EXPR, TREE_TYPE (reg), reg,
- build_int_2 (n_reg - 1, 0));
- u = build (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u);
- TREE_SIDE_EFFECTS (u) = 1;
+ u = build2 (BIT_AND_EXPR, TREE_TYPE (reg), reg,
+ size_int (n_reg - 1));
+ u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, u);
}
- emit_cmp_and_jump_insns
- (expand_expr (u, NULL_RTX, QImode, EXPAND_NORMAL),
- GEN_INT (8 - n_reg + 1), GE, const1_rtx, QImode, 1,
- lab_false);
+ t = fold_convert (TREE_TYPE (reg), size_int (8 - n_reg + 1));
+ t = build2 (GE_EXPR, boolean_type_node, u, t);
+ u = build1 (GOTO_EXPR, void_type_node, lab_false);
+ t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
+ gimplify_and_add (t, pre_p);
t = sav;
if (sav_ofs)
- t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
-
- u = build (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg,
- build_int_2 (n_reg, 0));
- TREE_SIDE_EFFECTS (u) = 1;
+ t = build2 (PLUS_EXPR, ptr_type_node, sav, size_int (sav_ofs));
+ u = build2 (POSTINCREMENT_EXPR, TREE_TYPE (reg), reg, size_int (n_reg));
u = build1 (CONVERT_EXPR, integer_type_node, u);
- TREE_SIDE_EFFECTS (u) = 1;
+ u = build2 (MULT_EXPR, integer_type_node, u, size_int (sav_scale));
+ t = build2 (PLUS_EXPR, ptr_type_node, t, u);
- u = build (MULT_EXPR, integer_type_node, u, build_int_2 (sav_scale, 0));
- TREE_SIDE_EFFECTS (u) = 1;
+ t = build2 (MODIFY_EXPR, void_type_node, addr, t);
+ gimplify_and_add (t, pre_p);
- 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);
+ t = build1 (GOTO_EXPR, void_type_node, lab_over);
+ gimplify_and_add (t, pre_p);
- emit_jump_insn (gen_jump (lab_over));
- emit_barrier ();
+ t = build1 (LABEL_EXPR, void_type_node, lab_false);
+ append_to_statement_list (t, pre_p);
- emit_label (lab_false);
- if (n_reg > 2)
+ if ((n_reg == 2 && reg != gpr) || n_reg > 2)
{
/* Ensure that we don't find any more args in regs.
- Alignment has taken care of the n_reg == 2 case. */
- t = build (MODIFY_EXPR, TREE_TYPE (reg), reg, build_int_2 (8, 0));
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ Alignment has taken care of the n_reg == 2 gpr case. */
+ t = build2 (MODIFY_EXPR, TREE_TYPE (reg), reg, size_int (8));
+ gimplify_and_add (t, pre_p);
}
}
@@ -5085,41 +6033,65 @@ rs6000_va_arg (tree valist, tree type)
t = ovf;
if (align != 1)
{
- t = build (PLUS_EXPR, TREE_TYPE (t), t, build_int_2 (align - 1, 0));
- t = build (BIT_AND_EXPR, TREE_TYPE (t), t, build_int_2 (-align, -1));
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (align - 1));
+ t = build2 (BIT_AND_EXPR, TREE_TYPE (t), t,
+ build_int_cst (NULL_TREE, -align));
}
- t = save_expr (t);
+ gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ u = build2 (MODIFY_EXPR, void_type_node, addr, t);
+ gimplify_and_add (u, pre_p);
- 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);
+ t = build2 (PLUS_EXPR, TREE_TYPE (t), t, size_int (size));
+ t = build2 (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
+ gimplify_and_add (t, pre_p);
if (lab_over)
- emit_label (lab_over);
+ {
+ t = build1 (LABEL_EXPR, void_type_node, lab_over);
+ append_to_statement_list (t, pre_p);
+ }
- if (indirect_p)
+ if (STRICT_ALIGNMENT
+ && (TYPE_ALIGN (type)
+ > (unsigned) BITS_PER_UNIT * (align < 4 ? 4 : align)))
{
- r = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (r, get_varargs_alias_set ());
- emit_move_insn (addr_rtx, r);
+ /* The value (of type complex double, for example) may not be
+ aligned in memory in the saved registers, so copy via a
+ temporary. (This is the same code as used for SPARC.) */
+ tree tmp = create_tmp_var (type, "va_arg_tmp");
+ tree dest_addr = build_fold_addr_expr (tmp);
+
+ tree copy = build_function_call_expr
+ (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree_cons (NULL_TREE, dest_addr,
+ tree_cons (NULL_TREE, addr,
+ tree_cons (NULL_TREE, size_int (rsize * 4),
+ NULL_TREE))));
+
+ gimplify_and_add (copy, pre_p);
+ addr = dest_addr;
}
- return addr_rtx;
+ addr = fold_convert (ptrtype, addr);
+ return build_va_arg_indirect_ref (addr);
}
/* Builtins. */
-#define def_builtin(MASK, NAME, TYPE, CODE) \
-do { \
- if ((MASK) & target_flags) \
- builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
- NULL, NULL_TREE); \
-} while (0)
+static void
+def_builtin (int mask, const char *name, tree type, int code)
+{
+ if (mask & target_flags)
+ {
+ if (rs6000_builtin_decls[code])
+ abort ();
+
+ rs6000_builtin_decls[code] =
+ lang_hooks.builtin_function (name, type, code, BUILT_IN_MD,
+ NULL, NULL_TREE);
+ }
+}
/* Simple ternary operations: VECd = foo (VECa, VECb, VECc). */
@@ -5135,19 +6107,35 @@ static const struct builtin_description bdesc_3arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vmsumshm, "__builtin_altivec_vmsumshm", ALTIVEC_BUILTIN_VMSUMSHM },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmsumuhs, "__builtin_altivec_vmsumuhs", ALTIVEC_BUILTIN_VMSUMUHS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmsumshs, "__builtin_altivec_vmsumshs", ALTIVEC_BUILTIN_VMSUMSHS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vperm_16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsel_16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vnmsubfp, "__builtin_altivec_vnmsubfp", ALTIVEC_BUILTIN_VNMSUBFP },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4sf, "__builtin_altivec_vperm_4sf", ALTIVEC_BUILTIN_VPERM_4SF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v4si, "__builtin_altivec_vperm_4si", ALTIVEC_BUILTIN_VPERM_4SI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v8hi, "__builtin_altivec_vperm_8hi", ALTIVEC_BUILTIN_VPERM_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vperm_v16qi, "__builtin_altivec_vperm_16qi", ALTIVEC_BUILTIN_VPERM_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4sf, "__builtin_altivec_vsel_4sf", ALTIVEC_BUILTIN_VSEL_4SF },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v4si, "__builtin_altivec_vsel_4si", ALTIVEC_BUILTIN_VSEL_4SI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v8hi, "__builtin_altivec_vsel_8hi", ALTIVEC_BUILTIN_VSEL_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsel_v16qi, "__builtin_altivec_vsel_16qi", ALTIVEC_BUILTIN_VSEL_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v16qi, "__builtin_altivec_vsldoi_16qi", ALTIVEC_BUILTIN_VSLDOI_16QI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v8hi, "__builtin_altivec_vsldoi_8hi", ALTIVEC_BUILTIN_VSLDOI_8HI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4si, "__builtin_altivec_vsldoi_4si", ALTIVEC_BUILTIN_VSLDOI_4SI },
+ { MASK_ALTIVEC, CODE_FOR_altivec_vsldoi_v4sf, "__builtin_altivec_vsldoi_4sf", ALTIVEC_BUILTIN_VSLDOI_4SF },
+
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madd", ALTIVEC_BUILTIN_VEC_MADD },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_madds", ALTIVEC_BUILTIN_VEC_MADDS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mladd", ALTIVEC_BUILTIN_VEC_MLADD },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mradds", ALTIVEC_BUILTIN_VEC_MRADDS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msum", ALTIVEC_BUILTIN_VEC_MSUM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshm", ALTIVEC_BUILTIN_VEC_VMSUMSHM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhm", ALTIVEC_BUILTIN_VEC_VMSUMUHM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsummbm", ALTIVEC_BUILTIN_VEC_VMSUMMBM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumubm", ALTIVEC_BUILTIN_VEC_VMSUMUBM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_msums", ALTIVEC_BUILTIN_VEC_MSUMS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumshs", ALTIVEC_BUILTIN_VEC_VMSUMSHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmsumuhs", ALTIVEC_BUILTIN_VEC_VMSUMUHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nmsub", ALTIVEC_BUILTIN_VEC_NMSUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_perm", ALTIVEC_BUILTIN_VEC_PERM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sel", ALTIVEC_BUILTIN_VEC_SEL },
};
/* DST operations: void foo (void *, const int, const char). */
@@ -5157,7 +6145,12 @@ static const struct builtin_description bdesc_dst[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_dst, "__builtin_altivec_dst", ALTIVEC_BUILTIN_DST },
{ MASK_ALTIVEC, CODE_FOR_altivec_dstt, "__builtin_altivec_dstt", ALTIVEC_BUILTIN_DSTT },
{ MASK_ALTIVEC, CODE_FOR_altivec_dstst, "__builtin_altivec_dstst", ALTIVEC_BUILTIN_DSTST },
- { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT }
+ { MASK_ALTIVEC, CODE_FOR_altivec_dststt, "__builtin_altivec_dststt", ALTIVEC_BUILTIN_DSTSTT },
+
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dst", ALTIVEC_BUILTIN_VEC_DST },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstt", ALTIVEC_BUILTIN_VEC_DSTT },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dstst", ALTIVEC_BUILTIN_VEC_DSTST },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_dststt", ALTIVEC_BUILTIN_VEC_DSTSTT }
};
/* Simple binary operations: VECc = foo (VECa, VECb). */
@@ -5176,7 +6169,7 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vadduws, "__builtin_altivec_vadduws", ALTIVEC_BUILTIN_VADDUWS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vaddsws, "__builtin_altivec_vaddsws", ALTIVEC_BUILTIN_VADDSWS },
{ MASK_ALTIVEC, CODE_FOR_andv4si3, "__builtin_altivec_vand", ALTIVEC_BUILTIN_VAND },
- { MASK_ALTIVEC, CODE_FOR_altivec_vandc, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
+ { MASK_ALTIVEC, CODE_FOR_andcv4si3, "__builtin_altivec_vandc", ALTIVEC_BUILTIN_VANDC },
{ MASK_ALTIVEC, CODE_FOR_altivec_vavgub, "__builtin_altivec_vavgub", ALTIVEC_BUILTIN_VAVGUB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vavgsb, "__builtin_altivec_vavgsb", ALTIVEC_BUILTIN_VAVGSB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vavguh, "__builtin_altivec_vavguh", ALTIVEC_BUILTIN_VAVGUH },
@@ -5228,14 +6221,12 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulosb, "__builtin_altivec_vmulosb", ALTIVEC_BUILTIN_VMULOSB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulouh, "__builtin_altivec_vmulouh", ALTIVEC_BUILTIN_VMULOUH },
{ MASK_ALTIVEC, CODE_FOR_altivec_vmulosh, "__builtin_altivec_vmulosh", ALTIVEC_BUILTIN_VMULOSH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vnor, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
+ { MASK_ALTIVEC, CODE_FOR_altivec_norv4si3, "__builtin_altivec_vnor", ALTIVEC_BUILTIN_VNOR },
{ MASK_ALTIVEC, CODE_FOR_iorv4si3, "__builtin_altivec_vor", ALTIVEC_BUILTIN_VOR },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuhum, "__builtin_altivec_vpkuhum", ALTIVEC_BUILTIN_VPKUHUM },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuwum, "__builtin_altivec_vpkuwum", ALTIVEC_BUILTIN_VPKUWUM },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkpx, "__builtin_altivec_vpkpx", ALTIVEC_BUILTIN_VPKPX },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuhss, "__builtin_altivec_vpkuhss", ALTIVEC_BUILTIN_VPKUHSS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkshss, "__builtin_altivec_vpkshss", ALTIVEC_BUILTIN_VPKSHSS },
- { MASK_ALTIVEC, CODE_FOR_altivec_vpkuwss, "__builtin_altivec_vpkuwss", ALTIVEC_BUILTIN_VPKUWSS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkswss, "__builtin_altivec_vpkswss", ALTIVEC_BUILTIN_VPKSWSS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkuhus, "__builtin_altivec_vpkuhus", ALTIVEC_BUILTIN_VPKUHUS },
{ MASK_ALTIVEC, CODE_FOR_altivec_vpkshus, "__builtin_altivec_vpkshus", ALTIVEC_BUILTIN_VPKSHUS },
@@ -5252,12 +6243,12 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vspltb, "__builtin_altivec_vspltb", ALTIVEC_BUILTIN_VSPLTB },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsplth, "__builtin_altivec_vsplth", ALTIVEC_BUILTIN_VSPLTH },
{ MASK_ALTIVEC, CODE_FOR_altivec_vspltw, "__builtin_altivec_vspltw", ALTIVEC_BUILTIN_VSPLTW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsrb, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsrh, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsrw, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsrab, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsrah, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
- { MASK_ALTIVEC, CODE_FOR_altivec_vsraw, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
+ { MASK_ALTIVEC, CODE_FOR_lshrv16qi3, "__builtin_altivec_vsrb", ALTIVEC_BUILTIN_VSRB },
+ { MASK_ALTIVEC, CODE_FOR_lshrv8hi3, "__builtin_altivec_vsrh", ALTIVEC_BUILTIN_VSRH },
+ { MASK_ALTIVEC, CODE_FOR_lshrv4si3, "__builtin_altivec_vsrw", ALTIVEC_BUILTIN_VSRW },
+ { MASK_ALTIVEC, CODE_FOR_ashrv16qi3, "__builtin_altivec_vsrab", ALTIVEC_BUILTIN_VSRAB },
+ { MASK_ALTIVEC, CODE_FOR_ashrv8hi3, "__builtin_altivec_vsrah", ALTIVEC_BUILTIN_VSRAH },
+ { MASK_ALTIVEC, CODE_FOR_ashrv4si3, "__builtin_altivec_vsraw", ALTIVEC_BUILTIN_VSRAW },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsr, "__builtin_altivec_vsr", ALTIVEC_BUILTIN_VSR },
{ MASK_ALTIVEC, CODE_FOR_altivec_vsro, "__builtin_altivec_vsro", ALTIVEC_BUILTIN_VSRO },
{ MASK_ALTIVEC, CODE_FOR_subv16qi3, "__builtin_altivec_vsububm", ALTIVEC_BUILTIN_VSUBUBM },
@@ -5278,6 +6269,134 @@ static struct builtin_description bdesc_2arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vsumsws, "__builtin_altivec_vsumsws", ALTIVEC_BUILTIN_VSUMSWS },
{ MASK_ALTIVEC, CODE_FOR_xorv4si3, "__builtin_altivec_vxor", ALTIVEC_BUILTIN_VXOR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_add", ALTIVEC_BUILTIN_VEC_ADD },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddfp", ALTIVEC_BUILTIN_VEC_VADDFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduwm", ALTIVEC_BUILTIN_VEC_VADDUWM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhm", ALTIVEC_BUILTIN_VEC_VADDUHM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubm", ALTIVEC_BUILTIN_VEC_VADDUBM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_addc", ALTIVEC_BUILTIN_VEC_ADDC },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_adds", ALTIVEC_BUILTIN_VEC_ADDS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsws", ALTIVEC_BUILTIN_VEC_VADDSWS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduws", ALTIVEC_BUILTIN_VEC_VADDUWS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddshs", ALTIVEC_BUILTIN_VEC_VADDSHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vadduhs", ALTIVEC_BUILTIN_VEC_VADDUHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddsbs", ALTIVEC_BUILTIN_VEC_VADDSBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vaddubs", ALTIVEC_BUILTIN_VEC_VADDUBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_and", ALTIVEC_BUILTIN_VEC_AND },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_andc", ALTIVEC_BUILTIN_VEC_ANDC },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_avg", ALTIVEC_BUILTIN_VEC_AVG },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsw", ALTIVEC_BUILTIN_VEC_VAVGSW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguw", ALTIVEC_BUILTIN_VEC_VAVGUW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsh", ALTIVEC_BUILTIN_VEC_VAVGSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavguh", ALTIVEC_BUILTIN_VEC_VAVGUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgsb", ALTIVEC_BUILTIN_VEC_VAVGSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vavgub", ALTIVEC_BUILTIN_VEC_VAVGUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpb", ALTIVEC_BUILTIN_VEC_CMPB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpeq", ALTIVEC_BUILTIN_VEC_CMPEQ },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpeqfp", ALTIVEC_BUILTIN_VEC_VCMPEQFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequw", ALTIVEC_BUILTIN_VEC_VCMPEQUW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequh", ALTIVEC_BUILTIN_VEC_VCMPEQUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpequb", ALTIVEC_BUILTIN_VEC_VCMPEQUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpge", ALTIVEC_BUILTIN_VEC_CMPGE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmpgt", ALTIVEC_BUILTIN_VEC_CMPGT },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtfp", ALTIVEC_BUILTIN_VEC_VCMPGTFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsw", ALTIVEC_BUILTIN_VEC_VCMPGTSW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuw", ALTIVEC_BUILTIN_VEC_VCMPGTUW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsh", ALTIVEC_BUILTIN_VEC_VCMPGTSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtuh", ALTIVEC_BUILTIN_VEC_VCMPGTUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtsb", ALTIVEC_BUILTIN_VEC_VCMPGTSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vcmpgtub", ALTIVEC_BUILTIN_VEC_VCMPGTUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmple", ALTIVEC_BUILTIN_VEC_CMPLE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_cmplt", ALTIVEC_BUILTIN_VEC_CMPLT },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_max", ALTIVEC_BUILTIN_VEC_MAX },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxfp", ALTIVEC_BUILTIN_VEC_VMAXFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsw", ALTIVEC_BUILTIN_VEC_VMAXSW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuw", ALTIVEC_BUILTIN_VEC_VMAXUW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsh", ALTIVEC_BUILTIN_VEC_VMAXSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxuh", ALTIVEC_BUILTIN_VEC_VMAXUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxsb", ALTIVEC_BUILTIN_VEC_VMAXSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmaxub", ALTIVEC_BUILTIN_VEC_VMAXUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergeh", ALTIVEC_BUILTIN_VEC_MERGEH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghw", ALTIVEC_BUILTIN_VEC_VMRGHW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghh", ALTIVEC_BUILTIN_VEC_VMRGHH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrghb", ALTIVEC_BUILTIN_VEC_VMRGHB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mergel", ALTIVEC_BUILTIN_VEC_MERGEL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglw", ALTIVEC_BUILTIN_VEC_VMRGLW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglh", ALTIVEC_BUILTIN_VEC_VMRGLH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmrglb", ALTIVEC_BUILTIN_VEC_VMRGLB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_min", ALTIVEC_BUILTIN_VEC_MIN },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminfp", ALTIVEC_BUILTIN_VEC_VMINFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsw", ALTIVEC_BUILTIN_VEC_VMINSW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuw", ALTIVEC_BUILTIN_VEC_VMINUW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsh", ALTIVEC_BUILTIN_VEC_VMINSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminuh", ALTIVEC_BUILTIN_VEC_VMINUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminsb", ALTIVEC_BUILTIN_VEC_VMINSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vminub", ALTIVEC_BUILTIN_VEC_VMINUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mule", ALTIVEC_BUILTIN_VEC_MULE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleub", ALTIVEC_BUILTIN_VEC_VMULEUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesb", ALTIVEC_BUILTIN_VEC_VMULESB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuleuh", ALTIVEC_BUILTIN_VEC_VMULEUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulesh", ALTIVEC_BUILTIN_VEC_VMULESH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mulo", ALTIVEC_BUILTIN_VEC_MULO },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosh", ALTIVEC_BUILTIN_VEC_VMULOSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulouh", ALTIVEC_BUILTIN_VEC_VMULOUH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmulosb", ALTIVEC_BUILTIN_VEC_VMULOSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vmuloub", ALTIVEC_BUILTIN_VEC_VMULOUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_nor", ALTIVEC_BUILTIN_VEC_NOR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_or", ALTIVEC_BUILTIN_VEC_OR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_pack", ALTIVEC_BUILTIN_VEC_PACK },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwum", ALTIVEC_BUILTIN_VEC_VPKUWUM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhum", ALTIVEC_BUILTIN_VEC_VPKUHUM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packpx", ALTIVEC_BUILTIN_VEC_PACKPX },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packs", ALTIVEC_BUILTIN_VEC_PACKS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswss", ALTIVEC_BUILTIN_VEC_VPKSWSS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuwus", ALTIVEC_BUILTIN_VEC_VPKUWUS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshss", ALTIVEC_BUILTIN_VEC_VPKSHSS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkuhus", ALTIVEC_BUILTIN_VEC_VPKUHUS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_packsu", ALTIVEC_BUILTIN_VEC_PACKSU },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkswus", ALTIVEC_BUILTIN_VEC_VPKSWUS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vpkshus", ALTIVEC_BUILTIN_VEC_VPKSHUS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rl", ALTIVEC_BUILTIN_VEC_RL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlw", ALTIVEC_BUILTIN_VEC_VRLW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlh", ALTIVEC_BUILTIN_VEC_VRLH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vrlb", ALTIVEC_BUILTIN_VEC_VRLB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sl", ALTIVEC_BUILTIN_VEC_SL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslw", ALTIVEC_BUILTIN_VEC_VSLW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslh", ALTIVEC_BUILTIN_VEC_VSLH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vslb", ALTIVEC_BUILTIN_VEC_VSLB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sll", ALTIVEC_BUILTIN_VEC_SLL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_slo", ALTIVEC_BUILTIN_VEC_SLO },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sr", ALTIVEC_BUILTIN_VEC_SR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrw", ALTIVEC_BUILTIN_VEC_VSRW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrh", ALTIVEC_BUILTIN_VEC_VSRH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrb", ALTIVEC_BUILTIN_VEC_VSRB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sra", ALTIVEC_BUILTIN_VEC_SRA },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsraw", ALTIVEC_BUILTIN_VEC_VSRAW },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrah", ALTIVEC_BUILTIN_VEC_VSRAH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsrab", ALTIVEC_BUILTIN_VEC_VSRAB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_srl", ALTIVEC_BUILTIN_VEC_SRL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sro", ALTIVEC_BUILTIN_VEC_SRO },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sub", ALTIVEC_BUILTIN_VEC_SUB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubfp", ALTIVEC_BUILTIN_VEC_VSUBFP },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuwm", ALTIVEC_BUILTIN_VEC_VSUBUWM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhm", ALTIVEC_BUILTIN_VEC_VSUBUHM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububm", ALTIVEC_BUILTIN_VEC_VSUBUBM },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subc", ALTIVEC_BUILTIN_VEC_SUBC },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_subs", ALTIVEC_BUILTIN_VEC_SUBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsws", ALTIVEC_BUILTIN_VEC_VSUBSWS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuws", ALTIVEC_BUILTIN_VEC_VSUBUWS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubshs", ALTIVEC_BUILTIN_VEC_VSUBSHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubuhs", ALTIVEC_BUILTIN_VEC_VSUBUHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsubsbs", ALTIVEC_BUILTIN_VEC_VSUBSBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsububs", ALTIVEC_BUILTIN_VEC_VSUBUBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum4s", ALTIVEC_BUILTIN_VEC_SUM4S },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4shs", ALTIVEC_BUILTIN_VEC_VSUM4SHS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4sbs", ALTIVEC_BUILTIN_VEC_VSUM4SBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vsum4ubs", ALTIVEC_BUILTIN_VEC_VSUM4UBS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sum2s", ALTIVEC_BUILTIN_VEC_SUM2S },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_sums", ALTIVEC_BUILTIN_VEC_SUMS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_xor", ALTIVEC_BUILTIN_VEC_XOR },
+
/* Place holder, leave as first spe builtin. */
{ 0, CODE_FOR_spe_evaddw, "__builtin_spe_evaddw", SPE_BUILTIN_EVADDW },
{ 0, CODE_FOR_spe_evand, "__builtin_spe_evand", SPE_BUILTIN_EVAND },
@@ -5420,7 +6539,7 @@ static struct builtin_description bdesc_2arg[] =
{ 0, CODE_FOR_spe_brinc, "__builtin_spe_brinc", SPE_BUILTIN_BRINC },
/* Place-holder. Leave as last binary SPE builtin. */
- { 0, CODE_FOR_xorv2si3, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR },
+ { 0, CODE_FOR_xorv2si3, "__builtin_spe_evxor", SPE_BUILTIN_EVXOR }
};
/* AltiVec predicates. */
@@ -5448,7 +6567,11 @@ static const struct builtin_description_predicates bdesc_altivec_preds[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_predicate_v8hi, "*vcmpequh.", "__builtin_altivec_vcmpequh_p", ALTIVEC_BUILTIN_VCMPEQUH_P },
{ MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpequb.", "__builtin_altivec_vcmpequb_p", ALTIVEC_BUILTIN_VCMPEQUB_P },
{ MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtsb.", "__builtin_altivec_vcmpgtsb_p", ALTIVEC_BUILTIN_VCMPGTSB_P },
- { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P }
+ { MASK_ALTIVEC, CODE_FOR_altivec_predicate_v16qi, "*vcmpgtub.", "__builtin_altivec_vcmpgtub_p", ALTIVEC_BUILTIN_VCMPGTUB_P },
+
+ { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpeq_p", ALTIVEC_BUILTIN_VCMPEQ_P },
+ { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpgt_p", ALTIVEC_BUILTIN_VCMPGT_P },
+ { MASK_ALTIVEC, 0, NULL, "__builtin_vec_vcmpge_p", ALTIVEC_BUILTIN_VCMPGE_P }
};
/* SPE predicates. */
@@ -5523,6 +6646,26 @@ static struct builtin_description bdesc_1arg[] =
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklpx, "__builtin_altivec_vupklpx", ALTIVEC_BUILTIN_VUPKLPX },
{ MASK_ALTIVEC, CODE_FOR_altivec_vupklsh, "__builtin_altivec_vupklsh", ALTIVEC_BUILTIN_VUPKLSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abs", ALTIVEC_BUILTIN_VEC_ABS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_abss", ALTIVEC_BUILTIN_VEC_ABSS },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_ceil", ALTIVEC_BUILTIN_VEC_CEIL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_expte", ALTIVEC_BUILTIN_VEC_EXPTE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_floor", ALTIVEC_BUILTIN_VEC_FLOOR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_loge", ALTIVEC_BUILTIN_VEC_LOGE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_mtvscr", ALTIVEC_BUILTIN_VEC_MTVSCR },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_re", ALTIVEC_BUILTIN_VEC_RE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_round", ALTIVEC_BUILTIN_VEC_ROUND },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_rsqrte", ALTIVEC_BUILTIN_VEC_RSQRTE },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_trunc", ALTIVEC_BUILTIN_VEC_TRUNC },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackh", ALTIVEC_BUILTIN_VEC_UNPACKH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsh", ALTIVEC_BUILTIN_VEC_VUPKHSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhpx", ALTIVEC_BUILTIN_VEC_VUPKHPX },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupkhsb", ALTIVEC_BUILTIN_VEC_VUPKHSB },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_unpackl", ALTIVEC_BUILTIN_VEC_UNPACKL },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklpx", ALTIVEC_BUILTIN_VEC_VUPKLPX },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsh", ALTIVEC_BUILTIN_VEC_VUPKLSH },
+ { MASK_ALTIVEC, CODE_FOR_nothing, "__builtin_vec_vupklsb", ALTIVEC_BUILTIN_VEC_VUPKLSB },
+
/* The SPE unary builtins must start with SPE_BUILTIN_EVABS and
end with SPE_BUILTIN_EVSUBFUSIAAW. */
{ 0, CODE_FOR_spe_evabs, "__builtin_spe_evabs", SPE_BUILTIN_EVABS },
@@ -5555,7 +6698,7 @@ static struct builtin_description bdesc_1arg[] =
{ 0, CODE_FOR_spe_evsubfumiaaw, "__builtin_spe_evsubfumiaaw", SPE_BUILTIN_EVSUBFUMIAAW },
/* Place-holder. Leave as last unary SPE builtin. */
- { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW },
+ { 0, CODE_FOR_spe_evsubfusiaaw, "__builtin_spe_evsubfusiaaw", SPE_BUILTIN_EVSUBFUSIAAW }
};
static rtx
@@ -5563,7 +6706,7 @@ rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target)
{
rtx pat;
tree arg0 = TREE_VALUE (arglist);
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
@@ -5583,8 +6726,8 @@ rs6000_expand_unop_builtin (enum insn_code icode, tree arglist, rtx target)
{
/* Only allow 5-bit *signed* literals. */
if (GET_CODE (op0) != CONST_INT
- || INTVAL (op0) > 0x1f
- || INTVAL (op0) < -0x1f)
+ || INTVAL (op0) > 15
+ || INTVAL (op0) < -16)
{
error ("argument 1 must be a 5-bit signed literal");
return const0_rtx;
@@ -5612,7 +6755,7 @@ altivec_expand_abs_builtin (enum insn_code icode, tree arglist, rtx target)
{
rtx pat, scratch1, scratch2;
tree arg0 = TREE_VALUE (arglist);
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
@@ -5645,8 +6788,8 @@ rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
rtx pat;
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
@@ -5713,15 +6856,15 @@ rs6000_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target)
}
static rtx
-altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
+altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
tree arglist, rtx target)
{
rtx pat, scratch;
tree cr6_form = TREE_VALUE (arglist);
tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
enum machine_mode tmode = SImode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
@@ -5735,8 +6878,7 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
else
cr6_form_int = TREE_INT_CST_LOW (cr6_form);
- if (mode0 != mode1)
- abort ();
+ gcc_assert (mode0 == mode1);
/* If we have invalid arguments, bail out before generating bad rtl. */
if (arg0 == error_mark_node || arg1 == error_mark_node)
@@ -5755,7 +6897,7 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
scratch = gen_reg_rtx (mode0);
pat = GEN_FCN (icode) (scratch, op0, op1,
- gen_rtx (SYMBOL_REF, Pmode, opcode));
+ gen_rtx_SYMBOL_REF (Pmode, opcode));
if (! pat)
return 0;
emit_insn (pat);
@@ -5768,24 +6910,24 @@ altivec_expand_predicate_builtin (enum insn_code icode, const char *opcode,
If you think this is disgusting, look at the specs for the
AltiVec predicates. */
- switch (cr6_form_int)
- {
- case 0:
- emit_insn (gen_cr6_test_for_zero (target));
- break;
- case 1:
- emit_insn (gen_cr6_test_for_zero_reverse (target));
- break;
- case 2:
- emit_insn (gen_cr6_test_for_lt (target));
- break;
- case 3:
- emit_insn (gen_cr6_test_for_lt_reverse (target));
- break;
- default:
- error ("argument 1 of __builtin_altivec_predicate is out of range");
- break;
- }
+ switch (cr6_form_int)
+ {
+ case 0:
+ emit_insn (gen_cr6_test_for_zero (target));
+ break;
+ case 1:
+ emit_insn (gen_cr6_test_for_zero_reverse (target));
+ break;
+ case 2:
+ emit_insn (gen_cr6_test_for_lt (target));
+ break;
+ case 3:
+ emit_insn (gen_cr6_test_for_lt_reverse (target));
+ break;
+ default:
+ error ("argument 1 of __builtin_altivec_predicate is out of range");
+ break;
+ }
return target;
}
@@ -5799,8 +6941,8 @@ altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target)
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = Pmode;
enum machine_mode mode1 = Pmode;
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
if (icode == CODE_FOR_nothing)
/* Builtin not supported on this processor. */
@@ -5815,7 +6957,7 @@ altivec_expand_lv_builtin (enum insn_code icode, tree arglist, rtx target)
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
- op1 = copy_to_mode_reg (mode1, op1);
+ op1 = copy_to_mode_reg (mode1, op1);
if (op0 == const0_rtx)
{
@@ -5842,9 +6984,9 @@ spe_expand_stv_builtin (enum insn_code icode, tree arglist)
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2 = expand_normal (arg2);
rtx pat;
enum machine_mode mode0 = insn_data[icode].operand[0].mode;
enum machine_mode mode1 = insn_data[icode].operand[1].mode;
@@ -5875,9 +7017,9 @@ altivec_expand_stv_builtin (enum insn_code icode, tree arglist)
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2 = expand_normal (arg2);
rtx pat, addr;
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode1 = Pmode;
@@ -5892,7 +7034,7 @@ altivec_expand_stv_builtin (enum insn_code icode, tree arglist)
if (! (*insn_data[icode].operand[1].predicate) (op0, tmode))
op0 = copy_to_mode_reg (tmode, op0);
- op2 = copy_to_mode_reg (mode2, op2);
+ op2 = copy_to_mode_reg (mode2, op2);
if (op1 == const0_rtx)
{
@@ -5917,9 +7059,9 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target)
tree arg0 = TREE_VALUE (arglist);
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2 = expand_normal (arg2);
enum machine_mode tmode = insn_data[icode].operand[0].mode;
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
@@ -5935,12 +7077,13 @@ rs6000_expand_ternop_builtin (enum insn_code icode, tree arglist, rtx target)
|| arg2 == error_mark_node)
return const0_rtx;
- if (icode == CODE_FOR_altivec_vsldoi_4sf
- || icode == CODE_FOR_altivec_vsldoi_4si
- || icode == CODE_FOR_altivec_vsldoi_8hi
- || icode == CODE_FOR_altivec_vsldoi_16qi)
+ if (icode == CODE_FOR_altivec_vsldoi_v4sf
+ || icode == CODE_FOR_altivec_vsldoi_v4si
+ || icode == CODE_FOR_altivec_vsldoi_v8hi
+ || icode == CODE_FOR_altivec_vsldoi_v16qi)
{
/* Only allow 4-bit unsigned literals. */
+ STRIP_NOPS (arg2);
if (TREE_CODE (arg2) != INTEGER_CST
|| TREE_INT_CST_LOW (arg2) & ~0xf)
{
@@ -5984,16 +7127,16 @@ altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
switch (fcode)
{
case ALTIVEC_BUILTIN_LD_INTERNAL_16qi:
- icode = CODE_FOR_altivec_lvx_16qi;
+ icode = CODE_FOR_altivec_lvx_v16qi;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_8hi:
- icode = CODE_FOR_altivec_lvx_8hi;
+ icode = CODE_FOR_altivec_lvx_v8hi;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_4si:
- icode = CODE_FOR_altivec_lvx_4si;
+ icode = CODE_FOR_altivec_lvx_v4si;
break;
case ALTIVEC_BUILTIN_LD_INTERNAL_4sf:
- icode = CODE_FOR_altivec_lvx_4sf;
+ icode = CODE_FOR_altivec_lvx_v4sf;
break;
default:
*expandedp = false;
@@ -6003,7 +7146,7 @@ altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
*expandedp = true;
arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
tmode = insn_data[icode].operand[0].mode;
mode0 = insn_data[icode].operand[1].mode;
@@ -6024,7 +7167,7 @@ altivec_expand_ld_builtin (tree exp, rtx target, bool *expandedp)
/* Expand the stvx builtins. */
static rtx
-altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
bool *expandedp)
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
@@ -6038,16 +7181,16 @@ altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
switch (fcode)
{
case ALTIVEC_BUILTIN_ST_INTERNAL_16qi:
- icode = CODE_FOR_altivec_stvx_16qi;
+ icode = CODE_FOR_altivec_stvx_v16qi;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_8hi:
- icode = CODE_FOR_altivec_stvx_8hi;
+ icode = CODE_FOR_altivec_stvx_v8hi;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_4si:
- icode = CODE_FOR_altivec_stvx_4si;
+ icode = CODE_FOR_altivec_stvx_v4si;
break;
case ALTIVEC_BUILTIN_ST_INTERNAL_4sf:
- icode = CODE_FOR_altivec_stvx_4sf;
+ icode = CODE_FOR_altivec_stvx_v4sf;
break;
default:
*expandedp = false;
@@ -6056,8 +7199,8 @@ altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
mode0 = insn_data[icode].operand[0].mode;
mode1 = insn_data[icode].operand[1].mode;
@@ -6076,7 +7219,7 @@ altivec_expand_st_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
/* Expand the dst builtins. */
static rtx
-altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
+altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
bool *expandedp)
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
@@ -6098,9 +7241,9 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
mode0 = insn_data[d->icode].operand[0].mode;
mode1 = insn_data[d->icode].operand[1].mode;
mode2 = insn_data[d->icode].operand[2].mode;
@@ -6116,12 +7259,12 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
if (TREE_CODE (arg2) != INTEGER_CST
|| TREE_INT_CST_LOW (arg2) & ~0x3)
{
- error ("argument to `%s' must be a 2-bit unsigned literal", d->name);
+ error ("argument to %qs must be a 2-bit unsigned literal", d->name);
return const0_rtx;
}
if (! (*insn_data[d->icode].operand[0].predicate) (op0, mode0))
- op0 = gen_rtx_MEM (mode0, copy_to_mode_reg (Pmode, op0));
+ op0 = copy_to_mode_reg (Pmode, op0);
if (! (*insn_data[d->icode].operand[1].predicate) (op1, mode1))
op1 = copy_to_mode_reg (mode1, op1);
@@ -6135,6 +7278,111 @@ altivec_expand_dst_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
return NULL_RTX;
}
+/* Expand vec_init builtin. */
+static rtx
+altivec_expand_vec_init_builtin (tree type, tree arglist, rtx target)
+{
+ enum machine_mode tmode = TYPE_MODE (type);
+ enum machine_mode inner_mode = GET_MODE_INNER (tmode);
+ int i, n_elt = GET_MODE_NUNITS (tmode);
+ rtvec v = rtvec_alloc (n_elt);
+
+ gcc_assert (VECTOR_MODE_P (tmode));
+
+ for (i = 0; i < n_elt; ++i, arglist = TREE_CHAIN (arglist))
+ {
+ rtx x = expand_normal (TREE_VALUE (arglist));
+ RTVEC_ELT (v, i) = gen_lowpart (inner_mode, x);
+ }
+
+ gcc_assert (arglist == NULL);
+
+ if (!target || !register_operand (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ rs6000_expand_vector_init (target, gen_rtx_PARALLEL (tmode, v));
+ return target;
+}
+
+/* Return the integer constant in ARG. Constrain it to be in the range
+ of the subparts of VEC_TYPE; issue an error if not. */
+
+static int
+get_element_number (tree vec_type, tree arg)
+{
+ unsigned HOST_WIDE_INT elt, max = TYPE_VECTOR_SUBPARTS (vec_type) - 1;
+
+ if (!host_integerp (arg, 1)
+ || (elt = tree_low_cst (arg, 1), elt > max))
+ {
+ error ("selector must be an integer constant in the range 0..%wi", max);
+ return 0;
+ }
+
+ return elt;
+}
+
+/* Expand vec_set builtin. */
+static rtx
+altivec_expand_vec_set_builtin (tree arglist)
+{
+ enum machine_mode tmode, mode1;
+ tree arg0, arg1, arg2;
+ int elt;
+ rtx op0, op1;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+
+ tmode = TYPE_MODE (TREE_TYPE (arg0));
+ mode1 = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
+ gcc_assert (VECTOR_MODE_P (tmode));
+
+ op0 = expand_expr (arg0, NULL_RTX, tmode, 0);
+ op1 = expand_expr (arg1, NULL_RTX, mode1, 0);
+ elt = get_element_number (TREE_TYPE (arg0), arg2);
+
+ if (GET_MODE (op1) != mode1 && GET_MODE (op1) != VOIDmode)
+ op1 = convert_modes (mode1, GET_MODE (op1), op1, true);
+
+ op0 = force_reg (tmode, op0);
+ op1 = force_reg (mode1, op1);
+
+ rs6000_expand_vector_set (op0, op1, elt);
+
+ return op0;
+}
+
+/* Expand vec_ext builtin. */
+static rtx
+altivec_expand_vec_ext_builtin (tree arglist, rtx target)
+{
+ enum machine_mode tmode, mode0;
+ tree arg0, arg1;
+ int elt;
+ rtx op0;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ op0 = expand_normal (arg0);
+ elt = get_element_number (TREE_TYPE (arg0), arg1);
+
+ tmode = TYPE_MODE (TREE_TYPE (TREE_TYPE (arg0)));
+ mode0 = TYPE_MODE (TREE_TYPE (arg0));
+ gcc_assert (VECTOR_MODE_P (mode0));
+
+ op0 = force_reg (mode0, op0);
+
+ if (optimize || !target || !register_operand (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ rs6000_expand_vector_extract (target, op0, elt);
+
+ return target;
+}
+
/* Expand the builtin in EXP and store the result in TARGET. Store
true in *EXPANDEDP if we found a builtin to expand. */
static rtx
@@ -6151,6 +7399,14 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
enum machine_mode tmode, mode0;
unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
+ if (fcode >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && fcode <= ALTIVEC_BUILTIN_OVERLOADED_LAST)
+ {
+ *expandedp = true;
+ error ("unresolved overload for Altivec builtin %qF", fndecl);
+ return const0_rtx;
+ }
+
target = altivec_expand_ld_builtin (exp, target, expandedp);
if (*expandedp)
return target;
@@ -6186,7 +7442,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
|| GET_MODE (target) != tmode
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
-
+
pat = GEN_FCN (icode) (target);
if (! pat)
return 0;
@@ -6196,7 +7452,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
case ALTIVEC_BUILTIN_MTVSCR:
icode = CODE_FOR_altivec_mtvscr;
arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
mode0 = insn_data[icode].operand[0].mode;
/* If we got invalid arguments bail out before generating bad rtl. */
@@ -6219,7 +7475,7 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
icode = CODE_FOR_altivec_dss;
arg0 = TREE_VALUE (arglist);
STRIP_NOPS (arg0);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
mode0 = insn_data[icode].operand[0].mode;
/* If we got invalid arguments bail out before generating bad rtl. */
@@ -6239,14 +7495,27 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
emit_insn (gen_altivec_dss (op0));
return NULL_RTX;
- case ALTIVEC_BUILTIN_COMPILETIME_ERROR:
- arg0 = TREE_VALUE (arglist);
- while (TREE_CODE (arg0) == NOP_EXPR || TREE_CODE (arg0) == ADDR_EXPR)
- arg0 = TREE_OPERAND (arg0, 0);
- error ("invalid parameter combination for `%s' AltiVec intrinsic",
- TREE_STRING_POINTER (arg0));
+ case ALTIVEC_BUILTIN_VEC_INIT_V4SI:
+ case ALTIVEC_BUILTIN_VEC_INIT_V8HI:
+ case ALTIVEC_BUILTIN_VEC_INIT_V16QI:
+ case ALTIVEC_BUILTIN_VEC_INIT_V4SF:
+ return altivec_expand_vec_init_builtin (TREE_TYPE (exp), arglist, target);
- return const0_rtx;
+ case ALTIVEC_BUILTIN_VEC_SET_V4SI:
+ case ALTIVEC_BUILTIN_VEC_SET_V8HI:
+ case ALTIVEC_BUILTIN_VEC_SET_V16QI:
+ case ALTIVEC_BUILTIN_VEC_SET_V4SF:
+ return altivec_expand_vec_set_builtin (arglist);
+
+ case ALTIVEC_BUILTIN_VEC_EXT_V4SI:
+ case ALTIVEC_BUILTIN_VEC_EXT_V8HI:
+ case ALTIVEC_BUILTIN_VEC_EXT_V16QI:
+ case ALTIVEC_BUILTIN_VEC_EXT_V4SF:
+ return altivec_expand_vec_ext_builtin (arglist, target);
+
+ default:
+ break;
+ /* Fall through. */
}
/* Expand abs* operations. */
@@ -6259,32 +7528,33 @@ altivec_expand_builtin (tree exp, rtx target, bool *expandedp)
dp = (struct builtin_description_predicates *) bdesc_altivec_preds;
for (i = 0; i < ARRAY_SIZE (bdesc_altivec_preds); i++, dp++)
if (dp->code == fcode)
- return altivec_expand_predicate_builtin (dp->icode, dp->opcode, arglist, target);
+ return altivec_expand_predicate_builtin (dp->icode, dp->opcode,
+ arglist, target);
/* LV* are funky. We initialized them differently. */
switch (fcode)
{
case ALTIVEC_BUILTIN_LVSL:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsl,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVSR:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvsr,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVEBX:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvebx,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVEHX:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvehx,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVEWX:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvewx,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVXL:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvxl,
- arglist, target);
+ arglist, target);
case ALTIVEC_BUILTIN_LVX:
return altivec_expand_lv_builtin (CODE_FOR_altivec_lvx,
- arglist, target);
+ arglist, target);
default:
break;
/* Fall through. */
@@ -6430,7 +7700,7 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp)
|| GET_MODE (target) != tmode
|| ! (*insn_data[icode].operand[0].predicate) (target, tmode))
target = gen_reg_rtx (tmode);
-
+
pat = GEN_FCN (icode) (target);
if (! pat)
return 0;
@@ -6439,7 +7709,7 @@ spe_expand_builtin (tree exp, rtx target, bool *expandedp)
case SPE_BUILTIN_MTSPEFSCR:
icode = CODE_FOR_spe_mtspefscr;
arg0 = TREE_VALUE (arglist);
- op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
+ op0 = expand_normal (arg0);
mode0 = insn_data[icode].operand[0].mode;
if (arg0 == error_mark_node)
@@ -6467,8 +7737,8 @@ spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target)
tree form = TREE_VALUE (arglist);
tree arg0 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg1 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
int form_int;
@@ -6482,8 +7752,7 @@ spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target)
else
form_int = TREE_INT_CST_LOW (form);
- if (mode0 != mode1)
- abort ();
+ gcc_assert (mode0 == mode1);
if (arg0 == error_mark_node || arg1 == error_mark_node)
return const0_rtx;
@@ -6532,7 +7801,7 @@ spe_expand_predicate_builtin (enum insn_code icode, tree arglist, rtx target)
case 0:
/* We need to get to the OV bit, which is the ORDERED bit. We
could generate (ordered:SI (reg:CC xx) (const_int 0)), but
- that's ugly and will trigger a validate_condition_mode abort.
+ that's ugly and will make validate_condition_mode die.
So let's just use another pattern. */
emit_insn (gen_move_from_CR_ov_bit (target, scratch));
return target;
@@ -6577,15 +7846,14 @@ spe_expand_evsel_builtin (enum insn_code icode, tree arglist, rtx target)
tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
tree arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
tree arg3 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (TREE_CHAIN (arglist))));
- rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
- rtx op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
- rtx op3 = expand_expr (arg3, NULL_RTX, VOIDmode, 0);
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx op2 = expand_normal (arg2);
+ rtx op3 = expand_normal (arg3);
enum machine_mode mode0 = insn_data[icode].operand[1].mode;
enum machine_mode mode1 = insn_data[icode].operand[2].mode;
- if (mode0 != mode1)
- abort ();
+ gcc_assert (mode0 == mode1);
if (arg0 == error_mark_node || arg1 == error_mark_node
|| arg2 == error_mark_node || arg3 == error_mark_node)
@@ -6628,8 +7896,8 @@ spe_expand_evsel_builtin (enum insn_code icode, tree arglist, rtx target)
static rtx
rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
- enum machine_mode mode ATTRIBUTE_UNUSED,
- int ignore ATTRIBUTE_UNUSED)
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ int ignore ATTRIBUTE_UNUSED)
{
tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
tree arglist = TREE_OPERAND (exp, 1);
@@ -6638,7 +7906,47 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
size_t i;
rtx ret;
bool success;
-
+
+ if (fcode == ALTIVEC_BUILTIN_MASK_FOR_LOAD
+ || fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
+ {
+ int icode = (int) CODE_FOR_altivec_lvsr;
+ enum machine_mode tmode = insn_data[icode].operand[0].mode;
+ enum machine_mode mode = insn_data[icode].operand[1].mode;
+ tree arg;
+ rtx op, addr, pat;
+
+ gcc_assert (TARGET_ALTIVEC);
+
+ arg = TREE_VALUE (arglist);
+ gcc_assert (TREE_CODE (TREE_TYPE (arg)) == POINTER_TYPE);
+ op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
+ addr = memory_address (mode, op);
+ if (fcode == ALTIVEC_BUILTIN_MASK_FOR_STORE)
+ op = addr;
+ else
+ {
+ /* For the load case need to negate the address. */
+ op = gen_reg_rtx (GET_MODE (addr));
+ emit_insn (gen_rtx_SET (VOIDmode, op,
+ gen_rtx_NEG (GET_MODE (addr), addr)));
+ }
+ op = gen_rtx_MEM (mode, op);
+
+ if (target == 0
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ target = gen_reg_rtx (tmode);
+
+ /*pat = gen_altivec_lvsr (target, op);*/
+ pat = GEN_FCN (icode) (target, op);
+ if (!pat)
+ return 0;
+ emit_insn (pat);
+
+ return target;
+ }
+
if (TARGET_ALTIVEC)
{
ret = altivec_expand_builtin (exp, target, &success);
@@ -6654,49 +7962,76 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
return ret;
}
- if (TARGET_ALTIVEC || TARGET_SPE)
- {
- /* Handle simple unary operations. */
- d = (struct builtin_description *) bdesc_1arg;
- for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
- if (d->code == fcode)
- return rs6000_expand_unop_builtin (d->icode, arglist, target);
+ gcc_assert (TARGET_ALTIVEC || TARGET_SPE);
- /* Handle simple binary operations. */
- d = (struct builtin_description *) bdesc_2arg;
- for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
- if (d->code == fcode)
- return rs6000_expand_binop_builtin (d->icode, arglist, target);
+ /* Handle simple unary operations. */
+ d = (struct builtin_description *) bdesc_1arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_unop_builtin (d->icode, arglist, target);
- /* Handle simple ternary operations. */
- d = (struct builtin_description *) bdesc_3arg;
- for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
- if (d->code == fcode)
- return rs6000_expand_ternop_builtin (d->icode, arglist, target);
- }
+ /* Handle simple binary operations. */
+ d = (struct builtin_description *) bdesc_2arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_binop_builtin (d->icode, arglist, target);
- abort ();
- return NULL_RTX;
+ /* Handle simple ternary operations. */
+ d = (struct builtin_description *) bdesc_3arg;
+ for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
+ if (d->code == fcode)
+ return rs6000_expand_ternop_builtin (d->icode, arglist, target);
+
+ gcc_unreachable ();
+}
+
+static tree
+build_opaque_vector_type (tree node, int nunits)
+{
+ node = copy_node (node);
+ TYPE_MAIN_VARIANT (node) = node;
+ return build_vector_type (node, nunits);
}
static void
rs6000_init_builtins (void)
{
- opaque_V2SI_type_node = copy_node (V2SI_type_node);
- opaque_V2SF_type_node = copy_node (V2SF_type_node);
+ V2SI_type_node = build_vector_type (intSI_type_node, 2);
+ V2SF_type_node = build_vector_type (float_type_node, 2);
+ V4HI_type_node = build_vector_type (intHI_type_node, 4);
+ V4SI_type_node = build_vector_type (intSI_type_node, 4);
+ V4SF_type_node = build_vector_type (float_type_node, 4);
+ V8HI_type_node = build_vector_type (intHI_type_node, 8);
+ V16QI_type_node = build_vector_type (intQI_type_node, 16);
+
+ unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
+ unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
+ unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
+
+ opaque_V2SF_type_node = build_opaque_vector_type (float_type_node, 2);
+ opaque_V2SI_type_node = build_opaque_vector_type (intSI_type_node, 2);
opaque_p_V2SI_type_node = build_pointer_type (opaque_V2SI_type_node);
+ opaque_V4SI_type_node = copy_node (V4SI_type_node);
/* The 'vector bool ...' types must be kept distinct from 'vector unsigned ...'
- types, especially in C++ land. Similarly, 'vector pixel' is distinct from+ 'vector unsigned short'. */
-
- bool_char_type_node = copy_node (unsigned_intQI_type_node);
- TYPE_MAIN_VARIANT (bool_char_type_node) = bool_char_type_node;
- bool_short_type_node = copy_node (unsigned_intHI_type_node);
- TYPE_MAIN_VARIANT (bool_short_type_node) = bool_short_type_node;
- bool_int_type_node = copy_node (unsigned_intSI_type_node);
- TYPE_MAIN_VARIANT (bool_int_type_node) = bool_int_type_node;
- pixel_type_node = copy_node (unsigned_intHI_type_node);
- TYPE_MAIN_VARIANT (pixel_type_node) = pixel_type_node;
+ types, especially in C++ land. Similarly, 'vector pixel' is distinct from
+ 'vector unsigned short'. */
+
+ bool_char_type_node = build_distinct_type_copy (unsigned_intQI_type_node);
+ bool_short_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
+ bool_int_type_node = build_distinct_type_copy (unsigned_intSI_type_node);
+ pixel_type_node = build_distinct_type_copy (unsigned_intHI_type_node);
+
+ long_integer_type_internal_node = long_integer_type_node;
+ long_unsigned_type_internal_node = long_unsigned_type_node;
+ intQI_type_internal_node = intQI_type_node;
+ uintQI_type_internal_node = unsigned_intQI_type_node;
+ intHI_type_internal_node = intHI_type_node;
+ uintHI_type_internal_node = unsigned_intHI_type_node;
+ intSI_type_internal_node = intSI_type_node;
+ uintSI_type_internal_node = unsigned_intSI_type_node;
+ float_type_internal_node = float_type_node;
+ void_type_internal_node = void_type_node;
(*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
get_identifier ("__bool char"),
@@ -6711,10 +8046,10 @@ rs6000_init_builtins (void)
get_identifier ("__pixel"),
pixel_type_node));
- bool_V16QI_type_node = make_vector (V16QImode, bool_char_type_node, 1);
- bool_V8HI_type_node = make_vector (V8HImode, bool_short_type_node, 1);
- bool_V4SI_type_node = make_vector (V4SImode, bool_int_type_node, 1);
- pixel_V8HI_type_node = make_vector (V8HImode, pixel_type_node, 1);
+ bool_V16QI_type_node = build_vector_type (bool_char_type_node, 16);
+ bool_V8HI_type_node = build_vector_type (bool_short_type_node, 8);
+ bool_V4SI_type_node = build_vector_type (bool_int_type_node, 4);
+ pixel_V8HI_type_node = build_vector_type (pixel_type_node, 8);
(*lang_hooks.decls.pushdecl) (build_decl (TYPE_DECL,
get_identifier ("__vector unsigned char"),
@@ -6759,6 +8094,12 @@ rs6000_init_builtins (void)
altivec_init_builtins ();
if (TARGET_ALTIVEC || TARGET_SPE)
rs6000_common_init_builtins ();
+
+#if TARGET_XCOFF
+ /* AIX libm provides clog as __clog. */
+ if (built_in_decls [BUILT_IN_CLOG])
+ set_user_assembler_name (built_in_decls [BUILT_IN_CLOG], "__clog");
+#endif
}
/* Search through a set of builtins and enable the mask bits.
@@ -6768,7 +8109,7 @@ rs6000_init_builtins (void)
END is the builtin enum at which to end. */
static void
enable_mask_for_builtins (struct builtin_description *desc, int size,
- enum rs6000_builtins start,
+ enum rs6000_builtins start,
enum rs6000_builtins end)
{
int i;
@@ -6921,7 +8262,7 @@ spe_init_builtins (void)
opaque_V2SI_type_node));
/* Initialize irregular SPE builtins. */
-
+
def_builtin (target_flags, "__builtin_spe_mtspefscr", void_ftype_int, SPE_BUILTIN_MTSPEFSCR);
def_builtin (target_flags, "__builtin_spe_mfspefscr", int_ftype_void, SPE_BUILTIN_MFSPEFSCR);
def_builtin (target_flags, "__builtin_spe_evstddx", void_ftype_v2si_pv2si_int, SPE_BUILTIN_EVSTDDX);
@@ -6980,7 +8321,7 @@ spe_init_builtins (void)
type = int_ftype_int_v2sf_v2sf;
break;
default:
- abort ();
+ gcc_unreachable ();
}
def_builtin (d->mask, d->name, type, d->code);
@@ -7001,7 +8342,7 @@ spe_init_builtins (void)
type = v2sf_ftype_4_v2sf;
break;
default:
- abort ();
+ gcc_unreachable ();
}
def_builtin (d->mask, d->name, type, d->code);
@@ -7014,6 +8355,8 @@ altivec_init_builtins (void)
struct builtin_description *d;
struct builtin_description_predicates *dp;
size_t i;
+ tree ftype;
+
tree pfloat_type_node = build_pointer_type (float_type_node);
tree pint_type_node = build_pointer_type (integer_type_node);
tree pshort_type_node = build_pointer_type (short_integer_type_node);
@@ -7028,6 +8371,21 @@ altivec_init_builtins (void)
tree pcvoid_type_node = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
+ tree int_ftype_opaque
+ = build_function_type_list (integer_type_node,
+ opaque_V4SI_type_node, NULL_TREE);
+
+ tree opaque_ftype_opaque_int
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, integer_type_node, NULL_TREE);
+ tree opaque_ftype_opaque_opaque_int
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, opaque_V4SI_type_node,
+ integer_type_node, NULL_TREE);
+ tree int_ftype_int_opaque_opaque
+ = build_function_type_list (integer_type_node,
+ integer_type_node, opaque_V4SI_type_node,
+ opaque_V4SI_type_node, NULL_TREE);
tree int_ftype_int_v4si_v4si
= build_function_type_list (integer_type_node,
integer_type_node, V4SI_type_node,
@@ -7061,6 +8419,9 @@ altivec_init_builtins (void)
tree void_ftype_int
= build_function_type_list (void_type_node, integer_type_node, NULL_TREE);
+ tree opaque_ftype_long_pcvoid
+ = build_function_type_list (opaque_V4SI_type_node,
+ long_integer_type_node, pcvoid_type_node, NULL_TREE);
tree v16qi_ftype_long_pcvoid
= build_function_type_list (V16QI_type_node,
long_integer_type_node, pcvoid_type_node, NULL_TREE);
@@ -7071,6 +8432,10 @@ altivec_init_builtins (void)
= build_function_type_list (V4SI_type_node,
long_integer_type_node, pcvoid_type_node, NULL_TREE);
+ tree void_ftype_opaque_long_pvoid
+ = build_function_type_list (void_type_node,
+ opaque_V4SI_type_node, long_integer_type_node,
+ pvoid_type_node, NULL_TREE);
tree void_ftype_v4si_long_pvoid
= build_function_type_list (void_type_node,
V4SI_type_node, long_integer_type_node,
@@ -7107,10 +8472,7 @@ altivec_init_builtins (void)
= build_function_type_list (void_type_node,
pcvoid_type_node, integer_type_node,
integer_type_node, NULL_TREE);
- tree int_ftype_pcchar
- = build_function_type_list (integer_type_node,
- pcchar_type_node, NULL_TREE);
-
+
def_builtin (MASK_ALTIVEC, "__builtin_altivec_ld_internal_4sf", v4sf_ftype_pcfloat,
ALTIVEC_BUILTIN_LD_INTERNAL_4sf);
def_builtin (MASK_ALTIVEC, "__builtin_altivec_st_internal_4sf", void_ftype_pfloat_v4sf,
@@ -7143,10 +8505,33 @@ altivec_init_builtins (void)
def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvxl", void_ftype_v4si_long_pvoid, ALTIVEC_BUILTIN_STVXL);
def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvebx", void_ftype_v16qi_long_pvoid, ALTIVEC_BUILTIN_STVEBX);
def_builtin (MASK_ALTIVEC, "__builtin_altivec_stvehx", void_ftype_v8hi_long_pvoid, ALTIVEC_BUILTIN_STVEHX);
-
- /* See altivec.h for usage of "__builtin_altivec_compiletime_error". */
- def_builtin (MASK_ALTIVEC, "__builtin_altivec_compiletime_error", int_ftype_pcchar,
- ALTIVEC_BUILTIN_COMPILETIME_ERROR);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ld", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LD);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lde", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ldl", opaque_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LDL);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsl", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSL);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvsr", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVSR);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvebx", v16qi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvehx", v8hi_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEHX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_lvewx", v4si_ftype_long_pcvoid, ALTIVEC_BUILTIN_VEC_LVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_st", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_ST);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ste", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stl", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STL);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvewx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEWX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvebx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEBX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_stvehx", void_ftype_opaque_long_pvoid, ALTIVEC_BUILTIN_VEC_STVEHX);
+
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_step", int_ftype_opaque, ALTIVEC_BUILTIN_VEC_STEP);
+
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_sld", opaque_ftype_opaque_opaque_int, ALTIVEC_BUILTIN_VEC_SLD);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_splat", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_SPLAT);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltw", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTW);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_vsplth", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTH);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_vspltb", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VSPLTB);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ctf", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTF);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfsx", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFSX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_vcfux", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_VCFUX);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_cts", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTS);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ctu", opaque_ftype_opaque_int, ALTIVEC_BUILTIN_VEC_CTU);
/* Add the DST variants. */
d = (struct builtin_description *) bdesc_dst;
@@ -7159,11 +8544,19 @@ altivec_init_builtins (void)
{
enum machine_mode mode1;
tree type;
+ bool is_overloaded = dp->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && dp->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
- mode1 = insn_data[dp->icode].operand[1].mode;
+ if (is_overloaded)
+ mode1 = VOIDmode;
+ else
+ mode1 = insn_data[dp->icode].operand[1].mode;
switch (mode1)
{
+ case VOIDmode:
+ type = int_ftype_int_opaque_opaque;
+ break;
case V4SImode:
type = int_ftype_int_v4si_v4si;
break;
@@ -7177,9 +8570,9 @@ altivec_init_builtins (void)
type = int_ftype_int_v4sf_v4sf;
break;
default:
- abort ();
+ gcc_unreachable ();
}
-
+
def_builtin (dp->mask, dp->name, type, dp->code);
}
@@ -7207,11 +8600,110 @@ altivec_init_builtins (void)
type = v4sf_ftype_v4sf;
break;
default:
- abort ();
+ gcc_unreachable ();
}
-
+
def_builtin (d->mask, d->name, type, d->code);
}
+
+ if (TARGET_ALTIVEC)
+ {
+ tree decl;
+
+ /* Initialize target builtin that implements
+ targetm.vectorize.builtin_mask_for_load. */
+
+ decl = lang_hooks.builtin_function ("__builtin_altivec_mask_for_load",
+ v16qi_ftype_long_pcvoid,
+ ALTIVEC_BUILTIN_MASK_FOR_LOAD,
+ BUILT_IN_MD, NULL,
+ tree_cons (get_identifier ("const"),
+ NULL_TREE, NULL_TREE));
+ /* Record the decl. Will be used by rs6000_builtin_mask_for_load. */
+ altivec_builtin_mask_for_load = decl;
+ }
+
+ /* Access to the vec_init patterns. */
+ ftype = build_function_type_list (V4SI_type_node, integer_type_node,
+ integer_type_node, integer_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4si", ftype,
+ ALTIVEC_BUILTIN_VEC_INIT_V4SI);
+
+ ftype = build_function_type_list (V8HI_type_node, short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node,
+ short_integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v8hi", ftype,
+ ALTIVEC_BUILTIN_VEC_INIT_V8HI);
+
+ ftype = build_function_type_list (V16QI_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, char_type_node,
+ char_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v16qi", ftype,
+ ALTIVEC_BUILTIN_VEC_INIT_V16QI);
+
+ ftype = build_function_type_list (V4SF_type_node, float_type_node,
+ float_type_node, float_type_node,
+ float_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_init_v4sf", ftype,
+ ALTIVEC_BUILTIN_VEC_INIT_V4SF);
+
+ /* Access to the vec_set patterns. */
+ ftype = build_function_type_list (V4SI_type_node, V4SI_type_node,
+ intSI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4si", ftype,
+ ALTIVEC_BUILTIN_VEC_SET_V4SI);
+
+ ftype = build_function_type_list (V8HI_type_node, V8HI_type_node,
+ intHI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v8hi", ftype,
+ ALTIVEC_BUILTIN_VEC_SET_V8HI);
+
+ ftype = build_function_type_list (V8HI_type_node, V16QI_type_node,
+ intQI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v16qi", ftype,
+ ALTIVEC_BUILTIN_VEC_SET_V16QI);
+
+ ftype = build_function_type_list (V4SF_type_node, V4SF_type_node,
+ float_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_set_v4sf", ftype,
+ ALTIVEC_BUILTIN_VEC_SET_V4SF);
+
+ /* Access to the vec_extract patterns. */
+ ftype = build_function_type_list (intSI_type_node, V4SI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4si", ftype,
+ ALTIVEC_BUILTIN_VEC_EXT_V4SI);
+
+ ftype = build_function_type_list (intHI_type_node, V8HI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v8hi", ftype,
+ ALTIVEC_BUILTIN_VEC_EXT_V8HI);
+
+ ftype = build_function_type_list (intQI_type_node, V16QI_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v16qi", ftype,
+ ALTIVEC_BUILTIN_VEC_EXT_V16QI);
+
+ ftype = build_function_type_list (float_type_node, V4SF_type_node,
+ integer_type_node, NULL_TREE);
+ def_builtin (MASK_ALTIVEC, "__builtin_vec_ext_v4sf", ftype,
+ ALTIVEC_BUILTIN_VEC_EXT_V4SF);
}
static void
@@ -7262,6 +8754,10 @@ rs6000_common_init_builtins (void)
integer_type_node, integer_type_node,
NULL_TREE);
+ tree opaque_ftype_opaque
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, NULL_TREE);
+
tree v2si_ftype_v2si
= build_function_type_list (opaque_V2SI_type_node,
opaque_V2SI_type_node, NULL_TREE);
@@ -7269,7 +8765,7 @@ rs6000_common_init_builtins (void)
tree v2sf_ftype_v2sf
= build_function_type_list (opaque_V2SF_type_node,
opaque_V2SF_type_node, NULL_TREE);
-
+
tree v2sf_ftype_v2si
= build_function_type_list (opaque_V2SF_type_node,
opaque_V2SI_type_node, NULL_TREE);
@@ -7296,6 +8792,9 @@ rs6000_common_init_builtins (void)
integer_type_node, integer_type_node,
NULL_TREE);
+ tree opaque_ftype_opaque_opaque
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, opaque_V4SI_type_node, NULL_TREE);
tree v4si_ftype_v4si_v4si
= build_function_type_list (V4SI_type_node,
V4SI_type_node, V4SI_type_node, NULL_TREE);
@@ -7333,6 +8832,10 @@ rs6000_common_init_builtins (void)
tree v4sf_ftype_v4sf_v4sf
= build_function_type_list (V4SF_type_node,
V4SF_type_node, V4SF_type_node, NULL_TREE);
+ tree opaque_ftype_opaque_opaque_opaque
+ = build_function_type_list (opaque_V4SI_type_node,
+ opaque_V4SI_type_node, opaque_V4SI_type_node,
+ opaque_V4SI_type_node, NULL_TREE);
tree v4sf_ftype_v4sf_v4sf_v4si
= build_function_type_list (V4SF_type_node,
V4SF_type_node, V4SF_type_node,
@@ -7341,7 +8844,7 @@ rs6000_common_init_builtins (void)
= build_function_type_list (V4SF_type_node,
V4SF_type_node, V4SF_type_node,
V4SF_type_node, NULL_TREE);
- tree v4si_ftype_v4si_v4si_v4si
+ tree v4si_ftype_v4si_v4si_v4si
= build_function_type_list (V4SI_type_node,
V4SI_type_node, V4SI_type_node,
V4SI_type_node, NULL_TREE);
@@ -7352,11 +8855,11 @@ rs6000_common_init_builtins (void)
= build_function_type_list (V8HI_type_node,
V8HI_type_node, V8HI_type_node,
V8HI_type_node, NULL_TREE);
- tree v4si_ftype_v8hi_v8hi_v4si
+ tree v4si_ftype_v8hi_v8hi_v4si
= build_function_type_list (V4SI_type_node,
V8HI_type_node, V8HI_type_node,
V4SI_type_node, NULL_TREE);
- tree v4si_ftype_v16qi_v16qi_v4si
+ tree v4si_ftype_v16qi_v16qi_v4si
= build_function_type_list (V4SI_type_node,
V16QI_type_node, V16QI_type_node,
V4SI_type_node, NULL_TREE);
@@ -7406,23 +8909,37 @@ rs6000_common_init_builtins (void)
d = (struct builtin_description *) bdesc_3arg;
for (i = 0; i < ARRAY_SIZE (bdesc_3arg); i++, d++)
{
-
enum machine_mode mode0, mode1, mode2, mode3;
tree type;
+ bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
+
+ if (is_overloaded)
+ {
+ mode0 = VOIDmode;
+ mode1 = VOIDmode;
+ mode2 = VOIDmode;
+ mode3 = VOIDmode;
+ }
+ else
+ {
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
+ continue;
+
+ mode0 = insn_data[d->icode].operand[0].mode;
+ mode1 = insn_data[d->icode].operand[1].mode;
+ mode2 = insn_data[d->icode].operand[2].mode;
+ mode3 = insn_data[d->icode].operand[3].mode;
+ }
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
- continue;
-
- mode0 = insn_data[d->icode].operand[0].mode;
- mode1 = insn_data[d->icode].operand[1].mode;
- mode2 = insn_data[d->icode].operand[2].mode;
- mode3 = insn_data[d->icode].operand[3].mode;
-
/* When all four are of the same mode. */
if (mode0 == mode1 && mode1 == mode2 && mode2 == mode3)
{
switch (mode0)
{
+ case VOIDmode:
+ type = opaque_ftype_opaque_opaque_opaque;
+ break;
case V4SImode:
type = v4si_ftype_v4si_v4si_v4si;
break;
@@ -7431,16 +8948,16 @@ rs6000_common_init_builtins (void)
break;
case V8HImode:
type = v8hi_ftype_v8hi_v8hi_v8hi;
- break;
+ break;
case V16QImode:
type = v16qi_ftype_v16qi_v16qi_v16qi;
- break;
+ break;
default:
- abort();
+ gcc_unreachable ();
}
}
else if (mode0 == mode1 && mode1 == mode2 && mode3 == V16QImode)
- {
+ {
switch (mode0)
{
case V4SImode:
@@ -7451,21 +8968,21 @@ rs6000_common_init_builtins (void)
break;
case V8HImode:
type = v8hi_ftype_v8hi_v8hi_v16qi;
- break;
+ break;
case V16QImode:
type = v16qi_ftype_v16qi_v16qi_v16qi;
- break;
+ break;
default:
- abort();
+ gcc_unreachable ();
}
}
- else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
+ else if (mode0 == V4SImode && mode1 == V16QImode && mode2 == V16QImode
&& mode3 == V4SImode)
type = v4si_ftype_v16qi_v16qi_v4si;
- else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
+ else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V8HImode
&& mode3 == V4SImode)
type = v4si_ftype_v8hi_v8hi_v4si;
- else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
+ else if (mode0 == V4SFmode && mode1 == V4SFmode && mode2 == V4SFmode
&& mode3 == V4SImode)
type = v4sf_ftype_v4sf_v4sf_v4si;
@@ -7490,7 +9007,7 @@ rs6000_common_init_builtins (void)
type = v4sf_ftype_v4sf_v4sf_int;
else
- abort ();
+ gcc_unreachable ();
def_builtin (d->mask, d->name, type, d->code);
}
@@ -7501,19 +9018,33 @@ rs6000_common_init_builtins (void)
{
enum machine_mode mode0, mode1, mode2;
tree type;
+ bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
- continue;
-
- mode0 = insn_data[d->icode].operand[0].mode;
- mode1 = insn_data[d->icode].operand[1].mode;
- mode2 = insn_data[d->icode].operand[2].mode;
+ if (is_overloaded)
+ {
+ mode0 = VOIDmode;
+ mode1 = VOIDmode;
+ mode2 = VOIDmode;
+ }
+ else
+ {
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
+ continue;
+
+ mode0 = insn_data[d->icode].operand[0].mode;
+ mode1 = insn_data[d->icode].operand[1].mode;
+ mode2 = insn_data[d->icode].operand[2].mode;
+ }
/* When all three operands are of the same mode. */
if (mode0 == mode1 && mode1 == mode2)
{
switch (mode0)
{
+ case VOIDmode:
+ type = opaque_ftype_opaque_opaque;
+ break;
case V4SFmode:
type = v4sf_ftype_v4sf_v4sf;
break;
@@ -7536,7 +9067,7 @@ rs6000_common_init_builtins (void)
type = int_ftype_int_int;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -7573,15 +9104,15 @@ rs6000_common_init_builtins (void)
/* vint, vshort, vint. */
else if (mode0 == V4SImode && mode1 == V8HImode && mode2 == V4SImode)
type = v4si_ftype_v8hi_v4si;
-
+
/* vint, vint, 5 bit literal. */
else if (mode0 == V4SImode && mode1 == V4SImode && mode2 == QImode)
type = v4si_ftype_v4si_int;
-
+
/* vshort, vshort, 5 bit literal. */
else if (mode0 == V8HImode && mode1 == V8HImode && mode2 == QImode)
type = v8hi_ftype_v8hi_int;
-
+
/* vchar, vchar, 5 bit literal. */
else if (mode0 == V16QImode && mode1 == V16QImode && mode2 == QImode)
type = v16qi_ftype_v16qi_int;
@@ -7589,7 +9120,7 @@ rs6000_common_init_builtins (void)
/* vfloat, vint, 5 bit literal. */
else if (mode0 == V4SFmode && mode1 == V4SImode && mode2 == QImode)
type = v4sf_ftype_v4si_int;
-
+
/* vint, vfloat, 5 bit literal. */
else if (mode0 == V4SImode && mode1 == V4SFmode && mode2 == QImode)
type = v4si_ftype_v4sf_int;
@@ -7603,9 +9134,10 @@ rs6000_common_init_builtins (void)
else if (mode0 == V2SImode && mode1 == SImode && mode2 == QImode)
type = v2si_ftype_int_char;
- /* int, x, x. */
- else if (mode0 == SImode)
+ else
{
+ /* int, x, x. */
+ gcc_assert (mode0 == SImode);
switch (mode1)
{
case V4SImode:
@@ -7621,13 +9153,10 @@ rs6000_common_init_builtins (void)
type = int_ftype_v8hi_v8hi;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
- else
- abort ();
-
def_builtin (d->mask, d->name, type, d->code);
}
@@ -7637,19 +9166,31 @@ rs6000_common_init_builtins (void)
{
enum machine_mode mode0, mode1;
tree type;
+ bool is_overloaded = d->code >= ALTIVEC_BUILTIN_OVERLOADED_FIRST
+ && d->code <= ALTIVEC_BUILTIN_OVERLOADED_LAST;
- if (d->name == 0 || d->icode == CODE_FOR_nothing)
- continue;
-
- mode0 = insn_data[d->icode].operand[0].mode;
- mode1 = insn_data[d->icode].operand[1].mode;
+ if (is_overloaded)
+ {
+ mode0 = VOIDmode;
+ mode1 = VOIDmode;
+ }
+ else
+ {
+ if (d->name == 0 || d->icode == CODE_FOR_nothing)
+ continue;
+
+ mode0 = insn_data[d->icode].operand[0].mode;
+ mode1 = insn_data[d->icode].operand[1].mode;
+ }
if (mode0 == V4SImode && mode1 == QImode)
- type = v4si_ftype_int;
+ type = v4si_ftype_int;
else if (mode0 == V8HImode && mode1 == QImode)
- type = v8hi_ftype_int;
+ type = v8hi_ftype_int;
else if (mode0 == V16QImode && mode1 == QImode)
- type = v16qi_ftype_int;
+ type = v16qi_ftype_int;
+ else if (mode0 == VOIDmode && mode1 == VOIDmode)
+ type = opaque_ftype_opaque;
else if (mode0 == V4SFmode && mode1 == V4SFmode)
type = v4sf_ftype_v4sf;
else if (mode0 == V8HImode && mode1 == V16QImode)
@@ -7667,7 +9208,7 @@ rs6000_common_init_builtins (void)
else if (mode0 == V2SImode && mode1 == QImode)
type = v2si_ftype_char;
else
- abort ();
+ gcc_unreachable ();
def_builtin (d->mask, d->name, type, d->code);
}
@@ -7676,36 +9217,53 @@ rs6000_common_init_builtins (void)
static void
rs6000_init_libfuncs (void)
{
- if (!TARGET_HARD_FLOAT)
- return;
-
- if (DEFAULT_ABI != ABI_V4)
+ if (DEFAULT_ABI != ABI_V4 && TARGET_XCOFF
+ && !TARGET_POWER2 && !TARGET_POWERPC)
{
- if (TARGET_XCOFF && ! TARGET_POWER2 && ! TARGET_POWERPC)
- {
- /* AIX library routines for float->int conversion. */
- set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc");
- set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc");
- set_conv_libfunc (sfix_optab, SImode, TFmode, "_qitrunc");
- set_conv_libfunc (ufix_optab, SImode, TFmode, "_quitrunc");
- }
+ /* AIX library routines for float->int conversion. */
+ set_conv_libfunc (sfix_optab, SImode, DFmode, "__itrunc");
+ set_conv_libfunc (ufix_optab, SImode, DFmode, "__uitrunc");
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "_qitrunc");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "_quitrunc");
+ }
+ if (!TARGET_IEEEQUAD)
/* AIX/Darwin/64-bit Linux quad floating point routines. */
- if (!TARGET_XL_COMPAT)
- {
- set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
- set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
- set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
- set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
- }
- else
- {
- set_optab_libfunc (add_optab, TFmode, "_xlqadd");
- set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
- set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
- set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
- }
- }
+ if (!TARGET_XL_COMPAT)
+ {
+ set_optab_libfunc (add_optab, TFmode, "__gcc_qadd");
+ set_optab_libfunc (sub_optab, TFmode, "__gcc_qsub");
+ set_optab_libfunc (smul_optab, TFmode, "__gcc_qmul");
+ set_optab_libfunc (sdiv_optab, TFmode, "__gcc_qdiv");
+
+ if (TARGET_SOFT_FLOAT)
+ {
+ set_optab_libfunc (neg_optab, TFmode, "__gcc_qneg");
+ set_optab_libfunc (eq_optab, TFmode, "__gcc_qeq");
+ set_optab_libfunc (ne_optab, TFmode, "__gcc_qne");
+ set_optab_libfunc (gt_optab, TFmode, "__gcc_qgt");
+ set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
+ set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
+ set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
+ set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
+
+ set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
+ set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
+ set_conv_libfunc (trunc_optab, SFmode, TFmode, "__gcc_qtos");
+ set_conv_libfunc (trunc_optab, DFmode, TFmode, "__gcc_qtod");
+ set_conv_libfunc (sfix_optab, SImode, TFmode, "__gcc_qtoi");
+ set_conv_libfunc (ufix_optab, SImode, TFmode, "__gcc_qtou");
+ set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
+ set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
+ }
+ }
+ else
+ {
+ set_optab_libfunc (add_optab, TFmode, "_xlqadd");
+ set_optab_libfunc (sub_optab, TFmode, "_xlqsub");
+ set_optab_libfunc (smul_optab, TFmode, "_xlqmul");
+ set_optab_libfunc (sdiv_optab, TFmode, "_xlqdiv");
+ }
else
{
/* 32-bit SVR4 quad floating point routines. */
@@ -7732,8 +9290,102 @@ rs6000_init_libfuncs (void)
set_conv_libfunc (sfix_optab, SImode, TFmode, "_q_qtoi");
set_conv_libfunc (ufix_optab, SImode, TFmode, "_q_qtou");
set_conv_libfunc (sfloat_optab, TFmode, SImode, "_q_itoq");
+ set_conv_libfunc (ufloat_optab, TFmode, SImode, "_q_utoq");
+ }
+}
+
+
+/* Expand a block clear operation, and return 1 if successful. Return 0
+ if we should let the compiler generate normal code.
+
+ operands[0] is the destination
+ operands[1] is the length
+ operands[3] is the alignment */
+
+int
+expand_block_clear (rtx operands[])
+{
+ rtx orig_dest = operands[0];
+ rtx bytes_rtx = operands[1];
+ rtx align_rtx = operands[3];
+ bool constp = (GET_CODE (bytes_rtx) == CONST_INT);
+ HOST_WIDE_INT align;
+ HOST_WIDE_INT bytes;
+ int offset;
+ int clear_bytes;
+ int clear_step;
+
+ /* If this is not a fixed size move, just call memcpy */
+ if (! constp)
+ return 0;
+
+ /* This must be a fixed size alignment */
+ gcc_assert (GET_CODE (align_rtx) == CONST_INT);
+ align = INTVAL (align_rtx) * BITS_PER_UNIT;
+
+ /* Anything to clear? */
+ bytes = INTVAL (bytes_rtx);
+ if (bytes <= 0)
+ return 1;
+
+ /* Use the builtin memset after a point, to avoid huge code bloat.
+ When optimize_size, avoid any significant code bloat; calling
+ memset is about 4 instructions, so allow for one instruction to
+ load zero and three to do clearing. */
+ if (TARGET_ALTIVEC && align >= 128)
+ clear_step = 16;
+ else if (TARGET_POWERPC64 && align >= 32)
+ clear_step = 8;
+ else
+ clear_step = 4;
+
+ if (optimize_size && bytes > 3 * clear_step)
+ return 0;
+ if (! optimize_size && bytes > 8 * clear_step)
+ return 0;
+
+ for (offset = 0; bytes > 0; offset += clear_bytes, bytes -= clear_bytes)
+ {
+ enum machine_mode mode = BLKmode;
+ rtx dest;
+
+ if (bytes >= 16 && TARGET_ALTIVEC && align >= 128)
+ {
+ clear_bytes = 16;
+ mode = V4SImode;
+ }
+ else if (bytes >= 8 && TARGET_POWERPC64
+ /* 64-bit loads and stores require word-aligned
+ displacements. */
+ && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
+ {
+ clear_bytes = 8;
+ mode = DImode;
+ }
+ else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
+ { /* move 4 bytes */
+ clear_bytes = 4;
+ mode = SImode;
+ }
+ else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
+ { /* move 2 bytes */
+ clear_bytes = 2;
+ mode = HImode;
+ }
+ else /* move 1 byte at a time */
+ {
+ clear_bytes = 1;
+ mode = QImode;
+ }
+
+ dest = adjust_address (orig_dest, mode, offset);
+
+ emit_move_insn (dest, CONST0_RTX (mode));
}
+
+ return 1;
}
+
/* Expand a block move operation, and return 1 if successful. Return 0
if we should let the compiler generate normal code.
@@ -7764,10 +9416,9 @@ expand_block_move (rtx operands[])
if (! constp)
return 0;
- /* If this is not a fixed size alignment, abort */
- if (GET_CODE (align_rtx) != CONST_INT)
- abort ();
- align = INTVAL (align_rtx);
+ /* This must be a fixed size alignment */
+ gcc_assert (GET_CODE (align_rtx) == CONST_INT);
+ align = INTVAL (align_rtx) * BITS_PER_UNIT;
/* Anything to move? */
bytes = INTVAL (bytes_rtx);
@@ -7775,20 +9426,28 @@ expand_block_move (rtx operands[])
return 1;
/* store_one_arg depends on expand_block_move to handle at least the size of
- reg_parm_stack_space. */
+ reg_parm_stack_space. */
if (bytes > (TARGET_POWERPC64 ? 64 : 32))
return 0;
for (offset = 0; bytes > 0; offset += move_bytes, bytes -= move_bytes)
{
union {
- rtx (*movstrsi) (rtx, rtx, rtx, rtx);
+ rtx (*movmemsi) (rtx, rtx, rtx, rtx);
rtx (*mov) (rtx, rtx);
} gen_func;
enum machine_mode mode = BLKmode;
rtx src, dest;
-
- if (TARGET_STRING
+
+ /* Altivec first, since it will be faster than a string move
+ when it applies, and usually not significantly larger. */
+ if (TARGET_ALTIVEC && bytes >= 16 && align >= 128)
+ {
+ move_bytes = 16;
+ mode = V4SImode;
+ gen_func.mov = gen_movv4si;
+ }
+ else if (TARGET_STRING
&& bytes > 24 /* move up to 32 bytes at a time */
&& ! fixed_regs[5]
&& ! fixed_regs[6]
@@ -7800,7 +9459,7 @@ expand_block_move (rtx operands[])
&& ! fixed_regs[12])
{
move_bytes = (bytes > 32) ? 32 : bytes;
- gen_func.movstrsi = gen_movstrsi_8reg;
+ gen_func.movmemsi = gen_movmemsi_8reg;
}
else if (TARGET_STRING
&& bytes > 16 /* move up to 24 bytes at a time */
@@ -7812,7 +9471,7 @@ expand_block_move (rtx operands[])
&& ! fixed_regs[10])
{
move_bytes = (bytes > 24) ? 24 : bytes;
- gen_func.movstrsi = gen_movstrsi_6reg;
+ gen_func.movmemsi = gen_movmemsi_6reg;
}
else if (TARGET_STRING
&& bytes > 8 /* move up to 16 bytes at a time */
@@ -7822,12 +9481,12 @@ expand_block_move (rtx operands[])
&& ! fixed_regs[8])
{
move_bytes = (bytes > 16) ? 16 : bytes;
- gen_func.movstrsi = gen_movstrsi_4reg;
+ gen_func.movmemsi = gen_movmemsi_4reg;
}
else if (bytes >= 8 && TARGET_POWERPC64
/* 64-bit loads and stores require word-aligned
displacements. */
- && (align >= 8 || (! STRICT_ALIGNMENT && align >= 4)))
+ && (align >= 64 || (!STRICT_ALIGNMENT && align >= 32)))
{
move_bytes = 8;
mode = DImode;
@@ -7836,15 +9495,15 @@ expand_block_move (rtx operands[])
else if (TARGET_STRING && bytes > 4 && !TARGET_POWERPC64)
{ /* move up to 8 bytes at a time */
move_bytes = (bytes > 8) ? 8 : bytes;
- gen_func.movstrsi = gen_movstrsi_2reg;
+ gen_func.movmemsi = gen_movmemsi_2reg;
}
- else if (bytes >= 4 && (align >= 4 || ! STRICT_ALIGNMENT))
+ else if (bytes >= 4 && (align >= 32 || !STRICT_ALIGNMENT))
{ /* move 4 bytes */
move_bytes = 4;
mode = SImode;
gen_func.mov = gen_movsi;
}
- else if (bytes >= 2 && (align >= 2 || ! STRICT_ALIGNMENT))
+ else if (bytes >= 2 && (align >= 16 || !STRICT_ALIGNMENT))
{ /* move 2 bytes */
move_bytes = 2;
mode = HImode;
@@ -7853,7 +9512,7 @@ expand_block_move (rtx operands[])
else if (TARGET_STRING && bytes > 1)
{ /* move up to 4 bytes at a time */
move_bytes = (bytes > 4) ? 4 : bytes;
- gen_func.movstrsi = gen_movstrsi_1reg;
+ gen_func.movmemsi = gen_movmemsi_1reg;
}
else /* move 1 byte at a time */
{
@@ -7861,14 +9520,14 @@ expand_block_move (rtx operands[])
mode = QImode;
gen_func.mov = gen_movqi;
}
-
+
src = adjust_address (orig_src, mode, offset);
dest = adjust_address (orig_dest, mode, offset);
-
- if (mode != BLKmode)
+
+ if (mode != BLKmode)
{
rtx tmp_reg = gen_reg_rtx (mode);
-
+
emit_insn ((*gen_func.mov) (tmp_reg, src));
stores[num_reg++] = (*gen_func.mov) (dest, tmp_reg);
}
@@ -7883,7 +9542,7 @@ expand_block_move (rtx operands[])
if (mode == BLKmode)
{
- /* Move the address into scratch registers. The movstrsi
+ /* Move the address into scratch registers. The movmemsi
patterns require zero offset. */
if (!REG_P (XEXP (src, 0)))
{
@@ -7891,15 +9550,15 @@ expand_block_move (rtx operands[])
src = replace_equiv_address (src, src_reg);
}
set_mem_size (src, GEN_INT (move_bytes));
-
+
if (!REG_P (XEXP (dest, 0)))
{
rtx dest_reg = copy_addr_to_reg (XEXP (dest, 0));
dest = replace_equiv_address (dest, dest_reg);
}
set_mem_size (dest, GEN_INT (move_bytes));
-
- emit_insn ((*gen_func.movstrsi) (dest, src,
+
+ emit_insn ((*gen_func.movmemsi) (dest, src,
GEN_INT (move_bytes & 31),
align_rtx));
}
@@ -7909,88 +9568,6 @@ expand_block_move (rtx operands[])
}
-/* 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 (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)) != SImode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode
- || 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. Here, the second vector element
- is a CLOBBER. It will be tested later. */
-
-int
-store_multiple_operation (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 + 1);
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode
- || 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;
-}
-
/* Return a string to perform a load_multiple operation.
operands[0] is the vector.
operands[1] is the source address.
@@ -8048,405 +9625,43 @@ rs6000_output_load_multiple (rtx operands[3])
return "{lsi|lswi} %2,%1,%N0";
}
-/* Return 1 for a parallel vrsave operation. */
-
-int
-vrsave_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int dest_regno, src_regno;
- int i;
-
- 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))) != UNSPEC_VOLATILE)
- return 0;
-
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
-
- if (dest_regno != VRSAVE_REGNO
- && src_regno != VRSAVE_REGNO)
- return 0;
-
- for (i = 1; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
-
- if (GET_CODE (elt) != CLOBBER
- && GET_CODE (elt) != SET)
- return 0;
- }
-
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for mfcr. */
-
-int
-mfcr_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- 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_SRC (XVECEXP (op, 0, 0))) != UNSPEC
- || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx exp = XVECEXP (op, 0, i);
- rtx unspec;
- int maskval;
- rtx src_reg;
-
- src_reg = XVECEXP (SET_SRC (exp), 0, 0);
-
- if (GET_CODE (src_reg) != REG
- || GET_MODE (src_reg) != CCmode
- || ! CR_REGNO_P (REGNO (src_reg)))
- return 0;
-
- if (GET_CODE (exp) != SET
- || GET_CODE (SET_DEST (exp)) != REG
- || GET_MODE (SET_DEST (exp)) != SImode
- || ! INT_REGNO_P (REGNO (SET_DEST (exp))))
- return 0;
- unspec = SET_SRC (exp);
- maskval = 1 << (MAX_CR_REGNO - REGNO (src_reg));
-
- if (GET_CODE (unspec) != UNSPEC
- || XINT (unspec, 1) != UNSPEC_MOVESI_FROM_CR
- || XVECLEN (unspec, 0) != 2
- || XVECEXP (unspec, 0, 0) != src_reg
- || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
- || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
- return 0;
- }
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for mtcrf. */
-
-int
-mtcrf_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- int i;
- rtx src_reg;
-
- /* Perform a quick check so we don't blow up below. */
- if (count < 1
- || GET_CODE (XVECEXP (op, 0, 0)) != SET
- || GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != UNSPEC
- || XVECLEN (SET_SRC (XVECEXP (op, 0, 0)), 0) != 2)
- return 0;
- src_reg = XVECEXP (SET_SRC (XVECEXP (op, 0, 0)), 0, 0);
-
- if (GET_CODE (src_reg) != REG
- || GET_MODE (src_reg) != SImode
- || ! INT_REGNO_P (REGNO (src_reg)))
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx exp = XVECEXP (op, 0, i);
- rtx unspec;
- int maskval;
-
- if (GET_CODE (exp) != SET
- || GET_CODE (SET_DEST (exp)) != REG
- || GET_MODE (SET_DEST (exp)) != CCmode
- || ! CR_REGNO_P (REGNO (SET_DEST (exp))))
- return 0;
- unspec = SET_SRC (exp);
- maskval = 1 << (MAX_CR_REGNO - REGNO (SET_DEST (exp)));
-
- if (GET_CODE (unspec) != UNSPEC
- || XINT (unspec, 1) != UNSPEC_MOVESI_TO_CR
- || XVECLEN (unspec, 0) != 2
- || XVECEXP (unspec, 0, 0) != src_reg
- || GET_CODE (XVECEXP (unspec, 0, 1)) != CONST_INT
- || INTVAL (XVECEXP (unspec, 0, 1)) != maskval)
- return 0;
- }
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for lmw. */
-
-int
-lmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int dest_regno;
- rtx src_addr;
- unsigned int base_regno;
- HOST_WIDE_INT offset;
- 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);
-
- if (dest_regno > 31
- || count != 32 - (int) dest_regno)
- return 0;
-
- 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, 0))
- {
- offset = INTVAL (XEXP (src_addr, 1));
- base_regno = REGNO (XEXP (src_addr, 0));
- }
- else
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
- rtx newaddr;
- rtx addr_reg;
- HOST_WIDE_INT newoffset;
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_DEST (elt)) != REG
- || GET_MODE (SET_DEST (elt)) != SImode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != SImode)
- return 0;
- newaddr = XEXP (SET_SRC (elt), 0);
- if (legitimate_indirect_address_p (newaddr, 0))
- {
- newoffset = 0;
- addr_reg = newaddr;
- }
- else if (legitimate_offset_address_p (SImode, newaddr, 0))
- {
- addr_reg = XEXP (newaddr, 0);
- newoffset = INTVAL (XEXP (newaddr, 1));
- }
- else
- return 0;
- if (REGNO (addr_reg) != base_regno
- || newoffset != offset + 4 * i)
- return 0;
- }
-
- return 1;
-}
-
-/* Return 1 for an PARALLEL suitable for stmw. */
-
-int
-stmw_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- int count = XVECLEN (op, 0);
- unsigned int src_regno;
- rtx dest_addr;
- unsigned int base_regno;
- HOST_WIDE_INT offset;
- 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);
-
- if (src_regno > 31
- || count != 32 - (int) src_regno)
- return 0;
-
- 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, 0))
- {
- offset = INTVAL (XEXP (dest_addr, 1));
- base_regno = REGNO (XEXP (dest_addr, 0));
- }
- else
- return 0;
-
- for (i = 0; i < count; i++)
- {
- rtx elt = XVECEXP (op, 0, i);
- rtx newaddr;
- rtx addr_reg;
- HOST_WIDE_INT newoffset;
-
- if (GET_CODE (elt) != SET
- || GET_CODE (SET_SRC (elt)) != REG
- || GET_MODE (SET_SRC (elt)) != SImode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != SImode)
- return 0;
- newaddr = XEXP (SET_DEST (elt), 0);
- if (legitimate_indirect_address_p (newaddr, 0))
- {
- newoffset = 0;
- addr_reg = newaddr;
- }
- else if (legitimate_offset_address_p (SImode, newaddr, 0))
- {
- addr_reg = XEXP (newaddr, 0);
- newoffset = INTVAL (XEXP (newaddr, 1));
- }
- else
- return 0;
- if (REGNO (addr_reg) != base_regno
- || newoffset != offset + 4 * i)
- return 0;
- }
-
- return 1;
-}
/* A validation routine: say whether CODE, a condition code, and MODE
match. The other alternatives either don't make sense or should
never be generated. */
-static void
+void
validate_condition_mode (enum rtx_code code, enum machine_mode mode)
{
- if (GET_RTX_CLASS (code) != '<'
- || GET_MODE_CLASS (mode) != MODE_CC)
- abort ();
+ gcc_assert ((GET_RTX_CLASS (code) == RTX_COMPARE
+ || GET_RTX_CLASS (code) == RTX_COMM_COMPARE)
+ && GET_MODE_CLASS (mode) == MODE_CC);
/* These don't make sense. */
- if ((code == GT || code == LT || code == GE || code == LE)
- && mode == CCUNSmode)
- abort ();
+ gcc_assert ((code != GT && code != LT && code != GE && code != LE)
+ || mode != CCUNSmode);
- if ((code == GTU || code == LTU || code == GEU || code == LEU)
- && mode != CCUNSmode)
- abort ();
+ gcc_assert ((code != GTU && code != LTU && code != GEU && code != LEU)
+ || mode == CCUNSmode);
- if (mode != CCFPmode
- && (code == ORDERED || code == UNORDERED
- || code == UNEQ || code == LTGT
- || code == UNGT || code == UNLT
- || code == UNGE || code == UNLE))
- abort ();
-
- /* These should never be generated except for
+ gcc_assert (mode == CCFPmode
+ || (code != ORDERED && code != UNORDERED
+ && code != UNEQ && code != LTGT
+ && code != UNGT && code != UNLT
+ && code != UNGE && code != UNLE));
+
+ /* These should never be generated except for
flag_finite_math_only. */
- if (mode == CCFPmode
- && ! flag_finite_math_only
- && (code == LE || code == GE
- || code == UNEQ || code == LTGT
- || code == UNGT || code == UNLT))
- abort ();
+ gcc_assert (mode != CCFPmode
+ || flag_finite_math_only
+ || (code != LE && code != GE
+ && code != UNEQ && code != LTGT
+ && code != UNGT && code != UNLT));
/* These are invalid; the information is not there. */
- if (mode == CCEQmode
- && code != EQ && code != NE)
- abort ();
-}
-
-/* Return 1 if OP is a comparison operation that is valid for a branch insn.
- We only check the opcode against the mode of the CC value here. */
-
-int
-branch_comparison_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- enum machine_mode cc_mode;
-
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- cc_mode = GET_MODE (XEXP (op, 0));
- if (GET_MODE_CLASS (cc_mode) != MODE_CC)
- return 0;
-
- validate_condition_mode (code, cc_mode);
-
- return 1;
-}
-
-/* Return 1 if OP is a comparison operation that is valid for a branch
- insn and which is true if the corresponding bit in the CC register
- is set. */
-
-int
-branch_positive_comparison_operator (rtx op, enum machine_mode mode)
-{
- enum rtx_code code;
-
- if (! branch_comparison_operator (op, mode))
- return 0;
-
- code = GET_CODE (op);
- return (code == EQ || code == LT || code == GT
- || code == LTU || code == GTU
- || code == UNORDERED);
-}
-
-/* Return 1 if OP is a comparison operation that is valid for an scc
- insn: it must be a positive comparison. */
-
-int
-scc_comparison_operator (rtx op, enum machine_mode mode)
-{
- return branch_positive_comparison_operator (op, mode);
-}
-
-int
-trap_comparison_operator (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- return GET_RTX_CLASS (GET_CODE (op)) == '<';
-}
-
-int
-boolean_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- return (code == AND || code == IOR || code == XOR);
-}
-
-int
-boolean_or_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
- return (code == IOR || code == XOR);
+ gcc_assert (mode != CCEQmode || code == EQ || code == NE);
}
-int
-min_max_operator (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
@@ -8637,17 +9852,39 @@ includes_rldicr_lshift_p (rtx shiftop, rtx andop)
return 0;
}
-/* Return 1 if REGNO (reg1) == REGNO (reg2) - 1 making them candidates
- for lfq and stfq insns.
+/* Return 1 if operands will generate a valid arguments to rlwimi
+instruction for insert with right shift in 64-bit mode. The mask may
+not start on the first bit or stop on the last bit because wrap-around
+effects of instruction do not correspond to semantics of RTL insn. */
+
+int
+insvdi_rshift_rlwimi_p (rtx sizeop, rtx startop, rtx shiftop)
+{
+ if (INTVAL (startop) > 32
+ && INTVAL (startop) < 64
+ && INTVAL (sizeop) > 1
+ && INTVAL (sizeop) + INTVAL (startop) < 64
+ && INTVAL (shiftop) > 0
+ && INTVAL (sizeop) + INTVAL (shiftop) < 32
+ && (64 - (INTVAL (shiftop) & 63)) >= INTVAL (sizeop))
+ return 1;
+
+ return 0;
+}
- Note reg1 and reg2 *must* be hard registers. To be sure we will
- abort if we are passed pseudo registers. */
+/* Return 1 if REGNO (reg1) == REGNO (reg2) - 1 making them candidates
+ for lfq and stfq insns iff the registers are hard registers. */
int
registers_ok_for_quad_peep (rtx reg1, rtx reg2)
{
/* We might have been passed a SUBREG. */
- if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
+ if (GET_CODE (reg1) != REG || GET_CODE (reg2) != REG)
+ return 0;
+
+ /* We might have been passed non floating point registers. */
+ if (!FP_REGNO_P (REGNO (reg1))
+ || !FP_REGNO_P (REGNO (reg2)))
return 0;
return (REGNO (reg1) == REGNO (reg2) - 1);
@@ -8658,10 +9895,18 @@ registers_ok_for_quad_peep (rtx reg1, rtx reg2)
(addr2 == addr1 + 8). */
int
-addrs_ok_for_quad_peep (rtx addr1, rtx addr2)
+mems_ok_for_quad_peep (rtx mem1, rtx mem2)
{
- unsigned int reg1;
- int offset1;
+ rtx addr1, addr2;
+ unsigned int reg1, reg2;
+ int offset1, offset2;
+
+ /* The mems cannot be volatile. */
+ if (MEM_VOLATILE_P (mem1) || MEM_VOLATILE_P (mem2))
+ return 0;
+
+ addr1 = XEXP (mem1, 0);
+ addr2 = XEXP (mem2, 0);
/* Extract an offset (if used) from the first addr. */
if (GET_CODE (addr1) == PLUS)
@@ -8671,11 +9916,11 @@ addrs_ok_for_quad_peep (rtx addr1, rtx addr2)
return 0;
else
{
- reg1 = REGNO (XEXP (addr1, 0));
+ reg1 = REGNO (XEXP (addr1, 0));
/* The offset must be constant! */
if (GET_CODE (XEXP (addr1, 1)) != CONST_INT)
- return 0;
- offset1 = INTVAL (XEXP (addr1, 1));
+ return 0;
+ offset1 = INTVAL (XEXP (addr1, 1));
}
}
else if (GET_CODE (addr1) != REG)
@@ -8687,23 +9932,36 @@ addrs_ok_for_quad_peep (rtx addr1, rtx addr2)
offset1 = 0;
}
- /* Make sure the second address is a (mem (plus (reg) (const_int)))
- or if it is (mem (reg)) then make sure that offset1 is -8 and the same
- register as addr1. */
- if (offset1 == -8 && GET_CODE (addr2) == REG && reg1 == REGNO (addr2))
- return 1;
- if (GET_CODE (addr2) != PLUS)
- return 0;
-
- if (GET_CODE (XEXP (addr2, 0)) != REG
- || GET_CODE (XEXP (addr2, 1)) != CONST_INT)
+ /* And now for the second addr. */
+ if (GET_CODE (addr2) == PLUS)
+ {
+ /* If not a REG, return zero. */
+ if (GET_CODE (XEXP (addr2, 0)) != REG)
+ return 0;
+ else
+ {
+ reg2 = REGNO (XEXP (addr2, 0));
+ /* The offset must be constant. */
+ if (GET_CODE (XEXP (addr2, 1)) != CONST_INT)
+ return 0;
+ offset2 = INTVAL (XEXP (addr2, 1));
+ }
+ }
+ else if (GET_CODE (addr2) != REG)
return 0;
+ else
+ {
+ reg2 = REGNO (addr2);
+ /* This was a simple (mem (reg)) expression. Offset is 0. */
+ offset2 = 0;
+ }
- if (reg1 != REGNO (XEXP (addr2, 0)))
+ /* Both of these must have the same base register. */
+ if (reg1 != reg2)
return 0;
/* The offset for the second addr must be 8 more than the first addr. */
- if (INTVAL (XEXP (addr2, 1)) != offset1 + 8)
+ if (offset2 != offset1 + 8)
return 0;
/* All the tests passed. addr1 and addr2 are valid for lfq or stfq
@@ -8716,31 +9974,31 @@ addrs_ok_for_quad_peep (rtx addr1, rtx addr2)
NO_REGS is returned. */
enum reg_class
-secondary_reload_class (enum reg_class class,
- enum machine_mode mode,
- rtx in)
+rs6000_secondary_reload_class (enum reg_class class,
+ enum machine_mode mode ATTRIBUTE_UNUSED,
+ rtx in)
{
int regno;
if (TARGET_ELF || (DEFAULT_ABI == ABI_DARWIN
#if TARGET_MACHO
- && MACHOPIC_INDIRECT
+ && MACHOPIC_INDIRECT
#endif
- ))
+ ))
{
/* We cannot copy a symbolic operand directly into anything
- other than BASE_REGS for TARGET_ELF. So indicate that a
- register from BASE_REGS is needed as an intermediate
- register.
-
+ other than BASE_REGS for TARGET_ELF. So indicate that a
+ register from BASE_REGS is needed as an intermediate
+ register.
+
On Darwin, pic addresses require a load from memory, which
needs a base register. */
if (class != BASE_REGS
- && (GET_CODE (in) == SYMBOL_REF
- || GET_CODE (in) == HIGH
- || GET_CODE (in) == LABEL_REF
- || GET_CODE (in) == CONST))
- return BASE_REGS;
+ && (GET_CODE (in) == SYMBOL_REF
+ || GET_CODE (in) == HIGH
+ || GET_CODE (in) == LABEL_REF
+ || GET_CODE (in) == CONST))
+ return BASE_REGS;
}
if (GET_CODE (in) == REG)
@@ -8788,7 +10046,7 @@ secondary_reload_class (enum reg_class class,
}
/* Given a comparison operation, return the bit number in CCR to test. We
- know this is a valid comparison.
+ know this is a valid comparison.
SCC_P is 1 if this is for an scc. That means that %D will have been
used instead of %C, so the bits will be in different places.
@@ -8804,14 +10062,12 @@ ccr_bit (rtx op, int scc_p)
int base_bit;
rtx reg;
- if (GET_RTX_CLASS (code) != '<')
+ if (!COMPARISON_P (op))
return -1;
reg = XEXP (op, 0);
- if (GET_CODE (reg) != REG
- || ! CR_REGNO_P (REGNO (reg)))
- abort ();
+ gcc_assert (GET_CODE (reg) == REG && CR_REGNO_P (REGNO (reg)));
cc_mode = GET_MODE (reg);
cc_regnum = REGNO (reg);
@@ -8821,10 +10077,10 @@ ccr_bit (rtx op, int scc_p)
/* When generating a sCOND operation, only positive conditions are
allowed. */
- if (scc_p && code != EQ && code != GT && code != LT && code != UNORDERED
- && code != GTU && code != LTU)
- abort ();
-
+ gcc_assert (!scc_p
+ || code == EQ || code == GT || code == LT || code == UNORDERED
+ || code == GTU || code == LTU);
+
switch (code)
{
case NE:
@@ -8848,13 +10104,13 @@ ccr_bit (rtx op, int scc_p)
return scc_p ? base_bit + 3 : base_bit + 1;
default:
- abort ();
+ gcc_unreachable ();
}
}
/* Return the GOT register. */
-struct rtx_def *
+rtx
rs6000_got_register (rtx value ATTRIBUTE_UNUSED)
{
/* The second flow pass currently (June 1999) can't update
@@ -8896,8 +10152,7 @@ extract_MB (rtx op)
from the left. */
if ((val & 0x80000000) == 0)
{
- if ((val & 0xffffffff) == 0)
- abort ();
+ gcc_assert (val & 0xffffffff);
i = 1;
while (((val <<= 1) & 0x80000000) == 0)
@@ -8929,8 +10184,7 @@ extract_ME (rtx op)
the right. */
if ((val & 1) == 0)
{
- if ((val & 0xffffffff) == 0)
- abort ();
+ gcc_assert (val & 0xffffffff);
i = 30;
while (((val >>= 1) & 1) == 0)
@@ -8970,7 +10224,7 @@ rs6000_get_some_local_dynamic_name (void)
rs6000_get_some_local_dynamic_name_1, 0))
return cfun->machine->some_ld_name;
- abort ();
+ gcc_unreachable ();
}
/* Helper function for rs6000_get_some_local_dynamic_name. */
@@ -8993,6 +10247,36 @@ rs6000_get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
return 0;
}
+/* Write out a function code label. */
+
+void
+rs6000_output_function_entry (FILE *file, const char *fname)
+{
+ if (fname[0] != '.')
+ {
+ switch (DEFAULT_ABI)
+ {
+ default:
+ gcc_unreachable ();
+
+ case ABI_AIX:
+ if (DOT_SYMBOLS)
+ putc ('.', file);
+ else
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "L.");
+ break;
+
+ case ABI_V4:
+ case ABI_DARWIN:
+ break;
+ }
+ }
+ if (TARGET_AIX)
+ RS6000_OUTPUT_BASENAME (file, fname);
+ else
+ assemble_name (file, fname);
+}
+
/* Print an operand. Recognize special options, documented below. */
#if TARGET_ELF
@@ -9043,7 +10327,7 @@ print_operand (FILE *file, rtx x, int code)
case 'B':
/* If the low-order bit is zero, write 'r'; otherwise, write 'l'
for 64-bit mask direction. */
- putc (((INT_LOWPART(x) & 1) == 0 ? 'r' : 'l'), file);
+ putc (((INT_LOWPART (x) & 1) == 0 ? 'r' : 'l'), file);
return;
/* %c is output_addr_const if a CONSTANT_ADDRESS_P, otherwise
@@ -9052,21 +10336,20 @@ print_operand (FILE *file, rtx x, int code)
case 'c':
/* X is a CR register. Print the number of the GT bit of the CR. */
if (GET_CODE (x) != REG || ! CR_REGNO_P (REGNO (x)))
- output_operand_lossage ("invalid %%E value");
+ output_operand_lossage ("invalid %%E value");
else
- fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
+ fprintf (file, "%d", 4 * (REGNO (x) - CR0_REGNO) + 1);
return;
case 'D':
- /* Like 'J' but get to the EQ bit. */
- if (GET_CODE (x) != REG)
- abort ();
+ /* Like 'J' but get to the GT bit only. */
+ gcc_assert (GET_CODE (x) == REG);
- /* Bit 1 is EQ bit. */
- i = 4 * (REGNO (x) - CR0_REGNO) + 2;
+ /* Bit 1 is GT bit. */
+ i = 4 * (REGNO (x) - CR0_REGNO) + 1;
- /* If we want bit 31, write a shift count of zero, not 32. */
- fprintf (file, "%d", i == 31 ? 0 : i + 1);
+ /* Add one for shift count in rlinm for scc. */
+ fprintf (file, "%d", i + 1);
return;
case 'E':
@@ -9192,7 +10475,7 @@ print_operand (FILE *file, rtx x, int code)
/* Write second word of DImode or DFmode reference. Works on register
or non-indexed memory only. */
if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x) + 1]);
+ fputs (reg_names[REGNO (x) + 1], file);
else if (GET_CODE (x) == MEM)
{
/* Handle possible auto-increment. Since it is pre-increment and
@@ -9211,7 +10494,7 @@ print_operand (FILE *file, rtx x, int code)
reg_names[SMALL_DATA_REG]);
}
return;
-
+
case 'm':
/* MB value for a mask operand. */
if (! mask_operand (x, SImode))
@@ -9263,15 +10546,15 @@ print_operand (FILE *file, rtx x, int code)
|| REGNO (XEXP (x, 0)) >= 32)
output_operand_lossage ("invalid %%P value");
else
- fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
+ fputs (reg_names[REGNO (XEXP (x, 0))], file);
return;
case 'q':
/* This outputs the logical code corresponding to a boolean
expression. The expression may have one or both operands
negated (if one, only the first one). For condition register
- logical operations, it will also treat the negated
- CR codes as NOTs, but not handle NOTs of them. */
+ logical operations, it will also treat the negated
+ CR codes as NOTs, but not handle NOTs of them. */
{
const char *const *t = 0;
const char *s;
@@ -9299,14 +10582,14 @@ print_operand (FILE *file, rtx x, int code)
else
s = t[1];
}
-
+
fputs (s, file);
}
return;
case 'Q':
if (TARGET_MFCRF)
- fputc (',',file);
+ fputc (',', file);
/* FALLTHRU */
else
return;
@@ -9353,15 +10636,13 @@ print_operand (FILE *file, rtx x, int code)
}
while (uval != 0)
--i, uval >>= 1;
- if (i < 0)
- abort ();
+ gcc_assert (i >= 0);
fprintf (file, "%d", i);
return;
case 't':
/* Like 'J' but get to the OVERFLOW/UNORDERED bit. */
- if (GET_CODE (x) != REG || GET_MODE (x) != CCmode)
- abort ();
+ gcc_assert (GET_CODE (x) == REG && GET_MODE (x) == CCmode);
/* Bit 3 is OV bit. */
i = 4 * (REGNO (x) - CR0_REGNO) + 3;
@@ -9386,7 +10667,7 @@ print_operand (FILE *file, rtx x, int code)
if (! INT_P (x))
output_operand_lossage ("invalid %%u value");
else
- fprintf (file, HOST_WIDE_INT_PRINT_HEX,
+ fprintf (file, HOST_WIDE_INT_PRINT_HEX,
(INT_LOWPART (x) >> 16) & 0xffff);
return;
@@ -9442,7 +10723,7 @@ print_operand (FILE *file, rtx x, int code)
fputs ("lge", file); /* 5 */
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -9450,7 +10731,7 @@ print_operand (FILE *file, rtx x, int code)
/* If constant, low-order 16 bits of constant, signed. Otherwise, write
normally. */
if (INT_P (x))
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
((INT_LOWPART (x) & 0xffff) ^ 0x8000) - 0x8000);
else
print_operand (file, x, 0);
@@ -9475,9 +10756,8 @@ print_operand (FILE *file, rtx x, int code)
{
val = CONST_DOUBLE_LOW (x);
- if (val == 0)
- abort ();
- else if (val < 0)
+ gcc_assert (val);
+ if (val < 0)
--i;
else
for ( ; i < 64; i++)
@@ -9498,7 +10778,7 @@ print_operand (FILE *file, rtx x, int code)
case 'Y':
/* Like 'L', for third word of TImode */
if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x) + 2]);
+ fputs (reg_names[REGNO (x) + 2], file);
else if (GET_CODE (x) == MEM)
{
if (GET_CODE (XEXP (x, 0)) == PRE_INC
@@ -9511,42 +10791,41 @@ print_operand (FILE *file, rtx x, int code)
reg_names[SMALL_DATA_REG]);
}
return;
-
+
case 'z':
/* X is a SYMBOL_REF. Write out the name preceded by a
period and without any trailing data in brackets. Used for function
names. If we are configured for System V (or the embedded ABI) on
the PowerPC, do not emit the period, since those systems do not use
TOCs and the like. */
- if (GET_CODE (x) != SYMBOL_REF)
- abort ();
-
- if (XSTR (x, 0)[0] != '.')
- {
- switch (DEFAULT_ABI)
- {
- default:
- abort ();
+ gcc_assert (GET_CODE (x) == SYMBOL_REF);
- case ABI_AIX:
- putc ('.', file);
- break;
+ /* Mark the decl as referenced so that cgraph will output the
+ function. */
+ if (SYMBOL_REF_DECL (x))
+ mark_decl_referenced (SYMBOL_REF_DECL (x));
- case ABI_V4:
- case ABI_DARWIN:
- break;
- }
+ /* For macho, check to see if we need a stub. */
+ if (TARGET_MACHO)
+ {
+ const char *name = XSTR (x, 0);
+#if TARGET_MACHO
+ if (MACHOPIC_INDIRECT
+ && machopic_classify_symbol (x) == MACHOPIC_UNDEFINED_FUNCTION)
+ name = machopic_indirection_name (x, /*stub_p=*/true);
+#endif
+ assemble_name (file, name);
}
- if (TARGET_AIX)
- RS6000_OUTPUT_BASENAME (file, XSTR (x, 0));
- else
+ else if (!DOT_SYMBOLS)
assemble_name (file, XSTR (x, 0));
+ else
+ rs6000_output_function_entry (file, XSTR (x, 0));
return;
case 'Z':
/* Like 'L', for last word of TImode. */
if (GET_CODE (x) == REG)
- fprintf (file, "%s", reg_names[REGNO (x) + 3]);
+ fputs (reg_names[REGNO (x) + 3], file);
else if (GET_CODE (x) == MEM)
{
if (GET_CODE (XEXP (x, 0)) == PRE_INC
@@ -9565,12 +10844,12 @@ print_operand (FILE *file, rtx x, int code)
{
rtx tmp;
- if (GET_CODE (x) != MEM)
- abort ();
+ gcc_assert (GET_CODE (x) == MEM);
tmp = XEXP (x, 0);
- if (TARGET_E500)
+ /* Ugly hack because %y is overloaded. */
+ if (TARGET_E500 && GET_MODE_SIZE (GET_MODE (x)) == 8)
{
/* Handle [reg]. */
if (GET_CODE (tmp) == REG)
@@ -9584,8 +10863,7 @@ print_operand (FILE *file, rtx x, int code)
{
int x;
- if (GET_CODE (XEXP (tmp, 0)) != REG)
- abort ();
+ gcc_assert (GET_CODE (XEXP (tmp, 0)) == REG);
x = INTVAL (XEXP (tmp, 1));
fprintf (file, "%d(%s)", x, reg_names[REGNO (XEXP (tmp, 0))]);
@@ -9594,10 +10872,19 @@ print_operand (FILE *file, rtx x, int code)
/* Fall through. Must be [reg+reg]. */
}
+ if (TARGET_ALTIVEC
+ && GET_CODE (tmp) == AND
+ && GET_CODE (XEXP (tmp, 1)) == CONST_INT
+ && INTVAL (XEXP (tmp, 1)) == -16)
+ tmp = XEXP (tmp, 0);
if (GET_CODE (tmp) == REG)
fprintf (file, "0,%s", reg_names[REGNO (tmp)]);
- else if (GET_CODE (tmp) == PLUS && GET_CODE (XEXP (tmp, 1)) == REG)
+ else
{
+ gcc_assert (GET_CODE (tmp) == PLUS
+ && REG_P (XEXP (tmp, 0))
+ && REG_P (XEXP (tmp, 1)));
+
if (REGNO (XEXP (tmp, 0)) == 0)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 1)) ],
reg_names[ REGNO (XEXP (tmp, 0)) ]);
@@ -9605,11 +10892,9 @@ print_operand (FILE *file, rtx x, int code)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (tmp, 0)) ],
reg_names[ REGNO (XEXP (tmp, 1)) ]);
}
- else
- abort ();
break;
}
-
+
case 0:
if (GET_CODE (x) == REG)
fprintf (file, "%s", reg_names[REGNO (x)]);
@@ -9653,11 +10938,12 @@ print_operand_address (FILE *file, rtx x)
if (small_data_operand (x, GET_MODE (x)))
fprintf (file, "@%s(%s)", SMALL_DATA_RELOC,
reg_names[SMALL_DATA_REG]);
- else if (TARGET_TOC)
- abort ();
+ else
+ gcc_assert (!TARGET_TOC);
}
else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == REG)
{
+ gcc_assert (REG_P (XEXP (x, 0)));
if (REGNO (XEXP (x, 0)) == 0)
fprintf (file, "%s,%s", reg_names[ REGNO (XEXP (x, 1)) ],
reg_names[ REGNO (XEXP (x, 0)) ]);
@@ -9670,7 +10956,7 @@ print_operand_address (FILE *file, rtx x)
INTVAL (XEXP (x, 1)), reg_names[ REGNO (XEXP (x, 0)) ]);
#if TARGET_ELF
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
- && CONSTANT_P (XEXP (x, 1)))
+ && CONSTANT_P (XEXP (x, 1)))
{
output_addr_const (file, XEXP (x, 1));
fprintf (file, "@l(%s)", reg_names[ REGNO (XEXP (x, 0)) ]);
@@ -9678,7 +10964,7 @@ print_operand_address (FILE *file, rtx x)
#endif
#if TARGET_MACHO
else if (GET_CODE (x) == LO_SUM && GET_CODE (XEXP (x, 0)) == REG
- && CONSTANT_P (XEXP (x, 1)))
+ && CONSTANT_P (XEXP (x, 1)))
{
fprintf (file, "lo16(");
output_addr_const (file, XEXP (x, 1));
@@ -9692,7 +10978,7 @@ print_operand_address (FILE *file, rtx x)
rtx contains_minus = XEXP (x, 1);
rtx minus, symref;
const char *name;
-
+
/* Find the (minus (sym) (toc)) buried in X, and temporarily
turn it into (sym) for output_addr_const. */
while (GET_CODE (XEXP (contains_minus, 0)) != MINUS)
@@ -9722,7 +11008,7 @@ print_operand_address (FILE *file, rtx x)
fprintf (file, "(%s)", reg_names[REGNO (XEXP (x, 0))]);
}
else
- abort ();
+ gcc_unreachable ();
}
/* Target hook for assembling integer objects. The PowerPC version has
@@ -9737,14 +11023,14 @@ rs6000_assemble_integer (rtx x, unsigned int size, int aligned_p)
/* Special handling for SI values. */
if (RELOCATABLE_NEEDS_FIXUP && size == 4 && aligned_p)
{
- extern int in_toc_section (void);
static int recurse = 0;
-
+
/* For -mrelocatable, we mark all addresses that need to be fixed up
in the .fixup section. */
if (TARGET_RELOCATABLE
- && !in_toc_section ()
- && !in_text_section ()
+ && in_section != toc_section
+ && in_section != text_section
+ && !unlikely_text_section_p (in_section)
&& !recurse
&& GET_CODE (x) != CONST_INT
&& GET_CODE (x) != CONST_DOUBLE
@@ -9795,10 +11081,12 @@ rs6000_assemble_visibility (tree decl, int vis)
{
/* Functions need to have their entry point symbol visibility set as
well as their descriptor symbol visibility. */
- if (DEFAULT_ABI == ABI_AIX && TREE_CODE (decl) == FUNCTION_DECL)
+ if (DEFAULT_ABI == ABI_AIX
+ && DOT_SYMBOLS
+ && TREE_CODE (decl) == FUNCTION_DECL)
{
static const char * const visibility_types[] = {
- NULL, "internal", "hidden", "protected"
+ NULL, "internal", "hidden", "protected"
};
const char *name, *type;
@@ -9820,7 +11108,7 @@ rs6000_reverse_condition (enum machine_mode mode, enum rtx_code code)
{
/* Reversal of FP compares takes care -- an ordered compare
becomes an unordered compare and vice versa. */
- if (mode == CCFPmode
+ if (mode == CCFPmode
&& (!flag_finite_math_only
|| code == UNLT || code == UNLE || code == UNGT || code == UNGE
|| code == UNEQ || code == LTGT))
@@ -9841,7 +11129,17 @@ rs6000_generate_compare (enum rtx_code code)
if (rs6000_compare_fp_p)
comp_mode = CCFPmode;
else if (code == GTU || code == LTU
- || code == GEU || code == LEU)
+ || code == GEU || code == LEU)
+ comp_mode = CCUNSmode;
+ else if ((code == EQ || code == NE)
+ && GET_CODE (rs6000_compare_op0) == SUBREG
+ && GET_CODE (rs6000_compare_op1) == SUBREG
+ && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op0)
+ && SUBREG_PROMOTED_UNSIGNED_P (rs6000_compare_op1))
+ /* These are unsigned values, perhaps there will be a later
+ ordering compare that can be shared with this one.
+ Unfortunately we cannot detect the signedness of the operands
+ for non-subregs. */
comp_mode = CCUNSmode;
else
comp_mode = CCmode;
@@ -9849,40 +11147,94 @@ rs6000_generate_compare (enum rtx_code code)
/* First, the compare. */
compare_result = gen_reg_rtx (comp_mode);
- /* SPE FP compare instructions on the GPRs. Yuck! */
+ /* E500 FP compare instructions on the GPRs. Yuck! */
if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
&& rs6000_compare_fp_p)
{
- rtx cmp, or1, or2, or_result, compare_result2;
+ rtx cmp, or_result, compare_result2;
+ enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
+
+ if (op_mode == VOIDmode)
+ op_mode = GET_MODE (rs6000_compare_op1);
- /* Note: The E500 comparison instructions set the GT bit (x +
- 1), on success. This explains the mess. */
+ /* The E500 FP compare instructions toggle the GT bit (CR bit 1) only.
+ This explains the following mess. */
switch (code)
{
- case EQ: case UNEQ: case NE: case LTGT:
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+ case EQ: case UNEQ: case NE: case LTGT:
+ switch (op_mode)
+ {
+ case SFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ case DFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
- case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
- cmp = flag_finite_math_only
- ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+
+ case GT: case GTU: case UNGT: case UNGE: case GE: case GEU:
+ switch (op_mode)
+ {
+ case SFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ case DFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfgt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
- case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
- cmp = flag_finite_math_only
- ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
- rs6000_compare_op1);
+
+ case LT: case LTU: case UNLT: case UNLE: case LE: case LEU:
+ switch (op_mode)
+ {
+ case SFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ case DFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdflt_gpr (compare_result, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
break;
- default:
- abort ();
+ default:
+ gcc_unreachable ();
}
/* Synthesize LE and GE from LT/GT || EQ. */
@@ -9896,30 +11248,39 @@ rs6000_generate_compare (enum rtx_code code)
case GE: code = GT; break;
case LEU: code = LT; break;
case GEU: code = GT; break;
- default: abort ();
+ default: gcc_unreachable ();
}
- or1 = gen_reg_rtx (SImode);
- or2 = gen_reg_rtx (SImode);
- or_result = gen_reg_rtx (CCEQmode);
compare_result2 = gen_reg_rtx (CCFPmode);
/* Do the EQ. */
- cmp = flag_finite_math_only
- ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1)
- : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
- rs6000_compare_op1);
- emit_insn (cmp);
+ switch (op_mode)
+ {
+ case SFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpsfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
- or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
- or2 = gen_rtx_GT (SImode, compare_result2, const0_rtx);
+ case DFmode:
+ cmp = flag_unsafe_math_optimizations
+ ? gen_tstdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1)
+ : gen_cmpdfeq_gpr (compare_result2, rs6000_compare_op0,
+ rs6000_compare_op1);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ emit_insn (cmp);
/* OR them together. */
- cmp = gen_rtx_SET (VOIDmode, or_result,
- gen_rtx_COMPARE (CCEQmode,
- gen_rtx_IOR (SImode, or1, or2),
- const_true_rtx));
+ or_result = gen_reg_rtx (CCFPmode);
+ cmp = gen_e500_cr_ior_compare (or_result, compare_result,
+ compare_result2);
compare_result = or_result;
code = EQ;
}
@@ -9927,8 +11288,8 @@ rs6000_generate_compare (enum rtx_code code)
{
if (code == NE || code == LTGT)
code = NE;
- else
- code = EQ;
+ else
+ code = EQ;
}
emit_insn (cmp);
@@ -9936,13 +11297,13 @@ rs6000_generate_compare (enum rtx_code code)
else
{
/* Generate XLC-compatible TFmode compare as PARALLEL with extra
- CLOBBERs to match cmptf_internal2 pattern. */
+ CLOBBERs to match cmptf_internal2 pattern. */
if (comp_mode == CCFPmode && TARGET_XL_COMPAT
- && GET_MODE (rs6000_compare_op0) == TFmode
- && (DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
- emit_insn (gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (9,
+ && GET_MODE (rs6000_compare_op0) == TFmode
+ && !TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128)
+ emit_insn (gen_rtx_PARALLEL (VOIDmode,
+ gen_rtvec (9,
gen_rtx_SET (VOIDmode,
compare_result,
gen_rtx_COMPARE (comp_mode,
@@ -9956,18 +11317,31 @@ rs6000_generate_compare (enum rtx_code code)
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (DFmode)))));
+ else if (GET_CODE (rs6000_compare_op1) == UNSPEC
+ && XINT (rs6000_compare_op1, 1) == UNSPEC_SP_TEST)
+ {
+ rtx op1 = XVECEXP (rs6000_compare_op1, 0, 0);
+ comp_mode = CCEQmode;
+ compare_result = gen_reg_rtx (CCEQmode);
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_testdi (compare_result,
+ rs6000_compare_op0, op1));
+ else
+ emit_insn (gen_stack_protect_testsi (compare_result,
+ rs6000_compare_op0, op1));
+ }
else
emit_insn (gen_rtx_SET (VOIDmode, compare_result,
gen_rtx_COMPARE (comp_mode,
- rs6000_compare_op0,
+ rs6000_compare_op0,
rs6000_compare_op1)));
}
-
+
/* Some kinds of FP comparisons need an OR operation;
under flag_finite_math_only we don't bother. */
if (rs6000_compare_fp_p
- && ! flag_finite_math_only
- && ! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
+ && !flag_finite_math_only
+ && !(TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)
&& (code == LE || code == GE
|| code == UNEQ || code == LTGT
|| code == UNGT || code == UNLT))
@@ -9975,7 +11349,7 @@ rs6000_generate_compare (enum rtx_code code)
enum rtx_code or1, or2;
rtx or1_rtx, or2_rtx, compare2_rtx;
rtx or_result = gen_reg_rtx (CCEQmode);
-
+
switch (code)
{
case LE: or1 = LT; or2 = EQ; break;
@@ -9984,12 +11358,12 @@ rs6000_generate_compare (enum rtx_code code)
case LTGT: or1 = LT; or2 = GT; break;
case UNGT: or1 = UNORDERED; or2 = GT; break;
case UNLT: or1 = UNORDERED; or2 = LT; break;
- default: abort ();
+ default: gcc_unreachable ();
}
validate_condition_mode (or1, comp_mode);
validate_condition_mode (or2, comp_mode);
- or1_rtx = gen_rtx (or1, SImode, compare_result, const0_rtx);
- or2_rtx = gen_rtx (or2, SImode, compare_result, const0_rtx);
+ or1_rtx = gen_rtx_fmt_ee (or1, SImode, compare_result, const0_rtx);
+ or2_rtx = gen_rtx_fmt_ee (or2, SImode, compare_result, const0_rtx);
compare2_rtx = gen_rtx_COMPARE (CCEQmode,
gen_rtx_IOR (SImode, or1_rtx, or2_rtx),
const_true_rtx);
@@ -10000,8 +11374,8 @@ rs6000_generate_compare (enum rtx_code code)
}
validate_condition_mode (code, GET_MODE (compare_result));
-
- return gen_rtx (code, VOIDmode, compare_result, const0_rtx);
+
+ return gen_rtx_fmt_ee (code, VOIDmode, compare_result, const0_rtx);
}
@@ -10025,13 +11399,12 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
PUT_MODE (condition_rtx, SImode);
t = XEXP (condition_rtx, 0);
- if (cond_code != NE && cond_code != EQ)
- abort ();
+ gcc_assert (cond_code == NE || cond_code == EQ);
if (cond_code == NE)
- emit_insn (gen_e500_flip_eq_bit (t, t));
+ emit_insn (gen_e500_flip_gt_bit (t, t));
- emit_insn (gen_move_from_CR_eq_bit (result, t));
+ emit_insn (gen_move_from_CR_gt_bit (result, t));
return;
}
@@ -10043,11 +11416,11 @@ rs6000_emit_sCOND (enum rtx_code code, rtx result)
rtx not_result = gen_reg_rtx (CCEQmode);
rtx not_op, rev_cond_rtx;
enum machine_mode cc_mode;
-
+
cc_mode = GET_MODE (XEXP (condition_rtx, 0));
- rev_cond_rtx = gen_rtx (rs6000_reverse_condition (cc_mode, cond_code),
- SImode, XEXP (condition_rtx, 0), const0_rtx);
+ rev_cond_rtx = gen_rtx_fmt_ee (rs6000_reverse_condition (cc_mode, cond_code),
+ SImode, XEXP (condition_rtx, 0), const0_rtx);
not_op = gen_rtx_COMPARE (CCEQmode, rev_cond_rtx, const0_rtx);
emit_insn (gen_rtx_SET (VOIDmode, not_result, not_op));
condition_rtx = gen_rtx_EQ (VOIDmode, not_result, const0_rtx);
@@ -10085,7 +11458,7 @@ rs6000_emit_cbranch (enum rtx_code code, rtx loc)
/* Return the string to output a conditional branch to LABEL, which is
the operand number of the label, or -1 if the branch is really a
- conditional return.
+ conditional return.
OP is the conditional expression. XEXP (OP, 0) is assumed to be a
condition code register and its mode specifies what kind of
@@ -10129,13 +11502,20 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
{
/* The efscmp/tst* instructions twiddle bit 2, which maps nicely
to the GT bit. */
- if (code == EQ)
- /* Opposite of GT. */
- code = GT;
- else if (code == NE)
- code = UNLE;
- else
- abort ();
+ switch (code)
+ {
+ case EQ:
+ /* Opposite of GT. */
+ code = GT;
+ break;
+
+ case NE:
+ code = UNLE;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
}
switch (code)
@@ -10146,23 +11526,23 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
ccode = "ne"; break;
case EQ: case UNEQ:
ccode = "eq"; break;
- case GE: case GEU:
+ case GE: case GEU:
ccode = "ge"; break;
- case GT: case GTU: case UNGT:
+ case GT: case GTU: case UNGT:
ccode = "gt"; break;
- case LE: case LEU:
+ case LE: case LEU:
ccode = "le"; break;
- case LT: case LTU: case UNLT:
+ case LT: case LTU: case UNLT:
ccode = "lt"; break;
case UNORDERED: ccode = "un"; break;
case ORDERED: ccode = "nu"; break;
case UNGE: ccode = "nl"; break;
case UNLE: ccode = "ng"; break;
default:
- abort ();
+ gcc_unreachable ();
}
-
- /* Maybe we have a guess as to how likely the branch is.
+
+ /* Maybe we have a guess as to how likely the branch is.
The old mnemonics don't have a way to specify this information. */
pred = "";
note = find_reg_note (insn, REG_BR_PROB, NULL_RTX);
@@ -10176,13 +11556,14 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
prediction. For older cpus we may as well always hint, but
assume not taken for branches that are very close to 50% as a
mispredicted taken branch is more expensive than a
- mispredicted not-taken branch. */
+ mispredicted not-taken branch. */
if (rs6000_always_hint
- || abs (prob) > REG_BR_PROB_BASE / 100 * 48)
+ || (abs (prob) > REG_BR_PROB_BASE / 100 * 48
+ && br_prob_note_reliable_p (note)))
{
if (abs (prob) > REG_BR_PROB_BASE / 20
&& ((prob > 0) ^ need_longbranch))
- pred = "+";
+ pred = "+";
else
pred = "-";
}
@@ -10212,25 +11593,292 @@ output_cbranch (rtx op, const char *label, int reversed, rtx insn)
return string;
}
-/* Return the string to flip the EQ bit on a CR. */
+/* Return the string to flip the GT bit on a CR. */
char *
-output_e500_flip_eq_bit (rtx dst, rtx src)
+output_e500_flip_gt_bit (rtx dst, rtx src)
{
static char string[64];
int a, b;
- if (GET_CODE (dst) != REG || ! CR_REGNO_P (REGNO (dst))
- || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
- abort ();
+ gcc_assert (GET_CODE (dst) == REG && CR_REGNO_P (REGNO (dst))
+ && GET_CODE (src) == REG && CR_REGNO_P (REGNO (src)));
- /* EQ bit. */
- a = 4 * (REGNO (dst) - CR0_REGNO) + 2;
- b = 4 * (REGNO (src) - CR0_REGNO) + 2;
+ /* GT bit. */
+ a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
+ b = 4 * (REGNO (src) - CR0_REGNO) + 1;
sprintf (string, "crnot %d,%d", a, b);
return string;
}
+/* Return insn index for the vector compare instruction for given CODE,
+ and DEST_MODE, OP_MODE. Return INSN_NOT_AVAILABLE if valid insn is
+ not available. */
+
+static int
+get_vec_cmp_insn (enum rtx_code code,
+ enum machine_mode dest_mode,
+ enum machine_mode op_mode)
+{
+ if (!TARGET_ALTIVEC)
+ return INSN_NOT_AVAILABLE;
+
+ switch (code)
+ {
+ case EQ:
+ if (dest_mode == V16QImode && op_mode == V16QImode)
+ return UNSPEC_VCMPEQUB;
+ if (dest_mode == V8HImode && op_mode == V8HImode)
+ return UNSPEC_VCMPEQUH;
+ if (dest_mode == V4SImode && op_mode == V4SImode)
+ return UNSPEC_VCMPEQUW;
+ if (dest_mode == V4SImode && op_mode == V4SFmode)
+ return UNSPEC_VCMPEQFP;
+ break;
+ case GE:
+ if (dest_mode == V4SImode && op_mode == V4SFmode)
+ return UNSPEC_VCMPGEFP;
+ case GT:
+ if (dest_mode == V16QImode && op_mode == V16QImode)
+ return UNSPEC_VCMPGTSB;
+ if (dest_mode == V8HImode && op_mode == V8HImode)
+ return UNSPEC_VCMPGTSH;
+ if (dest_mode == V4SImode && op_mode == V4SImode)
+ return UNSPEC_VCMPGTSW;
+ if (dest_mode == V4SImode && op_mode == V4SFmode)
+ return UNSPEC_VCMPGTFP;
+ break;
+ case GTU:
+ if (dest_mode == V16QImode && op_mode == V16QImode)
+ return UNSPEC_VCMPGTUB;
+ if (dest_mode == V8HImode && op_mode == V8HImode)
+ return UNSPEC_VCMPGTUH;
+ if (dest_mode == V4SImode && op_mode == V4SImode)
+ return UNSPEC_VCMPGTUW;
+ break;
+ default:
+ break;
+ }
+ return INSN_NOT_AVAILABLE;
+}
+
+/* Emit vector compare for operands OP0 and OP1 using code RCODE.
+ DMODE is expected destination mode. This is a recursive function. */
+
+static rtx
+rs6000_emit_vector_compare (enum rtx_code rcode,
+ rtx op0, rtx op1,
+ enum machine_mode dmode)
+{
+ int vec_cmp_insn;
+ rtx mask;
+ enum machine_mode dest_mode;
+ enum machine_mode op_mode = GET_MODE (op1);
+
+ gcc_assert (TARGET_ALTIVEC);
+ gcc_assert (GET_MODE (op0) == GET_MODE (op1));
+
+ /* Floating point vector compare instructions uses destination V4SImode.
+ Move destination to appropriate mode later. */
+ if (dmode == V4SFmode)
+ dest_mode = V4SImode;
+ else
+ dest_mode = dmode;
+
+ mask = gen_reg_rtx (dest_mode);
+ vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
+
+ if (vec_cmp_insn == INSN_NOT_AVAILABLE)
+ {
+ bool swap_operands = false;
+ bool try_again = false;
+ switch (rcode)
+ {
+ case LT:
+ rcode = GT;
+ swap_operands = true;
+ try_again = true;
+ break;
+ case LTU:
+ rcode = GTU;
+ swap_operands = true;
+ try_again = true;
+ break;
+ case NE:
+ /* Treat A != B as ~(A==B). */
+ {
+ enum insn_code nor_code;
+ rtx eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
+ dest_mode);
+
+ nor_code = one_cmpl_optab->handlers[(int)dest_mode].insn_code;
+ gcc_assert (nor_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (nor_code) (mask, eq_rtx));
+
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
+ case GE:
+ case GEU:
+ case LE:
+ case LEU:
+ /* Try GT/GTU/LT/LTU OR EQ */
+ {
+ rtx c_rtx, eq_rtx;
+ enum insn_code ior_code;
+ enum rtx_code new_code;
+
+ switch (rcode)
+ {
+ case GE:
+ new_code = GT;
+ break;
+
+ case GEU:
+ new_code = GTU;
+ break;
+
+ case LE:
+ new_code = LT;
+ break;
+
+ case LEU:
+ new_code = LTU;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ c_rtx = rs6000_emit_vector_compare (new_code,
+ op0, op1, dest_mode);
+ eq_rtx = rs6000_emit_vector_compare (EQ, op0, op1,
+ dest_mode);
+
+ ior_code = ior_optab->handlers[(int)dest_mode].insn_code;
+ gcc_assert (ior_code != CODE_FOR_nothing);
+ emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (try_again)
+ {
+ vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
+ /* You only get two chances. */
+ gcc_assert (vec_cmp_insn != INSN_NOT_AVAILABLE);
+ }
+
+ if (swap_operands)
+ {
+ rtx tmp;
+ tmp = op0;
+ op0 = op1;
+ op1 = tmp;
+ }
+ }
+
+ emit_insn (gen_rtx_SET (VOIDmode, mask,
+ gen_rtx_UNSPEC (dest_mode,
+ gen_rtvec (2, op0, op1),
+ vec_cmp_insn)));
+ if (dmode != dest_mode)
+ {
+ rtx temp = gen_reg_rtx (dest_mode);
+ convert_move (temp, mask, 0);
+ return temp;
+ }
+ return mask;
+}
+
+/* Return vector select instruction for MODE. Return INSN_NOT_AVAILABLE, if
+ valid insn doesn exist for given mode. */
+
+static int
+get_vsel_insn (enum machine_mode mode)
+{
+ switch (mode)
+ {
+ case V4SImode:
+ return UNSPEC_VSEL4SI;
+ break;
+ case V4SFmode:
+ return UNSPEC_VSEL4SF;
+ break;
+ case V8HImode:
+ return UNSPEC_VSEL8HI;
+ break;
+ case V16QImode:
+ return UNSPEC_VSEL16QI;
+ break;
+ default:
+ return INSN_NOT_AVAILABLE;
+ break;
+ }
+ return INSN_NOT_AVAILABLE;
+}
+
+/* Emit vector select insn where DEST is destination using
+ operands OP1, OP2 and MASK. */
+
+static void
+rs6000_emit_vector_select (rtx dest, rtx op1, rtx op2, rtx mask)
+{
+ rtx t, temp;
+ enum machine_mode dest_mode = GET_MODE (dest);
+ int vsel_insn_index = get_vsel_insn (GET_MODE (dest));
+
+ temp = gen_reg_rtx (dest_mode);
+
+ /* For each vector element, select op1 when mask is 1 otherwise
+ select op2. */
+ t = gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_UNSPEC (dest_mode,
+ gen_rtvec (3, op2, op1, mask),
+ vsel_insn_index));
+ emit_insn (t);
+ emit_move_insn (dest, temp);
+ return;
+}
+
+/* Emit vector conditional expression.
+ DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands.
+ CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */
+
+int
+rs6000_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
+ rtx cond, rtx cc_op0, rtx cc_op1)
+{
+ enum machine_mode dest_mode = GET_MODE (dest);
+ enum rtx_code rcode = GET_CODE (cond);
+ rtx mask;
+
+ if (!TARGET_ALTIVEC)
+ return 0;
+
+ /* Get the vector mask for the given relational operations. */
+ mask = rs6000_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
+
+ rs6000_emit_vector_select (dest, op1, op2, mask);
+
+ return 1;
+}
+
/* 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. */
@@ -10245,6 +11893,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
enum machine_mode compare_mode = GET_MODE (op0);
enum machine_mode result_mode = GET_MODE (dest);
rtx temp;
+ bool is_against_zero;
/* These modes should always match. */
if (GET_MODE (op1) != compare_mode
@@ -10266,7 +11915,18 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
return 0;
}
else if (TARGET_E500 && TARGET_HARD_FLOAT && !TARGET_FPRS
- && GET_MODE_CLASS (compare_mode) == MODE_FLOAT)
+ && SCALAR_FLOAT_MODE_P (compare_mode))
+ return 0;
+
+ is_against_zero = op1 == CONST0_RTX (compare_mode);
+
+ /* A floating-point subtract might overflow, underflow, or produce
+ an inexact result, thus changing the floating-point flags, so it
+ can't be generated if we care about that. It's safe if one side
+ of the construct is zero, since then no subtract will be
+ generated. */
+ if (SCALAR_FLOAT_MODE_P (compare_mode)
+ && flag_trapping_math && ! is_against_zero)
return 0;
/* Eliminate half of the comparisons by switching operands, this
@@ -10284,10 +11944,10 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
it'll probably be faster to use a branch here too. */
if (code == UNEQ && HONOR_NANS (compare_mode))
return 0;
-
+
if (GET_CODE (op1) == CONST_DOUBLE)
REAL_VALUE_FROM_CONST_DOUBLE (c1, op1);
-
+
/* We're going to try to implement comparisons by performing
a subtract, then comparing against zero. Unfortunately,
Inf - Inf is NaN which is not zero, and so if we don't
@@ -10298,17 +11958,21 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
&& (GET_CODE (op1) != CONST_DOUBLE || real_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 (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 (compare_mode);
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_MINUS (compare_mode, op0, op1)));
- op0 = temp;
- op1 = CONST0_RTX (compare_mode);
+ if (! is_against_zero)
+ {
+ temp = gen_reg_rtx (compare_mode);
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ gen_rtx_MINUS (compare_mode, op0, op1)));
+ op0 = temp;
+ op1 = CONST0_RTX (compare_mode);
+ }
/* If we don't care about NaNs we can reduce some of the comparisons
down to faster ones. */
@@ -10351,7 +12015,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
case EQ:
temp = gen_reg_rtx (compare_mode);
- emit_insn (gen_rtx_SET (VOIDmode, temp,
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
gen_rtx_NEG (compare_mode,
gen_rtx_ABS (compare_mode, op0))));
op0 = temp;
@@ -10377,7 +12041,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
/* a GT 0 <-> (a GE 0 && -a UNLT 0) */
temp = gen_reg_rtx (result_mode);
emit_insn (gen_rtx_SET (VOIDmode, temp,
- gen_rtx_IF_THEN_ELSE (result_mode,
+ gen_rtx_IF_THEN_ELSE (result_mode,
gen_rtx_GE (VOIDmode,
op0, op1),
true_cond, false_cond)));
@@ -10390,7 +12054,7 @@ rs6000_emit_cmove (rtx dest, rtx op, rtx true_cond, rtx false_cond)
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_insn (gen_rtx_SET (VOIDmode, dest,
@@ -10456,18 +12120,454 @@ rs6000_emit_minmax (rtx dest, enum rtx_code code, rtx op0, rtx op1)
c = GEU;
if (code == SMAX || code == UMAX)
- target = emit_conditional_move (dest, c, op0, op1, mode,
+ target = emit_conditional_move (dest, c, op0, op1, mode,
op0, op1, mode, 0);
else
- target = emit_conditional_move (dest, c, op0, op1, mode,
+ target = emit_conditional_move (dest, c, op0, op1, mode,
op1, op0, mode, 0);
- if (target == NULL_RTX)
- abort ();
+ gcc_assert (target);
if (target != dest)
emit_move_insn (dest, target);
}
-/* Emit instructions to move SRC to DST. Called by splitters for
+/* Emit instructions to perform a load-reserved/store-conditional operation.
+ The operation performed is an atomic
+ (set M (CODE:MODE M OP))
+ If not NULL, BEFORE is atomically set to M before the operation, and
+ AFTER is set to M after the operation (that is, (CODE:MODE M OP)).
+ If SYNC_P then a memory barrier is emitted before the operation.
+ Either OP or M may be wrapped in a NOT operation. */
+
+void
+rs6000_emit_sync (enum rtx_code code, enum machine_mode mode,
+ rtx m, rtx op, rtx before_param, rtx after_param,
+ bool sync_p)
+{
+ enum machine_mode used_mode;
+ rtx the_op, set_before, set_after, set_atomic, cc_scratch, before, after;
+ rtx used_m;
+ rtvec vec;
+ HOST_WIDE_INT imask = GET_MODE_MASK (mode);
+ rtx shift = NULL_RTX;
+
+ if (sync_p)
+ emit_insn (gen_memory_barrier ());
+
+ if (GET_CODE (m) == NOT)
+ used_m = XEXP (m, 0);
+ else
+ used_m = m;
+
+ /* If this is smaller than SImode, we'll have to use SImode with
+ adjustments. */
+ if (mode == QImode || mode == HImode)
+ {
+ rtx newop, oldop;
+
+ if (MEM_ALIGN (used_m) >= 32)
+ {
+ int ishift = 0;
+ if (BYTES_BIG_ENDIAN)
+ ishift = GET_MODE_BITSIZE (SImode) - GET_MODE_BITSIZE (mode);
+
+ shift = GEN_INT (ishift);
+ }
+ else
+ {
+ rtx addrSI, aligned_addr;
+ int shift_mask = mode == QImode ? 0x18 : 0x10;
+
+ addrSI = force_reg (SImode, gen_lowpart_common (SImode,
+ XEXP (used_m, 0)));
+ shift = gen_reg_rtx (SImode);
+
+ emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
+ GEN_INT (shift_mask)));
+ emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
+
+ aligned_addr = expand_binop (Pmode, and_optab,
+ XEXP (used_m, 0),
+ GEN_INT (-4), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ used_m = change_address (used_m, SImode, aligned_addr);
+ set_mem_align (used_m, 32);
+ /* It's safe to keep the old alias set of USED_M, because
+ the operation is atomic and only affects the original
+ USED_M. */
+ if (GET_CODE (m) == NOT)
+ m = gen_rtx_NOT (SImode, used_m);
+ else
+ m = used_m;
+ }
+
+ if (GET_CODE (op) == NOT)
+ {
+ oldop = lowpart_subreg (SImode, XEXP (op, 0), mode);
+ oldop = gen_rtx_NOT (SImode, oldop);
+ }
+ else
+ oldop = lowpart_subreg (SImode, op, mode);
+
+ switch (code)
+ {
+ case IOR:
+ case XOR:
+ newop = expand_binop (SImode, and_optab,
+ oldop, GEN_INT (imask), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ emit_insn (gen_ashlsi3 (newop, newop, shift));
+ break;
+
+ case AND:
+ newop = expand_binop (SImode, ior_optab,
+ oldop, GEN_INT (~imask), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ emit_insn (gen_rotlsi3 (newop, newop, shift));
+ break;
+
+ case PLUS:
+ case MINUS:
+ {
+ rtx mask;
+
+ newop = expand_binop (SImode, and_optab,
+ oldop, GEN_INT (imask), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ emit_insn (gen_ashlsi3 (newop, newop, shift));
+
+ mask = gen_reg_rtx (SImode);
+ emit_move_insn (mask, GEN_INT (imask));
+ emit_insn (gen_ashlsi3 (mask, mask, shift));
+
+ if (code == PLUS)
+ newop = gen_rtx_PLUS (SImode, m, newop);
+ else
+ newop = gen_rtx_MINUS (SImode, m, newop);
+ newop = gen_rtx_AND (SImode, newop, mask);
+ newop = gen_rtx_IOR (SImode, newop,
+ gen_rtx_AND (SImode,
+ gen_rtx_NOT (SImode, mask),
+ m));
+ break;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+
+ if (GET_CODE (m) == NOT)
+ {
+ rtx mask, xorm;
+
+ mask = gen_reg_rtx (SImode);
+ emit_move_insn (mask, GEN_INT (imask));
+ emit_insn (gen_ashlsi3 (mask, mask, shift));
+
+ xorm = gen_rtx_XOR (SImode, used_m, mask);
+ /* Depending on the value of 'op', the XOR or the operation might
+ be able to be simplified away. */
+ newop = simplify_gen_binary (code, SImode, xorm, newop);
+ }
+ op = newop;
+ used_mode = SImode;
+ before = gen_reg_rtx (used_mode);
+ after = gen_reg_rtx (used_mode);
+ }
+ else
+ {
+ used_mode = mode;
+ before = before_param;
+ after = after_param;
+
+ if (before == NULL_RTX)
+ before = gen_reg_rtx (used_mode);
+ if (after == NULL_RTX)
+ after = gen_reg_rtx (used_mode);
+ }
+
+ if ((code == PLUS || code == MINUS || GET_CODE (m) == NOT)
+ && used_mode != mode)
+ the_op = op; /* Computed above. */
+ else if (GET_CODE (op) == NOT && GET_CODE (m) != NOT)
+ the_op = gen_rtx_fmt_ee (code, used_mode, op, m);
+ else
+ the_op = gen_rtx_fmt_ee (code, used_mode, m, op);
+
+ set_after = gen_rtx_SET (VOIDmode, after, the_op);
+ set_before = gen_rtx_SET (VOIDmode, before, used_m);
+ set_atomic = gen_rtx_SET (VOIDmode, used_m,
+ gen_rtx_UNSPEC (used_mode,
+ gen_rtvec (1, the_op),
+ UNSPEC_SYNC_OP));
+ cc_scratch = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (CCmode));
+
+ if ((code == PLUS || code == MINUS) && used_mode != mode)
+ vec = gen_rtvec (5, set_after, set_before, set_atomic, cc_scratch,
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ else
+ vec = gen_rtvec (4, set_after, set_before, set_atomic, cc_scratch);
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, vec));
+
+ /* Shift and mask the return values properly. */
+ if (used_mode != mode && before_param)
+ {
+ emit_insn (gen_lshrsi3 (before, before, shift));
+ convert_move (before_param, before, 1);
+ }
+
+ if (used_mode != mode && after_param)
+ {
+ emit_insn (gen_lshrsi3 (after, after, shift));
+ convert_move (after_param, after, 1);
+ }
+
+ /* The previous sequence will end with a branch that's dependent on
+ the conditional store, so placing an isync will ensure that no
+ other instructions (especially, no load or store instructions)
+ can start before the atomic operation completes. */
+ if (sync_p)
+ emit_insn (gen_isync ());
+}
+
+/* A subroutine of the atomic operation splitters. Jump to LABEL if
+ COND is true. Mark the jump as unlikely to be taken. */
+
+static void
+emit_unlikely_jump (rtx cond, rtx label)
+{
+ rtx very_unlikely = GEN_INT (REG_BR_PROB_BASE / 100 - 1);
+ rtx x;
+
+ x = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, label, pc_rtx);
+ x = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx, x));
+ REG_NOTES (x) = gen_rtx_EXPR_LIST (REG_BR_PROB, very_unlikely, NULL_RTX);
+}
+
+/* A subroutine of the atomic operation splitters. Emit a load-locked
+ instruction in MODE. */
+
+static void
+emit_load_locked (enum machine_mode mode, rtx reg, rtx mem)
+{
+ rtx (*fn) (rtx, rtx) = NULL;
+ if (mode == SImode)
+ fn = gen_load_locked_si;
+ else if (mode == DImode)
+ fn = gen_load_locked_di;
+ emit_insn (fn (reg, mem));
+}
+
+/* A subroutine of the atomic operation splitters. Emit a store-conditional
+ instruction in MODE. */
+
+static void
+emit_store_conditional (enum machine_mode mode, rtx res, rtx mem, rtx val)
+{
+ rtx (*fn) (rtx, rtx, rtx) = NULL;
+ if (mode == SImode)
+ fn = gen_store_conditional_si;
+ else if (mode == DImode)
+ fn = gen_store_conditional_di;
+
+ /* Emit sync before stwcx. to address PPC405 Erratum. */
+ if (PPC405_ERRATUM77)
+ emit_insn (gen_memory_barrier ());
+
+ emit_insn (fn (res, mem, val));
+}
+
+/* Expand an an atomic fetch-and-operate pattern. CODE is the binary operation
+ to perform. MEM is the memory on which to operate. VAL is the second
+ operand of the binary operator. BEFORE and AFTER are optional locations to
+ return the value of MEM either before of after the operation. SCRATCH is
+ a scratch register. */
+
+void
+rs6000_split_atomic_op (enum rtx_code code, rtx mem, rtx val,
+ rtx before, rtx after, rtx scratch)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+ emit_insn (gen_memory_barrier ());
+
+ label = gen_label_rtx ();
+ emit_label (label);
+ label = gen_rtx_LABEL_REF (VOIDmode, label);
+
+ if (before == NULL_RTX)
+ before = scratch;
+ emit_load_locked (mode, before, mem);
+
+ if (code == NOT)
+ x = gen_rtx_AND (mode, gen_rtx_NOT (mode, before), val);
+ else if (code == AND)
+ x = gen_rtx_UNSPEC (mode, gen_rtvec (2, before, val), UNSPEC_AND);
+ else
+ x = gen_rtx_fmt_ee (code, mode, before, val);
+
+ if (after != NULL_RTX)
+ emit_insn (gen_rtx_SET (VOIDmode, after, copy_rtx (x)));
+ emit_insn (gen_rtx_SET (VOIDmode, scratch, x));
+
+ emit_store_conditional (mode, cond, mem, scratch);
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label);
+
+ emit_insn (gen_isync ());
+}
+
+/* Expand an atomic compare and swap operation. MEM is the memory on which
+ to operate. OLDVAL is the old value to be compared. NEWVAL is the new
+ value to be stored. SCRATCH is a scratch GPR. */
+
+void
+rs6000_split_compare_and_swap (rtx retval, rtx mem, rtx oldval, rtx newval,
+ rtx scratch)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+ emit_insn (gen_memory_barrier ());
+
+ label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+
+ emit_load_locked (mode, retval, mem);
+
+ x = gen_rtx_COMPARE (CCmode, retval, oldval);
+ emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label2);
+
+ emit_move_insn (scratch, newval);
+ emit_store_conditional (mode, cond, mem, scratch);
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+
+ emit_insn (gen_isync ());
+ emit_label (XEXP (label2, 0));
+}
+
+/* Expand an atomic test and set operation. MEM is the memory on which
+ to operate. VAL is the value set. SCRATCH is a scratch GPR. */
+
+void
+rs6000_split_lock_test_and_set (rtx retval, rtx mem, rtx val, rtx scratch)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx label, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+ emit_insn (gen_memory_barrier ());
+
+ label = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ emit_label (XEXP (label, 0));
+
+ emit_load_locked (mode, retval, mem);
+ emit_move_insn (scratch, val);
+ emit_store_conditional (mode, cond, mem, scratch);
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label);
+
+ emit_insn (gen_isync ());
+}
+
+void
+rs6000_expand_compare_and_swapqhi (rtx dst, rtx mem, rtx oldval, rtx newval)
+{
+ enum machine_mode mode = GET_MODE (mem);
+ rtx addrSI, align, wdst, shift, mask;
+ HOST_WIDE_INT shift_mask = mode == QImode ? 0x18 : 0x10;
+ HOST_WIDE_INT imask = GET_MODE_MASK (mode);
+
+ /* Shift amount for subword relative to aligned word. */
+ addrSI = force_reg (SImode, gen_lowpart_common (SImode, XEXP (mem, 0)));
+ shift = gen_reg_rtx (SImode);
+ emit_insn (gen_rlwinm (shift, addrSI, GEN_INT (3),
+ GEN_INT (shift_mask)));
+ emit_insn (gen_xorsi3 (shift, shift, GEN_INT (shift_mask)));
+
+ /* Shift and mask old value into position within word. */
+ oldval = convert_modes (SImode, mode, oldval, 1);
+ oldval = expand_binop (SImode, and_optab,
+ oldval, GEN_INT (imask), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ emit_insn (gen_ashlsi3 (oldval, oldval, shift));
+
+ /* Shift and mask new value into position within word. */
+ newval = convert_modes (SImode, mode, newval, 1);
+ newval = expand_binop (SImode, and_optab,
+ newval, GEN_INT (imask), NULL_RTX,
+ 1, OPTAB_LIB_WIDEN);
+ emit_insn (gen_ashlsi3 (newval, newval, shift));
+
+ /* Mask for insertion. */
+ mask = gen_reg_rtx (SImode);
+ emit_move_insn (mask, GEN_INT (imask));
+ emit_insn (gen_ashlsi3 (mask, mask, shift));
+
+ /* Address of aligned word containing subword. */
+ align = expand_binop (Pmode, and_optab, XEXP (mem, 0), GEN_INT (-4),
+ NULL_RTX, 1, OPTAB_LIB_WIDEN);
+ mem = change_address (mem, SImode, align);
+ set_mem_align (mem, 32);
+ MEM_VOLATILE_P (mem) = 1;
+
+ wdst = gen_reg_rtx (SImode);
+ emit_insn (gen_sync_compare_and_swapqhi_internal (wdst, mask,
+ oldval, newval, mem));
+
+ emit_move_insn (dst, gen_lowpart (mode, wdst));
+}
+
+void
+rs6000_split_compare_and_swapqhi (rtx dest, rtx mask,
+ rtx oldval, rtx newval, rtx mem,
+ rtx scratch)
+{
+ rtx label1, label2, x, cond = gen_rtx_REG (CCmode, CR0_REGNO);
+
+ emit_insn (gen_memory_barrier ());
+ label1 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ label2 = gen_rtx_LABEL_REF (VOIDmode, gen_label_rtx ());
+ emit_label (XEXP (label1, 0));
+
+ emit_load_locked (SImode, scratch, mem);
+
+ /* Mask subword within loaded value for comparison with oldval.
+ Use UNSPEC_AND to avoid clobber.*/
+ emit_insn (gen_rtx_SET (SImode, dest,
+ gen_rtx_UNSPEC (SImode,
+ gen_rtvec (2, scratch, mask),
+ UNSPEC_AND)));
+
+ x = gen_rtx_COMPARE (CCmode, dest, oldval);
+ emit_insn (gen_rtx_SET (VOIDmode, cond, x));
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label2);
+
+ /* Clear subword within loaded value for insertion of new value. */
+ emit_insn (gen_rtx_SET (SImode, scratch,
+ gen_rtx_AND (SImode,
+ gen_rtx_NOT (SImode, mask), scratch)));
+ emit_insn (gen_iorsi3 (scratch, scratch, newval));
+ emit_store_conditional (SImode, cond, mem, scratch);
+
+ x = gen_rtx_NE (VOIDmode, cond, const0_rtx);
+ emit_unlikely_jump (x, label1);
+
+ emit_insn (gen_isync ());
+ emit_label (XEXP (label2, 0));
+}
+
+
+ /* Emit instructions to move SRC to DST. Called by splitters for
multi-register moves. It will emit at most one instruction for
each register that is accessed; that is, it won't emit li/lis pairs
(or equivalent for 64-bit code). One of SRC or DST must be a hard
@@ -10488,25 +12588,26 @@ rs6000_split_multireg_move (rtx dst, rtx src)
reg = REG_P (dst) ? REGNO (dst) : REGNO (src);
mode = GET_MODE (dst);
- nregs = HARD_REGNO_NREGS (reg, mode);
+ nregs = hard_regno_nregs[reg][mode];
if (FP_REGNO_P (reg))
reg_mode = DFmode;
else if (ALTIVEC_REGNO_P (reg))
reg_mode = V16QImode;
+ else if (TARGET_E500_DOUBLE && mode == TFmode)
+ reg_mode = DFmode;
else
reg_mode = word_mode;
reg_mode_size = GET_MODE_SIZE (reg_mode);
-
- if (reg_mode_size * nregs != GET_MODE_SIZE (mode))
- abort ();
-
+
+ gcc_assert (reg_mode_size * nregs == GET_MODE_SIZE (mode));
+
if (REG_P (src) && REG_P (dst) && (REGNO (src) < REGNO (dst)))
{
/* Move register range backwards, if we might have destructive
overlap. */
int i;
for (i = nregs - 1; i >= 0; i--)
- emit_insn (gen_rtx_SET (VOIDmode,
+ emit_insn (gen_rtx_SET (VOIDmode,
simplify_gen_subreg (reg_mode, dst, mode,
i * reg_mode_size),
simplify_gen_subreg (reg_mode, src, mode,
@@ -10518,31 +12619,29 @@ rs6000_split_multireg_move (rtx dst, rtx src)
int j = -1;
bool used_update = false;
- if (GET_CODE (src) == MEM && INT_REGNO_P (reg))
- {
- rtx breg;
+ if (MEM_P (src) && INT_REGNO_P (reg))
+ {
+ rtx breg;
if (GET_CODE (XEXP (src, 0)) == PRE_INC
|| GET_CODE (XEXP (src, 0)) == PRE_DEC)
{
rtx delta_rtx;
breg = XEXP (XEXP (src, 0), 0);
- delta_rtx = GET_CODE (XEXP (src, 0)) == PRE_INC
- ? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
- : GEN_INT (-GET_MODE_SIZE (GET_MODE (src)));
+ delta_rtx = (GET_CODE (XEXP (src, 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (src)))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (src))));
emit_insn (TARGET_32BIT
? gen_addsi3 (breg, breg, delta_rtx)
: gen_adddi3 (breg, breg, delta_rtx));
- src = gen_rtx_MEM (mode, breg);
+ src = replace_equiv_address (src, breg);
}
- else if (! offsettable_memref_p (src))
+ else if (! rs6000_offsettable_memref_p (src))
{
- rtx newsrc, basereg;
+ rtx basereg;
basereg = gen_rtx_REG (Pmode, reg);
emit_insn (gen_rtx_SET (VOIDmode, basereg, XEXP (src, 0)));
- newsrc = gen_rtx_MEM (GET_MODE (src), basereg);
- MEM_COPY_ATTRIBUTES (newsrc, src);
- src = newsrc;
+ src = replace_equiv_address (src, basereg);
}
breg = XEXP (src, 0);
@@ -10566,9 +12665,9 @@ rs6000_split_multireg_move (rtx dst, rtx src)
{
rtx delta_rtx;
breg = XEXP (XEXP (dst, 0), 0);
- delta_rtx = GET_CODE (XEXP (dst, 0)) == PRE_INC
- ? GEN_INT (GET_MODE_SIZE (GET_MODE (dst)))
- : GEN_INT (-GET_MODE_SIZE (GET_MODE (dst)));
+ delta_rtx = (GET_CODE (XEXP (dst, 0)) == PRE_INC
+ ? GEN_INT (GET_MODE_SIZE (GET_MODE (dst)))
+ : GEN_INT (-GET_MODE_SIZE (GET_MODE (dst))));
/* We have to update the breg before doing the store.
Use store with update, if available. */
@@ -10577,32 +12676,34 @@ rs6000_split_multireg_move (rtx dst, rtx src)
{
rtx nsrc = simplify_gen_subreg (reg_mode, src, mode, 0);
emit_insn (TARGET_32BIT
- ? gen_movsi_update (breg, breg, delta_rtx, nsrc)
- : gen_movdi_update (breg, breg, delta_rtx, nsrc));
+ ? (TARGET_POWERPC64
+ ? gen_movdi_si_update (breg, breg, delta_rtx, nsrc)
+ : gen_movsi_update (breg, breg, delta_rtx, nsrc))
+ : gen_movdi_di_update (breg, breg, delta_rtx, nsrc));
used_update = true;
}
else
emit_insn (TARGET_32BIT
? gen_addsi3 (breg, breg, delta_rtx)
: gen_adddi3 (breg, breg, delta_rtx));
- dst = gen_rtx_MEM (mode, breg);
+ dst = replace_equiv_address (dst, breg);
}
- else if (! offsettable_memref_p (dst))
- abort ();
+ else
+ gcc_assert (rs6000_offsettable_memref_p (dst));
}
for (i = 0; i < nregs; i++)
- {
+ {
/* Calculate index to next subword. */
++j;
- if (j == nregs)
+ if (j == nregs)
j = 0;
- /* If compiler already emitted move of first word by
+ /* If compiler already emitted move of first word by
store with update, no need to do anything. */
if (j == 0 && used_update)
continue;
-
+
emit_insn (gen_rtx_SET (VOIDmode,
simplify_gen_subreg (reg_mode, dst, mode,
j * reg_mode_size),
@@ -10626,7 +12727,7 @@ first_reg_to_save (void)
/* Find lowest numbered live register. */
for (first_reg = 13; first_reg <= 31; first_reg++)
- if (regs_ever_live[first_reg]
+ if (regs_ever_live[first_reg]
&& (! call_used_regs[first_reg]
|| (first_reg == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
@@ -10670,6 +12771,13 @@ first_altivec_reg_to_save (void)
if (! TARGET_ALTIVEC_ABI)
return LAST_ALTIVEC_REGNO + 1;
+ /* On Darwin, the unwind routines are compiled without
+ TARGET_ALTIVEC, and use save_world to save/restore the
+ altivec registers when necessary. */
+ if (DEFAULT_ABI == ABI_DARWIN && current_function_calls_eh_return
+ && ! TARGET_ALTIVEC)
+ return FIRST_ALTIVEC_REGNO + 20;
+
/* Find lowest numbered live register. */
for (i = FIRST_ALTIVEC_REGNO + 20; i <= LAST_ALTIVEC_REGNO; ++i)
if (regs_ever_live[i])
@@ -10687,6 +12795,13 @@ compute_vrsave_mask (void)
{
unsigned int i, mask = 0;
+ /* On Darwin, the unwind routines are compiled without
+ TARGET_ALTIVEC, and use save_world to save/restore the
+ call-saved altivec registers when necessary. */
+ if (DEFAULT_ABI == ABI_DARWIN && current_function_calls_eh_return
+ && ! TARGET_ALTIVEC)
+ mask |= 0xFFF;
+
/* First, find out if we use _any_ altivec registers. */
for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i)
if (regs_ever_live[i])
@@ -10714,6 +12829,59 @@ compute_vrsave_mask (void)
return mask;
}
+/* For a very restricted set of circumstances, we can cut down the
+ size of prologues/epilogues by calling our own save/restore-the-world
+ routines. */
+
+static void
+compute_save_world_info (rs6000_stack_t *info_ptr)
+{
+ info_ptr->world_save_p = 1;
+ info_ptr->world_save_p
+ = (WORLD_SAVE_P (info_ptr)
+ && DEFAULT_ABI == ABI_DARWIN
+ && ! (current_function_calls_setjmp && flag_exceptions)
+ && info_ptr->first_fp_reg_save == FIRST_SAVED_FP_REGNO
+ && info_ptr->first_gp_reg_save == FIRST_SAVED_GP_REGNO
+ && info_ptr->first_altivec_reg_save == FIRST_SAVED_ALTIVEC_REGNO
+ && info_ptr->cr_save_p);
+
+ /* This will not work in conjunction with sibcalls. Make sure there
+ are none. (This check is expensive, but seldom executed.) */
+ if (WORLD_SAVE_P (info_ptr))
+ {
+ rtx insn;
+ for ( insn = get_last_insn_anywhere (); insn; insn = PREV_INSN (insn))
+ if ( GET_CODE (insn) == CALL_INSN
+ && SIBLING_CALL_P (insn))
+ {
+ info_ptr->world_save_p = 0;
+ break;
+ }
+ }
+
+ if (WORLD_SAVE_P (info_ptr))
+ {
+ /* Even if we're not touching VRsave, make sure there's room on the
+ stack for it, if it looks like we're calling SAVE_WORLD, which
+ will attempt to save it. */
+ info_ptr->vrsave_size = 4;
+
+ /* "Save" the VRsave register too if we're saving the world. */
+ if (info_ptr->vrsave_mask == 0)
+ info_ptr->vrsave_mask = compute_vrsave_mask ();
+
+ /* Because the Darwin register save/restore routines only handle
+ F14 .. F31 and V20 .. V31 as per the ABI, perform a consistency
+ check. */
+ gcc_assert (info_ptr->first_fp_reg_save >= FIRST_SAVED_FP_REGNO
+ && (info_ptr->first_altivec_reg_save
+ >= FIRST_SAVED_ALTIVEC_REGNO));
+ }
+ return;
+}
+
+
static void
is_altivec_return_reg (rtx reg, void *xyes)
{
@@ -10777,11 +12945,11 @@ is_altivec_return_reg (rtx reg, void *xyes)
| Parameter save area (P) | 8
+---------------------------------------+
| Alloca space (A) | 8+P
- +---------------------------------------+
+ +---------------------------------------+
| Varargs save area (V) | 8+P+A
- +---------------------------------------+
+ +---------------------------------------+
| Local variable space (L) | 8+P+A+V
- +---------------------------------------+
+ +---------------------------------------+
| Float/int conversion temporary (X) | 8+P+A+V+L
+---------------------------------------+
| Save area for AltiVec registers (W) | 8+P+A+V+L+X
@@ -10790,14 +12958,14 @@ is_altivec_return_reg (rtx reg, void *xyes)
+---------------------------------------+
| Save area for VRSAVE register (Z) | 8+P+A+V+L+X+W+Y
+---------------------------------------+
- | SPE: area for 64-bit GP registers |
- +---------------------------------------+
- | SPE alignment padding |
- +---------------------------------------+
+ | SPE: area for 64-bit GP registers |
+ +---------------------------------------+
+ | SPE alignment padding |
+ +---------------------------------------+
| saved CR (C) | 8+P+A+V+L+X+W+Y+Z
- +---------------------------------------+
+ +---------------------------------------+
| Save area for GP registers (G) | 8+P+A+V+L+X+W+Y+Z+C
- +---------------------------------------+
+ +---------------------------------------+
| Save area for FP registers (F) | 8+P+A+V+L+X+W+Y+Z+C+G
+---------------------------------------+
old SP->| back chain to caller's caller |
@@ -10823,24 +12991,22 @@ is_altivec_return_reg (rtx reg, void *xyes)
static rs6000_stack_t *
rs6000_stack_info (void)
{
- static rs6000_stack_t info, zero_info;
+ static rs6000_stack_t info;
rs6000_stack_t *info_ptr = &info;
int reg_size = TARGET_32BIT ? 4 : 8;
int ehrd_size;
int save_align;
HOST_WIDE_INT non_fixed_size;
- /* Zero all fields portably. */
- info = zero_info;
+ memset (&info, 0, sizeof (info));
if (TARGET_SPE)
{
/* Cache value so we don't rescan instruction chain over and over. */
if (cfun->machine->insn_chain_scanned_p == 0)
- {
- cfun->machine->insn_chain_scanned_p = 1;
- info_ptr->spe_64bit_regs_used = (int) spe_func_has_64bit_regs_p ();
- }
+ cfun->machine->insn_chain_scanned_p
+ = spe_func_has_64bit_regs_p () + 1;
+ info_ptr->spe_64bit_regs_used = cfun->machine->insn_chain_scanned_p - 1;
}
/* Select which calling sequence. */
@@ -10848,7 +13014,7 @@ rs6000_stack_info (void)
/* Calculate which registers need to be saved & save area size. */
info_ptr->first_gp_reg_save = first_reg_to_save ();
- /* Assume that we will have to save RS6000_PIC_OFFSET_TABLE_REGNUM,
+ /* Assume that we will have to save RS6000_PIC_OFFSET_TABLE_REGNUM,
even if it currently looks like we won't. */
if (((TARGET_TOC && TARGET_MINIMAL_TOC)
|| (flag_pic == 1 && DEFAULT_ABI == ABI_V4)
@@ -10885,10 +13051,9 @@ rs6000_stack_info (void)
|| cfun->machine->ra_needs_full_frame);
/* Determine if we need to save the link register. */
- if (rs6000_ra_ever_killed ()
- || (DEFAULT_ABI == ABI_AIX
- && current_function_profile
- && !TARGET_PROFILE_KERNEL)
+ if ((DEFAULT_ABI == ABI_AIX
+ && current_function_profile
+ && !TARGET_PROFILE_KERNEL)
#ifdef TARGET_RELOCATABLE
|| (TARGET_RELOCATABLE && (get_pool_size () != 0))
#endif
@@ -10896,17 +13061,15 @@ rs6000_stack_info (void)
&& !FP_SAVE_INLINE (info_ptr->first_fp_reg_save))
|| info_ptr->first_altivec_reg_save <= LAST_ALTIVEC_REGNO
|| (DEFAULT_ABI == ABI_V4 && current_function_calls_alloca)
- || (DEFAULT_ABI == ABI_DARWIN
- && flag_pic
- && current_function_uses_pic_offset_table)
- || info_ptr->calls_p)
+ || info_ptr->calls_p
+ || rs6000_ra_ever_killed ())
{
info_ptr->lr_save_p = 1;
regs_ever_live[LINK_REGISTER_REGNUM] = 1;
}
/* Determine if we need to save the condition code registers. */
- if (regs_ever_live[CR2_REGNO]
+ if (regs_ever_live[CR2_REGNO]
|| regs_ever_live[CR3_REGNO]
|| regs_ever_live[CR4_REGNO])
{
@@ -10935,10 +13098,16 @@ rs6000_stack_info (void)
/* Determine various sizes. */
info_ptr->reg_size = reg_size;
info_ptr->fixed_size = RS6000_SAVE_AREA;
- info_ptr->varargs_size = RS6000_VARARGS_AREA;
info_ptr->vars_size = RS6000_ALIGN (get_frame_size (), 8);
info_ptr->parm_size = RS6000_ALIGN (current_function_outgoing_args_size,
TARGET_ALTIVEC ? 16 : 8);
+ if (FRAME_GROWS_DOWNWARD)
+ info_ptr->vars_size
+ += RS6000_ALIGN (info_ptr->fixed_size + info_ptr->vars_size
+ + info_ptr->parm_size,
+ ABI_STACK_BOUNDARY / BITS_PER_UNIT)
+ - (info_ptr->fixed_size + info_ptr->vars_size
+ + info_ptr->parm_size);
if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
info_ptr->spe_gp_size = 8 * (32 - info_ptr->first_gp_reg_save);
@@ -10955,12 +13124,14 @@ rs6000_stack_info (void)
else
info_ptr->vrsave_size = 0;
+ compute_save_world_info (info_ptr);
+
/* Calculate the offsets. */
switch (DEFAULT_ABI)
{
case ABI_NONE:
default:
- abort ();
+ gcc_unreachable ();
case ABI_AIX:
case ABI_DARWIN:
@@ -10972,10 +13143,11 @@ rs6000_stack_info (void)
info_ptr->vrsave_save_offset
= info_ptr->gp_save_offset - info_ptr->vrsave_size;
- /* Align stack so vector save area is on a quadword boundary. */
+ /* Align stack so vector save area is on a quadword boundary.
+ The padding goes above the vectors. */
if (info_ptr->altivec_size != 0)
info_ptr->altivec_padding_size
- = 16 - (-info_ptr->vrsave_save_offset % 16);
+ = info_ptr->vrsave_save_offset & 0xF;
else
info_ptr->altivec_padding_size = 0;
@@ -10983,6 +13155,8 @@ rs6000_stack_info (void)
= info_ptr->vrsave_save_offset
- info_ptr->altivec_padding_size
- info_ptr->altivec_size;
+ gcc_assert (info_ptr->altivec_size == 0
+ || info_ptr->altivec_save_offset % 16 == 0);
/* Adjust for AltiVec case. */
info_ptr->ehrd_offset = info_ptr->altivec_save_offset - ehrd_size;
@@ -10999,24 +13173,23 @@ rs6000_stack_info (void)
info_ptr->cr_save_offset = info_ptr->gp_save_offset - info_ptr->cr_size;
if (TARGET_SPE_ABI && info_ptr->spe_64bit_regs_used != 0)
- {
- /* Align stack so SPE GPR save area is aligned on a
- double-word boundary. */
- if (info_ptr->spe_gp_size != 0)
- info_ptr->spe_padding_size
- = 8 - (-info_ptr->cr_save_offset % 8);
- else
- info_ptr->spe_padding_size = 0;
-
- info_ptr->spe_gp_save_offset
- = info_ptr->cr_save_offset
- - info_ptr->spe_padding_size
- - info_ptr->spe_gp_size;
-
- /* Adjust for SPE case. */
- info_ptr->toc_save_offset
- = info_ptr->spe_gp_save_offset - info_ptr->toc_size;
- }
+ {
+ /* Align stack so SPE GPR save area is aligned on a
+ double-word boundary. */
+ if (info_ptr->spe_gp_size != 0)
+ info_ptr->spe_padding_size
+ = 8 - (-info_ptr->cr_save_offset % 8);
+ else
+ info_ptr->spe_padding_size = 0;
+
+ info_ptr->spe_gp_save_offset
+ = info_ptr->cr_save_offset
+ - info_ptr->spe_padding_size
+ - info_ptr->spe_gp_size;
+
+ /* Adjust for SPE case. */
+ info_ptr->ehrd_offset = info_ptr->spe_gp_save_offset;
+ }
else if (TARGET_ALTIVEC_ABI)
{
info_ptr->vrsave_save_offset
@@ -11035,12 +13208,11 @@ rs6000_stack_info (void)
- info_ptr->altivec_size;
/* Adjust for AltiVec case. */
- info_ptr->toc_save_offset
- = info_ptr->altivec_save_offset - info_ptr->toc_size;
+ info_ptr->ehrd_offset = info_ptr->altivec_save_offset;
}
else
- 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->ehrd_offset = info_ptr->cr_save_offset;
+ info_ptr->ehrd_offset -= ehrd_size;
info_ptr->lr_save_offset = reg_size;
break;
}
@@ -11054,15 +13226,12 @@ rs6000_stack_info (void)
+ info_ptr->spe_padding_size
+ ehrd_size
+ info_ptr->cr_size
- + info_ptr->lr_size
- + info_ptr->vrsave_size
- + info_ptr->toc_size,
+ + info_ptr->vrsave_size,
save_align);
non_fixed_size = (info_ptr->vars_size
+ info_ptr->parm_size
- + info_ptr->save_size
- + info_ptr->varargs_size);
+ + info_ptr->save_size);
info_ptr->total_size = RS6000_ALIGN (non_fixed_size + info_ptr->fixed_size,
ABI_STACK_BOUNDARY / BITS_PER_UNIT);
@@ -11118,9 +13287,6 @@ rs6000_stack_info (void)
if (! info_ptr->cr_save_p)
info_ptr->cr_save_offset = 0;
- if (! info_ptr->toc_save_p)
- info_ptr->toc_save_offset = 0;
-
return info_ptr;
}
@@ -11147,10 +13313,23 @@ spe_func_has_64bit_regs_p (void)
{
rtx i;
+ /* FIXME: This should be implemented with attributes...
+
+ (set_attr "spe64" "true")....then,
+ if (get_spe64(insn)) return true;
+
+ It's the only reliable way to do the stuff below. */
+
i = PATTERN (insn);
- if (GET_CODE (i) == SET
- && SPE_VECTOR_MODE (GET_MODE (SET_SRC (i))))
- return true;
+ if (GET_CODE (i) == SET)
+ {
+ enum machine_mode mode = GET_MODE (SET_SRC (i));
+
+ if (SPE_VECTOR_MODE (mode))
+ return true;
+ if (TARGET_E500_DOUBLE && mode == DFmode)
+ return true;
+ }
}
}
@@ -11203,9 +13382,6 @@ debug_stack_info (rs6000_stack_t *info)
if (info->cr_save_p)
fprintf (stderr, "\tcr_save_p = %5d\n", info->cr_save_p);
- if (info->toc_save_p)
- fprintf (stderr, "\ttoc_save_p = %5d\n", info->toc_save_p);
-
if (info->vrsave_mask)
fprintf (stderr, "\tvrsave_mask = 0x%x\n", info->vrsave_mask);
@@ -11239,9 +13415,6 @@ debug_stack_info (rs6000_stack_t *info)
if (info->cr_save_offset)
fprintf (stderr, "\tcr_save_offset = %5d\n", info->cr_save_offset);
- if (info->toc_save_offset)
- fprintf (stderr, "\ttoc_save_offset = %5d\n", info->toc_save_offset);
-
if (info->varargs_save_offset)
fprintf (stderr, "\tvarargs_save_offset = %5d\n", info->varargs_save_offset);
@@ -11249,9 +13422,6 @@ debug_stack_info (rs6000_stack_t *info)
fprintf (stderr, "\ttotal_size = "HOST_WIDE_INT_PRINT_DEC"\n",
info->total_size);
- if (info->varargs_size)
- fprintf (stderr, "\tvarargs_size = %5d\n", info->varargs_size);
-
if (info->vars_size)
fprintf (stderr, "\tvars_size = "HOST_WIDE_INT_PRINT_DEC"\n",
info->vars_size);
@@ -11285,15 +13455,9 @@ debug_stack_info (rs6000_stack_t *info)
fprintf (stderr, "\tspe_padding_size = %5d\n",
info->spe_padding_size);
- if (info->lr_size)
- fprintf (stderr, "\tlr_size = %5d\n", info->lr_size);
-
if (info->cr_size)
fprintf (stderr, "\tcr_size = %5d\n", info->cr_size);
- if (info->toc_size)
- fprintf (stderr, "\ttoc_size = %5d\n", info->toc_size);
-
if (info->save_size)
fprintf (stderr, "\tsave_size = %5d\n", info->save_size);
@@ -11342,14 +13506,14 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
if (decl)
{
if (TARGET_ALTIVEC_VRSAVE)
- {
+ {
for (type = TYPE_ARG_TYPES (TREE_TYPE (decl));
type; type = TREE_CHAIN (type))
{
if (TREE_CODE (TREE_VALUE (type)) == VECTOR_TYPE)
return false;
}
- }
+ }
if (DEFAULT_ABI == ABI_DARWIN
|| (*targetm.binds_local_p) (decl))
{
@@ -11363,6 +13527,24 @@ rs6000_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
return false;
}
+/* NULL if INSN insn is valid within a low-overhead loop.
+ Otherwise return why doloop cannot be applied.
+ PowerPC uses the COUNT register for branch on table instructions. */
+
+static const char *
+rs6000_invalid_within_doloop (rtx insn)
+{
+ if (CALL_P (insn))
+ return "Function call in the loop.";
+
+ if (JUMP_P (insn)
+ && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
+ || GET_CODE (PATTERN (insn)) == ADDR_VEC))
+ return "Computed branch in the loop.";
+
+ return NULL;
+}
+
static int
rs6000_ra_ever_killed (void)
{
@@ -11388,7 +13570,7 @@ rs6000_ra_ever_killed (void)
When we're called from the epilogue, we need to avoid counting
this as a store. */
-
+
push_topmost_sequence ();
top = get_insns ();
pop_topmost_sequence ();
@@ -11398,10 +13580,12 @@ rs6000_ra_ever_killed (void)
{
if (INSN_P (insn))
{
- if (FIND_REG_INC_NOTE (insn, reg))
- return 1;
- else if (GET_CODE (insn) == CALL_INSN
- && !SIBLING_CALL_P (insn))
+ if (CALL_P (insn))
+ {
+ if (!SIBLING_CALL_P (insn))
+ return 1;
+ }
+ else if (find_regno_note (insn, REG_INC, LINK_REGISTER_REGNUM))
return 1;
else if (set_of (reg, insn) != NULL_RTX
&& !prologue_epilogue_contains (insn))
@@ -11430,15 +13614,49 @@ rs6000_emit_load_toc_table (int fromprolog)
rtx dest, insn;
dest = gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM);
- if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
+ if (TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic)
+ {
+ char buf[30];
+ rtx lab, tmp1, tmp2, got, tempLR;
+
+ ASM_GENERATE_INTERNAL_LABEL (buf, "LCF", rs6000_pic_labelno);
+ lab = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (buf));
+ if (flag_pic == 2)
+ got = gen_rtx_SYMBOL_REF (Pmode, toc_label_name);
+ else
+ got = rs6000_got_sym ();
+ tmp1 = tmp2 = dest;
+ if (!fromprolog)
+ {
+ tmp1 = gen_reg_rtx (Pmode);
+ tmp2 = gen_reg_rtx (Pmode);
+ }
+ tempLR = (fromprolog
+ ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
+ : gen_reg_rtx (Pmode));
+ insn = emit_insn (gen_load_toc_v4_PIC_1 (tempLR, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_move_insn (tmp1, tempLR);
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_insn (gen_load_toc_v4_PIC_3b (tmp2, tmp1, got, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ insn = emit_insn (gen_load_toc_v4_PIC_3c (dest, tmp2, got, lab));
+ if (fromprolog)
+ rs6000_maybe_dead (insn);
+ }
+ else if (TARGET_ELF && DEFAULT_ABI == ABI_V4 && flag_pic == 1)
{
- rtx temp = (fromprolog
- ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
- : gen_reg_rtx (Pmode));
- insn = emit_insn (gen_load_toc_v4_pic_si (temp));
+ rtx tempLR = (fromprolog
+ ? gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)
+ : gen_reg_rtx (Pmode));
+
+ insn = emit_insn (gen_load_toc_v4_pic_si (tempLR));
if (fromprolog)
rs6000_maybe_dead (insn);
- insn = emit_move_insn (dest, temp);
+ insn = emit_move_insn (dest, tempLR);
if (fromprolog)
rs6000_maybe_dead (insn);
}
@@ -11452,13 +13670,6 @@ rs6000_emit_load_toc_table (int fromprolog)
? gen_rtx_REG (Pmode, 0)
: gen_reg_rtx (Pmode));
- /* possibly create the toc section */
- if (! toc_initialized)
- {
- toc_section ();
- function_section (current_function_decl);
- }
-
if (fromprolog)
{
rtx symF, symL;
@@ -11504,8 +13715,10 @@ rs6000_emit_load_toc_table (int fromprolog)
if (fromprolog)
rs6000_maybe_dead (insn);
}
- else if (DEFAULT_ABI == ABI_AIX)
+ else
{
+ gcc_assert (DEFAULT_ABI == ABI_AIX);
+
if (TARGET_32BIT)
insn = emit_insn (gen_load_toc_aix_si (dest));
else
@@ -11513,8 +13726,6 @@ rs6000_emit_load_toc_table (int fromprolog)
if (fromprolog)
rs6000_maybe_dead (insn);
}
- else
- abort ();
}
/* Emit instructions to restore the link register after determining where
@@ -11539,14 +13750,15 @@ rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
|| current_function_calls_alloca
|| info->total_size > 32767)
{
- emit_move_insn (operands[1], gen_rtx_MEM (Pmode, frame_rtx));
+ tmp = gen_frame_mem (Pmode, frame_rtx);
+ emit_move_insn (operands[1], tmp);
frame_rtx = operands[1];
}
else if (info->push_p)
sp_offset = info->total_size;
tmp = plus_constant (frame_rtx, info->lr_save_offset + sp_offset);
- tmp = gen_rtx_MEM (Pmode, tmp);
+ tmp = gen_frame_mem (Pmode, tmp);
emit_move_insn (tmp, operands[0]);
}
else
@@ -11555,20 +13767,20 @@ rs6000_emit_eh_reg_restore (rtx source, rtx scratch)
static GTY(()) int set = -1;
-int
+int
get_TOC_alias_set (void)
{
if (set == -1)
set = new_alias_set ();
return set;
-}
+}
/* This returns nonzero if the current function uses the TOC. This is
determined by the presence of (use (unspec ... UNSPEC_TOC)), which
is generated by the ABI_V4 load_toc_* patterns. */
#if TARGET_ELF
static int
-uses_TOC (void)
+uses_TOC (void)
{
rtx insn;
@@ -11578,7 +13790,7 @@ uses_TOC (void)
rtx pat = PATTERN (insn);
int i;
- if (GET_CODE (pat) == PARALLEL)
+ if (GET_CODE (pat) == PARALLEL)
for (i = 0; i < XVECLEN (pat, 0); i++)
{
rtx sub = XVECEXP (pat, 0, i);
@@ -11596,14 +13808,14 @@ uses_TOC (void)
#endif
rtx
-create_TOC_reference (rtx symbol)
+create_TOC_reference (rtx symbol)
{
if (no_new_pseudos)
regs_ever_live[TOC_REGISTER] = 1;
- return gen_rtx_PLUS (Pmode,
+ return gen_rtx_PLUS (Pmode,
gen_rtx_REG (Pmode, TOC_REGISTER),
- gen_rtx_CONST (Pmode,
- gen_rtx_MINUS (Pmode, symbol,
+ gen_rtx_CONST (Pmode,
+ gen_rtx_MINUS (Pmode, symbol,
gen_rtx_SYMBOL_REF (Pmode, toc_label_name))));
}
@@ -11621,12 +13833,12 @@ rs6000_aix_emit_builtin_unwind_init (void)
rtx tocompare = gen_reg_rtx (SImode);
rtx no_toc_save_needed = gen_label_rtx ();
- mem = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
+ mem = gen_frame_mem (Pmode, hard_frame_pointer_rtx);
emit_move_insn (stack_top, mem);
- mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (2 * GET_MODE_SIZE (Pmode))));
+ mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_top,
+ GEN_INT (2 * GET_MODE_SIZE (Pmode))));
emit_move_insn (opcode_addr, mem);
emit_move_insn (opcode, gen_rtx_MEM (SImode, opcode_addr));
emit_move_insn (tocompare, gen_int_mode (TARGET_32BIT ? 0x80410014
@@ -11636,22 +13848,22 @@ rs6000_aix_emit_builtin_unwind_init (void)
SImode, NULL_RTX, NULL_RTX,
no_toc_save_needed);
- mem = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode, stack_top,
- GEN_INT (5 * GET_MODE_SIZE (Pmode))));
+ mem = gen_frame_mem (Pmode,
+ gen_rtx_PLUS (Pmode, stack_top,
+ GEN_INT (5 * GET_MODE_SIZE (Pmode))));
emit_move_insn (mem, gen_rtx_REG (Pmode, 2));
emit_label (no_toc_save_needed);
}
-/* This ties together stack memory (MEM with an alias set of
- rs6000_sr_alias_set) and the change to the stack pointer. */
+/* This ties together stack memory (MEM with an alias set of frame_alias_set)
+ and the change to the stack pointer. */
static void
rs6000_emit_stack_tie (void)
{
- rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
+ rtx mem = gen_frame_mem (BLKmode,
+ gen_rtx_REG (Pmode, STACK_POINTER_REGNUM));
- set_mem_alias_set (mem, rs6000_sr_alias_set);
emit_insn (gen_stack_tie (mem));
}
@@ -11665,12 +13877,19 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
rtx insn;
rtx stack_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
rtx tmp_reg = gen_rtx_REG (Pmode, 0);
- rtx todec = GEN_INT (-size);
+ rtx todec = gen_int_mode (-size, Pmode);
+
+ if (INTVAL (todec) != -size)
+ {
+ warning (0, "stack frame too large");
+ emit_insn (gen_trap ());
+ return;
+ }
if (current_function_limit_stack)
{
if (REG_P (stack_limit_rtx)
- && REGNO (stack_limit_rtx) > 1
+ && REGNO (stack_limit_rtx) > 1
&& REGNO (stack_limit_rtx) <= 31)
{
emit_insn (TARGET_32BIT
@@ -11689,8 +13908,8 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
&& DEFAULT_ABI == ABI_V4)
{
rtx toload = gen_rtx_CONST (VOIDmode,
- gen_rtx_PLUS (Pmode,
- stack_limit_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_limit_rtx,
GEN_INT (size)));
emit_insn (gen_elf_high (tmp_reg, toload));
@@ -11699,7 +13918,7 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
const0_rtx));
}
else
- warning ("stack limit expression is not supported");
+ warning (0, "stack limit expression is not supported");
}
if (copy_r12 || ! TARGET_UPDATE)
@@ -11710,7 +13929,7 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
if (size > 32767)
{
/* Need a note here so that try_split doesn't get confused. */
- if (get_last_insn() == NULL_RTX)
+ if (get_last_insn () == NULL_RTX)
emit_note (NOTE_INSN_DELETED);
insn = emit_move_insn (tmp_reg, todec);
try_split (PATTERN (insn), insn, 0);
@@ -11720,7 +13939,7 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
insn = emit_insn (TARGET_32BIT
? gen_movsi_update (stack_reg, stack_reg,
todec, stack_reg)
- : gen_movdi_update (stack_reg, stack_reg,
+ : gen_movdi_di_update (stack_reg, stack_reg,
todec, stack_reg));
}
else
@@ -11731,11 +13950,11 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
emit_move_insn (gen_rtx_MEM (Pmode, stack_reg),
gen_rtx_REG (Pmode, 12));
}
-
+
RTX_FRAME_RELATED_P (insn) = 1;
- REG_NOTES (insn) =
+ REG_NOTES (insn) =
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode, stack_reg,
+ gen_rtx_SET (VOIDmode, stack_reg,
gen_rtx_PLUS (Pmode, stack_reg,
GEN_INT (-size))),
REG_NOTES (insn));
@@ -11748,7 +13967,7 @@ rs6000_emit_allocate_stack (HOST_WIDE_INT size, int copy_r12)
its hand so much. */
static void
-rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
+rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
rtx reg2, rtx rreg)
{
rtx real, temp;
@@ -11765,12 +13984,12 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
if (reg2 != NULL_RTX)
real = replace_rtx (real, reg2, rreg);
-
- real = replace_rtx (real, reg,
+
+ real = replace_rtx (real, reg,
gen_rtx_PLUS (Pmode, gen_rtx_REG (Pmode,
STACK_POINTER_REGNUM),
GEN_INT (val)));
-
+
/* We expect that 'real' is either a SET or a PARALLEL containing
SETs (and possibly other stuff). In a PARALLEL, all the SETs
are important so they all have to be marked RTX_FRAME_RELATED_P. */
@@ -11778,7 +13997,7 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
if (GET_CODE (real) == SET)
{
rtx set = real;
-
+
temp = simplify_rtx (SET_SRC (set));
if (temp)
SET_SRC (set) = temp;
@@ -11792,14 +14011,16 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
XEXP (SET_DEST (set), 0) = temp;
}
}
- else if (GET_CODE (real) == PARALLEL)
+ else
{
int i;
+
+ gcc_assert (GET_CODE (real) == PARALLEL);
for (i = 0; i < XVECLEN (real, 0); i++)
if (GET_CODE (XVECEXP (real, 0, i)) == SET)
{
rtx set = XVECEXP (real, 0, i);
-
+
temp = simplify_rtx (SET_SRC (set));
if (temp)
SET_SRC (set) = temp;
@@ -11815,8 +14036,6 @@ rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
RTX_FRAME_RELATED_P (set) = 1;
}
}
- else
- abort ();
if (TARGET_SPE)
real = spe_synthesize_frame_save (real);
@@ -11845,10 +14064,9 @@ spe_synthesize_frame_save (rtx real)
This is so we can differentiate between 64-bit and 32-bit saves.
Words cannot describe this nastiness. */
- if (GET_CODE (SET_DEST (real)) != MEM
- || GET_CODE (XEXP (SET_DEST (real), 0)) != PLUS
- || GET_CODE (SET_SRC (real)) != REG)
- abort ();
+ gcc_assert (GET_CODE (SET_DEST (real)) == MEM
+ && GET_CODE (XEXP (SET_DEST (real), 0)) == PLUS
+ && GET_CODE (SET_SRC (real)) == REG);
/* Transform:
(set (mem (plus (reg x) (const y)))
@@ -11905,7 +14123,7 @@ generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
vrsave,
gen_rtx_UNSPEC_VOLATILE (SImode,
gen_rtvec (2, reg, vrsave),
- 30));
+ UNSPECV_SET_VRSAVE));
nclobs = 1;
@@ -11953,7 +14171,7 @@ generate_set_vrsave (rtx reg, rs6000_stack_t *info, int epiloguep)
Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
static void
-emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
+emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
unsigned int regno, int offset, HOST_WIDE_INT total_size)
{
rtx reg, offset_rtx, insn, mem, addr, int_rtx;
@@ -11963,12 +14181,13 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
/* Some cases that need register indexed addressing. */
if ((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode)
|| (TARGET_SPE_ABI
&& SPE_VECTOR_MODE (mode)
&& !SPE_CONST_OFFSET_OK (offset)))
{
/* Whomever calls us must make sure r11 is available in the
- flow path of instructions in the prologue. */
+ flow path of instructions in the prologue. */
offset_rtx = gen_rtx_REG (Pmode, 11);
emit_move_insn (offset_rtx, int_rtx);
@@ -11984,8 +14203,7 @@ emit_frame_save (rtx frame_reg, rtx frame_ptr, enum machine_mode mode,
reg = gen_rtx_REG (mode, regno);
addr = gen_rtx_PLUS (Pmode, frame_reg, offset_rtx);
- mem = gen_rtx_MEM (mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (mode, addr);
insn = emit_move_insn (mem, reg);
@@ -12002,7 +14220,8 @@ gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
int_rtx = GEN_INT (offset);
- if (TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ if ((TARGET_SPE_ABI && SPE_VECTOR_MODE (mode))
+ || (TARGET_E500_DOUBLE && mode == DFmode))
{
offset_rtx = gen_rtx_REG (Pmode, FIXED_SCRATCH);
emit_move_insn (offset_rtx, int_rtx);
@@ -12010,9 +14229,26 @@ gen_frame_mem_offset (enum machine_mode mode, rtx reg, int offset)
else
offset_rtx = int_rtx;
- return gen_rtx_MEM (mode, gen_rtx_PLUS (Pmode, reg, offset_rtx));
+ return gen_frame_mem (mode, gen_rtx_PLUS (Pmode, reg, offset_rtx));
}
+/* Look for user-defined global regs. We should not save and restore these,
+ and cannot use stmw/lmw if there are any in its range. */
+
+static bool
+no_global_regs_above (int first_greg)
+{
+ int i;
+ for (i = 0; i < 32 - first_greg; i++)
+ if (global_regs[first_greg + i])
+ return false;
+ return true;
+}
+
+#ifndef TARGET_FIX_AND_CONTINUE
+#define TARGET_FIX_AND_CONTINUE 0
+#endif
+
/* Emit function prologue as insns. */
void
@@ -12029,24 +14265,40 @@ rs6000_emit_prologue (void)
int saving_FPRs_inline;
int using_store_multiple;
HOST_WIDE_INT sp_offset = 0;
-
- if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
- {
- reg_mode = V2SImode;
- reg_size = 8;
- }
+
+ if (TARGET_FIX_AND_CONTINUE)
+ {
+ /* gdb on darwin arranges to forward a function from the old
+ address by modifying the first 5 instructions of the function
+ to branch to the overriding function. This is necessary to
+ permit function pointers that point to the old function to
+ actually forward to the new function. */
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ emit_insn (gen_nop ());
+ }
+
+ if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
+ {
+ reg_mode = V2SImode;
+ reg_size = 8;
+ }
using_store_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& (!TARGET_SPE_ABI
|| info->spe_64bit_regs_used == 0)
- && info->first_gp_reg_save < 31);
+ && info->first_gp_reg_save < 31
+ && no_global_regs_above (info->first_gp_reg_save));
saving_FPRs_inline = (info->first_fp_reg_save == 64
|| FP_SAVE_INLINE (info->first_fp_reg_save)
|| current_function_calls_eh_return
|| cfun->machine->ra_need_lr);
/* For V.4, update stack before we do any saving and set back pointer. */
- if (info->push_p
+ if (! WORLD_SAVE_P (info)
+ && info->push_p
&& (DEFAULT_ABI == ABI_V4
|| current_function_calls_eh_return))
{
@@ -12054,7 +14306,7 @@ rs6000_emit_prologue (void)
sp_offset = info->total_size;
else
frame_reg_rtx = frame_ptr_rtx;
- rs6000_emit_allocate_stack (info->total_size,
+ rs6000_emit_allocate_stack (info->total_size,
(frame_reg_rtx != sp_reg_rtx
&& (info->cr_save_p
|| info->lr_save_p
@@ -12065,8 +14317,123 @@ rs6000_emit_prologue (void)
rs6000_emit_stack_tie ();
}
+ /* Handle world saves specially here. */
+ if (WORLD_SAVE_P (info))
+ {
+ int i, j, sz;
+ rtx treg;
+ rtvec p;
+ rtx reg0;
+
+ /* save_world expects lr in r0. */
+ reg0 = gen_rtx_REG (Pmode, 0);
+ if (info->lr_save_p)
+ {
+ insn = emit_move_insn (reg0,
+ gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* The SAVE_WORLD and RESTORE_WORLD routines make a number of
+ assumptions about the offsets of various bits of the stack
+ frame. */
+ gcc_assert (info->gp_save_offset == -220
+ && info->fp_save_offset == -144
+ && info->lr_save_offset == 8
+ && info->cr_save_offset == 4
+ && info->push_p
+ && info->lr_save_p
+ && (!current_function_calls_eh_return
+ || info->ehrd_offset == -432)
+ && info->vrsave_save_offset == -224
+ && info->altivec_save_offset == -416);
+
+ treg = gen_rtx_REG (SImode, 11);
+ emit_move_insn (treg, GEN_INT (-info->total_size));
+
+ /* SAVE_WORLD takes the caller's LR in R0 and the frame size
+ in R11. It also clobbers R12, so beware! */
+
+ /* Preserve CR2 for save_world prologues */
+ sz = 5;
+ sz += 32 - info->first_gp_reg_save;
+ sz += 64 - info->first_fp_reg_save;
+ sz += LAST_ALTIVEC_REGNO - info->first_altivec_reg_save + 1;
+ p = rtvec_alloc (sz);
+ j = 0;
+ RTVEC_ELT (p, j++) = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (Pmode,
+ LINK_REGISTER_REGNUM));
+ RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
+ gen_rtx_SYMBOL_REF (Pmode,
+ "*save_world"));
+ /* We do floats first so that the instruction pattern matches
+ properly. */
+ for (i = 0; i < 64 - info->first_fp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->fp_save_offset
+ + sp_offset + 8 * i));
+ rtx mem = gen_frame_mem (DFmode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+ for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
+ {
+ rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->altivec_save_offset
+ + sp_offset + 16 * i));
+ rtx mem = gen_frame_mem (V4SImode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset + reg_size * i));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+
+ {
+ /* CR register traditionally saved as CR2. */
+ rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->cr_save_offset
+ + sp_offset));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg);
+ }
+ /* Explain about use of R0. */
+ if (info->lr_save_p)
+ {
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->lr_save_offset
+ + sp_offset));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, mem, reg0);
+ }
+ /* Explain what happens to the stack pointer. */
+ {
+ rtx newval = gen_rtx_PLUS (Pmode, sp_reg_rtx, treg);
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, sp_reg_rtx, newval);
+ }
+
+ insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ treg, GEN_INT (-info->total_size));
+ sp_offset = info->total_size;
+ }
+
/* Save AltiVec registers if needed. */
- if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
+ if (!WORLD_SAVE_P (info) && TARGET_ALTIVEC_ABI && info->altivec_size != 0)
{
int i;
@@ -12087,10 +14454,8 @@ rs6000_emit_prologue (void)
emit_move_insn (areg, GEN_INT (offset));
/* AltiVec addressing mode is [reg+reg]. */
- mem = gen_rtx_MEM (V4SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
-
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (V4SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx, areg));
insn = emit_move_insn (mem, savereg);
@@ -12122,13 +14487,15 @@ rs6000_emit_prologue (void)
else
emit_insn (gen_rtx_SET (VOIDmode, reg, vrsave));
- /* Save VRSAVE. */
- offset = info->vrsave_save_offset + sp_offset;
- mem
- = gen_rtx_MEM (SImode,
- gen_rtx_PLUS (Pmode, frame_reg_rtx, GEN_INT (offset)));
- set_mem_alias_set (mem, rs6000_sr_alias_set);
- insn = emit_move_insn (mem, reg);
+ if (!WORLD_SAVE_P (info))
+ {
+ /* Save VRSAVE. */
+ offset = info->vrsave_save_offset + sp_offset;
+ mem = gen_frame_mem (SImode,
+ gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (offset)));
+ insn = emit_move_insn (mem, reg);
+ }
/* Include the registers in the mask. */
emit_insn (gen_iorsi3 (reg, reg, GEN_INT ((int) info->vrsave_mask)));
@@ -12137,40 +14504,57 @@ rs6000_emit_prologue (void)
}
/* If we use the link register, get it into r0. */
- if (info->lr_save_p)
- emit_move_insn (gen_rtx_REG (Pmode, 0),
- gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
+ if (!WORLD_SAVE_P (info) && info->lr_save_p)
+ {
+ insn = emit_move_insn (gen_rtx_REG (Pmode, 0),
+ gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
/* If we need to save CR, put it into r12. */
- if (info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
+ if (!WORLD_SAVE_P (info) && info->cr_save_p && frame_reg_rtx != frame_ptr_rtx)
{
+ rtx set;
+
cr_save_rtx = gen_rtx_REG (SImode, 12);
- emit_insn (gen_movesi_from_cr (cr_save_rtx));
+ insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ /* Now, there's no way that dwarf2out_frame_debug_expr is going
+ to understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)'.
+ But that's OK. All we have to do is specify that _one_ condition
+ code register is saved in this stack slot. The thrower's epilogue
+ will then restore all the call-saved registers.
+ We use CR2_REGNO (70) to be compatible with gcc-2.95 on Linux. */
+ set = gen_rtx_SET (VOIDmode, cr_save_rtx,
+ gen_rtx_REG (SImode, CR2_REGNO));
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ set,
+ REG_NOTES (insn));
}
/* Do any required saving of fpr's. If only one or two to save, do
it ourselves. Otherwise, call function. */
- if (saving_FPRs_inline)
+ if (!WORLD_SAVE_P (info) && saving_FPRs_inline)
{
int i;
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- if ((regs_ever_live[info->first_fp_reg_save+i]
+ if ((regs_ever_live[info->first_fp_reg_save+i]
&& ! call_used_regs[info->first_fp_reg_save+i]))
emit_frame_save (frame_reg_rtx, frame_ptr_rtx, DFmode,
info->first_fp_reg_save + i,
info->fp_save_offset + sp_offset + 8 * i,
info->total_size);
}
- else if (info->first_fp_reg_save != 64)
+ else if (!WORLD_SAVE_P (info) && info->first_fp_reg_save != 64)
{
int i;
char rname[30];
const char *alloc_rname;
rtvec p;
p = rtvec_alloc (2 + 64 - info->first_fp_reg_save);
-
- RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
- gen_rtx_REG (Pmode,
+
+ RTVEC_ELT (p, 0) = gen_rtx_CLOBBER (VOIDmode,
+ gen_rtx_REG (Pmode,
LINK_REGISTER_REGNUM));
sprintf (rname, "%s%d%s", SAVE_FP_PREFIX,
info->first_fp_reg_save - 32, SAVE_FP_SUFFIX);
@@ -12183,21 +14567,20 @@ rs6000_emit_prologue (void)
rtx addr, reg, mem;
reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->fp_save_offset
+ GEN_INT (info->fp_save_offset
+ sp_offset + 8*i));
- mem = gen_rtx_MEM (DFmode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (DFmode, addr);
RTVEC_ELT (p, i + 2) = gen_rtx_SET (VOIDmode, mem, reg);
}
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
/* Save GPRs. This is done as a PARALLEL if we are using
the store-multiple instructions. */
- if (using_store_multiple)
+ if (!WORLD_SAVE_P (info) && using_store_multiple)
{
rtvec p;
int i;
@@ -12206,29 +14589,28 @@ rs6000_emit_prologue (void)
{
rtx addr, reg, mem;
reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->gp_save_offset
- + sp_offset
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset
+ reg_size * i));
- mem = gen_rtx_MEM (reg_mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (reg_mode, addr);
RTVEC_ELT (p, i) = gen_rtx_SET (VOIDmode, mem, reg);
}
insn = emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
- else
+ else if (!WORLD_SAVE_P (info))
{
int i;
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- if ((regs_ever_live[info->first_gp_reg_save+i]
- && (! call_used_regs[info->first_gp_reg_save+i]
- || (i+info->first_gp_reg_save
+ if ((regs_ever_live[info->first_gp_reg_save + i]
+ && (!call_used_regs[info->first_gp_reg_save + i]
+ || (i + info->first_gp_reg_save
== RS6000_PIC_OFFSET_TABLE_REGNUM
&& TARGET_TOC && TARGET_MINIMAL_TOC)))
- || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
+ || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{
@@ -12249,8 +14631,7 @@ rs6000_emit_prologue (void)
b = GEN_INT (offset);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
- mem = gen_rtx_MEM (V2SImode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (V2SImode, addr);
insn = emit_move_insn (mem, reg);
if (GET_CODE (b) == CONST_INT)
@@ -12262,15 +14643,14 @@ rs6000_emit_prologue (void)
}
else
{
- addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->gp_save_offset
- + sp_offset
+ addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset
+ reg_size * i));
- mem = gen_rtx_MEM (reg_mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (reg_mode, addr);
insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
}
}
@@ -12290,11 +14670,10 @@ rs6000_emit_prologue (void)
reg = gen_rtx_REG (reg_mode, 2);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (sp_offset + 5 * reg_size));
- mem = gen_rtx_MEM (reg_mode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (reg_mode, addr);
insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
NULL_RTX, NULL_RTX);
PATTERN (insn) = gen_blockage ();
}
@@ -12313,100 +14692,117 @@ rs6000_emit_prologue (void)
}
/* Save lr if we used it. */
- if (info->lr_save_p)
+ if (!WORLD_SAVE_P (info) && info->lr_save_p)
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->lr_save_offset + sp_offset));
rtx reg = gen_rtx_REG (Pmode, 0);
rtx mem = gen_rtx_MEM (Pmode, addr);
- /* This should not be of rs6000_sr_alias_set, because of
+ /* This should not be of frame_alias_set, because of
__builtin_return_address. */
-
+
insn = emit_move_insn (mem, reg);
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- reg, gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM));
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
}
/* Save CR if we use any that must be preserved. */
- if (info->cr_save_p)
+ if (!WORLD_SAVE_P (info) && info->cr_save_p)
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->cr_save_offset + sp_offset));
- rtx mem = gen_rtx_MEM (SImode, addr);
-
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ rtx mem = gen_frame_mem (SImode, addr);
+ /* See the large comment above about why CR2_REGNO is used. */
+ rtx magic_eh_cr_reg = gen_rtx_REG (SImode, CR2_REGNO);
/* If r12 was used to hold the original sp, copy cr into r0 now
that it's free. */
if (REGNO (frame_reg_rtx) == 12)
{
+ rtx set;
+
cr_save_rtx = gen_rtx_REG (SImode, 0);
- emit_insn (gen_movesi_from_cr (cr_save_rtx));
+ insn = emit_insn (gen_movesi_from_cr (cr_save_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ set = gen_rtx_SET (VOIDmode, cr_save_rtx, magic_eh_cr_reg);
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ set,
+ REG_NOTES (insn));
+
}
insn = emit_move_insn (mem, cr_save_rtx);
- /* Now, there's no way that dwarf2out_frame_debug_expr is going
- to understand '(unspec:SI [(reg:CC 68) ...] UNSPEC_MOVESI_FROM_CR)'.
- But that's OK. All we have to do is specify that _one_ condition
- code register is saved in this stack slot. The thrower's epilogue
- will then restore all the call-saved registers.
- We use CR2_REGNO (70) to be compatible with gcc-2.95 on Linux. */
- rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
- cr_save_rtx, gen_rtx_REG (SImode, CR2_REGNO));
+ rs6000_frame_related (insn, frame_ptr_rtx, info->total_size,
+ NULL_RTX, NULL_RTX);
}
- /* Update stack and set back pointer unless this is V.4,
+ /* Update stack and set back pointer unless this is V.4,
for which it was done previously. */
- if (info->push_p
+ if (!WORLD_SAVE_P (info) && info->push_p
&& !(DEFAULT_ABI == ABI_V4 || current_function_calls_eh_return))
rs6000_emit_allocate_stack (info->total_size, FALSE);
/* Set frame pointer, if needed. */
if (frame_pointer_needed)
{
- insn = emit_move_insn (gen_rtx_REG (Pmode, FRAME_POINTER_REGNUM),
+ insn = emit_move_insn (gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM),
sp_reg_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
}
/* If we are using RS6000_PIC_OFFSET_TABLE_REGNUM, we need to set it up. */
if ((TARGET_TOC && TARGET_MINIMAL_TOC && get_pool_size () != 0)
- || (DEFAULT_ABI == ABI_V4 && flag_pic == 1
+ || (DEFAULT_ABI == ABI_V4
+ && (flag_pic == 1 || (flag_pic && TARGET_SECURE_PLT))
&& regs_ever_live[RS6000_PIC_OFFSET_TABLE_REGNUM]))
- {
- /* If emit_load_toc_table will use the link register, we need to save
- it. We use R12 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
- && DEFAULT_ABI != ABI_AIX
- && flag_pic
- && ! info->lr_save_p
- && EXIT_BLOCK_PTR->pred != NULL);
- if (save_LR_around_toc_setup)
- {
- rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
- rs6000_maybe_dead (emit_move_insn (frame_ptr_rtx, lr));
+ {
+ /* If emit_load_toc_table will use the link register, we need to save
+ it. We use R12 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
+ && DEFAULT_ABI != ABI_AIX
+ && flag_pic
+ && ! info->lr_save_p
+ && EDGE_COUNT (EXIT_BLOCK_PTR->preds) > 0);
+ if (save_LR_around_toc_setup)
+ {
+ rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
+
+ insn = emit_move_insn (frame_ptr_rtx, lr);
+ rs6000_maybe_dead (insn);
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ rs6000_emit_load_toc_table (TRUE);
+
+ insn = emit_move_insn (lr, frame_ptr_rtx);
+ rs6000_maybe_dead (insn);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
rs6000_emit_load_toc_table (TRUE);
- rs6000_maybe_dead (emit_move_insn (lr, frame_ptr_rtx));
- }
- else
- rs6000_emit_load_toc_table (TRUE);
- }
+ }
#if TARGET_MACHO
if (DEFAULT_ABI == ABI_DARWIN
&& flag_pic && current_function_uses_pic_offset_table)
{
- rtx dest = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
- const char *picbase = machopic_function_base_name ();
- rtx src = gen_rtx_SYMBOL_REF (Pmode, picbase);
+ rtx lr = gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM);
+ rtx src = machopic_function_base_sym ();
+
+ /* Save and restore LR locally around this call (in R0). */
+ if (!info->lr_save_p)
+ rs6000_maybe_dead (emit_move_insn (gen_rtx_REG (Pmode, 0), lr));
+
+ rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (lr, src)));
- rs6000_maybe_dead (emit_insn (gen_load_macho_picbase (dest, src)));
+ insn = emit_move_insn (gen_rtx_REG (Pmode,
+ RS6000_PIC_OFFSET_TABLE_REGNUM),
+ lr);
+ rs6000_maybe_dead (insn);
- rs6000_maybe_dead (
- emit_move_insn (gen_rtx_REG (Pmode, RS6000_PIC_OFFSET_TABLE_REGNUM),
- gen_rtx_REG (Pmode, LINK_REGISTER_REGNUM)));
+ if (!info->lr_save_p)
+ rs6000_maybe_dead (emit_move_insn (lr, gen_rtx_REG (Pmode, 0)));
}
#endif
}
@@ -12414,7 +14810,7 @@ rs6000_emit_prologue (void)
/* Write function prologue. */
static void
-rs6000_output_function_prologue (FILE *file,
+rs6000_output_function_prologue (FILE *file,
HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
rs6000_stack_t *info = rs6000_stack_info ();
@@ -12466,13 +14862,13 @@ rs6000_output_function_prologue (FILE *file,
if (TARGET_DEBUG_STACK)
debug_rtx_list (get_insns (), 100);
- final (get_insns (), file, FALSE, FALSE);
+ final (get_insns (), file, FALSE);
end_sequence ();
}
rs6000_pic_labelno++;
}
-
+
/* Emit function epilogue as insns.
At present, dwarf2out_frame_debug_expr doesn't understand
@@ -12506,12 +14902,13 @@ rs6000_emit_epilogue (int sibcall)
using_load_multiple = (TARGET_MULTIPLE && ! TARGET_POWERPC64
&& (!TARGET_SPE_ABI
|| info->spe_64bit_regs_used == 0)
- && info->first_gp_reg_save < 31);
+ && info->first_gp_reg_save < 31
+ && no_global_regs_above (info->first_gp_reg_save));
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
+ use_backchain_to_restore_sp = (frame_pointer_needed
|| current_function_calls_alloca
|| info->total_size > 32767);
using_mfcr_multiple = (rs6000_cpu == PROCESSOR_PPC601
@@ -12519,6 +14916,97 @@ rs6000_emit_epilogue (int sibcall)
|| rs6000_cpu == PROCESSOR_PPC750
|| optimize_size);
+ if (WORLD_SAVE_P (info))
+ {
+ int i, j;
+ char rname[30];
+ const char *alloc_rname;
+ rtvec p;
+
+ /* eh_rest_world_r10 will return to the location saved in the LR
+ stack slot (which is not likely to be our caller.)
+ Input: R10 -- stack adjustment. Clobbers R0, R11, R12, R7, R8.
+ rest_world is similar, except any R10 parameter is ignored.
+ The exception-handling stuff that was here in 2.95 is no
+ longer necessary. */
+
+ p = rtvec_alloc (9
+ + 1
+ + 32 - info->first_gp_reg_save
+ + LAST_ALTIVEC_REGNO + 1 - info->first_altivec_reg_save
+ + 63 + 1 - info->first_fp_reg_save);
+
+ strcpy (rname, ((current_function_calls_eh_return) ?
+ "*eh_rest_world_r10" : "*rest_world"));
+ alloc_rname = ggc_strdup (rname);
+
+ j = 0;
+ RTVEC_ELT (p, j++) = gen_rtx_RETURN (VOIDmode);
+ RTVEC_ELT (p, j++) = gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode,
+ LINK_REGISTER_REGNUM));
+ RTVEC_ELT (p, j++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_SYMBOL_REF (Pmode, alloc_rname));
+ /* The instruction pattern requires a clobber here;
+ it is shared with the restVEC helper. */
+ RTVEC_ELT (p, j++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 11));
+
+ {
+ /* CR register traditionally saved as CR2. */
+ rtx reg = gen_rtx_REG (reg_mode, CR2_REGNO);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->cr_save_offset));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ }
+
+ for (i = 0; i < 32 - info->first_gp_reg_save; i++)
+ {
+ rtx reg = gen_rtx_REG (reg_mode, info->first_gp_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + reg_size * i));
+ rtx mem = gen_frame_mem (reg_mode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ }
+ for (i = 0; info->first_altivec_reg_save + i <= LAST_ALTIVEC_REGNO; i++)
+ {
+ rtx reg = gen_rtx_REG (V4SImode, info->first_altivec_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->altivec_save_offset
+ + 16 * i));
+ rtx mem = gen_frame_mem (V4SImode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ }
+ for (i = 0; info->first_fp_reg_save + i <= 63; i++)
+ {
+ rtx reg = gen_rtx_REG (DFmode, info->first_fp_reg_save + i);
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->fp_save_offset
+ + 8 * i));
+ rtx mem = gen_frame_mem (DFmode, addr);
+
+ RTVEC_ELT (p, j++) = gen_rtx_SET (VOIDmode, reg, mem);
+ }
+ RTVEC_ELT (p, j++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 0));
+ RTVEC_ELT (p, j++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 12));
+ RTVEC_ELT (p, j++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 7));
+ RTVEC_ELT (p, j++)
+ = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, 8));
+ RTVEC_ELT (p, j++)
+ = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, 10));
+ emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ return;
+ }
+
/* If we have a frame pointer, a call to alloca, or a large stack
frame, restore the old stack pointer using the backchain. Otherwise,
we know what size to update it with. */
@@ -12531,7 +15019,6 @@ rs6000_emit_epilogue (int sibcall)
emit_move_insn (frame_reg_rtx,
gen_rtx_MEM (Pmode, sp_reg_rtx));
-
}
else if (info->push_p)
{
@@ -12547,7 +15034,7 @@ rs6000_emit_epilogue (int sibcall)
GEN_INT (info->total_size)));
}
}
-
+
/* Restore AltiVec registers if needed. */
if (TARGET_ALTIVEC_ABI && info->altivec_size != 0)
{
@@ -12566,8 +15053,7 @@ rs6000_emit_epilogue (int sibcall)
/* AltiVec addressing mode is [reg+reg]. */
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, areg);
- mem = gen_rtx_MEM (V4SImode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (V4SImode, addr);
emit_move_insn (gen_rtx_REG (V4SImode, i), mem);
}
@@ -12581,8 +15067,7 @@ rs6000_emit_epilogue (int sibcall)
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->vrsave_save_offset + sp_offset));
- mem = gen_rtx_MEM (SImode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (SImode, addr);
reg = gen_rtx_REG (SImode, 12);
emit_move_insn (reg, mem);
@@ -12595,28 +15080,24 @@ rs6000_emit_epilogue (int sibcall)
rtx mem = gen_frame_mem_offset (Pmode, frame_reg_rtx,
info->lr_save_offset + sp_offset);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
-
emit_move_insn (gen_rtx_REG (Pmode, 0), mem);
}
-
+
/* Get the old cr if we saved it. */
if (info->cr_save_p)
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (info->cr_save_offset + sp_offset));
- rtx mem = gen_rtx_MEM (SImode, addr);
-
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ rtx mem = gen_frame_mem (SImode, addr);
emit_move_insn (gen_rtx_REG (SImode, 12), mem);
}
-
+
/* Set LR here to try to overlap restores below. */
if (info->lr_save_p)
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)
{
@@ -12626,9 +15107,7 @@ rs6000_emit_epilogue (int sibcall)
{
rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
GEN_INT (sp_offset + 5 * reg_size));
- rtx mem = gen_rtx_MEM (reg_mode, addr);
-
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ rtx mem = gen_frame_mem (reg_mode, addr);
emit_move_insn (gen_rtx_REG (reg_mode, 2), mem);
}
@@ -12644,12 +15123,11 @@ rs6000_emit_epilogue (int sibcall)
mem = gen_frame_mem_offset (reg_mode, frame_reg_rtx,
info->ehrd_offset + sp_offset
+ reg_size * (int) i);
- set_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. */
if (using_load_multiple)
@@ -12658,15 +15136,13 @@ rs6000_emit_epilogue (int sibcall)
p = rtvec_alloc (32 - info->first_gp_reg_save);
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
{
- rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->gp_save_offset
- + sp_offset
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset
+ reg_size * i));
- rtx mem = gen_rtx_MEM (reg_mode, addr);
-
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ rtx mem = gen_frame_mem (reg_mode, addr);
- RTVEC_ELT (p, i) =
+ RTVEC_ELT (p, i) =
gen_rtx_SET (VOIDmode,
gen_rtx_REG (reg_mode, info->first_gp_reg_save + i),
mem);
@@ -12675,19 +15151,19 @@ rs6000_emit_epilogue (int sibcall)
}
else
for (i = 0; i < 32 - info->first_gp_reg_save; i++)
- if ((regs_ever_live[info->first_gp_reg_save+i]
- && (! call_used_regs[info->first_gp_reg_save+i]
- || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
+ if ((regs_ever_live[info->first_gp_reg_save + i]
+ && (!call_used_regs[info->first_gp_reg_save + i]
+ || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& TARGET_TOC && TARGET_MINIMAL_TOC)))
- || (i+info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
+ || (i + info->first_gp_reg_save == RS6000_PIC_OFFSET_TABLE_REGNUM
&& ((DEFAULT_ABI == ABI_V4 && flag_pic != 0)
|| (DEFAULT_ABI == ABI_DARWIN && flag_pic))))
{
- rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->gp_save_offset
- + sp_offset
+ rtx addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
+ GEN_INT (info->gp_save_offset
+ + sp_offset
+ reg_size * i));
- rtx mem = gen_rtx_MEM (reg_mode, addr);
+ rtx mem = gen_frame_mem (reg_mode, addr);
/* Restore 64-bit quantities for SPE. */
if (TARGET_SPE_ABI && info->spe_64bit_regs_used != 0)
@@ -12704,30 +15180,27 @@ rs6000_emit_epilogue (int sibcall)
b = GEN_INT (offset);
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx, b);
- mem = gen_rtx_MEM (V2SImode, addr);
+ mem = gen_frame_mem (V2SImode, addr);
}
- set_mem_alias_set (mem, rs6000_sr_alias_set);
-
- emit_move_insn (gen_rtx_REG (reg_mode,
+ emit_move_insn (gen_rtx_REG (reg_mode,
info->first_gp_reg_save + i), mem);
}
/* Restore fpr's if we need to do it without calling a function. */
if (restoring_FPRs_inline)
for (i = 0; i < 64 - info->first_fp_reg_save; i++)
- if ((regs_ever_live[info->first_fp_reg_save+i]
+ if ((regs_ever_live[info->first_fp_reg_save+i]
&& ! call_used_regs[info->first_fp_reg_save+i]))
{
rtx addr, mem;
addr = gen_rtx_PLUS (Pmode, frame_reg_rtx,
- GEN_INT (info->fp_save_offset
- + sp_offset
+ GEN_INT (info->fp_save_offset
+ + sp_offset
+ 8 * i));
- mem = gen_rtx_MEM (DFmode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (DFmode, addr);
- emit_move_insn (gen_rtx_REG (DFmode,
+ emit_move_insn (gen_rtx_REG (DFmode,
info->first_fp_reg_save + i),
mem);
}
@@ -12737,21 +15210,20 @@ rs6000_emit_epilogue (int sibcall)
{
rtx r12_rtx = gen_rtx_REG (SImode, 12);
int count = 0;
-
+
if (using_mfcr_multiple)
{
for (i = 0; i < 8; i++)
if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
count++;
- if (count == 0)
- abort ();
+ gcc_assert (count);
}
if (using_mfcr_multiple && count > 1)
{
rtvec p;
int ndx;
-
+
p = rtvec_alloc (count);
ndx = 0;
@@ -12762,49 +15234,38 @@ rs6000_emit_epilogue (int sibcall)
RTVEC_ELT (r, 0) = r12_rtx;
RTVEC_ELT (r, 1) = GEN_INT (1 << (7-i));
RTVEC_ELT (p, ndx) =
- gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
+ gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CR0_REGNO+i),
gen_rtx_UNSPEC (CCmode, r, UNSPEC_MOVESI_TO_CR));
ndx++;
}
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
- if (ndx != count)
- abort ();
+ gcc_assert (ndx == count);
}
else
for (i = 0; i < 8; i++)
if (regs_ever_live[CR0_REGNO+i] && ! call_used_regs[CR0_REGNO+i])
{
- emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode,
+ emit_insn (gen_movsi_to_cr_one (gen_rtx_REG (CCmode,
CR0_REGNO+i),
r12_rtx));
}
}
/* If this is V.4, unwind the stack pointer after all of the loads
- have been done. We need to emit a block here so that sched
- doesn't decide to move the sp change before the register restores
- (which may not have any obvious dependency on the stack). This
- doesn't hurt performance, because there is no scheduling that can
- be done after this point. */
- if (DEFAULT_ABI == ABI_V4
- || current_function_calls_eh_return)
+ have been done. */
+ if (frame_reg_rtx != sp_reg_rtx)
{
- if (frame_reg_rtx != sp_reg_rtx)
- rs6000_emit_stack_tie ();
-
- if (use_backchain_to_restore_sp)
- {
- emit_move_insn (sp_reg_rtx, frame_reg_rtx);
- }
- else if (sp_offset != 0)
- {
- emit_insn (TARGET_32BIT
- ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
- GEN_INT (sp_offset))
- : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
- GEN_INT (sp_offset)));
- }
+ /* This blockage is needed so that sched doesn't decide to move
+ the sp change before the register restores. */
+ rs6000_emit_stack_tie ();
+ emit_move_insn (sp_reg_rtx, frame_reg_rtx);
}
+ else if (sp_offset != 0)
+ emit_insn (TARGET_32BIT
+ ? gen_addsi3 (sp_reg_rtx, sp_reg_rtx,
+ GEN_INT (sp_offset))
+ : gen_adddi3 (sp_reg_rtx, sp_reg_rtx,
+ GEN_INT (sp_offset)));
if (current_function_calls_eh_return)
{
@@ -12823,8 +15284,8 @@ rs6000_emit_epilogue (int sibcall)
p = rtvec_alloc (2);
RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
- RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
- gen_rtx_REG (Pmode,
+ RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode,
+ gen_rtx_REG (Pmode,
LINK_REGISTER_REGNUM));
/* If we have to restore more than two FP registers, branch to the
@@ -12835,7 +15296,7 @@ rs6000_emit_epilogue (int sibcall)
char rname[30];
const char *alloc_rname;
- sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
+ sprintf (rname, "%s%d%s", RESTORE_FP_PREFIX,
info->first_fp_reg_save - 32, RESTORE_FP_SUFFIX);
alloc_rname = ggc_strdup (rname);
RTVEC_ELT (p, 2) = gen_rtx_USE (VOIDmode,
@@ -12847,16 +15308,15 @@ rs6000_emit_epilogue (int sibcall)
rtx addr, mem;
addr = gen_rtx_PLUS (Pmode, sp_reg_rtx,
GEN_INT (info->fp_save_offset + 8*i));
- mem = gen_rtx_MEM (DFmode, addr);
- set_mem_alias_set (mem, rs6000_sr_alias_set);
+ mem = gen_frame_mem (DFmode, addr);
- RTVEC_ELT (p, i+3) =
+ RTVEC_ELT (p, i+3) =
gen_rtx_SET (VOIDmode,
gen_rtx_REG (DFmode, info->first_fp_reg_save + i),
mem);
}
}
-
+
emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
}
}
@@ -12864,11 +15324,9 @@ rs6000_emit_epilogue (int sibcall)
/* Write function epilogue. */
static void
-rs6000_output_function_epilogue (FILE *file,
+rs6000_output_function_epilogue (FILE *file,
HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
- rs6000_stack_t *info = rs6000_stack_info ();
-
if (! HAVE_epilogue)
{
rtx insn = get_last_insn ();
@@ -12901,7 +15359,7 @@ rs6000_output_function_epilogue (FILE *file,
if (TARGET_DEBUG_STACK)
debug_rtx_list (get_insns (), 100);
- final (get_insns (), file, FALSE, FALSE);
+ final (get_insns (), file, FALSE);
end_sequence ();
}
}
@@ -12916,8 +15374,8 @@ rs6000_output_function_epilogue (FILE *file,
&& NOTE_P (insn)
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED_LABEL)
insn = PREV_INSN (insn);
- if (insn
- && (LABEL_P (insn)
+ if (insn
+ && (LABEL_P (insn)
|| (NOTE_P (insn)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))
fputs ("\tnop\n", file);
@@ -12939,13 +15397,14 @@ rs6000_output_function_epilogue (FILE *file,
System V.4 Powerpc's (and the embedded ABI derived from it) use a
different traceback table. */
if (DEFAULT_ABI == ABI_AIX && ! flag_inhibit_size_directive
- && rs6000_traceback != traceback_none)
+ && rs6000_traceback != traceback_none && !current_function_is_thunk)
{
const char *fname = NULL;
const char *language_string = lang_hooks.name;
int fixed_parms = 0, float_parms = 0, parm_info = 0;
int i;
int optional_tbtab;
+ rs6000_stack_t *info = rs6000_stack_info ();
if (rs6000_traceback == traceback_full)
optional_tbtab = 1;
@@ -12986,23 +15445,26 @@ rs6000_output_function_epilogue (FILE *file,
official way to discover the language being compiled, so we
use language_string.
C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9.
- Java is 13. Objective-C is 14. */
+ Java is 13. Objective-C is 14. Objective-C++ isn't assigned
+ a number, so for now use 9. */
if (! strcmp (language_string, "GNU C"))
i = 0;
- else if (! strcmp (language_string, "GNU F77"))
+ else if (! strcmp (language_string, "GNU F77")
+ || ! strcmp (language_string, "GNU F95"))
i = 1;
else if (! strcmp (language_string, "GNU Pascal"))
i = 2;
else if (! strcmp (language_string, "GNU Ada"))
i = 3;
- else if (! strcmp (language_string, "GNU C++"))
+ else if (! strcmp (language_string, "GNU C++")
+ || ! strcmp (language_string, "GNU Objective-C++"))
i = 9;
else if (! strcmp (language_string, "GNU Java"))
i = 13;
else if (! strcmp (language_string, "GNU Objective-C"))
i = 14;
else
- abort ();
+ gcc_unreachable ();
fprintf (file, "%d,", i);
/* 8 single bit fields: global linkage (not set for C extern linkage,
@@ -13049,18 +15511,26 @@ rs6000_output_function_epilogue (FILE *file,
if (GET_CODE (parameter) == REG)
{
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if (SCALAR_FLOAT_MODE_P (mode))
{
int bits;
float_parms++;
- if (mode == SFmode)
- bits = 0x2;
- else if (mode == DFmode || mode == TFmode)
- bits = 0x3;
- else
- abort ();
+ switch (mode)
+ {
+ case SFmode:
+ bits = 0x2;
+ break;
+
+ case DFmode:
+ case TFmode:
+ bits = 0x3;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
/* If only one bit will fit, don't or in this entry. */
if (next_parm_info_bit > 0)
@@ -13110,17 +15580,12 @@ rs6000_output_function_epilogue (FILE *file,
/* Offset from start of code to tb table. */
fputs ("\t.long ", file);
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LT");
-#if TARGET_AIX
- RS6000_OUTPUT_BASENAME (file, fname);
-#else
- assemble_name (file, fname);
-#endif
- fputs ("-.", file);
-#if TARGET_AIX
- RS6000_OUTPUT_BASENAME (file, fname);
-#else
- assemble_name (file, fname);
-#endif
+ if (TARGET_AIX)
+ RS6000_OUTPUT_BASENAME (file, fname);
+ else
+ assemble_name (file, fname);
+ putc ('-', file);
+ rs6000_output_function_entry (file, fname);
putc ('\n', file);
/* Interrupt handler mask. */
@@ -13183,8 +15648,8 @@ rs6000_output_function_epilogue (FILE *file,
not support varargs. */
static void
-rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
- HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
+rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
+ HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
tree function)
{
rtx this, insn, funexp;
@@ -13192,6 +15657,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
reload_completed = 1;
epilogue_completed = 1;
no_new_pseudos = 1;
+ reset_block_changes ();
/* Mark the end of the (empty) prologue. */
emit_note (NOTE_INSN_PROLOGUE_END);
@@ -13252,7 +15718,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
#endif
/* gen_sibcall expects reload to convert scratch pseudo to LR so we must
- generate sibcall RTL explicitly to avoid constraint abort. */
+ generate sibcall RTL explicitly. */
insn = emit_call_insn (
gen_rtx_PARALLEL (VOIDmode,
gen_rtvec (4,
@@ -13274,7 +15740,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
insn_locators_initialize ();
shorten_branches (insn);
final_start_function (insn, file, 1);
- final (insn, file, 1, 0);
+ final (insn, file, 1);
final_end_function ();
reload_completed = 0;
@@ -13285,7 +15751,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* A quick summary of the various types of 'constant-pool tables'
under PowerPC:
- Target Flags Name One table per
+ Target Flags Name One table per
AIX (none) AIX TOC object file
AIX -mfull-toc AIX TOC object file
AIX -mminimal-toc AIX minimal TOC translation unit
@@ -13294,7 +15760,7 @@ rs6000_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
SVR4/EABI -fPIC SVR4 PIC translation unit
SVR4/EABI -mrelocatable EABI TOC function
SVR4/EABI -maix AIX TOC object file
- SVR4/EABI -maix -mminimal-toc
+ SVR4/EABI -maix -mminimal-toc
AIX minimal TOC translation unit
Name Reg. Set by entries contains:
@@ -13319,7 +15785,7 @@ rs6000_hash_constant (rtx k)
unsigned result = (code << 3) ^ mode;
const char *format;
int flen, fidx;
-
+
format = GET_RTX_FORMAT (code);
flen = strlen (format);
fidx = 0;
@@ -13370,7 +15836,7 @@ rs6000_hash_constant (rtx k)
else
{
size_t i;
- for (i = 0; i < sizeof(HOST_WIDE_INT)/sizeof(unsigned); i++)
+ for (i = 0; i < sizeof (HOST_WIDE_INT) / sizeof (unsigned); i++)
result = result * 613 + (unsigned) (XWINT (k, fidx)
>> CHAR_BIT * i);
}
@@ -13378,7 +15844,7 @@ rs6000_hash_constant (rtx k)
case '0':
break;
default:
- abort ();
+ gcc_unreachable ();
}
return result;
@@ -13387,7 +15853,7 @@ rs6000_hash_constant (rtx k)
static unsigned
toc_hash_function (const void *hash_entry)
{
- const struct toc_hash_struct *thc =
+ const struct toc_hash_struct *thc =
(const struct toc_hash_struct *) hash_entry;
return rs6000_hash_constant (thc->key) ^ thc->key_mode;
}
@@ -13413,11 +15879,11 @@ toc_hash_eq (const void *h1, const void *h2)
to whether or not an object is a vtable. */
#define VTABLE_NAME_P(NAME) \
- (strncmp ("_vt.", name, strlen("_vt.")) == 0 \
+ (strncmp ("_vt.", name, strlen ("_vt.")) == 0 \
|| strncmp ("_ZTV", name, strlen ("_ZTV")) == 0 \
|| strncmp ("_ZTT", name, strlen ("_ZTT")) == 0 \
|| strncmp ("_ZTI", name, strlen ("_ZTI")) == 0 \
- || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
+ || strncmp ("_ZTC", name, strlen ("_ZTC")) == 0)
void
rs6000_output_symbol_ref (FILE *file, rtx x)
@@ -13425,12 +15891,12 @@ rs6000_output_symbol_ref (FILE *file, rtx x)
/* Currently C++ toc references to vtables can be emitted before it
is decided whether the vtable is public or private. If this is
the case, then the linker will eventually complain that there is
- a reference to an unknown section. Thus, for vtables only,
+ a reference to an unknown section. Thus, for vtables only,
we emit the TOC reference to reference the symbol and not the
section. */
const char *name = XSTR (x, 0);
- if (VTABLE_NAME_P (name))
+ if (VTABLE_NAME_P (name))
{
RS6000_OUTPUT_BASENAME (file, name);
}
@@ -13448,10 +15914,9 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
const char *name = buf;
const char *real_name;
rtx base = x;
- int offset = 0;
+ HOST_WIDE_INT offset = 0;
- if (TARGET_NO_TOC)
- abort ();
+ gcc_assert (!TARGET_NO_TOC);
/* When the linker won't eliminate them, don't output duplicate
TOC entries (this happens on AIX if there is any kind of TOC,
@@ -13461,29 +15926,29 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
{
struct toc_hash_struct *h;
void * * found;
-
+
/* Create toc_hash_table. This can't be done at OVERRIDE_OPTIONS
- time because GGC is not initialized at that point. */
+ time because GGC is not initialized at that point. */
if (toc_hash_table == NULL)
- toc_hash_table = htab_create_ggc (1021, toc_hash_function,
+ toc_hash_table = htab_create_ggc (1021, toc_hash_function,
toc_hash_eq, NULL);
h = ggc_alloc (sizeof (*h));
h->key = x;
h->key_mode = mode;
h->labelno = labelno;
-
+
found = htab_find_slot (toc_hash_table, h, 1);
if (*found == NULL)
*found = h;
- else /* This is indeed a duplicate.
+ else /* This is indeed a duplicate.
Set this label equal to that label. */
{
fputs ("\t.set ", file);
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
fprintf (file, "%d,", labelno);
ASM_OUTPUT_INTERNAL_LABEL_PREFIX (file, "LC");
- fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
+ fprintf (file, "%d\n", ((*(const struct toc_hash_struct **)
found)->labelno));
return;
}
@@ -13503,13 +15968,17 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
/* Handle FP constants specially. Note that if we have a minimal
TOC, things we put here aren't actually in the TOC, so we can allow
FP constants. */
- if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == TFmode)
+ if (GET_CODE (x) == CONST_DOUBLE &&
+ (GET_MODE (x) == TFmode || GET_MODE (x) == TDmode))
{
REAL_VALUE_TYPE rv;
long k[4];
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
+ if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
+ REAL_VALUE_TO_TARGET_DECIMAL128 (rv, k);
+ else
+ REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, k);
if (TARGET_64BIT)
{
@@ -13538,13 +16007,18 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
return;
}
}
- else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == DFmode)
+ else if (GET_CODE (x) == CONST_DOUBLE &&
+ (GET_MODE (x) == DFmode || GET_MODE (x) == DDmode))
{
REAL_VALUE_TYPE rv;
long k[2];
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
+
+ if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
+ REAL_VALUE_TO_TARGET_DECIMAL64 (rv, k);
+ else
+ REAL_VALUE_TO_TARGET_DOUBLE (rv, k);
if (TARGET_64BIT)
{
@@ -13569,13 +16043,17 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
return;
}
}
- else if (GET_CODE (x) == CONST_DOUBLE && GET_MODE (x) == SFmode)
+ else if (GET_CODE (x) == CONST_DOUBLE &&
+ (GET_MODE (x) == SFmode || GET_MODE (x) == SDmode))
{
REAL_VALUE_TYPE rv;
long l;
REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- REAL_VALUE_TO_TARGET_SINGLE (rv, l);
+ if (DECIMAL_FLOAT_MODE_P (GET_MODE (x)))
+ REAL_VALUE_TO_TARGET_DECIMAL32 (rv, l);
+ else
+ REAL_VALUE_TO_TARGET_SINGLE (rv, l);
if (TARGET_64BIT)
{
@@ -13615,8 +16093,8 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
}
#else
{
- low = INTVAL (x) & 0xffffffff;
- high = (HOST_WIDE_INT) INTVAL (x) >> 32;
+ low = INTVAL (x) & 0xffffffff;
+ high = (HOST_WIDE_INT) INTVAL (x) >> 32;
}
#endif
@@ -13630,8 +16108,8 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
For a 32-bit target, CONST_INT values are loaded and shifted
entirely within `low' and can be stored in one TOC entry. */
- if (TARGET_64BIT && POINTER_SIZE < GET_MODE_BITSIZE (mode))
- abort ();/* It would be easy to make this work, but it doesn't now. */
+ /* It would be easy to make this work, but it doesn't now. */
+ gcc_assert (!TARGET_64BIT || POINTER_SIZE >= GET_MODE_BITSIZE (mode));
if (POINTER_SIZE > GET_MODE_BITSIZE (mode))
{
@@ -13683,21 +16161,30 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
if (GET_CODE (x) == CONST)
{
- if (GET_CODE (XEXP (x, 0)) != PLUS)
- abort ();
+ gcc_assert (GET_CODE (XEXP (x, 0)) == PLUS);
base = XEXP (XEXP (x, 0), 0);
offset = INTVAL (XEXP (XEXP (x, 0), 1));
}
-
- if (GET_CODE (base) == SYMBOL_REF)
- name = XSTR (base, 0);
- else if (GET_CODE (base) == LABEL_REF)
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (base, 0)));
- else if (GET_CODE (base) == CODE_LABEL)
- ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));
- else
- abort ();
+
+ switch (GET_CODE (base))
+ {
+ case SYMBOL_REF:
+ name = XSTR (base, 0);
+ break;
+
+ case LABEL_REF:
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L",
+ CODE_LABEL_NUMBER (XEXP (base, 0)));
+ break;
+
+ case CODE_LABEL:
+ ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (base));
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
real_name = (*targetm.strip_name_encoding) (name);
if (TARGET_MINIMAL_TOC)
@@ -13707,9 +16194,9 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
fprintf (file, "\t.tc %s", real_name);
if (offset < 0)
- fprintf (file, ".N%d", - offset);
+ fprintf (file, ".N" HOST_WIDE_INT_PRINT_UNSIGNED, - offset);
else if (offset)
- fprintf (file, ".P%d", offset);
+ fprintf (file, ".P" HOST_WIDE_INT_PRINT_UNSIGNED, offset);
fputs ("[TC],", file);
}
@@ -13724,9 +16211,9 @@ output_toc (FILE *file, rtx x, int labelno, enum machine_mode mode)
{
RS6000_OUTPUT_BASENAME (file, name);
if (offset < 0)
- fprintf (file, "%d", offset);
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset);
else if (offset > 0)
- fprintf (file, "+%d", offset);
+ fprintf (file, "+" HOST_WIDE_INT_PRINT_DEC, offset);
}
else
output_addr_const (file, x);
@@ -13813,8 +16300,8 @@ output_ascii (FILE *file, const char *p, int n)
the name. */
void
-rs6000_gen_section_name (char **buf, const char *filename,
- const char *section_desc)
+rs6000_gen_section_name (char **buf, const char *filename,
+ const char *section_desc)
{
const char *q, *after_last_slash, *last_period = 0;
char *p;
@@ -13838,14 +16325,14 @@ rs6000_gen_section_name (char **buf, const char *filename,
for (q = after_last_slash; *q; q++)
{
if (q == last_period)
- {
+ {
strcpy (p, section_desc);
p += strlen (section_desc);
break;
- }
+ }
else if (ISALNUM (*q))
- *p++ = *q;
+ *p++ = *q;
}
if (last_period == 0)
@@ -13859,6 +16346,10 @@ rs6000_gen_section_name (char **buf, const char *filename,
void
output_profile_hook (int labelno ATTRIBUTE_UNUSED)
{
+ /* Non-standard profiling for kernels, which just saves LR then calls
+ _mcount without worrying about arg saves. The idea is to change
+ the function prologue as little as possible as it isn't easy to
+ account for arg save/restore code added just for _mcount. */
if (TARGET_PROFILE_KERNEL)
return;
@@ -13867,7 +16358,7 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED)
#ifndef NO_PROFILE_COUNTERS
# define NO_PROFILE_COUNTERS 0
#endif
- if (NO_PROFILE_COUNTERS)
+ if (NO_PROFILE_COUNTERS)
emit_library_call (init_one_libfunc (RS6000_MCOUNT), 0, VOIDmode, 0);
else
{
@@ -13894,12 +16385,9 @@ output_profile_hook (int labelno ATTRIBUTE_UNUSED)
#if TARGET_MACHO
/* For PIC code, set up a stub and collect the caller's address
from r0, which is where the prologue puts it. */
- if (MACHOPIC_INDIRECT)
- {
- mcount_name = machopic_stub_name (mcount_name);
- if (current_function_uses_pic_offset_table)
- caller_addr_regno = 0;
- }
+ if (MACHOPIC_INDIRECT
+ && current_function_uses_pic_offset_table)
+ caller_addr_regno = 0;
#endif
emit_library_call (gen_rtx_SYMBOL_REF (Pmode, mcount_name),
0, VOIDmode, 1,
@@ -13913,27 +16401,42 @@ void
output_function_profiler (FILE *file, int labelno)
{
char buf[100];
- int save_lr = 8;
switch (DEFAULT_ABI)
{
default:
- abort ();
+ gcc_unreachable ();
case ABI_V4:
- save_lr = 4;
if (!TARGET_32BIT)
{
- warning ("no profiling of 64-bit code for this ABI");
+ warning (0, "no profiling of 64-bit code for this ABI");
return;
}
ASM_GENERATE_INTERNAL_LABEL (buf, "LP", labelno);
fprintf (file, "\tmflr %s\n", reg_names[0]);
- if (flag_pic == 1)
+ if (NO_PROFILE_COUNTERS)
+ {
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
+ reg_names[0], reg_names[1]);
+ }
+ else if (TARGET_SECURE_PLT && flag_pic)
+ {
+ asm_fprintf (file, "\tbcl 20,31,1f\n1:\n\t{st|stw} %s,4(%s)\n",
+ reg_names[0], reg_names[1]);
+ asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
+ asm_fprintf (file, "\t{cau|addis} %s,%s,",
+ reg_names[12], reg_names[12]);
+ assemble_name (file, buf);
+ asm_fprintf (file, "-1b@ha\n\t{cal|la} %s,", reg_names[0]);
+ assemble_name (file, buf);
+ asm_fprintf (file, "-1b@l(%s)\n", reg_names[12]);
+ }
+ else if (flag_pic == 1)
{
fputs ("\tbl _GLOBAL_OFFSET_TABLE_@local-4\n", file);
- asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
- reg_names[0], save_lr, reg_names[1]);
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
+ reg_names[0], reg_names[1]);
asm_fprintf (file, "\tmflr %s\n", reg_names[12]);
asm_fprintf (file, "\t{l|lwz} %s,", reg_names[0]);
assemble_name (file, buf);
@@ -13941,14 +16444,14 @@ output_function_profiler (FILE *file, int labelno)
}
else if (flag_pic > 1)
{
- asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
- reg_names[0], save_lr, reg_names[1]);
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
+ reg_names[0], reg_names[1]);
/* Now, we need to get the address of the label. */
- fputs ("\tbl 1f\n\t.long ", file);
+ fputs ("\tbcl 20,31,1f\n\t.long ", file);
assemble_name (file, buf);
fputs ("-.\n1:", file);
asm_fprintf (file, "\tmflr %s\n", reg_names[11]);
- asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
+ asm_fprintf (file, "\t{l|lwz} %s,0(%s)\n",
reg_names[0], reg_names[11]);
asm_fprintf (file, "\t{cax|add} %s,%s,%s\n",
reg_names[0], reg_names[0], reg_names[11]);
@@ -13958,8 +16461,8 @@ output_function_profiler (FILE *file, int labelno)
asm_fprintf (file, "\t{liu|lis} %s,", reg_names[12]);
assemble_name (file, buf);
fputs ("@ha\n", file);
- asm_fprintf (file, "\t{st|stw} %s,%d(%s)\n",
- reg_names[0], save_lr, reg_names[1]);
+ asm_fprintf (file, "\t{st|stw} %s,4(%s)\n",
+ reg_names[0], reg_names[1]);
asm_fprintf (file, "\t{cal|la} %s,", reg_names[0]);
assemble_name (file, buf);
asm_fprintf (file, "@l(%s)\n", reg_names[12]);
@@ -13968,7 +16471,6 @@ output_function_profiler (FILE *file, int labelno)
/* ABI_V4 saves the static chain reg with ASM_OUTPUT_REG_PUSH. */
fprintf (file, "\tbl %s%s\n",
RS6000_MCOUNT, flag_pic ? "@plt" : "");
-
break;
case ABI_AIX:
@@ -13979,13 +16481,12 @@ output_function_profiler (FILE *file, int labelno)
}
else
{
- if (TARGET_32BIT)
- abort ();
+ gcc_assert (!TARGET_32BIT);
asm_fprintf (file, "\tmflr %s\n", reg_names[0]);
asm_fprintf (file, "\tstd %s,16(%s)\n", reg_names[0], reg_names[1]);
- if (current_function_needs_context)
+ if (cfun->static_chain_decl != NULL)
{
asm_fprintf (file, "\tstd %s,24(%s)\n",
reg_names[STATIC_CHAIN_REGNUM], reg_names[1]);
@@ -14001,12 +16502,6 @@ output_function_profiler (FILE *file, int labelno)
}
-static int
-rs6000_use_dfa_pipeline_interface (void)
-{
- return 1;
-}
-
/* Power4 load update and store update instructions are cracked into a
load or store and an integer insn which are executed in the same cycle.
Branches have their own dispatch slot which does not count against the
@@ -14014,8 +16509,8 @@ rs6000_use_dfa_pipeline_interface (void)
instructions to issue in this cycle. */
static int
-rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
- int verbose ATTRIBUTE_UNUSED,
+rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
+ int verbose ATTRIBUTE_UNUSED,
rtx insn, int more)
{
if (GET_CODE (PATTERN (insn)) == USE
@@ -14025,9 +16520,9 @@ rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
if (rs6000_sched_groups)
{
if (is_microcoded_insn (insn))
- return 0;
+ return 0;
else if (is_cracked_insn (insn))
- return more > 2 ? more - 2 : 0;
+ return more > 2 ? more - 2 : 0;
}
return more - 1;
@@ -14037,8 +16532,7 @@ rs6000_variable_issue (FILE *stream ATTRIBUTE_UNUSED,
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
static int
-rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn ATTRIBUTE_UNUSED,
- int cost)
+rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
{
if (! recog_memoized (insn))
return 0;
@@ -14050,6 +16544,17 @@ rs6000_adjust_cost (rtx insn, rtx link, rtx dep_insn ATTRIBUTE_UNUSED,
{
/* Data dependency; DEP_INSN writes a register that INSN reads
some cycles later. */
+
+ /* Separate a load from a narrower, dependent store. */
+ if (rs6000_sched_groups
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (PATTERN (dep_insn)) == SET
+ && GET_CODE (XEXP (PATTERN (insn), 1)) == MEM
+ && GET_CODE (XEXP (PATTERN (dep_insn), 0)) == MEM
+ && (GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (insn), 1)))
+ > GET_MODE_SIZE (GET_MODE (XEXP (PATTERN (dep_insn), 0)))))
+ return cost + 14;
+
switch (get_attr_type (insn))
{
case TYPE_JMPREG:
@@ -14111,7 +16616,7 @@ is_microcoded_insn (rtx insn)
|| type == TYPE_LOAD_UX
|| type == TYPE_STORE_UX
|| type == TYPE_MFCR)
- return true;
+ return true;
}
return false;
@@ -14153,6 +16658,11 @@ is_dispatch_slot_restricted (rtx insn)
case TYPE_IDIV:
case TYPE_LDIV:
return 2;
+ case TYPE_LOAD_L:
+ case TYPE_STORE_C:
+ case TYPE_ISYNC:
+ case TYPE_SYNC:
+ return 4;
default:
if (rs6000_cpu == PROCESSOR_POWER5
&& is_cracked_insn (insn))
@@ -14176,14 +16686,14 @@ is_cracked_insn (rtx insn)
{
enum attr_type type = get_attr_type (insn);
if (type == TYPE_LOAD_U || type == TYPE_STORE_U
- || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
- || type == TYPE_FPLOAD_UX || type == TYPE_FPSTORE_UX
- || type == TYPE_LOAD_EXT || type == TYPE_DELAYED_CR
- || type == TYPE_COMPARE || type == TYPE_DELAYED_COMPARE
- || type == TYPE_IMUL_COMPARE || type == TYPE_LMUL_COMPARE
- || type == TYPE_IDIV || type == TYPE_LDIV
- || type == TYPE_INSERT_WORD)
- return true;
+ || type == TYPE_FPLOAD_U || type == TYPE_FPSTORE_U
+ || type == TYPE_FPLOAD_UX || type == TYPE_FPSTORE_UX
+ || type == TYPE_LOAD_EXT || type == TYPE_DELAYED_CR
+ || type == TYPE_COMPARE || type == TYPE_DELAYED_COMPARE
+ || type == TYPE_IMUL_COMPARE || type == TYPE_LMUL_COMPARE
+ || type == TYPE_IDIV || type == TYPE_LDIV
+ || type == TYPE_INSERT_WORD)
+ return true;
}
return false;
@@ -14204,7 +16714,7 @@ is_branch_slot_insn (rtx insn)
{
enum attr_type type = get_attr_type (insn);
if (type == TYPE_BRANCH || type == TYPE_JMPREG)
- return true;
+ return true;
return false;
}
@@ -14252,22 +16762,23 @@ rs6000_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
if (is_dispatch_slot_restricted (insn)
&& reload_completed
- && current_sched_info->sched_max_insns_priority
+ && current_sched_info->sched_max_insns_priority
&& rs6000_sched_restricted_insns_priority)
{
- /* Prioritize insns that can be dispatched only in the first dispatch slot. */
+ /* Prioritize insns that can be dispatched only in the first
+ dispatch slot. */
if (rs6000_sched_restricted_insns_priority == 1)
- /* Attach highest priority to insn. This means that in
- haifa-sched.c:ready_sort(), dispatch-slot restriction considerations
+ /* Attach highest priority to insn. This means that in
+ haifa-sched.c:ready_sort(), dispatch-slot restriction considerations
precede 'priority' (critical path) considerations. */
- return current_sched_info->sched_max_insns_priority;
+ return current_sched_info->sched_max_insns_priority;
else if (rs6000_sched_restricted_insns_priority == 2)
- /* Increase priority of insn by a minimal amount. This means that in
- haifa-sched.c:ready_sort(), only 'priority' (critical path) considerations
- precede dispatch-slot restriction considerations. */
- return (priority + 1);
- }
+ /* Increase priority of insn by a minimal amount. This means that in
+ haifa-sched.c:ready_sort(), only 'priority' (critical path)
+ considerations precede dispatch-slot restriction considerations. */
+ return (priority + 1);
+ }
return priority;
}
@@ -14292,7 +16803,7 @@ rs6000_issue_rate (void)
case CPU_PPC750:
case CPU_PPC7400:
case CPU_PPC8540:
- return 2;
+ return 2;
case CPU_RIOS2:
case CPU_PPC604:
case CPU_PPC604E:
@@ -14346,7 +16857,7 @@ is_mem_ref (rtx pat)
}
/* Determine if PAT is a PATTERN of a load insn. */
-
+
static bool
is_load_insn1 (rtx pat)
{
@@ -14420,34 +16931,36 @@ is_store_insn (rtx insn)
costly by the given target. */
static bool
-rs6000_is_costly_dependence (rtx insn, rtx next, rtx link, int cost, int distance)
-{
- /* If the flag is not enbled - no dependence is considered costly;
- allow all dependent insns in the same group.
+rs6000_is_costly_dependence (rtx insn, rtx next, rtx link, int cost,
+ int distance)
+{
+ /* If the flag is not enabled - no dependence is considered costly;
+ allow all dependent insns in the same group.
This is the most aggressive option. */
if (rs6000_sched_costly_dep == no_dep_costly)
return false;
- /* If the flag is set to 1 - a dependence is always considered costly;
+ /* If the flag is set to 1 - a dependence is always considered costly;
do not allow dependent instructions in the same group.
This is the most conservative option. */
if (rs6000_sched_costly_dep == all_deps_costly)
- return true;
+ return true;
- if (rs6000_sched_costly_dep == store_to_load_dep_costly
- && is_load_insn (next)
+ if (rs6000_sched_costly_dep == store_to_load_dep_costly
+ && is_load_insn (next)
&& is_store_insn (insn))
/* Prevent load after store in the same group. */
return true;
if (rs6000_sched_costly_dep == true_store_to_load_dep_costly
- && is_load_insn (next)
+ && is_load_insn (next)
&& is_store_insn (insn)
&& (!link || (int) REG_NOTE_KIND (link) == 0))
- /* Prevent load after store in the same group if it is a true dependence. */
+ /* Prevent load after store in the same group if it is a true
+ dependence. */
return true;
-
- /* The flag is set to X; dependences with latency >= X are considered costly,
+
+ /* The flag is set to X; dependences with latency >= X are considered costly,
and will not be scheduled in the same group. */
if (rs6000_sched_costly_dep <= max_dep_latency
&& ((cost - distance) >= (int)rs6000_sched_costly_dep))
@@ -14456,33 +16969,31 @@ rs6000_is_costly_dependence (rtx insn, rtx next, rtx link, int cost, int distanc
return false;
}
-/* Return the next insn after INSN that is found before TAIL is reached,
+/* Return the next insn after INSN that is found before TAIL is reached,
skipping any "non-active" insns - insns that will not actually occupy
an issue slot. Return NULL_RTX if such an insn is not found. */
static rtx
get_next_active_insn (rtx insn, rtx tail)
{
- rtx next_insn;
-
- if (!insn || insn == tail)
+ if (insn == NULL_RTX || insn == tail)
return NULL_RTX;
- next_insn = NEXT_INSN (insn);
-
- while (next_insn
- && next_insn != tail
- && (GET_CODE(next_insn) == NOTE
- || GET_CODE (PATTERN (next_insn)) == USE
- || GET_CODE (PATTERN (next_insn)) == CLOBBER))
+ while (1)
{
- next_insn = NEXT_INSN (next_insn);
- }
-
- if (!next_insn || next_insn == tail)
- return NULL_RTX;
+ insn = NEXT_INSN (insn);
+ if (insn == NULL_RTX || insn == tail)
+ return NULL_RTX;
- return next_insn;
+ if (CALL_P (insn)
+ || JUMP_P (insn)
+ || (NONJUMP_INSN_P (insn)
+ && GET_CODE (PATTERN (insn)) != USE
+ && GET_CODE (PATTERN (insn)) != CLOBBER
+ && INSN_CODE (insn) != CODE_FOR_stack_tie))
+ break;
+ }
+ return insn;
}
/* Return whether the presence of INSN causes a dispatch group termination
@@ -14514,13 +17025,13 @@ insn_terminates_group_p (rtx insn, enum group_termination which_group)
if (which_group == current_group)
{
if (is_branch_slot_insn (insn))
- return true;
+ return true;
return false;
}
else if (which_group == previous_group)
{
if (is_dispatch_slot_restricted (insn))
- return true;
+ return true;
return false;
}
@@ -14542,23 +17053,23 @@ is_costly_group (rtx *group_insns, rtx next_insn)
{
rtx insn = group_insns[i];
if (!insn)
- continue;
+ continue;
for (link = INSN_DEPEND (insn); link != 0; link = XEXP (link, 1))
- {
- rtx next = XEXP (link, 0);
- if (next == next_insn)
- {
- cost = insn_cost (insn, link, next_insn);
- if (rs6000_is_costly_dependence (insn, next_insn, link, cost, 0))
- return true;
- }
- }
+ {
+ rtx next = XEXP (link, 0);
+ if (next == next_insn)
+ {
+ cost = insn_cost (insn, link, next_insn);
+ if (rs6000_is_costly_dependence (insn, next_insn, link, cost, 0))
+ return true;
+ }
+ }
}
return false;
}
-/* Utility of the function redefine_groups.
+/* Utility of the function redefine_groups.
Check if it is too costly to schedule NEXT_INSN together with GROUP_INSNS
in the same dispatch group. If so, insert nops before NEXT_INSN, in order
to keep it "far" (in a separate group) from GROUP_INSNS, following
@@ -14566,14 +17077,15 @@ is_costly_group (rtx *group_insns, rtx next_insn)
-minsert_sched_nops = X:
(1) X == sched_finish_regroup_exact: insert exactly as many nops as needed
in order to force NEXT_INSN into a separate group.
- (2) X < sched_finish_regroup_exact: insert exactly X nops.
- GROUP_END, CAN_ISSUE_MORE and GROUP_COUNT record the state after nop
+ (2) X < sched_finish_regroup_exact: insert exactly X nops.
+ GROUP_END, CAN_ISSUE_MORE and GROUP_COUNT record the state after nop
insertion (has a group just ended, how many vacant issue slots remain in the
last group, and how many dispatch groups were encountered so far). */
-static int
-force_new_group (int sched_verbose, FILE *dump, rtx *group_insns, rtx next_insn,
- bool *group_end, int can_issue_more, int *group_count)
+static int
+force_new_group (int sched_verbose, FILE *dump, rtx *group_insns,
+ rtx next_insn, bool *group_end, int can_issue_more,
+ int *group_count)
{
rtx nop;
bool force;
@@ -14593,95 +17105,96 @@ force_new_group (int sched_verbose, FILE *dump, rtx *group_insns, rtx next_insn,
if (sched_verbose > 6)
fprintf (dump,"force: group count = %d, can_issue_more = %d\n",
- *group_count ,can_issue_more);
+ *group_count ,can_issue_more);
if (rs6000_sched_insert_nops == sched_finish_regroup_exact)
{
if (*group_end)
- can_issue_more = 0;
+ can_issue_more = 0;
/* Since only a branch can be issued in the last issue_slot, it is
sufficient to insert 'can_issue_more - 1' nops if next_insn is not
a branch. If next_insn is a branch, we insert 'can_issue_more' nops;
- in this case the last nop will start a new group and the branch will be
- forced to the new group. */
+ in this case the last nop will start a new group and the branch
+ will be forced to the new group. */
if (can_issue_more && !is_branch_slot_insn (next_insn))
- can_issue_more--;
+ can_issue_more--;
while (can_issue_more > 0)
- {
- nop = gen_nop();
- emit_insn_before (nop, next_insn);
- can_issue_more--;
- }
+ {
+ nop = gen_nop ();
+ emit_insn_before (nop, next_insn);
+ can_issue_more--;
+ }
*group_end = true;
return 0;
- }
+ }
if (rs6000_sched_insert_nops < sched_finish_regroup_exact)
{
int n_nops = rs6000_sched_insert_nops;
- /* Nops can't be issued from the branch slot, so the effective
- issue_rate for nops is 'issue_rate - 1'. */
+ /* Nops can't be issued from the branch slot, so the effective
+ issue_rate for nops is 'issue_rate - 1'. */
if (can_issue_more == 0)
- can_issue_more = issue_rate;
+ can_issue_more = issue_rate;
can_issue_more--;
if (can_issue_more == 0)
- {
- can_issue_more = issue_rate - 1;
- (*group_count)++;
- end = true;
- for (i = 0; i < issue_rate; i++)
- {
- group_insns[i] = 0;
- }
- }
+ {
+ can_issue_more = issue_rate - 1;
+ (*group_count)++;
+ end = true;
+ for (i = 0; i < issue_rate; i++)
+ {
+ group_insns[i] = 0;
+ }
+ }
while (n_nops > 0)
- {
- nop = gen_nop ();
- emit_insn_before (nop, next_insn);
- if (can_issue_more == issue_rate - 1) /* new group begins */
- end = false;
- can_issue_more--;
- if (can_issue_more == 0)
- {
- can_issue_more = issue_rate - 1;
- (*group_count)++;
- end = true;
- for (i = 0; i < issue_rate; i++)
- {
- group_insns[i] = 0;
- }
- }
- n_nops--;
- }
+ {
+ nop = gen_nop ();
+ emit_insn_before (nop, next_insn);
+ if (can_issue_more == issue_rate - 1) /* new group begins */
+ end = false;
+ can_issue_more--;
+ if (can_issue_more == 0)
+ {
+ can_issue_more = issue_rate - 1;
+ (*group_count)++;
+ end = true;
+ for (i = 0; i < issue_rate; i++)
+ {
+ group_insns[i] = 0;
+ }
+ }
+ n_nops--;
+ }
/* Scale back relative to 'issue_rate' (instead of 'issue_rate - 1'). */
- can_issue_more++;
+ can_issue_more++;
- *group_end = /* Is next_insn going to start a new group? */
- (end
+ /* Is next_insn going to start a new group? */
+ *group_end
+ = (end
|| (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
|| (can_issue_more <= 2 && is_cracked_insn (next_insn))
|| (can_issue_more < issue_rate &&
- insn_terminates_group_p (next_insn, previous_group)));
+ insn_terminates_group_p (next_insn, previous_group)));
if (*group_end && end)
- (*group_count)--;
+ (*group_count)--;
if (sched_verbose > 6)
- fprintf (dump, "done force: group count = %d, can_issue_more = %d\n",
- *group_count, can_issue_more);
- return can_issue_more;
- }
+ fprintf (dump, "done force: group count = %d, can_issue_more = %d\n",
+ *group_count, can_issue_more);
+ return can_issue_more;
+ }
return can_issue_more;
}
/* This function tries to synch the dispatch groups that the compiler "sees"
- with the dispatch groups that the processor dispatcher is expected to
+ with the dispatch groups that the processor dispatcher is expected to
form in practice. It tries to achieve this synchronization by forcing the
estimated processor grouping on the compiler (as opposed to the function
'pad_goups' which tries to force the scheduler's grouping on the processor).
@@ -14696,7 +17209,7 @@ force_new_group (int sched_verbose, FILE *dump, rtx *group_insns, rtx next_insn,
between the insns.
The function estimates the group boundaries that the processor will form as
- folllows: It keeps track of how many vacant issue slots are available after
+ follows: It keeps track of how many vacant issue slots are available after
each insn. A subsequent insn will start a new group if one of the following
4 cases applies:
- no more vacant issue slots remain in the current dispatch group.
@@ -14705,7 +17218,7 @@ force_new_group (int sched_verbose, FILE *dump, rtx *group_insns, rtx next_insn,
- only the last 2 or less issue slots, including the branch slot, are vacant,
which means that a cracked insn (which occupies two issue slots) can't be
issued in this group.
- - less than 'issue_rate' slots are vacant, and the next insn always needs to
+ - less than 'issue_rate' slots are vacant, and the next insn always needs to
start a new group. */
static int
@@ -14722,7 +17235,7 @@ redefine_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
/* Initialize. */
issue_rate = rs6000_issue_rate ();
group_insns = alloca (issue_rate * sizeof (rtx));
- for (i = 0; i < issue_rate; i++)
+ for (i = 0; i < issue_rate; i++)
{
group_insns[i] = 0;
}
@@ -14736,43 +17249,45 @@ redefine_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
slot = (issue_rate - can_issue_more);
group_insns[slot] = insn;
can_issue_more =
- rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
+ rs6000_variable_issue (dump, sched_verbose, insn, can_issue_more);
if (insn_terminates_group_p (insn, current_group))
- can_issue_more = 0;
+ can_issue_more = 0;
next_insn = get_next_active_insn (insn, tail);
if (next_insn == NULL_RTX)
- return group_count + 1;
+ return group_count + 1;
- group_end = /* Is next_insn going to start a new group? */
- (can_issue_more == 0
- || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
- || (can_issue_more <= 2 && is_cracked_insn (next_insn))
- || (can_issue_more < issue_rate &&
- insn_terminates_group_p (next_insn, previous_group)));
+ /* Is next_insn going to start a new group? */
+ group_end
+ = (can_issue_more == 0
+ || (can_issue_more == 1 && !is_branch_slot_insn (next_insn))
+ || (can_issue_more <= 2 && is_cracked_insn (next_insn))
+ || (can_issue_more < issue_rate &&
+ insn_terminates_group_p (next_insn, previous_group)));
- can_issue_more = force_new_group (sched_verbose, dump, group_insns,
- next_insn, &group_end, can_issue_more, &group_count);
+ can_issue_more = force_new_group (sched_verbose, dump, group_insns,
+ next_insn, &group_end, can_issue_more,
+ &group_count);
if (group_end)
- {
- group_count++;
- can_issue_more = 0;
- for (i = 0; i < issue_rate; i++)
- {
- group_insns[i] = 0;
- }
- }
+ {
+ group_count++;
+ can_issue_more = 0;
+ for (i = 0; i < issue_rate; i++)
+ {
+ group_insns[i] = 0;
+ }
+ }
if (GET_MODE (next_insn) == TImode && can_issue_more)
- PUT_MODE(next_insn, VOIDmode);
+ PUT_MODE (next_insn, VOIDmode);
else if (!can_issue_more && GET_MODE (next_insn) != TImode)
- PUT_MODE (next_insn, TImode);
+ PUT_MODE (next_insn, TImode);
insn = next_insn;
if (can_issue_more == 0)
- can_issue_more = issue_rate;
- } /* while */
+ can_issue_more = issue_rate;
+ } /* while */
return group_count;
}
@@ -14808,33 +17323,33 @@ pad_groups (FILE *dump, int sched_verbose, rtx prev_head_insn, rtx tail)
group_end = (next_insn == NULL_RTX || GET_MODE (next_insn) == TImode);
if (next_insn == NULL_RTX)
- break;
+ break;
if (group_end)
- {
- /* If the scheduler had marked group termination at this location
- (between insn and next_indn), and neither insn nor next_insn will
- force group termination, pad the group with nops to force group
- termination. */
- if (can_issue_more
- && (rs6000_sched_insert_nops == sched_finish_pad_groups)
- && !insn_terminates_group_p (insn, current_group)
- && !insn_terminates_group_p (next_insn, previous_group))
- {
- if (!is_branch_slot_insn(next_insn))
- can_issue_more--;
-
- while (can_issue_more)
- {
- nop = gen_nop ();
- emit_insn_before (nop, next_insn);
- can_issue_more--;
- }
- }
-
- can_issue_more = issue_rate;
- group_count++;
- }
+ {
+ /* If the scheduler had marked group termination at this location
+ (between insn and next_indn), and neither insn nor next_insn will
+ force group termination, pad the group with nops to force group
+ termination. */
+ if (can_issue_more
+ && (rs6000_sched_insert_nops == sched_finish_pad_groups)
+ && !insn_terminates_group_p (insn, current_group)
+ && !insn_terminates_group_p (next_insn, previous_group))
+ {
+ if (!is_branch_slot_insn (next_insn))
+ can_issue_more--;
+
+ while (can_issue_more)
+ {
+ nop = gen_nop ();
+ emit_insn_before (nop, next_insn);
+ can_issue_more--;
+ }
+ }
+
+ can_issue_more = issue_rate;
+ group_count++;
+ }
insn = next_insn;
next_insn = get_next_active_insn (insn, tail);
@@ -14857,16 +17372,16 @@ rs6000_sched_finish (FILE *dump, int sched_verbose)
if (reload_completed && rs6000_sched_groups)
{
if (rs6000_sched_insert_nops == sched_finish_none)
- return;
+ return;
if (rs6000_sched_insert_nops == sched_finish_pad_groups)
- n_groups = pad_groups (dump, sched_verbose,
- current_sched_info->prev_head,
- current_sched_info->next_tail);
+ n_groups = pad_groups (dump, sched_verbose,
+ current_sched_info->prev_head,
+ current_sched_info->next_tail);
else
- n_groups = redefine_groups (dump, sched_verbose,
- current_sched_info->prev_head,
- current_sched_info->next_tail);
+ n_groups = redefine_groups (dump, sched_verbose,
+ current_sched_info->prev_head,
+ current_sched_info->next_tail);
if (sched_verbose >= 6)
{
@@ -14887,7 +17402,7 @@ rs6000_trampoline_size (void)
switch (DEFAULT_ABI)
{
default:
- abort ();
+ gcc_unreachable ();
case ABI_AIX:
ret = (TARGET_32BIT) ? 12 : 24;
@@ -14909,25 +17424,24 @@ rs6000_trampoline_size (void)
void
rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
{
- enum machine_mode pmode = Pmode;
int regsize = (TARGET_32BIT) ? 4 : 8;
- rtx ctx_reg = force_reg (pmode, cxt);
+ rtx ctx_reg = force_reg (Pmode, cxt);
switch (DEFAULT_ABI)
{
default:
- abort ();
+ gcc_unreachable ();
/* Macros to shorten the code expansions below. */
-#define MEM_DEREF(addr) gen_rtx_MEM (pmode, memory_address (pmode, addr))
+#define MEM_DEREF(addr) gen_rtx_MEM (Pmode, memory_address (Pmode, addr))
#define MEM_PLUS(addr,offset) \
- gen_rtx_MEM (pmode, memory_address (pmode, plus_constant (addr, offset)))
+ gen_rtx_MEM (Pmode, memory_address (Pmode, plus_constant (addr, offset)))
/* Under AIX, just build the 3 word function descriptor */
case ABI_AIX:
{
- rtx fn_reg = gen_reg_rtx (pmode);
- rtx toc_reg = gen_reg_rtx (pmode);
+ rtx fn_reg = gen_reg_rtx (Pmode);
+ rtx toc_reg = gen_reg_rtx (Pmode);
emit_move_insn (fn_reg, MEM_DEREF (fnaddr));
emit_move_insn (toc_reg, MEM_PLUS (fnaddr, regsize));
emit_move_insn (MEM_DEREF (addr), fn_reg);
@@ -14939,12 +17453,12 @@ rs6000_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
/* Under V.4/eabi/darwin, __trampoline_setup does the real work. */
case ABI_DARWIN:
case ABI_V4:
- emit_library_call (gen_rtx_SYMBOL_REF (SImode, "__trampoline_setup"),
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__trampoline_setup"),
FALSE, VOIDmode, 4,
- addr, pmode,
+ addr, Pmode,
GEN_INT (rs6000_trampoline_size ()), SImode,
- fnaddr, pmode,
- ctx_reg, pmode);
+ fnaddr, Pmode,
+ ctx_reg, Pmode);
break;
}
@@ -14960,21 +17474,28 @@ const struct attribute_spec rs6000_attribute_table[] =
{ "altivec", 1, 1, false, true, false, rs6000_handle_altivec_attribute },
{ "longcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
{ "shortcall", 0, 0, false, true, true, rs6000_handle_longcall_attribute },
+ { "ms_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
+ { "gcc_struct", 0, 0, false, false, false, rs6000_handle_struct_attribute },
+#ifdef SUBTARGET_ATTRIBUTE_TABLE
+ SUBTARGET_ATTRIBUTE_TABLE,
+#endif
{ NULL, 0, 0, false, false, false, NULL }
};
/* Handle the "altivec" attribute. The attribute may have
arguments as follows:
- __attribute__((altivec(vector__)))
- __attribute__((altivec(pixel__))) (always followed by 'unsigned short')
- __attribute__((altivec(bool__))) (always followed by 'unsigned')
+ __attribute__((altivec(vector__)))
+ __attribute__((altivec(pixel__))) (always followed by 'unsigned short')
+ __attribute__((altivec(bool__))) (always followed by 'unsigned')
and may appear more than once (e.g., 'vector bool char') in a
given declaration. */
static tree
-rs6000_handle_altivec_attribute (tree *node, tree name, tree args,
+rs6000_handle_altivec_attribute (tree *node,
+ tree name ATTRIBUTE_UNUSED,
+ tree args,
int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
@@ -14983,7 +17504,7 @@ rs6000_handle_altivec_attribute (tree *node, tree name, tree args,
int unsigned_p;
char altivec_type
= ((args && TREE_CODE (args) == TREE_LIST && TREE_VALUE (args)
- && TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
+ && TREE_CODE (TREE_VALUE (args)) == IDENTIFIER_NODE)
? *IDENTIFIER_POINTER (TREE_VALUE (args))
: '?');
@@ -14995,47 +17516,66 @@ rs6000_handle_altivec_attribute (tree *node, tree name, tree args,
mode = TYPE_MODE (type);
- if (rs6000_warn_altivec_long
- && (type == long_unsigned_type_node || type == long_integer_type_node))
- warning ("use of 'long' in AltiVec types is deprecated; use 'int'");
+ /* Check for invalid AltiVec type qualifiers. */
+ if (type == long_unsigned_type_node || type == long_integer_type_node)
+ {
+ if (TARGET_64BIT)
+ error ("use of %<long%> in AltiVec types is invalid for 64-bit code");
+ else if (rs6000_warn_altivec_long)
+ warning (0, "use of %<long%> in AltiVec types is deprecated; use %<int%>");
+ }
+ else if (type == long_long_unsigned_type_node
+ || type == long_long_integer_type_node)
+ error ("use of %<long long%> in AltiVec types is invalid");
+ else if (type == double_type_node)
+ error ("use of %<double%> in AltiVec types is invalid");
+ else if (type == long_double_type_node)
+ error ("use of %<long double%> in AltiVec types is invalid");
+ else if (type == boolean_type_node)
+ error ("use of boolean types in AltiVec types is invalid");
+ else if (TREE_CODE (type) == COMPLEX_TYPE)
+ error ("use of %<complex%> in AltiVec types is invalid");
+ else if (DECIMAL_FLOAT_MODE_P (mode))
+ error ("use of decimal floating point types in AltiVec types is invalid");
switch (altivec_type)
{
case 'v':
- unsigned_p = TREE_UNSIGNED (type);
+ unsigned_p = TYPE_UNSIGNED (type);
switch (mode)
{
- case SImode:
- result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
- break;
- case HImode:
- result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
- break;
- case QImode:
- result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
- break;
- case SFmode: result = V4SF_type_node; break;
- /* If the user says 'vector int bool', we may be handed the 'bool'
- attribute _before_ the 'vector' attribute, and so select the proper
- type in the 'b' case below. */
- case V4SImode: case V8HImode: case V16QImode: result = type;
- default: break;
+ case SImode:
+ result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
+ break;
+ case HImode:
+ result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
+ break;
+ case QImode:
+ result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
+ break;
+ case SFmode: result = V4SF_type_node; break;
+ /* If the user says 'vector int bool', we may be handed the 'bool'
+ attribute _before_ the 'vector' attribute, and so select the
+ proper type in the 'b' case below. */
+ case V4SImode: case V8HImode: case V16QImode: case V4SFmode:
+ result = type;
+ default: break;
}
break;
case 'b':
switch (mode)
{
- case SImode: case V4SImode: result = bool_V4SI_type_node; break;
- case HImode: case V8HImode: result = bool_V8HI_type_node; break;
- case QImode: case V16QImode: result = bool_V16QI_type_node;
- default: break;
+ case SImode: case V4SImode: result = bool_V4SI_type_node; break;
+ case HImode: case V8HImode: result = bool_V8HI_type_node; break;
+ case QImode: case V16QImode: result = bool_V16QI_type_node;
+ default: break;
}
break;
case 'p':
switch (mode)
{
- case V8HImode: result = pixel_V8HI_type_node;
- default: break;
+ case V8HImode: result = pixel_V8HI_type_node;
+ default: break;
}
default: break;
}
@@ -15045,9 +17585,7 @@ rs6000_handle_altivec_attribute (tree *node, tree name, tree args,
*no_add_attrs = true; /* No need to hang on to the attribute. */
- if (!result)
- warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- else
+ if (result)
*node = reconstruct_complex_type (*node, result);
return NULL_TREE;
@@ -15064,6 +17602,14 @@ rs6000_mangle_fundamental_type (tree type)
if (type == pixel_type_node) return "u7__pixel";
if (type == bool_int_type_node) return "U6__booli";
+ /* Mangle IBM extended float long double as `g' (__float128) on
+ powerpc*-linux where long-double-64 previously was the default. */
+ if (TYPE_MAIN_VARIANT (type) == long_double_type_node
+ && TARGET_ELF
+ && TARGET_LONG_DOUBLE_128
+ && !TARGET_IEEEQUAD)
+ return "g";
+
/* For all other types, use normal C++ mangling. */
return NULL;
}
@@ -15072,16 +17618,16 @@ rs6000_mangle_fundamental_type (tree type)
struct attribute_spec.handler. */
static tree
-rs6000_handle_longcall_attribute (tree *node, tree name,
- tree args ATTRIBUTE_UNUSED,
- int flags ATTRIBUTE_UNUSED,
+rs6000_handle_longcall_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED,
bool *no_add_attrs)
{
if (TREE_CODE (*node) != FUNCTION_TYPE
&& TREE_CODE (*node) != FIELD_DECL
&& TREE_CODE (*node) != TYPE_DECL)
{
- warning ("`%s' attribute only applies to functions",
+ warning (OPT_Wattributes, "%qs attribute only applies to functions",
IDENTIFIER_POINTER (name));
*no_add_attrs = true;
}
@@ -15100,12 +17646,16 @@ rs6000_set_default_type_attributes (tree type)
TYPE_ATTRIBUTES (type) = tree_cons (get_identifier ("longcall"),
NULL_TREE,
TYPE_ATTRIBUTES (type));
+
+#if TARGET_MACHO
+ darwin_set_default_type_attributes (type);
+#endif
}
/* Return a reference suitable for calling a function with the
longcall attribute. */
-struct rtx_def *
+rtx
rs6000_longcall_ref (rtx call_ref)
{
const char *call_name;
@@ -15128,59 +17678,119 @@ rs6000_longcall_ref (rtx call_ref)
return force_reg (Pmode, call_ref);
}
-#ifdef USING_ELFOS_H
+#ifndef TARGET_USE_MS_BITFIELD_LAYOUT
+#define TARGET_USE_MS_BITFIELD_LAYOUT 0
+#endif
-/* A C statement or statements to switch to the appropriate section
- for output of RTX in mode MODE. You can assume that RTX is some
- kind of constant in RTL. The argument MODE is redundant except in
- the case of a `const_int' rtx. Select the section by calling
- `text_section' or one of the alternatives for other sections.
+/* Handle a "ms_struct" or "gcc_struct" attribute; arguments as in
+ struct attribute_spec.handler. */
+static tree
+rs6000_handle_struct_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ tree *type = NULL;
+ if (DECL_P (*node))
+ {
+ if (TREE_CODE (*node) == TYPE_DECL)
+ type = &TREE_TYPE (*node);
+ }
+ else
+ type = node;
+
+ if (!(type && (TREE_CODE (*type) == RECORD_TYPE
+ || TREE_CODE (*type) == UNION_TYPE)))
+ {
+ warning (OPT_Wattributes, "%qs attribute ignored", IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
- Do not define this macro if you put all constants in the read-only
- data section. */
+ else if ((is_attribute_p ("ms_struct", name)
+ && lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (*type)))
+ || ((is_attribute_p ("gcc_struct", name)
+ && lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (*type)))))
+ {
+ warning (OPT_Wattributes, "%qs incompatible attribute ignored",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+static bool
+rs6000_ms_bitfield_layout_p (tree record_type)
+{
+ return (TARGET_USE_MS_BITFIELD_LAYOUT &&
+ !lookup_attribute ("gcc_struct", TYPE_ATTRIBUTES (record_type)))
+ || lookup_attribute ("ms_struct", TYPE_ATTRIBUTES (record_type));
+}
+
+#ifdef USING_ELFOS_H
+
+/* A get_unnamed_section callback, used for switching to toc_section. */
static void
-rs6000_elf_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
+rs6000_elf_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
{
- if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
- toc_section ();
+ if (DEFAULT_ABI == ABI_AIX
+ && TARGET_MINIMAL_TOC
+ && !TARGET_RELOCATABLE)
+ {
+ if (!toc_initialized)
+ {
+ toc_initialized = 1;
+ fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
+ (*targetm.asm_out.internal_label) (asm_out_file, "LCTOC", 0);
+ fprintf (asm_out_file, "\t.tc ");
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],");
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
+ fprintf (asm_out_file, "\n");
+
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
+ fprintf (asm_out_file, " = .+32768\n");
+ }
+ else
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
+ }
+ else if (DEFAULT_ABI == ABI_AIX && !TARGET_RELOCATABLE)
+ fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP);
else
- default_elf_select_rtx_section (mode, x, align);
+ {
+ fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP);
+ if (!toc_initialized)
+ {
+ ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1");
+ fprintf (asm_out_file, " = .+32768\n");
+ toc_initialized = 1;
+ }
+ }
}
-/* A C statement or statements to switch to the appropriate
- section for output of DECL. DECL is either a `VAR_DECL' node
- or a constant of some sort. RELOC indicates whether forming
- the initial value of DECL requires link-time relocations. */
+/* Implement TARGET_ASM_INIT_SECTIONS. */
static void
-rs6000_elf_select_section (tree decl, int reloc,
- unsigned HOST_WIDE_INT align)
+rs6000_elf_asm_init_sections (void)
{
- /* Pretend that we're always building for a shared library when
- ABI_AIX, because otherwise we end up with dynamic relocations
- in read-only sections. This happens for function pointers,
- references to vtables in typeinfo, and probably other cases. */
- default_elf_select_section_1 (decl, reloc, align,
- flag_pic || DEFAULT_ABI == ABI_AIX);
+ toc_section
+ = get_unnamed_section (0, rs6000_elf_output_toc_section_asm_op, NULL);
+
+ sdata2_section
+ = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
+ SDATA2_SECTION_ASM_OP);
}
-/* A C statement to build up a unique section name, expressed as a
- STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
- RELOC indicates whether the initial value of EXP requires
- link-time relocations. If you do not define this macro, GCC will use
- the symbol name prefixed by `.' as the section name. Note - this
- macro can now be called for uninitialized data items as well as
- initialized data and functions. */
+/* Implement TARGET_SELECT_RTX_SECTION. */
-static void
-rs6000_elf_unique_section (tree decl, int reloc)
+static section *
+rs6000_elf_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align)
{
- /* As above, pretend that we're always building for a shared library
- when ABI_AIX, to avoid dynamic relocations in read-only sections. */
- default_unique_section_1 (decl, reloc,
- flag_pic || DEFAULT_ABI == ABI_AIX);
+ if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
+ return toc_section;
+ else
+ return default_elf_select_rtx_section (mode, x, align);
}
/* For a SYMBOL_REF, set generic flags and then perform some
@@ -15210,7 +17820,7 @@ rs6000_elf_encode_section_info (tree decl, rtx rtl, int first)
}
}
-static bool
+bool
rs6000_elf_in_small_data_p (tree decl)
{
if (rs6000_sdata == SDATA_NONE)
@@ -15224,10 +17834,6 @@ rs6000_elf_in_small_data_p (tree decl)
if (TREE_CODE (decl) == FUNCTION_DECL)
return false;
- /* Thread-local vars can't go in the small data area. */
- if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
- return false;
-
if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl))
{
const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
@@ -15255,7 +17861,14 @@ rs6000_elf_in_small_data_p (tree decl)
}
#endif /* USING_ELFOS_H */
+
+/* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P. */
+static bool
+rs6000_use_blocks_for_constant_p (enum machine_mode mode, rtx x)
+{
+ return !ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode);
+}
/* Return a REG that occurs in ADDR with coefficient 1.
ADDR can be effectively incremented by incrementing REG.
@@ -15264,7 +17877,7 @@ rs6000_elf_in_small_data_p (tree decl)
register by this routine since our caller will try to
increment the returned register via an "la" instruction. */
-struct rtx_def *
+rtx
find_addr_reg (rtx addr)
{
while (GET_CODE (addr) == PLUS)
@@ -15280,11 +17893,10 @@ find_addr_reg (rtx addr)
else if (CONSTANT_P (XEXP (addr, 1)))
addr = XEXP (addr, 0);
else
- abort ();
+ gcc_unreachable ();
}
- if (GET_CODE (addr) == REG && REGNO (addr) != 0)
- return addr;
- abort ();
+ gcc_assert (GET_CODE (addr) == REG && REGNO (addr) != 0);
+ return addr;
}
void
@@ -15295,42 +17907,17 @@ rs6000_fatal_bad_address (rtx op)
#if TARGET_MACHO
-#if 0
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-symbolic_operand (rtx op)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
- case CONST:
- op = XEXP (op, 0);
- return (GET_CODE (op) == SYMBOL_REF ||
- (GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
- default:
- return 0;
- }
-}
-#endif
-
-#if TARGET_MACHO
-
static tree branch_island_list = 0;
/* Remember to generate a branch island for far calls to the given
function. */
-static void
-add_compiler_branch_island (tree label_name, tree function_name, int line_number)
+static void
+add_compiler_branch_island (tree label_name, tree function_name,
+ int line_number)
{
tree branch_island = build_tree_list (function_name, label_name);
- TREE_TYPE (branch_island) = build_int_2 (line_number, 0);
+ TREE_TYPE (branch_island) = build_int_cst (NULL_TREE, line_number);
TREE_CHAIN (branch_island) = branch_island_list;
branch_island_list = branch_island;
}
@@ -15359,8 +17946,7 @@ macho_branch_islands (void)
const char *label =
IDENTIFIER_POINTER (BRANCH_ISLAND_LABEL_NAME (branch_island));
const char *name =
- darwin_strip_name_encoding (
- IDENTIFIER_POINTER (BRANCH_ISLAND_FUNCTION_NAME (branch_island)));
+ IDENTIFIER_POINTER (BRANCH_ISLAND_FUNCTION_NAME (branch_island));
char name_buf[512];
/* Cheap copy of the details from the Darwin ASM_OUTPUT_LABELREF(). */
if (name[0] == '*' || name[0] == '&')
@@ -15374,8 +17960,7 @@ macho_branch_islands (void)
strcat (tmp_buf, label);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- fprintf (asm_out_file, "\t.stabd 68,0," HOST_WIDE_INT_PRINT_UNSIGNED "\n",
- BRANCH_ISLAND_LINE_NUMBER(branch_island));
+ dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
if (flag_pic)
{
@@ -15384,21 +17969,21 @@ macho_branch_islands (void)
strcat (tmp_buf, "_pic\n");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic:\n\tmflr r11\n");
-
+
strcat (tmp_buf, "\taddis r11,r11,ha16(");
strcat (tmp_buf, name_buf);
strcat (tmp_buf, " - ");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic)\n");
-
+
strcat (tmp_buf, "\tmtlr r0\n");
-
+
strcat (tmp_buf, "\taddi r12,r11,lo16(");
strcat (tmp_buf, name_buf);
strcat (tmp_buf, " - ");
strcat (tmp_buf, label);
strcat (tmp_buf, "_pic)\n");
-
+
strcat (tmp_buf, "\tmtctr r12\n\tbctr\n");
}
else
@@ -15412,8 +17997,7 @@ macho_branch_islands (void)
output_asm_insn (tmp_buf, 0);
#if defined (DBX_DEBUGGING_INFO) || defined (XCOFF_DEBUGGING_INFO)
if (write_symbols == DBX_DEBUG || write_symbols == XCOFF_DEBUG)
- fprintf(asm_out_file, "\t.stabd 68,0," HOST_WIDE_INT_PRINT_UNSIGNED "\n",
- BRANCH_ISLAND_LINE_NUMBER (branch_island));
+ dbxout_stabd (N_SLINE, BRANCH_ISLAND_LINE_NUMBER (branch_island));
#endif /* DBX_DEBUGGING_INFO || XCOFF_DEBUGGING_INFO */
}
@@ -15450,21 +18034,31 @@ get_prev_label (tree function_name)
return 0;
}
+#ifndef DARWIN_LINKER_GENERATES_ISLANDS
+#define DARWIN_LINKER_GENERATES_ISLANDS 0
+#endif
+
+/* KEXTs still need branch islands. */
+#define DARWIN_GENERATE_ISLANDS (!DARWIN_LINKER_GENERATES_ISLANDS \
+ || flag_mkernel || flag_apple_kext)
+
/* INSN is either a function call or a millicode call. It may have an
- unconditional jump in its delay slot.
+ unconditional jump in its delay slot.
CALL_DEST is the routine we are calling. */
char *
-output_call (rtx insn, rtx *operands, int dest_operand_number, int cookie_operand_number)
+output_call (rtx insn, rtx *operands, int dest_operand_number,
+ int cookie_operand_number)
{
static char buf[256];
- if (GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
+ if (DARWIN_GENERATE_ISLANDS
+ && GET_CODE (operands[dest_operand_number]) == SYMBOL_REF
&& (INTVAL (operands[cookie_operand_number]) & CALL_LONG))
{
tree labelname;
tree funname = get_identifier (XSTR (operands[dest_operand_number], 0));
-
+
if (no_previous_def (funname))
{
int line_number = 0;
@@ -15495,8 +18089,6 @@ output_call (rtx insn, rtx *operands, int dest_operand_number, int cookie_operan
return buf;
}
-#endif /* TARGET_MACHO */
-
/* Generate PIC and indirect symbol stubs. */
void
@@ -15519,43 +18111,53 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
GEN_LAZY_PTR_NAME_FOR_SYMBOL (lazy_ptr_name, symb, length);
if (flag_pic == 2)
- machopic_picsymbol_stub1_section ();
+ switch_to_section (darwin_sections[machopic_picsymbol_stub1_section]);
else
- machopic_symbol_stub1_section ();
- fprintf (file, "\t.align 2\n");
-
- fprintf (file, "%s:\n", stub);
- fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+ switch_to_section (darwin_sections[machopic_symbol_stub1_section]);
if (flag_pic == 2)
{
+ fprintf (file, "\t.align 5\n");
+
+ fprintf (file, "%s:\n", stub);
+ fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+
label++;
- local_label_0 = alloca (sizeof("\"L0000000000$spb\""));
+ local_label_0 = alloca (sizeof ("\"L00000000000$spb\""));
sprintf (local_label_0, "\"L%011d$spb\"", label);
-
+
fprintf (file, "\tmflr r0\n");
fprintf (file, "\tbcl 20,31,%s\n", local_label_0);
fprintf (file, "%s:\n\tmflr r11\n", local_label_0);
fprintf (file, "\taddis r11,r11,ha16(%s-%s)\n",
lazy_ptr_name, local_label_0);
fprintf (file, "\tmtlr r0\n");
- fprintf (file, "\tlwzu r12,lo16(%s-%s)(r11)\n",
+ fprintf (file, "\t%s r12,lo16(%s-%s)(r11)\n",
+ (TARGET_64BIT ? "ldu" : "lwzu"),
lazy_ptr_name, local_label_0);
fprintf (file, "\tmtctr r12\n");
fprintf (file, "\tbctr\n");
}
else
- {
- fprintf (file, "\tlis r11,ha16(%s)\n", lazy_ptr_name);
- fprintf (file, "\tlwzu r12,lo16(%s)(r11)\n", lazy_ptr_name);
- fprintf (file, "\tmtctr r12\n");
- fprintf (file, "\tbctr\n");
- }
-
- machopic_lazy_symbol_ptr_section ();
+ {
+ fprintf (file, "\t.align 4\n");
+
+ fprintf (file, "%s:\n", stub);
+ fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
+
+ fprintf (file, "\tlis r11,ha16(%s)\n", lazy_ptr_name);
+ fprintf (file, "\t%s r12,lo16(%s)(r11)\n",
+ (TARGET_64BIT ? "ldu" : "lwzu"),
+ lazy_ptr_name);
+ fprintf (file, "\tmtctr r12\n");
+ fprintf (file, "\tbctr\n");
+ }
+
+ switch_to_section (darwin_sections[machopic_lazy_symbol_ptr_section]);
fprintf (file, "%s:\n", lazy_ptr_name);
fprintf (file, "\t.indirect_symbol %s\n", symbol_name);
- fprintf (file, "\t.long dyld_stub_binding_helper\n");
+ fprintf (file, "%sdyld_stub_binding_helper\n",
+ (TARGET_64BIT ? DOUBLE_INT_ASM_OP : "\t.long\t"));
}
/* Legitimize PIC addresses. If the address is already
@@ -15563,10 +18165,10 @@ machopic_output_stub (FILE *file, const char *symb, const char *stub)
position-independent addresses go into a reg. This is REG if non
zero, otherwise we allocate register(s) as necessary. */
-#define SMALL_INT(X) ((unsigned) (INTVAL(X) + 0x8000) < 0x10000)
+#define SMALL_INT(X) ((UINTVAL (X) + 0x8000) < 0x10000)
rtx
-rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
+rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
rtx reg)
{
rtx base, offset;
@@ -15576,25 +18178,22 @@ rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
if (GET_CODE (orig) == CONST)
{
+ rtx reg_temp;
+
if (GET_CODE (XEXP (orig, 0)) == PLUS
&& XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
return orig;
- if (GET_CODE (XEXP (orig, 0)) == PLUS)
- {
- /* Use a different reg for the intermediate value, as
- it will be marked UNCHANGING. */
- rtx reg_temp = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
- base =
- rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
- Pmode, reg_temp);
- offset =
- rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
- Pmode, reg);
- }
- else
- abort ();
+ /* Use a different reg for the intermediate value, as
+ it will be marked UNCHANGING. */
+ reg_temp = no_new_pseudos ? reg : gen_reg_rtx (Pmode);
+ base = rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 0),
+ Pmode, reg_temp);
+ offset =
+ rs6000_machopic_legitimize_pic_address (XEXP (XEXP (orig, 0), 1),
+ Pmode, reg);
if (GET_CODE (offset) == CONST_INT)
{
@@ -15608,31 +18207,78 @@ rs6000_machopic_legitimize_pic_address (rtx orig, enum machine_mode mode,
return machopic_legitimize_pic_address (mem, Pmode, reg);
}
}
- return gen_rtx (PLUS, Pmode, base, offset);
+ return gen_rtx_PLUS (Pmode, base, offset);
}
/* Fall back on generic machopic code. */
return machopic_legitimize_pic_address (orig, mode, reg);
}
-/* This is just a placeholder to make linking work without having to
- add this to the generic Darwin EXTRA_SECTIONS. If -mcall-aix is
- ever needed for Darwin (not too likely!) this would have to get a
- real definition. */
+/* Output a .machine directive for the Darwin assembler, and call
+ the generic start_file routine. */
-void
-toc_section (void)
+static void
+rs6000_darwin_file_start (void)
{
+ static const struct
+ {
+ const char *arg;
+ const char *name;
+ int if_set;
+ } mapping[] = {
+ { "ppc64", "ppc64", MASK_64BIT },
+ { "970", "ppc970", MASK_PPC_GPOPT | MASK_MFCRF | MASK_POWERPC64 },
+ { "power4", "ppc970", 0 },
+ { "G5", "ppc970", 0 },
+ { "7450", "ppc7450", 0 },
+ { "7400", "ppc7400", MASK_ALTIVEC },
+ { "G4", "ppc7400", 0 },
+ { "750", "ppc750", 0 },
+ { "740", "ppc750", 0 },
+ { "G3", "ppc750", 0 },
+ { "604e", "ppc604e", 0 },
+ { "604", "ppc604", 0 },
+ { "603e", "ppc603", 0 },
+ { "603", "ppc603", 0 },
+ { "601", "ppc601", 0 },
+ { NULL, "ppc", 0 } };
+ const char *cpu_id = "";
+ size_t i;
+
+ rs6000_file_start ();
+ darwin_file_start ();
+
+ /* Determine the argument to -mcpu=. Default to G3 if not specified. */
+ for (i = 0; i < ARRAY_SIZE (rs6000_select); i++)
+ if (rs6000_select[i].set_arch_p && rs6000_select[i].string
+ && rs6000_select[i].string[0] != '\0')
+ cpu_id = rs6000_select[i].string;
+
+ /* Look through the mapping array. Pick the first name that either
+ matches the argument, has a bit set in IF_SET that is also set
+ in the target flags, or has a NULL name. */
+
+ i = 0;
+ while (mapping[i].arg != NULL
+ && strcmp (mapping[i].arg, cpu_id) != 0
+ && (mapping[i].if_set & target_flags) == 0)
+ i++;
+
+ fprintf (asm_out_file, "\t.machine %s\n", mapping[i].name);
}
#endif /* TARGET_MACHO */
#if TARGET_ELF
-static unsigned int
-rs6000_elf_section_type_flags (tree decl, const char *name, int reloc)
+static int
+rs6000_elf_reloc_rw_mask (void)
{
- return default_section_type_flags_1 (decl, name, reloc,
- flag_pic || DEFAULT_ABI == ABI_AIX);
+ if (flag_pic)
+ return 3;
+ else if (DEFAULT_ABI == ABI_AIX)
+ return 2;
+ else
+ return 0;
}
/* Record an element in the table of global constructors. SYMBOL is
@@ -15651,14 +18297,14 @@ rs6000_elf_asm_out_constructor (rtx symbol, int priority)
if (priority != DEFAULT_INIT_PRIORITY)
{
sprintf (buf, ".ctors.%.5u",
- /* Invert the numbering so the linker puts us in the proper
- order; constructors are run from right to left, and the
- linker sorts in increasing order. */
- MAX_INIT_PRIORITY - priority);
+ /* Invert the numbering so the linker puts us in the proper
+ order; constructors are run from right to left, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - priority);
section = buf;
}
- named_section_flags (section, SECTION_WRITE);
+ switch_to_section (get_section (section, SECTION_WRITE, NULL));
assemble_align (POINTER_SIZE);
if (TARGET_RELOCATABLE)
@@ -15680,14 +18326,14 @@ rs6000_elf_asm_out_destructor (rtx symbol, int priority)
if (priority != DEFAULT_INIT_PRIORITY)
{
sprintf (buf, ".dtors.%.5u",
- /* Invert the numbering so the linker puts us in the proper
- order; constructors are run from right to left, and the
- linker sorts in increasing order. */
- MAX_INIT_PRIORITY - priority);
+ /* Invert the numbering so the linker puts us in the proper
+ order; constructors are run from right to left, and the
+ linker sorts in increasing order. */
+ MAX_INIT_PRIORITY - priority);
section = buf;
}
- named_section_flags (section, SECTION_WRITE);
+ switch_to_section (get_section (section, SECTION_WRITE, NULL));
assemble_align (POINTER_SIZE);
if (TARGET_RELOCATABLE)
@@ -15708,26 +18354,32 @@ rs6000_elf_declare_function_name (FILE *file, const char *name, tree decl)
fputs ("\t.section\t\".opd\",\"aw\"\n\t.align 3\n", file);
ASM_OUTPUT_LABEL (file, name);
fputs (DOUBLE_INT_ASM_OP, file);
- putc ('.', file);
- assemble_name (file, name);
- fputs (",.TOC.@tocbase,0\n\t.previous\n\t.size\t", file);
- assemble_name (file, name);
- fputs (",24\n\t.type\t.", file);
- assemble_name (file, name);
- fputs (",@function\n", file);
- if (TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
- {
- fputs ("\t.globl\t.", file);
+ rs6000_output_function_entry (file, name);
+ fputs (",.TOC.@tocbase,0\n\t.previous\n", file);
+ if (DOT_SYMBOLS)
+ {
+ fputs ("\t.size\t", file);
+ assemble_name (file, name);
+ fputs (",24\n\t.type\t.", file);
assemble_name (file, name);
- putc ('\n', file);
+ fputs (",@function\n", file);
+ if (TREE_PUBLIC (decl) && ! DECL_WEAK (decl))
+ {
+ fputs ("\t.globl\t.", file);
+ assemble_name (file, name);
+ putc ('\n', file);
+ }
}
+ else
+ ASM_OUTPUT_TYPE_DIRECTIVE (file, name, "function");
ASM_DECLARE_RESULT (file, DECL_RESULT (decl));
- putc ('.', file);
- ASM_OUTPUT_LABEL (file, name);
+ rs6000_output_function_entry (file, name);
+ fputs (":\n", file);
return;
}
if (TARGET_RELOCATABLE
+ && !TARGET_SECURE_PLT
&& (get_pool_size () != 0 || current_function_profile)
&& uses_TOC ())
{
@@ -15780,6 +18432,16 @@ rs6000_elf_end_indicate_exec_stack (void)
#if TARGET_XCOFF
static void
+rs6000_xcoff_asm_output_anchor (rtx symbol)
+{
+ char buffer[100];
+
+ sprintf (buffer, "$ + " HOST_WIDE_INT_PRINT_DEC,
+ SYMBOL_REF_BLOCK_OFFSET (symbol));
+ ASM_OUTPUT_DEF (asm_out_file, XSTR (symbol, 0), buffer);
+}
+
+static void
rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
{
fputs (GLOBAL_ASM_OP, stream);
@@ -15787,8 +18449,82 @@ rs6000_xcoff_asm_globalize_label (FILE *stream, const char *name)
putc ('\n', stream);
}
+/* A get_unnamed_decl callback, used for read-only sections. PTR
+ points to the section string variable. */
+
+static void
+rs6000_xcoff_output_readonly_section_asm_op (const void *directive)
+{
+ fprintf (asm_out_file, "\t.csect %s[RO],3\n",
+ *(const char *const *) directive);
+}
+
+/* Likewise for read-write sections. */
+
+static void
+rs6000_xcoff_output_readwrite_section_asm_op (const void *directive)
+{
+ fprintf (asm_out_file, "\t.csect %s[RW],3\n",
+ *(const char *const *) directive);
+}
+
+/* A get_unnamed_section callback, used for switching to toc_section. */
+
+static void
+rs6000_xcoff_output_toc_section_asm_op (const void *data ATTRIBUTE_UNUSED)
+{
+ if (TARGET_MINIMAL_TOC)
+ {
+ /* toc_section is always selected at least once from
+ rs6000_xcoff_file_start, so this is guaranteed to
+ always be defined once and only once in each file. */
+ if (!toc_initialized)
+ {
+ fputs ("\t.toc\nLCTOC..1:\n", asm_out_file);
+ fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file);
+ toc_initialized = 1;
+ }
+ fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n",
+ (TARGET_32BIT ? "" : ",3"));
+ }
+ else
+ fputs ("\t.toc\n", asm_out_file);
+}
+
+/* Implement TARGET_ASM_INIT_SECTIONS. */
+
+static void
+rs6000_xcoff_asm_init_sections (void)
+{
+ read_only_data_section
+ = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
+ &xcoff_read_only_section_name);
+
+ private_data_section
+ = get_unnamed_section (SECTION_WRITE,
+ rs6000_xcoff_output_readwrite_section_asm_op,
+ &xcoff_private_data_section_name);
+
+ read_only_private_data_section
+ = get_unnamed_section (0, rs6000_xcoff_output_readonly_section_asm_op,
+ &xcoff_private_data_section_name);
+
+ toc_section
+ = get_unnamed_section (0, rs6000_xcoff_output_toc_section_asm_op, NULL);
+
+ readonly_data_section = read_only_data_section;
+ exception_section = data_section;
+}
+
+static int
+rs6000_xcoff_reloc_rw_mask (void)
+{
+ return 3;
+}
+
static void
-rs6000_xcoff_asm_named_section (const char *name, unsigned int flags)
+rs6000_xcoff_asm_named_section (const char *name, unsigned int flags,
+ tree decl ATTRIBUTE_UNUSED)
{
int smclass;
static const char * const suffix[3] = { "PR", "RO", "RW" };
@@ -15805,23 +18541,23 @@ rs6000_xcoff_asm_named_section (const char *name, unsigned int flags)
name, suffix[smclass], flags & SECTION_ENTSIZE);
}
-static void
-rs6000_xcoff_select_section (tree decl, int reloc,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+static section *
+rs6000_xcoff_select_section (tree decl, int reloc,
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
- if (decl_readonly_section_1 (decl, reloc, 1))
+ if (decl_readonly_section (decl, reloc))
{
if (TREE_PUBLIC (decl))
- read_only_data_section ();
+ return read_only_data_section;
else
- read_only_private_data_section ();
+ return read_only_private_data_section;
}
else
{
if (TREE_PUBLIC (decl))
- data_section ();
+ return data_section;
else
- private_data_section ();
+ return private_data_section;
}
}
@@ -15850,14 +18586,14 @@ rs6000_xcoff_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED)
However, if this is being placed in the TOC it must be output as a
toc entry. */
-static void
-rs6000_xcoff_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
+static section *
+rs6000_xcoff_select_rtx_section (enum machine_mode mode, rtx x,
+ unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
{
if (ASM_OUTPUT_SPECIAL_POOL_ENTRY_P (x, mode))
- toc_section ();
+ return toc_section;
else
- read_only_private_data_section ();
+ return read_only_private_data_section;
}
/* Remove any trailing [DS] or the like from the symbol name. */
@@ -15881,7 +18617,7 @@ static unsigned int
rs6000_xcoff_section_type_flags (tree decl, const char *name, int reloc)
{
unsigned int align;
- unsigned int flags = default_section_type_flags_1 (decl, name, reloc, 1);
+ unsigned int flags = default_section_type_flags (decl, name, reloc);
/* Align to at least UNIT size. */
if (flags & SECTION_CODE)
@@ -15920,10 +18656,9 @@ rs6000_xcoff_file_start (void)
fputs ("\t.file\t", asm_out_file);
output_quoted_string (asm_out_file, main_input_filename);
fputc ('\n', asm_out_file);
- toc_section ();
if (write_symbols != NO_DEBUG)
- private_data_section ();
- text_section ();
+ switch_to_section (private_data_section);
+ switch_to_section (text_section);
if (profile_flag)
fprintf (asm_out_file, "\t.extern %s\n", RS6000_MCOUNT);
rs6000_file_start ();
@@ -15935,256 +18670,390 @@ rs6000_xcoff_file_start (void)
static void
rs6000_xcoff_file_end (void)
{
- text_section ();
+ switch_to_section (text_section);
fputs ("_section_.text:\n", asm_out_file);
- data_section ();
+ switch_to_section (data_section);
fputs (TARGET_32BIT
? "\t.long _section_.text\n" : "\t.llong _section_.text\n",
asm_out_file);
}
#endif /* TARGET_XCOFF */
-#if TARGET_MACHO
-/* Cross-module name binding. Darwin does not support overriding
- functions at dynamic-link time. */
-
-static bool
-rs6000_binds_local_p (tree decl)
-{
- return default_binds_local_p_1 (decl, 0);
-}
-#endif
-
/* Compute a (partial) cost for rtx X. Return true if the complete
cost has been computed, and false if subexpressions should be
scanned. In either case, *TOTAL contains the cost result. */
static bool
-rs6000_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
- int *total)
+rs6000_rtx_costs (rtx x, int code, int outer_code, int *total)
{
+ enum machine_mode mode = GET_MODE (x);
+
switch (code)
{
- /* On the RS/6000, if it is valid in the insn, it is free.
- So this always returns 0. */
+ /* On the RS/6000, if it is valid in the insn, it is free. */
case CONST_INT:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- case CONST_DOUBLE:
- case HIGH:
- *total = 0;
- return true;
-
- case PLUS:
- *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
- && ((unsigned HOST_WIDE_INT) (INTVAL (XEXP (x, 1))
- + 0x8000) >= 0x10000)
- && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
- ? COSTS_N_INSNS (2)
- : COSTS_N_INSNS (1));
- return true;
-
- case AND:
- case IOR:
- case XOR:
- *total = ((GET_CODE (XEXP (x, 1)) == CONST_INT
- && (INTVAL (XEXP (x, 1)) & (~ (HOST_WIDE_INT) 0xffff)) != 0
- && ((INTVAL (XEXP (x, 1)) & 0xffff) != 0))
- ? COSTS_N_INSNS (2)
- : COSTS_N_INSNS (1));
- return true;
-
- case MULT:
- if (optimize_size)
+ if (((outer_code == SET
+ || outer_code == PLUS
+ || outer_code == MINUS)
+ && (satisfies_constraint_I (x)
+ || satisfies_constraint_L (x)))
+ || (outer_code == AND
+ && (satisfies_constraint_K (x)
+ || (mode == SImode
+ ? satisfies_constraint_L (x)
+ : satisfies_constraint_J (x))
+ || mask_operand (x, mode)
+ || (mode == DImode
+ && mask64_operand (x, DImode))))
+ || ((outer_code == IOR || outer_code == XOR)
+ && (satisfies_constraint_K (x)
+ || (mode == SImode
+ ? satisfies_constraint_L (x)
+ : satisfies_constraint_J (x))))
+ || outer_code == ASHIFT
+ || outer_code == ASHIFTRT
+ || outer_code == LSHIFTRT
+ || outer_code == ROTATE
+ || outer_code == ROTATERT
+ || outer_code == ZERO_EXTRACT
+ || (outer_code == MULT
+ && satisfies_constraint_I (x))
+ || ((outer_code == DIV || outer_code == UDIV
+ || outer_code == MOD || outer_code == UMOD)
+ && exact_log2 (INTVAL (x)) >= 0)
+ || (outer_code == COMPARE
+ && (satisfies_constraint_I (x)
+ || satisfies_constraint_K (x)))
+ || (outer_code == EQ
+ && (satisfies_constraint_I (x)
+ || satisfies_constraint_K (x)
+ || (mode == SImode
+ ? satisfies_constraint_L (x)
+ : satisfies_constraint_J (x))))
+ || (outer_code == GTU
+ && satisfies_constraint_I (x))
+ || (outer_code == LTU
+ && satisfies_constraint_P (x)))
{
- *total = COSTS_N_INSNS (2);
+ *total = 0;
return true;
}
- switch (rs6000_cpu)
+ else if ((outer_code == PLUS
+ && reg_or_add_cint_operand (x, VOIDmode))
+ || (outer_code == MINUS
+ && reg_or_sub_cint_operand (x, VOIDmode))
+ || ((outer_code == SET
+ || outer_code == IOR
+ || outer_code == XOR)
+ && (INTVAL (x)
+ & ~ (unsigned HOST_WIDE_INT) 0xffffffff) == 0))
{
- case PROCESSOR_RIOS1:
- case PROCESSOR_PPC405:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? COSTS_N_INSNS (5)
- : (INTVAL (XEXP (x, 1)) >= -256
- && INTVAL (XEXP (x, 1)) <= 255)
- ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4));
- return true;
-
- case PROCESSOR_PPC440:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? COSTS_N_INSNS (3)
- : COSTS_N_INSNS (2));
- return true;
-
- case PROCESSOR_RS64A:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (20) : COSTS_N_INSNS (34)
- : (INTVAL (XEXP (x, 1)) >= -256
- && INTVAL (XEXP (x, 1)) <= 255)
- ? COSTS_N_INSNS (8) : COSTS_N_INSNS (12));
- return true;
-
- case PROCESSOR_RIOS2:
- case PROCESSOR_MPCCORE:
- case PROCESSOR_PPC604e:
- *total = COSTS_N_INSNS (2);
- return true;
-
- case PROCESSOR_PPC601:
- *total = COSTS_N_INSNS (5);
+ *total = COSTS_N_INSNS (1);
return true;
+ }
+ /* FALLTHRU */
- case PROCESSOR_PPC603:
- case PROCESSOR_PPC7400:
- case PROCESSOR_PPC750:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? COSTS_N_INSNS (5)
- : (INTVAL (XEXP (x, 1)) >= -256
- && INTVAL (XEXP (x, 1)) <= 255)
- ? COSTS_N_INSNS (2) : COSTS_N_INSNS (3));
- return true;
+ case CONST_DOUBLE:
+ if (mode == DImode && code == CONST_DOUBLE)
+ {
+ if ((outer_code == IOR || outer_code == XOR)
+ && CONST_DOUBLE_HIGH (x) == 0
+ && (CONST_DOUBLE_LOW (x)
+ & ~ (unsigned HOST_WIDE_INT) 0xffff) == 0)
+ {
+ *total = 0;
+ return true;
+ }
+ else if ((outer_code == AND && and64_2_operand (x, DImode))
+ || ((outer_code == SET
+ || outer_code == IOR
+ || outer_code == XOR)
+ && CONST_DOUBLE_HIGH (x) == 0))
+ {
+ *total = COSTS_N_INSNS (1);
+ return true;
+ }
+ }
+ /* FALLTHRU */
- case PROCESSOR_PPC7450:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? COSTS_N_INSNS (4)
- : COSTS_N_INSNS (3));
- return true;
+ case CONST:
+ case HIGH:
+ case SYMBOL_REF:
+ case MEM:
+ /* When optimizing for size, MEM should be slightly more expensive
+ than generating address, e.g., (plus (reg) (const)).
+ L1 cache latency is about two instructions. */
+ *total = optimize_size ? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (2);
+ return true;
- case PROCESSOR_PPC403:
- case PROCESSOR_PPC604:
- case PROCESSOR_PPC8540:
- *total = COSTS_N_INSNS (4);
- return true;
+ case LABEL_REF:
+ *total = 0;
+ return true;
- case PROCESSOR_PPC620:
- case PROCESSOR_PPC630:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (5) : COSTS_N_INSNS (7)
- : (INTVAL (XEXP (x, 1)) >= -256
- && INTVAL (XEXP (x, 1)) <= 255)
- ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4));
- return true;
+ case PLUS:
+ if (mode == DFmode)
+ {
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG)
+ *total = rs6000_cost->dmul - rs6000_cost->fp;
+ else
+ *total = rs6000_cost->dmul;
+ }
+ else
+ *total = rs6000_cost->fp;
+ }
+ else if (mode == SFmode)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+ *total = 0;
+ else
+ *total = rs6000_cost->fp;
+ }
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
- case PROCESSOR_POWER4:
- case PROCESSOR_POWER5:
- *total = (GET_CODE (XEXP (x, 1)) != CONST_INT
- ? GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (3) : COSTS_N_INSNS (4)
- : COSTS_N_INSNS (2));
- return true;
+ case MINUS:
+ if (mode == DFmode)
+ {
+ if (GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG)
+ *total = 0;
+ else
+ *total = rs6000_cost->dmul;
+ }
+ else
+ *total = rs6000_cost->fp;
+ }
+ else if (mode == SFmode)
+ {
+ /* FNMA accounted in outer NEG. */
+ if (outer_code == NEG && GET_CODE (XEXP (x, 0)) == MULT)
+ *total = 0;
+ else
+ *total = rs6000_cost->fp;
+ }
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
- default:
- abort ();
+ case MULT:
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && satisfies_constraint_I (XEXP (x, 1)))
+ {
+ if (INTVAL (XEXP (x, 1)) >= -256
+ && INTVAL (XEXP (x, 1)) <= 255)
+ *total = rs6000_cost->mulsi_const9;
+ else
+ *total = rs6000_cost->mulsi_const;
}
+ /* FMA accounted in outer PLUS/MINUS. */
+ else if ((mode == DFmode || mode == SFmode)
+ && (outer_code == PLUS || outer_code == MINUS))
+ *total = 0;
+ else if (mode == DFmode)
+ *total = rs6000_cost->dmul;
+ else if (mode == SFmode)
+ *total = rs6000_cost->fp;
+ else if (mode == DImode)
+ *total = rs6000_cost->muldi;
+ else
+ *total = rs6000_cost->mulsi;
+ return false;
case DIV:
case MOD:
- if (GET_CODE (XEXP (x, 1)) == CONST_INT
- && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
+ if (FLOAT_MODE_P (mode))
{
- *total = COSTS_N_INSNS (2);
- return true;
+ *total = mode == DFmode ? rs6000_cost->ddiv
+ : rs6000_cost->sdiv;
+ return false;
}
/* FALLTHRU */
case UDIV:
case UMOD:
- switch (rs6000_cpu)
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT
+ && exact_log2 (INTVAL (XEXP (x, 1))) >= 0)
{
- case PROCESSOR_RIOS1:
- *total = COSTS_N_INSNS (19);
- return true;
+ if (code == DIV || code == MOD)
+ /* Shift, addze */
+ *total = COSTS_N_INSNS (2);
+ else
+ /* Shift */
+ *total = COSTS_N_INSNS (1);
+ }
+ else
+ {
+ if (GET_MODE (XEXP (x, 1)) == DImode)
+ *total = rs6000_cost->divdi;
+ else
+ *total = rs6000_cost->divsi;
+ }
+ /* Add in shift and subtract for MOD. */
+ if (code == MOD || code == UMOD)
+ *total += COSTS_N_INSNS (2);
+ return false;
- case PROCESSOR_RIOS2:
- *total = COSTS_N_INSNS (13);
- return true;
+ case FFS:
+ *total = COSTS_N_INSNS (4);
+ return false;
- case PROCESSOR_RS64A:
- *total = (GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (65)
- : COSTS_N_INSNS (67));
- return true;
+ case NOT:
+ if (outer_code == AND || outer_code == IOR || outer_code == XOR)
+ {
+ *total = 0;
+ return false;
+ }
+ /* FALLTHRU */
- case PROCESSOR_MPCCORE:
- *total = COSTS_N_INSNS (6);
- return true;
+ case AND:
+ case IOR:
+ case XOR:
+ case ZERO_EXTRACT:
+ *total = COSTS_N_INSNS (1);
+ return false;
- case PROCESSOR_PPC403:
- *total = COSTS_N_INSNS (33);
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ case ROTATE:
+ case ROTATERT:
+ /* Handle mul_highpart. */
+ if (outer_code == TRUNCATE
+ && GET_CODE (XEXP (x, 0)) == MULT)
+ {
+ if (mode == DImode)
+ *total = rs6000_cost->muldi;
+ else
+ *total = rs6000_cost->mulsi;
return true;
+ }
+ else if (outer_code == AND)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
- case PROCESSOR_PPC405:
- *total = COSTS_N_INSNS (35);
- return true;
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ if (GET_CODE (XEXP (x, 0)) == MEM)
+ *total = 0;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
- case PROCESSOR_PPC440:
- *total = COSTS_N_INSNS (34);
- return true;
+ case COMPARE:
+ case NEG:
+ case ABS:
+ if (!FLOAT_MODE_P (mode))
+ {
+ *total = COSTS_N_INSNS (1);
+ return false;
+ }
+ /* FALLTHRU */
- case PROCESSOR_PPC601:
- *total = COSTS_N_INSNS (36);
- return true;
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case UNSIGNED_FIX:
+ case FLOAT_TRUNCATE:
+ *total = rs6000_cost->fp;
+ return false;
- case PROCESSOR_PPC603:
- *total = COSTS_N_INSNS (37);
- return true;
+ case FLOAT_EXTEND:
+ if (mode == DFmode)
+ *total = 0;
+ else
+ *total = rs6000_cost->fp;
+ return false;
- case PROCESSOR_PPC604:
- case PROCESSOR_PPC604e:
- *total = COSTS_N_INSNS (20);
+ case UNSPEC:
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_FRSP:
+ *total = rs6000_cost->fp;
return true;
- case PROCESSOR_PPC620:
- case PROCESSOR_PPC630:
- *total = (GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (21)
- : COSTS_N_INSNS (37));
- return true;
+ default:
+ break;
+ }
+ break;
- case PROCESSOR_PPC750:
- case PROCESSOR_PPC8540:
- case PROCESSOR_PPC7400:
- *total = COSTS_N_INSNS (19);
+ case CALL:
+ case IF_THEN_ELSE:
+ if (optimize_size)
+ {
+ *total = COSTS_N_INSNS (1);
return true;
+ }
+ else if (FLOAT_MODE_P (mode)
+ && TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS)
+ {
+ *total = rs6000_cost->fp;
+ return false;
+ }
+ break;
- case PROCESSOR_PPC7450:
- *total = COSTS_N_INSNS (23);
+ case EQ:
+ case GTU:
+ case LTU:
+ /* Carry bit requires mode == Pmode.
+ NEG or PLUS already counted so only add one. */
+ if (mode == Pmode
+ && (outer_code == NEG || outer_code == PLUS))
+ {
+ *total = COSTS_N_INSNS (1);
return true;
+ }
+ if (outer_code == SET)
+ {
+ if (XEXP (x, 1) == const0_rtx)
+ {
+ *total = COSTS_N_INSNS (2);
+ return true;
+ }
+ else if (mode == Pmode)
+ {
+ *total = COSTS_N_INSNS (3);
+ return false;
+ }
+ }
+ /* FALLTHRU */
- case PROCESSOR_POWER4:
- case PROCESSOR_POWER5:
- *total = (GET_MODE (XEXP (x, 1)) != DImode
- ? COSTS_N_INSNS (18)
- : COSTS_N_INSNS (34));
+ case GT:
+ case LT:
+ case UNORDERED:
+ if (outer_code == SET && (XEXP (x, 1) == const0_rtx))
+ {
+ *total = COSTS_N_INSNS (2);
return true;
-
- default:
- abort ();
}
-
- case FFS:
- *total = COSTS_N_INSNS (4);
- return true;
-
- case MEM:
- /* MEM should be slightly more expensive than (plus (reg) (const)). */
- *total = 5;
- return true;
+ /* CC COMPARE. */
+ if (outer_code == COMPARE)
+ {
+ *total = 0;
+ return true;
+ }
+ break;
default:
- return false;
+ break;
}
+
+ return false;
}
/* A C expression returning the cost of moving data from a register of class
CLASS1 to one of CLASS2. */
int
-rs6000_register_move_cost (enum machine_mode mode,
+rs6000_register_move_cost (enum machine_mode mode,
enum reg_class from, enum reg_class to)
{
/* Moves from/to GENERAL_REGS. */
@@ -16198,22 +19067,23 @@ rs6000_register_move_cost (enum machine_mode mode,
return (rs6000_memory_move_cost (mode, from, 0)
+ rs6000_memory_move_cost (mode, GENERAL_REGS, 0));
-/* It's more expensive to move CR_REGS than CR0_REGS because of the shift.... */
+ /* It's more expensive to move CR_REGS than CR0_REGS because of the
+ shift. */
else if (from == CR_REGS)
return 4;
else
-/* A move will cost one instruction per GPR moved. */
- return 2 * HARD_REGNO_NREGS (0, mode);
+ /* A move will cost one instruction per GPR moved. */
+ return 2 * hard_regno_nregs[0][mode];
}
-/* Moving between two similar registers is just one instruction. */
+ /* Moving between two similar registers is just one instruction. */
else if (reg_classes_intersect_p (to, from))
return mode == TFmode ? 4 : 2;
-/* Everything else has to go through GENERAL_REGS. */
+ /* Everything else has to go through GENERAL_REGS. */
else
- return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
+ return (rs6000_register_move_cost (mode, GENERAL_REGS, to)
+ rs6000_register_move_cost (mode, from, GENERAL_REGS));
}
@@ -16221,19 +19091,122 @@ rs6000_register_move_cost (enum machine_mode mode,
or from memory. */
int
-rs6000_memory_move_cost (enum machine_mode mode, enum reg_class class,
+rs6000_memory_move_cost (enum machine_mode mode, enum reg_class class,
int in ATTRIBUTE_UNUSED)
{
if (reg_classes_intersect_p (class, GENERAL_REGS))
- return 4 * HARD_REGNO_NREGS (0, mode);
+ return 4 * hard_regno_nregs[0][mode];
else if (reg_classes_intersect_p (class, FLOAT_REGS))
- return 4 * HARD_REGNO_NREGS (32, mode);
+ return 4 * hard_regno_nregs[32][mode];
else if (reg_classes_intersect_p (class, ALTIVEC_REGS))
- return 4 * HARD_REGNO_NREGS (FIRST_ALTIVEC_REGNO, mode);
+ return 4 * hard_regno_nregs[FIRST_ALTIVEC_REGNO][mode];
else
return 4 + rs6000_register_move_cost (mode, class, GENERAL_REGS);
}
+/* Newton-Raphson approximation of single-precision floating point divide n/d.
+ Assumes no trapping math and finite arguments. */
+
+void
+rs6000_emit_swdivsf (rtx res, rtx n, rtx d)
+{
+ rtx x0, e0, e1, y1, u0, v0, one;
+
+ x0 = gen_reg_rtx (SFmode);
+ e0 = gen_reg_rtx (SFmode);
+ e1 = gen_reg_rtx (SFmode);
+ y1 = gen_reg_rtx (SFmode);
+ u0 = gen_reg_rtx (SFmode);
+ v0 = gen_reg_rtx (SFmode);
+ one = force_reg (SFmode, CONST_DOUBLE_FROM_REAL_VALUE (dconst1, SFmode));
+
+ /* x0 = 1./d estimate */
+ emit_insn (gen_rtx_SET (VOIDmode, x0,
+ gen_rtx_UNSPEC (SFmode, gen_rtvec (1, d),
+ UNSPEC_FRES)));
+ /* e0 = 1. - d * x0 */
+ emit_insn (gen_rtx_SET (VOIDmode, e0,
+ gen_rtx_MINUS (SFmode, one,
+ gen_rtx_MULT (SFmode, d, x0))));
+ /* e1 = e0 + e0 * e0 */
+ emit_insn (gen_rtx_SET (VOIDmode, e1,
+ gen_rtx_PLUS (SFmode,
+ gen_rtx_MULT (SFmode, e0, e0), e0)));
+ /* y1 = x0 + e1 * x0 */
+ emit_insn (gen_rtx_SET (VOIDmode, y1,
+ gen_rtx_PLUS (SFmode,
+ gen_rtx_MULT (SFmode, e1, x0), x0)));
+ /* u0 = n * y1 */
+ emit_insn (gen_rtx_SET (VOIDmode, u0,
+ gen_rtx_MULT (SFmode, n, y1)));
+ /* v0 = n - d * u0 */
+ emit_insn (gen_rtx_SET (VOIDmode, v0,
+ gen_rtx_MINUS (SFmode, n,
+ gen_rtx_MULT (SFmode, d, u0))));
+ /* res = u0 + v0 * y1 */
+ emit_insn (gen_rtx_SET (VOIDmode, res,
+ gen_rtx_PLUS (SFmode,
+ gen_rtx_MULT (SFmode, v0, y1), u0)));
+}
+
+/* Newton-Raphson approximation of double-precision floating point divide n/d.
+ Assumes no trapping math and finite arguments. */
+
+void
+rs6000_emit_swdivdf (rtx res, rtx n, rtx d)
+{
+ rtx x0, e0, e1, e2, y1, y2, y3, u0, v0, one;
+
+ x0 = gen_reg_rtx (DFmode);
+ e0 = gen_reg_rtx (DFmode);
+ e1 = gen_reg_rtx (DFmode);
+ e2 = gen_reg_rtx (DFmode);
+ y1 = gen_reg_rtx (DFmode);
+ y2 = gen_reg_rtx (DFmode);
+ y3 = gen_reg_rtx (DFmode);
+ u0 = gen_reg_rtx (DFmode);
+ v0 = gen_reg_rtx (DFmode);
+ one = force_reg (DFmode, CONST_DOUBLE_FROM_REAL_VALUE (dconst1, DFmode));
+
+ /* x0 = 1./d estimate */
+ emit_insn (gen_rtx_SET (VOIDmode, x0,
+ gen_rtx_UNSPEC (DFmode, gen_rtvec (1, d),
+ UNSPEC_FRES)));
+ /* e0 = 1. - d * x0 */
+ emit_insn (gen_rtx_SET (VOIDmode, e0,
+ gen_rtx_MINUS (DFmode, one,
+ gen_rtx_MULT (SFmode, d, x0))));
+ /* y1 = x0 + e0 * x0 */
+ emit_insn (gen_rtx_SET (VOIDmode, y1,
+ gen_rtx_PLUS (DFmode,
+ gen_rtx_MULT (DFmode, e0, x0), x0)));
+ /* e1 = e0 * e0 */
+ emit_insn (gen_rtx_SET (VOIDmode, e1,
+ gen_rtx_MULT (DFmode, e0, e0)));
+ /* y2 = y1 + e1 * y1 */
+ emit_insn (gen_rtx_SET (VOIDmode, y2,
+ gen_rtx_PLUS (DFmode,
+ gen_rtx_MULT (DFmode, e1, y1), y1)));
+ /* e2 = e1 * e1 */
+ emit_insn (gen_rtx_SET (VOIDmode, e2,
+ gen_rtx_MULT (DFmode, e1, e1)));
+ /* y3 = y2 + e2 * y2 */
+ emit_insn (gen_rtx_SET (VOIDmode, y3,
+ gen_rtx_PLUS (DFmode,
+ gen_rtx_MULT (DFmode, e2, y2), y2)));
+ /* u0 = n * y3 */
+ emit_insn (gen_rtx_SET (VOIDmode, u0,
+ gen_rtx_MULT (DFmode, n, y3)));
+ /* v0 = n - d * u0 */
+ emit_insn (gen_rtx_SET (VOIDmode, v0,
+ gen_rtx_MINUS (DFmode, n,
+ gen_rtx_MULT (DFmode, d, u0))));
+ /* res = u0 + v0 * y3 */
+ emit_insn (gen_rtx_SET (VOIDmode, res,
+ gen_rtx_PLUS (DFmode,
+ gen_rtx_MULT (DFmode, v0, y3), u0)));
+}
+
/* Return an RTX representing where to find the function value of a
function returning MODE. */
static rtx
@@ -16281,6 +19254,26 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
enum machine_mode mode;
unsigned int regno;
+ /* Special handling for structs in darwin64. */
+ if (rs6000_darwin64_abi
+ && TYPE_MODE (valtype) == BLKmode
+ && TREE_CODE (valtype) == RECORD_TYPE
+ && int_size_in_bytes (valtype) > 0)
+ {
+ CUMULATIVE_ARGS valcum;
+ rtx valret;
+
+ valcum.words = 0;
+ valcum.fregno = FP_ARG_MIN_REG;
+ valcum.vregno = ALTIVEC_ARG_MIN_REG;
+ /* Do a trial code generation as if this were going to be passed as
+ an argument; if any part goes in memory, we return NULL. */
+ valret = rs6000_darwin64_record_arg (&valcum, valtype, 1, true);
+ if (valret)
+ return valret;
+ /* Otherwise fall through to standard ABI rules. */
+ }
+
if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DImode)
{
/* Long long return value need be split in -mpowerpc64, 32bit ABI. */
@@ -16294,22 +19287,46 @@ rs6000_function_value (tree valtype, tree func ATTRIBUTE_UNUSED)
GP_ARG_RETURN + 1),
GEN_INT (4))));
}
+ if (TARGET_32BIT && TARGET_POWERPC64 && TYPE_MODE (valtype) == DCmode)
+ {
+ return gen_rtx_PARALLEL (DCmode,
+ gen_rtvec (4,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode, GP_ARG_RETURN),
+ const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 1),
+ GEN_INT (4)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 2),
+ GEN_INT (8)),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 3),
+ GEN_INT (12))));
+ }
- if ((INTEGRAL_TYPE_P (valtype)
- && TYPE_PRECISION (valtype) < BITS_PER_WORD)
+ mode = TYPE_MODE (valtype);
+ if ((INTEGRAL_TYPE_P (valtype) && GET_MODE_BITSIZE (mode) < BITS_PER_WORD)
|| POINTER_TYPE_P (valtype))
mode = TARGET_32BIT ? SImode : DImode;
- else
- mode = TYPE_MODE (valtype);
- if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ regno = GP_ARG_RETURN;
+ else if (SCALAR_FLOAT_TYPE_P (valtype) && TARGET_HARD_FLOAT && TARGET_FPRS)
regno = FP_ARG_RETURN;
else if (TREE_CODE (valtype) == COMPLEX_TYPE
&& targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode);
else if (TREE_CODE (valtype) == VECTOR_TYPE
- && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI)
+ && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI
+ && ALTIVEC_VECTOR_MODE (mode))
regno = ALTIVEC_ARG_RETURN;
+ else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
+ && (mode == DFmode || mode == DCmode))
+ return spe_build_register_parallel (mode, GP_ARG_RETURN);
else
regno = GP_ARG_RETURN;
@@ -16323,7 +19340,23 @@ rs6000_libcall_value (enum machine_mode mode)
{
unsigned int regno;
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
+ if (TARGET_32BIT && TARGET_POWERPC64 && mode == DImode)
+ {
+ /* Long long return value need be split in -mpowerpc64, 32bit ABI. */
+ return gen_rtx_PARALLEL (DImode,
+ gen_rtvec (2,
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode, GP_ARG_RETURN),
+ const0_rtx),
+ gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SImode,
+ GP_ARG_RETURN + 1),
+ GEN_INT (4))));
+ }
+
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ regno = GP_ARG_RETURN;
+ else if (SCALAR_FLOAT_MODE_P (mode)
&& TARGET_HARD_FLOAT && TARGET_FPRS)
regno = FP_ARG_RETURN;
else if (ALTIVEC_VECTOR_MODE (mode)
@@ -16331,6 +19364,9 @@ rs6000_libcall_value (enum machine_mode mode)
regno = ALTIVEC_ARG_RETURN;
else if (COMPLEX_MODE_P (mode) && targetm.calls.split_complex_arg)
return rs6000_complex_function_value (mode);
+ else if (TARGET_E500_DOUBLE && TARGET_HARD_FLOAT
+ && (mode == DFmode || mode == DCmode))
+ return spe_build_register_parallel (mode, GP_ARG_RETURN);
else
regno = GP_ARG_RETURN;
@@ -16345,29 +19381,39 @@ rs6000_initial_elimination_offset (int from, int to)
rs6000_stack_t *info = rs6000_stack_info ();
HOST_WIDE_INT offset;
- if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ if (from == HARD_FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
offset = info->push_p ? 0 : -info->total_size;
- else if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
+ else if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
+ {
+ offset = info->push_p ? 0 : -info->total_size;
+ if (FRAME_GROWS_DOWNWARD)
+ offset += info->fixed_size + info->vars_size + info->parm_size;
+ }
+ else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
+ offset = FRAME_GROWS_DOWNWARD
+ ? info->fixed_size + info->vars_size + info->parm_size
+ : 0;
+ else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
offset = info->total_size;
else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
offset = info->push_p ? info->total_size : 0;
else if (from == RS6000_PIC_OFFSET_TABLE_REGNUM)
offset = 0;
else
- abort ();
+ gcc_unreachable ();
return offset;
}
-/* Return true if TYPE is of type __ev64_opaque__. */
+/* Return true if TYPE is a SPE or AltiVec opaque type. */
static bool
-is_ev64_opaque_type (tree type)
+rs6000_is_opaque_type (tree type)
{
- return (TARGET_SPE
- && (type == opaque_V2SI_type_node
+ return (type == opaque_V2SI_type_node
|| type == opaque_V2SF_type_node
- || type == opaque_p_V2SI_type_node));
+ || type == opaque_p_V2SI_type_node
+ || type == opaque_V4SI_type_node);
}
static rtx
@@ -16375,7 +19421,11 @@ rs6000_dwarf_register_span (rtx reg)
{
unsigned regno;
- if (!TARGET_SPE || !SPE_VECTOR_MODE (GET_MODE (reg)))
+ if (TARGET_SPE
+ && (SPE_VECTOR_MODE (GET_MODE (reg))
+ || (TARGET_E500_DOUBLE && GET_MODE (reg) == DFmode)))
+ ;
+ else
return NULL_RTX;
regno = REGNO (reg);
@@ -16423,10 +19473,67 @@ rs6000_dbx_register_number (unsigned int regno)
return 612;
/* SPE high reg number. We get these values of regno from
rs6000_dwarf_register_span. */
- if (regno >= 1200 && regno < 1232)
- return regno;
+ gcc_assert (regno >= 1200 && regno < 1232);
+ return regno;
+}
+
+/* target hook eh_return_filter_mode */
+static enum machine_mode
+rs6000_eh_return_filter_mode (void)
+{
+ return TARGET_32BIT ? SImode : word_mode;
+}
- abort ();
+/* Target hook for scalar_mode_supported_p. */
+static bool
+rs6000_scalar_mode_supported_p (enum machine_mode mode)
+{
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ return true;
+ else
+ return default_scalar_mode_supported_p (mode);
+}
+
+/* Target hook for vector_mode_supported_p. */
+static bool
+rs6000_vector_mode_supported_p (enum machine_mode mode)
+{
+
+ if (TARGET_SPE && SPE_VECTOR_MODE (mode))
+ return true;
+
+ else if (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (mode))
+ return true;
+
+ else
+ return false;
+}
+
+/* Target hook for invalid_arg_for_unprototyped_fn. */
+static const char *
+invalid_arg_for_unprototyped_fn (tree typelist, tree funcdecl, tree val)
+{
+ return (!rs6000_darwin64_abi
+ && typelist == 0
+ && TREE_CODE (TREE_TYPE (val)) == VECTOR_TYPE
+ && (funcdecl == NULL_TREE
+ || (TREE_CODE (funcdecl) == FUNCTION_DECL
+ && DECL_BUILT_IN_CLASS (funcdecl) != BUILT_IN_MD)))
+ ? N_("AltiVec argument passed to unprototyped function")
+ : NULL;
+}
+
+/* For TARGET_SECURE_PLT 32-bit PIC code we can save PIC register
+ setup by using __stack_chk_fail_local hidden function instead of
+ calling __stack_chk_fail directly. Otherwise it is better to call
+ __stack_chk_fail directly. */
+
+static tree
+rs6000_stack_protect_fail (void)
+{
+ return (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT && flag_pic)
+ ? default_hidden_stack_protect_fail ()
+ : default_external_stack_protect_fail ();
}
#include "gt-rs6000.h"
diff --git a/contrib/gcc/config/rs6000/rs6000.h b/contrib/gcc/config/rs6000/rs6000.h
index 01a97da..3294bd2 100644
--- a/contrib/gcc/config/rs6000/rs6000.h
+++ b/contrib/gcc/config/rs6000/rs6000.h
@@ -1,6 +1,7 @@
/* Definitions of target machine for GNU compiler, for IBM RS/6000.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
This file is part of GCC.
@@ -17,8 +18,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Note that some other tm.h files include this one and then override
many of the definitions. */
@@ -40,11 +41,22 @@
#define TARGET_AIX 0
#endif
+/* Control whether function entry points use a "dot" symbol when
+ ABI_AIX. */
+#define DOT_SYMBOLS 1
+
/* Default string to use for cpu if not specified. */
#ifndef TARGET_CPU_DEFAULT
#define TARGET_CPU_DEFAULT ((char *)0)
#endif
+/* If configured for PPC405, support PPC405CR Erratum77. */
+#ifdef CONFIG_PPC405CR
+#define PPC405_ERRATUM77 (rs6000_cpu == PROCESSOR_PPC405)
+#else
+#define PPC405_ERRATUM77 0
+#endif
+
/* Common ASM definitions used by ASM_SPEC among the various targets
for handling -mcpu=xxx switches. */
#define ASM_CPU_SPEC \
@@ -61,6 +73,8 @@
%{mcpu=power3: -mppc64} \
%{mcpu=power4: -mpower4} \
%{mcpu=power5: -mpower4} \
+%{mcpu=power5+: -mpower4} \
+%{mcpu=power6: -mpower4 -maltivec} \
%{mcpu=powerpc: -mppc} \
%{mcpu=rios: -mpwr} \
%{mcpu=rios1: -mpwr} \
@@ -124,252 +138,59 @@
/* Architecture type. */
-extern int target_flags;
-
-/* Use POWER architecture instructions and MQ register. */
-#define MASK_POWER 0x00000001
-
-/* Use POWER2 extensions to POWER architecture. */
-#define MASK_POWER2 0x00000002
-
-/* Use PowerPC architecture instructions. */
-#define MASK_POWERPC 0x00000004
-
-/* Use PowerPC General Purpose group optional instructions, e.g. fsqrt. */
-#define MASK_PPC_GPOPT 0x00000008
-
-/* Use PowerPC Graphics group optional instructions, e.g. fsel. */
-#define MASK_PPC_GFXOPT 0x00000010
-
-/* Use PowerPC-64 architecture instructions. */
-#define MASK_POWERPC64 0x00000020
-
-/* Use revised mnemonic names defined for PowerPC architecture. */
-#define MASK_NEW_MNEMONICS 0x00000040
-
-/* Disable placing fp constants in the TOC; can be turned on when the
- TOC overflows. */
-#define MASK_NO_FP_IN_TOC 0x00000080
-
-/* Disable placing symbol+offset constants in the TOC; can be turned on when
- the TOC overflows. */
-#define MASK_NO_SUM_IN_TOC 0x00000100
+/* Define TARGET_MFCRF if the target assembler does not support the
+ optional field operand for mfcr. */
-/* Output only one TOC entry per module. Normally linking fails if
- there are more than 16K unique variables/constants in an executable. With
- this option, linking fails only if there are more than 16K modules, or
- if there are more than 16K unique variables/constant in a single module.
-
- This is at the cost of having 2 extra loads and one extra store per
- function, and one less allocable register. */
-#define MASK_MINIMAL_TOC 0x00000200
-
-/* Nonzero for the 64 bit ABIs: longs and pointers are 64 bits. The
- chip is running in "64-bit mode", in which CR0 is set in dot
- operations based on all 64 bits of the register, bdnz works on 64-bit
- ctr, lr is 64 bits, and so on. Requires MASK_POWERPC64. */
-#define MASK_64BIT 0x00000400
-
-/* Disable use of FPRs. */
-#define MASK_SOFT_FLOAT 0x00000800
-
-/* Enable load/store multiple, even on PowerPC */
-#define MASK_MULTIPLE 0x00001000
-
-/* Use string instructions for block moves */
-#define MASK_STRING 0x00002000
-
-/* Disable update form of load/store */
-#define MASK_NO_UPDATE 0x00004000
-
-/* Disable fused multiply/add operations */
-#define MASK_NO_FUSED_MADD 0x00008000
-
-/* Nonzero if we need to schedule the prolog and epilog. */
-#define MASK_SCHED_PROLOG 0x00010000
-
-/* Use AltiVec instructions. */
-#define MASK_ALTIVEC 0x00020000
-
-/* Return small structures in memory (as the AIX ABI requires). */
-#define MASK_AIX_STRUCT_RET 0x00040000
-
-/* Use single field mfcr instruction. */
-#define MASK_MFCRF 0x00080000
+#ifndef HAVE_AS_MFCRF
+#undef TARGET_MFCRF
+#define TARGET_MFCRF 0
+#endif
-/* The only remaining free bits are 0x00600000. linux64.h uses
- 0x00100000, and sysv4.h uses 0x00800000 -> 0x40000000.
- 0x80000000 is not available because target_flags is signed. */
+/* Define TARGET_POPCNTB if the target assembler does not support the
+ popcount byte instruction. */
-#define TARGET_POWER (target_flags & MASK_POWER)
-#define TARGET_POWER2 (target_flags & MASK_POWER2)
-#define TARGET_POWERPC (target_flags & MASK_POWERPC)
-#define TARGET_PPC_GPOPT (target_flags & MASK_PPC_GPOPT)
-#define TARGET_PPC_GFXOPT (target_flags & MASK_PPC_GFXOPT)
-#define TARGET_NEW_MNEMONICS (target_flags & MASK_NEW_MNEMONICS)
-#define TARGET_NO_FP_IN_TOC (target_flags & MASK_NO_FP_IN_TOC)
-#define TARGET_NO_SUM_IN_TOC (target_flags & MASK_NO_SUM_IN_TOC)
-#define TARGET_MINIMAL_TOC (target_flags & MASK_MINIMAL_TOC)
-#define TARGET_64BIT (target_flags & MASK_64BIT)
-#define TARGET_SOFT_FLOAT (target_flags & MASK_SOFT_FLOAT)
-#define TARGET_MULTIPLE (target_flags & MASK_MULTIPLE)
-#define TARGET_STRING (target_flags & MASK_STRING)
-#define TARGET_NO_UPDATE (target_flags & MASK_NO_UPDATE)
-#define TARGET_NO_FUSED_MADD (target_flags & MASK_NO_FUSED_MADD)
-#define TARGET_SCHED_PROLOG (target_flags & MASK_SCHED_PROLOG)
-#define TARGET_ALTIVEC (target_flags & MASK_ALTIVEC)
-#define TARGET_AIX_STRUCT_RET (target_flags & MASK_AIX_STRUCT_RET)
+#ifndef HAVE_AS_POPCNTB
+#undef TARGET_POPCNTB
+#define TARGET_POPCNTB 0
+#endif
-/* Define TARGET_MFCRF if the target assembler supports the optional
- field operand for mfcr and the target processor supports the
- instruction. */
+/* Define TARGET_FPRND if the target assembler does not support the
+ fp rounding instructions. */
-#ifdef HAVE_AS_MFCRF
-#define TARGET_MFCRF (target_flags & MASK_MFCRF)
-#else
-#define TARGET_MFCRF 0
+#ifndef HAVE_AS_FPRND
+#undef TARGET_FPRND
+#define TARGET_FPRND 0
#endif
+#ifndef TARGET_SECURE_PLT
+#define TARGET_SECURE_PLT 0
+#endif
#define TARGET_32BIT (! TARGET_64BIT)
-#define TARGET_HARD_FLOAT (! TARGET_SOFT_FLOAT)
-#define TARGET_UPDATE (! TARGET_NO_UPDATE)
-#define TARGET_FUSED_MADD (! TARGET_NO_FUSED_MADD)
-
-/* Emit a dtp-relative reference to a TLS variable. */
-
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- rs6000_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
#ifndef HAVE_AS_TLS
#define HAVE_AS_TLS 0
#endif
+/* Return 1 for a symbol ref for a thread-local storage symbol. */
+#define RS6000_SYMBOL_REF_TLS_P(RTX) \
+ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
+
#ifdef IN_LIBGCC2
/* For libgcc2 we make sure this is a compile time constant */
-#if defined (__64BIT__) || defined (__powerpc64__)
+#if defined (__64BIT__) || defined (__powerpc64__) || defined (__ppc64__)
+#undef TARGET_POWERPC64
#define TARGET_POWERPC64 1
#else
+#undef TARGET_POWERPC64
#define TARGET_POWERPC64 0
#endif
#else
-#define TARGET_POWERPC64 (target_flags & MASK_POWERPC64)
+ /* The option machinery will define this. */
#endif
-#define TARGET_XL_COMPAT 0
-
-/* Run-time compilation parameters selecting different hardware subsets.
-
- 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 \
- {{"power", MASK_POWER | MASK_MULTIPLE | MASK_STRING, \
- N_("Use POWER instruction set")}, \
- {"power2", (MASK_POWER | MASK_MULTIPLE | MASK_STRING \
- | MASK_POWER2), \
- N_("Use POWER2 instruction set")}, \
- {"no-power2", - MASK_POWER2, \
- N_("Do not use POWER2 instruction set")}, \
- {"no-power", - (MASK_POWER | MASK_POWER2 | MASK_MULTIPLE \
- | MASK_STRING), \
- N_("Do not use POWER instruction set")}, \
- {"powerpc", MASK_POWERPC, \
- N_("Use PowerPC instruction set")}, \
- {"no-powerpc", - (MASK_POWERPC | MASK_PPC_GPOPT \
- | MASK_PPC_GFXOPT | MASK_POWERPC64), \
- N_("Do not use PowerPC instruction set")}, \
- {"powerpc-gpopt", MASK_POWERPC | MASK_PPC_GPOPT, \
- N_("Use PowerPC General Purpose group optional instructions")},\
- {"no-powerpc-gpopt", - MASK_PPC_GPOPT, \
- N_("Do not use PowerPC General Purpose group optional instructions")},\
- {"powerpc-gfxopt", MASK_POWERPC | MASK_PPC_GFXOPT, \
- N_("Use PowerPC Graphics group optional instructions")},\
- {"no-powerpc-gfxopt", - MASK_PPC_GFXOPT, \
- N_("Do not use PowerPC Graphics group optional instructions")},\
- {"powerpc64", MASK_POWERPC64, \
- N_("Use PowerPC-64 instruction set")}, \
- {"no-powerpc64", - MASK_POWERPC64, \
- N_("Do not use PowerPC-64 instruction set")}, \
- {"altivec", MASK_ALTIVEC , \
- N_("Use AltiVec instructions")}, \
- {"no-altivec", - MASK_ALTIVEC , \
- N_("Do not use AltiVec instructions")}, \
- {"new-mnemonics", MASK_NEW_MNEMONICS, \
- N_("Use new mnemonics for PowerPC architecture")},\
- {"old-mnemonics", -MASK_NEW_MNEMONICS, \
- N_("Use old mnemonics for PowerPC architecture")},\
- {"full-toc", - (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC \
- | MASK_MINIMAL_TOC), \
- N_("Put everything in the regular TOC")}, \
- {"fp-in-toc", - MASK_NO_FP_IN_TOC, \
- N_("Place floating point constants in TOC")}, \
- {"no-fp-in-toc", MASK_NO_FP_IN_TOC, \
- N_("Do not place floating point constants in TOC")},\
- {"sum-in-toc", - MASK_NO_SUM_IN_TOC, \
- N_("Place symbol+offset constants in TOC")}, \
- {"no-sum-in-toc", MASK_NO_SUM_IN_TOC, \
- N_("Do not place symbol+offset constants in TOC")},\
- {"minimal-toc", MASK_MINIMAL_TOC, \
- "Use only one TOC entry per procedure"}, \
- {"minimal-toc", - (MASK_NO_FP_IN_TOC | MASK_NO_SUM_IN_TOC), \
- ""}, \
- {"no-minimal-toc", - MASK_MINIMAL_TOC, \
- N_("Place variable addresses in the regular TOC")},\
- {"hard-float", - MASK_SOFT_FLOAT, \
- N_("Use hardware floating point")}, \
- {"soft-float", MASK_SOFT_FLOAT, \
- N_("Do not use hardware floating point")}, \
- {"multiple", MASK_MULTIPLE, \
- N_("Generate load/store multiple instructions")}, \
- {"no-multiple", - MASK_MULTIPLE, \
- N_("Do not generate load/store multiple instructions")},\
- {"string", MASK_STRING, \
- N_("Generate string instructions for block moves")},\
- {"no-string", - MASK_STRING, \
- N_("Do not generate string instructions for block moves")},\
- {"update", - MASK_NO_UPDATE, \
- N_("Generate load/store with update instructions")},\
- {"no-update", MASK_NO_UPDATE, \
- N_("Do not generate load/store with update instructions")},\
- {"fused-madd", - MASK_NO_FUSED_MADD, \
- N_("Generate fused multiply/add instructions")},\
- {"no-fused-madd", MASK_NO_FUSED_MADD, \
- N_("Do not generate fused multiply/add instructions")},\
- {"sched-prolog", MASK_SCHED_PROLOG, \
- ""}, \
- {"no-sched-prolog", -MASK_SCHED_PROLOG, \
- N_("Do not schedule the start and end of the procedure")},\
- {"sched-epilog", MASK_SCHED_PROLOG, \
- ""}, \
- {"no-sched-epilog", -MASK_SCHED_PROLOG, \
- ""}, \
- {"aix-struct-return", MASK_AIX_STRUCT_RET, \
- N_("Return all structures in memory (AIX default)")},\
- {"svr4-struct-return", - MASK_AIX_STRUCT_RET, \
- N_("Return small structures in registers (SVR4 default)")},\
- {"no-aix-struct-return", - MASK_AIX_STRUCT_RET, \
- ""}, \
- {"no-svr4-struct-return", MASK_AIX_STRUCT_RET, \
- ""}, \
- {"mfcrf", MASK_MFCRF, \
- N_("Generate single field mfcr instruction")}, \
- {"no-mfcrf", - MASK_MFCRF, \
- N_("Do not generate single field mfcr instruction")},\
- SUBTARGET_SWITCHES \
- {"", TARGET_DEFAULT | MASK_SCHED_PROLOG, \
- ""}}
-
#define TARGET_DEFAULT (MASK_POWER | MASK_MULTIPLE | MASK_STRING)
-/* This is meant to be redefined in the host dependent files */
-#define SUBTARGET_SWITCHES
-
/* Processor type. Order must match cpu attribute in MD file. */
enum processor_type
{
@@ -438,46 +259,6 @@ enum group_termination
previous_group
};
-/* This is meant to be overridden in target specific files. */
-#define SUBTARGET_OPTIONS
-
-#define TARGET_OPTIONS \
-{ \
- {"cpu=", &rs6000_select[1].string, \
- N_("Use features of and schedule code for given CPU"), 0}, \
- {"tune=", &rs6000_select[2].string, \
- N_("Schedule code for given CPU"), 0}, \
- {"debug=", &rs6000_debug_name, N_("Enable debug output"), 0}, \
- {"traceback=", &rs6000_traceback_name, \
- N_("Select full, part, or no traceback table"), 0}, \
- {"abi=", &rs6000_abi_string, N_("Specify ABI to use"), 0}, \
- {"long-double-", &rs6000_long_double_size_string, \
- N_("Specify size of long double (64 or 128 bits)"), 0}, \
- {"isel=", &rs6000_isel_string, \
- N_("Specify yes/no if isel instructions should be generated"), 0}, \
- {"spe=", &rs6000_spe_string, \
- N_("Specify yes/no if SPE SIMD instructions should be generated"), 0},\
- {"float-gprs=", &rs6000_float_gprs_string, \
- N_("Specify yes/no if using floating point in the GPRs"), 0}, \
- {"vrsave=", &rs6000_altivec_vrsave_string, \
- N_("Specify yes/no if VRSAVE instructions should be generated for AltiVec"), 0}, \
- {"longcall", &rs6000_longcall_switch, \
- N_("Avoid all range limits on call instructions"), 0}, \
- {"no-longcall", &rs6000_longcall_switch, "", 0}, \
- {"warn-altivec-long", &rs6000_warn_altivec_long_switch, \
- N_("Warn about deprecated 'vector long ...' AltiVec type usage"), 0}, \
- {"no-warn-altivec-long", &rs6000_warn_altivec_long_switch, "", 0}, \
- {"sched-costly-dep=", &rs6000_sched_costly_dep_str, \
- N_("Determine which dependences between insns are considered costly"), 0}, \
- {"insert-sched-nops=", &rs6000_sched_insert_nops_str, \
- N_("Specify which post scheduling nop insertion scheme to apply"), 0}, \
- {"align-", &rs6000_alignment_string, \
- N_("Specify alignment of structure fields default/natural"), 0}, \
- {"prioritize-restricted-insns=", &rs6000_sched_restricted_insns_priority_str, \
- N_("Specify scheduling priority for dispatch slot restricted insns"), 0}, \
- SUBTARGET_OPTIONS \
-}
-
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-cpu is ignored if -mcpu is specified.
--with-tune is ignored if -mtune is specified.
@@ -501,7 +282,6 @@ extern struct rs6000_cpu_select rs6000_select[];
/* Debug support */
extern const char *rs6000_debug_name; /* Name for -mdebug-xxxx option */
-extern const char *rs6000_abi_string; /* for -mabi={sysv,darwin,eabi,aix,altivec} */
extern int rs6000_debug_stack; /* debug stack applications */
extern int rs6000_debug_arg; /* debug argument handling */
@@ -512,32 +292,15 @@ extern const char *rs6000_traceback_name; /* Type of traceback table. */
/* These are separate from target_flags because we've run out of bits
there. */
-extern const char *rs6000_long_double_size_string;
extern int rs6000_long_double_type_size;
+extern int rs6000_ieeequad;
extern int rs6000_altivec_abi;
extern int rs6000_spe_abi;
-extern int rs6000_isel;
-extern int rs6000_spe;
extern int rs6000_float_gprs;
-extern const char *rs6000_float_gprs_string;
-extern const char *rs6000_isel_string;
-extern const char *rs6000_spe_string;
-extern const char *rs6000_altivec_vrsave_string;
-extern int rs6000_altivec_vrsave;
-extern const char *rs6000_longcall_switch;
-extern int rs6000_default_long_calls;
-extern const char* rs6000_alignment_string;
extern int rs6000_alignment_flags;
-extern const char *rs6000_sched_restricted_insns_priority_str;
-extern int rs6000_sched_restricted_insns_priority;
-extern const char *rs6000_sched_costly_dep_str;
-extern enum rs6000_dependence_cost rs6000_sched_costly_dep;
extern const char *rs6000_sched_insert_nops_str;
extern enum rs6000_nop_insertion rs6000_sched_insert_nops;
-extern int rs6000_warn_altivec_long;
-extern const char *rs6000_warn_altivec_long_switch;
-
/* Alignment options for fields in structures for sub-targets following
AIX-like ABI.
ALIGN_POWER word-aligns FP doubles (default AIX ABI).
@@ -546,7 +309,7 @@ extern const char *rs6000_warn_altivec_long_switch;
Override the macro definitions when compiling libobjc to avoid undefined
reference to rs6000_alignment_flags due to library's use of GCC alignment
macros which use the macros below. */
-
+
#ifndef IN_TARGET_LIBS
#define MASK_ALIGN_POWER 0x00000000
#define MASK_ALIGN_NATURAL 0x00000001
@@ -556,14 +319,19 @@ extern const char *rs6000_warn_altivec_long_switch;
#endif
#define TARGET_LONG_DOUBLE_128 (rs6000_long_double_type_size == 128)
+#define TARGET_IEEEQUAD rs6000_ieeequad
#define TARGET_ALTIVEC_ABI rs6000_altivec_abi
-#define TARGET_ALTIVEC_VRSAVE rs6000_altivec_vrsave
#define TARGET_SPE_ABI 0
#define TARGET_SPE 0
#define TARGET_E500 0
#define TARGET_ISEL 0
#define TARGET_FPRS 1
+#define TARGET_E500_SINGLE 0
+#define TARGET_E500_DOUBLE 0
+
+/* E500 processors only support plain "sync", not lwsync. */
+#define TARGET_NO_LWSYNC TARGET_E500
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
@@ -587,6 +355,7 @@ extern const char *rs6000_warn_altivec_long_switch;
/* Target pragma. */
#define REGISTER_TARGET_PRAGMAS() do { \
c_register_pragma (0, "longcall", rs6000_pragma_longcall); \
+ targetm.resolve_overloaded_builtin = altivec_resolve_overloaded_builtin; \
} while (0)
/* Target #defines. */
@@ -682,7 +451,6 @@ extern const char *rs6000_warn_altivec_long_switch;
target machine. If you don't define this, the default is one
word. */
#define LONG_TYPE_SIZE (TARGET_32BIT ? 32 : 64)
-#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
@@ -704,9 +472,6 @@ extern const char *rs6000_warn_altivec_long_switch;
words. */
#define LONG_DOUBLE_TYPE_SIZE rs6000_long_double_type_size
-/* Constant which presents upper bound of the above value. */
-#define MAX_LONG_DOUBLE_TYPE_SIZE 128
-
/* Define this to set long double type size to use in libgcc2.c, which can
not depend on target_flags. */
#ifdef __LONG_DOUBLE_128__
@@ -740,7 +505,9 @@ extern const char *rs6000_warn_altivec_long_switch;
that the object would ordinarily have. */
#define LOCAL_ALIGNMENT(TYPE, ALIGN) \
((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) ? 128 : \
- (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE) ? 64 : ALIGN)
+ (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 : \
+ (TARGET_SPE && TREE_CODE (TYPE) == VECTOR_TYPE \
+ && SPE_VECTOR_MODE (TYPE_MODE (TYPE))) ? 64 : ALIGN)
/* Alignment of field after `int : 0' in a structure. */
#define EMPTY_FIELD_BOUNDARY 32
@@ -756,9 +523,13 @@ extern const char *rs6000_warn_altivec_long_switch;
store_bit_field() will force (subreg:DI (reg:V2SI x))'s to the
back-end. Because a single GPR can hold a V2SI, but not a DI, the
best thing to do is set structs to BLKmode and avoid Severe Tire
- Damage. */
+ Damage.
+
+ On e500 v2, DF and DI modes suffer from the same anomaly. DF can
+ fit into 1, whereas DI still needs two. */
#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) \
- (TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE)
+ ((TARGET_SPE && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \
+ || (TARGET_E500_DOUBLE && (MODE) == DFmode))
/* A bit-field declared as `int' forces `int' alignment for the struct. */
#define PCC_BITFIELD_TYPE_MATTERS 1
@@ -772,9 +543,11 @@ extern const char *rs6000_warn_altivec_long_switch;
: (ALIGN))
/* Make arrays of chars word-aligned for the same reasons.
- Align vectors to 128 bits. */
+ Align vectors to 128 bits. Align SPE vectors and E500 v2 doubles to
+ 64 bits. */
#define DATA_ALIGNMENT(TYPE, ALIGN) \
(TREE_CODE (TYPE) == VECTOR_TYPE ? (TARGET_SPE_ABI ? 64 : 128) \
+ : (TARGET_E500_DOUBLE && TYPE_MODE (TYPE) == DFmode) ? 64 \
: TREE_CODE (TYPE) == ARRAY_TYPE \
&& TYPE_MODE (TREE_TYPE (TYPE)) == QImode \
&& (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
@@ -813,15 +586,18 @@ extern const char *rs6000_warn_altivec_long_switch;
We also create a pseudo register for float/int conversions, that will
really represent the memory location used. It is represented here as
a register, in order to work around problems in allocating stack storage
- in inline functions. */
+ in inline functions.
-#define FIRST_PSEUDO_REGISTER 113
+ Another pseudo (not included in DWARF_FRAME_REGISTERS) is soft frame
+ pointer, which is eventually eliminated in favor of SP or FP. */
+
+#define FIRST_PSEUDO_REGISTER 114
/* This must be included for pre gcc 3.0 glibc compatibility. */
#define PRE_GCC3_DWARF_FRAME_REGISTERS 77
/* Add 32 dwarf columns for synthetic SPE registers. */
-#define DWARF_FRAME_REGISTERS (FIRST_PSEUDO_REGISTER + 32)
+#define DWARF_FRAME_REGISTERS ((FIRST_PSEUDO_REGISTER - 1) + 32)
/* The SPE has an additional 32 synthetic registers, with DWARF debug
info numbering for these registers starting at 1200. While eh_frame
@@ -835,13 +611,28 @@ extern const char *rs6000_warn_altivec_long_switch;
avoid invalidating older SPE eh_frame info.
We must map them here to avoid huge unwinder tables mostly consisting
- of unused space. */
+ of unused space. */
#define DWARF_REG_TO_UNWIND_COLUMN(r) \
- ((r) > 1200 ? ((r) - 1200 + FIRST_PSEUDO_REGISTER) : (r))
+ ((r) > 1200 ? ((r) - 1200 + FIRST_PSEUDO_REGISTER - 1) : (r))
+
+/* Use standard DWARF numbering for DWARF debugging information. */
+#define DBX_REGISTER_NUMBER(REGNO) rs6000_dbx_register_number (REGNO)
/* Use gcc hard register numbering for eh_frame. */
#define DWARF_FRAME_REGNUM(REGNO) (REGNO)
+/* Map register numbers held in the call frame info that gcc has
+ collected using DWARF_FRAME_REGNUM to those that should be output in
+ .debug_frame and .eh_frame. We continue to use gcc hard reg numbers
+ for .eh_frame, but use the numbers mandated by the various ABIs for
+ .debug_frame. rs6000_emit_prologue has translated any combination of
+ CR2, CR3, CR4 saves to a save of CR2. The actual code emitted saves
+ the whole of CR, so we map CR2_REGNO to the DWARF reg for CR. */
+#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) \
+ ((FOR_EH) ? (REGNO) \
+ : (REGNO) == CR2_REGNO ? 64 \
+ : DBX_REGISTER_NUMBER (REGNO))
+
/* 1 for registers that have pervasive standard uses
and are not available for the register allocator.
@@ -862,7 +653,7 @@ extern const char *rs6000_warn_altivec_long_switch;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1 \
- , 1, 1 \
+ , 1, 1, 1 \
}
/* 1 for registers not available across function calls.
@@ -882,7 +673,7 @@ extern const char *rs6000_warn_altivec_long_switch;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
1, 1 \
- , 1, 1 \
+ , 1, 1, 1 \
}
/* Like `CALL_USED_REGISTERS' except this macro doesn't require that
@@ -890,7 +681,7 @@ extern const char *rs6000_warn_altivec_long_switch;
(`CALL_USED_REGISTERS' must be a superset of `FIXED_REGISTERS').
This macro is optional. If not specified, it defaults to the value
of `CALL_USED_REGISTERS'. */
-
+
#define CALL_REALLY_USED_REGISTERS \
{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, FIXED_R13, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
@@ -901,7 +692,7 @@ extern const char *rs6000_warn_altivec_long_switch;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
0, 0 \
- , 0, 0 \
+ , 0, 0, 0 \
}
#define MQ_REGNO 64
@@ -920,6 +711,10 @@ extern const char *rs6000_warn_altivec_long_switch;
#define SPE_ACC_REGNO 111
#define SPEFSCR_REGNO 112
+#define FIRST_SAVED_ALTIVEC_REGNO (FIRST_ALTIVEC_REGNO+20)
+#define FIRST_SAVED_FP_REGNO (14+32)
+#define FIRST_SAVED_GP_REGNO 13
+
/* List the order in which to allocate registers. Each register must be
listed once, even those in FIXED_REGISTERS.
@@ -927,31 +722,31 @@ extern const char *rs6000_warn_altivec_long_switch;
fp0 (not saved or used for anything)
fp13 - fp2 (not saved; incoming fp arg registers)
fp1 (not saved; return value)
- fp31 - fp14 (saved; order given to save least number)
+ fp31 - fp14 (saved; order given to save least number)
cr7, cr6 (not saved or special)
cr1 (not saved, but used for FP operations)
cr0 (not saved, but used for arithmetic operations)
cr4, cr3, cr2 (saved)
- r0 (not saved; cannot be base reg)
+ r0 (not saved; cannot be base reg)
r9 (not saved; best for TImode)
r11, r10, r8-r4 (not saved; highest used first to make less conflict)
- r3 (not saved; return value register)
+ r3 (not saved; return value register)
r31 - r13 (saved; order given to save least number)
r12 (not saved; if used for DImode or DFmode would use r13)
mq (not saved; best to use it if we can)
ctr (not saved; when we have the choice ctr is better)
lr (saved)
- cr5, r1, r2, ap, xer, vrsave, vscr (fixed)
+ cr5, r1, r2, ap, xer (fixed)
+ v0 - v1 (not saved or used for anything)
+ v13 - v3 (not saved; incoming vector arg registers)
+ v2 (not saved; incoming vector arg reg; return value)
+ v19 - v14 (not saved or used for anything)
+ v31 - v20 (saved; order given to save least number)
+ vrsave, vscr (fixed)
spe_acc, spefscr (fixed)
-
- AltiVec registers:
- v0 - v1 (not saved or used for anything)
- v13 - v3 (not saved; incoming vector arg registers)
- v2 (not saved; incoming vector arg reg; return value)
- v19 - v14 (not saved or used for anything)
- v31 - v20 (saved; order given to save least number)
+ sfp (fixed)
*/
-
+
#if FIXED_R2 == 1
#define MAYBE_R2_AVAILABLE
#define MAYBE_R2_FIXED 2,
@@ -960,28 +755,28 @@ extern const char *rs6000_warn_altivec_long_switch;
#define MAYBE_R2_FIXED
#endif
-#define REG_ALLOC_ORDER \
- {32, \
- 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
- 33, \
- 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \
- 50, 49, 48, 47, 46, \
- 75, 74, 69, 68, 72, 71, 70, \
- 0, MAYBE_R2_AVAILABLE \
- 9, 11, 10, 8, 7, 6, 5, 4, \
- 3, \
- 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
- 18, 17, 16, 15, 14, 13, 12, \
- 64, 66, 65, \
- 73, 1, MAYBE_R2_FIXED 67, 76, \
- /* AltiVec registers. */ \
- 77, 78, \
- 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
- 79, \
- 96, 95, 94, 93, 92, 91, \
- 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, \
- 97, 109, 110 \
- , 111, 112 \
+#define REG_ALLOC_ORDER \
+ {32, \
+ 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, \
+ 33, \
+ 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, \
+ 50, 49, 48, 47, 46, \
+ 75, 74, 69, 68, 72, 71, 70, \
+ 0, MAYBE_R2_AVAILABLE \
+ 9, 11, 10, 8, 7, 6, 5, 4, \
+ 3, \
+ 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, \
+ 18, 17, 16, 15, 14, 13, 12, \
+ 64, 66, 65, \
+ 73, 1, MAYBE_R2_FIXED 67, 76, \
+ /* AltiVec registers. */ \
+ 77, 78, \
+ 90, 89, 88, 87, 86, 85, 84, 83, 82, 81, 80, \
+ 79, \
+ 96, 95, 94, 93, 92, 91, \
+ 108, 107, 106, 105, 104, 103, 102, 101, 100, 99, 98, 97, \
+ 109, 110, \
+ 111, 112, 113 \
}
/* True if register is floating-point. */
@@ -994,7 +789,8 @@ extern const char *rs6000_warn_altivec_long_switch;
#define CR_REGNO_NOT_CR0_P(N) ((N) >= 69 && (N) <= 75)
/* True if register is an integer register. */
-#define INT_REGNO_P(N) ((N) <= 31 || (N) == ARG_POINTER_REGNUM)
+#define INT_REGNO_P(N) \
+ ((N) <= 31 || (N) == ARG_POINTER_REGNUM || (N) == FRAME_POINTER_REGNUM)
/* SPE SIMD registers are just the GPRs. */
#define SPE_SIMD_REGNO_P(N) ((N) <= 31)
@@ -1006,29 +802,13 @@ extern const char *rs6000_warn_altivec_long_switch;
#define ALTIVEC_REGNO_P(N) ((N) >= FIRST_ALTIVEC_REGNO && (N) <= LAST_ALTIVEC_REGNO)
/* 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.
-
- For the SPE, GPRs are 64 bits but only 32 bits are visible in
- scalar instructions. The upper 32 bits are only available to the
- SIMD instructions.
-
- POWER and PowerPC GPRs hold 32 bits worth;
- PowerPC64 GPRs and FPRs point register holds 64 bits worth. */
-
-#define HARD_REGNO_NREGS(REGNO, MODE) \
- (FP_REGNO_P (REGNO) \
- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
- : (SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE)) \
- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_SPE_WORD - 1) / UNITS_PER_SPE_WORD) \
- : ALTIVEC_REGNO_P (REGNO) \
- ? ((GET_MODE_SIZE (MODE) + UNITS_PER_ALTIVEC_WORD - 1) / UNITS_PER_ALTIVEC_WORD) \
- : ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+ to hold something of mode MODE. */
+
+#define HARD_REGNO_NREGS(REGNO, MODE) rs6000_hard_regno_nregs ((REGNO), (MODE))
#define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) \
((TARGET_32BIT && TARGET_POWERPC64 \
- && (MODE == DImode || MODE == DFmode) \
+ && (GET_MODE_SIZE (MODE) > 4) \
&& INT_REGNO_P (REGNO)) ? 1 : 0)
#define ALTIVEC_VECTOR_MODE(MODE) \
@@ -1043,44 +823,24 @@ extern const char *rs6000_warn_altivec_long_switch;
|| (MODE) == V1DImode \
|| (MODE) == V2SImode)
-/* Define this macro to be nonzero if the port is prepared to handle
- insns involving vector mode MODE. At the very least, it must have
- move patterns for this mode. */
-
-#define VECTOR_MODE_SUPPORTED_P(MODE) \
- ((TARGET_SPE && SPE_VECTOR_MODE (MODE)) \
- || (TARGET_ALTIVEC && ALTIVEC_VECTOR_MODE (MODE)))
-
-/* Value is 1 if hard register REGNO can hold a value of machine-mode MODE.
- For POWER and PowerPC, the GPRs can hold any mode, but values bigger
- than one register cannot go past R31. The float
- registers only can hold floating modes and DImode, and CR register only
- can hold CC modes. We cannot put TImode anywhere except general
- register and it must be able to fit within the register set. */
-
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (INT_REGNO_P (REGNO) ? \
- INT_REGNO_P (REGNO + HARD_REGNO_NREGS (REGNO, MODE) - 1) \
- : FP_REGNO_P (REGNO) ? \
- ((GET_MODE_CLASS (MODE) == MODE_FLOAT \
- && FP_REGNO_P (REGNO + HARD_REGNO_NREGS (REGNO, MODE) - 1)) \
- || (GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) == UNITS_PER_FP_WORD)) \
- : ALTIVEC_REGNO_P (REGNO) ? ALTIVEC_VECTOR_MODE (MODE) \
- : SPE_SIMD_REGNO_P (REGNO) && TARGET_SPE && SPE_VECTOR_MODE (MODE) ? 1 \
- : CR_REGNO_P (REGNO) ? GET_MODE_CLASS (MODE) == MODE_CC \
- : XER_REGNO_P (REGNO) ? (MODE) == PSImode \
- : GET_MODE_SIZE (MODE) <= UNITS_PER_WORD)
+#define UNITS_PER_SIMD_WORD \
+ (TARGET_ALTIVEC ? UNITS_PER_ALTIVEC_WORD \
+ : (TARGET_SPE ? UNITS_PER_SPE_WORD : UNITS_PER_WORD))
+
+/* Value is TRUE if hard register REGNO can hold a value of
+ machine-mode MODE. */
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ rs6000_hard_regno_mode_ok_p[(int)(MODE)][REGNO]
/* 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) \
- (GET_MODE_CLASS (MODE1) == MODE_FLOAT \
- ? GET_MODE_CLASS (MODE2) == MODE_FLOAT \
- : GET_MODE_CLASS (MODE2) == MODE_FLOAT \
- ? GET_MODE_CLASS (MODE1) == MODE_FLOAT \
+ (SCALAR_FLOAT_MODE_P (MODE1) \
+ ? SCALAR_FLOAT_MODE_P (MODE2) \
+ : SCALAR_FLOAT_MODE_P (MODE2) \
+ ? SCALAR_FLOAT_MODE_P (MODE1) \
: GET_MODE_CLASS (MODE1) == MODE_CC \
? GET_MODE_CLASS (MODE2) == MODE_CC \
: GET_MODE_CLASS (MODE2) == MODE_CC \
@@ -1120,9 +880,9 @@ extern const char *rs6000_warn_altivec_long_switch;
#define BRANCH_COST 3
/* Override BRANCH_COST heuristic which empirically produces worse
- performance for fold_range_test(). */
+ performance for removing short circuiting from the logical ops. */
-#define RANGE_TEST_NON_SHORT_CIRCUIT 0
+#define LOGICAL_OP_NON_SHORT_CIRCUIT 0
/* A fixed register used at prologue and epilogue generation to fix
addressing modes. The SPE needs heavy addressing fixes at the last
@@ -1137,62 +897,10 @@ extern const char *rs6000_warn_altivec_long_switch;
#define FIXED_SCRATCH (TARGET_SPE ? 14 : 11)
-/* Define this macro to change register usage conditional on target flags.
- Set MQ register fixed (already call_used) if not POWER architecture
- (RIOS1, RIOS2, RSC, and PPC601) so that it will not be allocated.
- 64-bit AIX reserves GPR13 for thread-private data.
- Conditionally disable FPRs. */
+/* Define this macro to change register usage conditional on target
+ flags. */
-#define CONDITIONAL_REGISTER_USAGE \
-{ \
- int i; \
- if (! TARGET_POWER) \
- fixed_regs[64] = 1; \
- if (TARGET_64BIT) \
- fixed_regs[13] = call_used_regs[13] \
- = call_really_used_regs[13] = 1; \
- if (TARGET_SOFT_FLOAT || !TARGET_FPRS) \
- for (i = 32; i < 64; i++) \
- fixed_regs[i] = call_used_regs[i] \
- = call_really_used_regs[i] = 1; \
- if (DEFAULT_ABI == ABI_V4 \
- && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM \
- && flag_pic == 2) \
- fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
- if (DEFAULT_ABI == ABI_V4 \
- && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM \
- && flag_pic == 1) \
- fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
- if (DEFAULT_ABI == ABI_DARWIN \
- && PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) \
- global_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = call_really_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
- if (TARGET_TOC && TARGET_MINIMAL_TOC) \
- fixed_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] \
- = call_used_regs[RS6000_PIC_OFFSET_TABLE_REGNUM] = 1; \
- if (TARGET_ALTIVEC) \
- global_regs[VSCR_REGNO] = 1; \
- if (TARGET_SPE) \
- { \
- global_regs[SPEFSCR_REGNO] = 1; \
- fixed_regs[FIXED_SCRATCH] \
- = call_used_regs[FIXED_SCRATCH] \
- = call_really_used_regs[FIXED_SCRATCH] = 1; \
- } \
- if (! TARGET_ALTIVEC) \
- { \
- for (i = FIRST_ALTIVEC_REGNO; i <= LAST_ALTIVEC_REGNO; ++i) \
- fixed_regs[i] = call_used_regs[i] = call_really_used_regs[i] = 1; \
- call_really_used_regs[VRSAVE_REGNO] = 1; \
- } \
- if (TARGET_ALTIVEC_ABI) \
- for (i = FIRST_ALTIVEC_REGNO; i < FIRST_ALTIVEC_REGNO + 20; ++i) \
- call_used_regs[i] = call_really_used_regs[i] = 1; \
-}
+#define CONDITIONAL_REGISTER_USAGE rs6000_conditional_register_usage ()
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
@@ -1204,7 +912,10 @@ extern const char *rs6000_warn_altivec_long_switch;
#define STACK_POINTER_REGNUM 1
/* Base register for access to local variables of the function. */
-#define FRAME_POINTER_REGNUM 31
+#define HARD_FRAME_POINTER_REGNUM 31
+
+/* Base register for access to local variables of the function. */
+#define FRAME_POINTER_REGNUM 113
/* Value should be nonzero if functions must have frame pointers.
Zero means the frame pointer need not be set up (and parms
@@ -1316,26 +1027,26 @@ enum reg_class
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0xfffffffe, 0x00000000, 0x00000008, 0x00000000 }, /* BASE_REGS */ \
- { 0xffffffff, 0x00000000, 0x00000008, 0x00000000 }, /* GENERAL_REGS */ \
+ { 0xfffffffe, 0x00000000, 0x00000008, 0x00020000 }, /* BASE_REGS */ \
+ { 0xffffffff, 0x00000000, 0x00000008, 0x00020000 }, /* GENERAL_REGS */ \
{ 0x00000000, 0xffffffff, 0x00000000, 0x00000000 }, /* FLOAT_REGS */ \
{ 0x00000000, 0x00000000, 0xffffe000, 0x00001fff }, /* ALTIVEC_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00002000 }, /* VRSAVE_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00004000 }, /* VSCR_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00008000 }, /* SPE_ACC_REGS */ \
{ 0x00000000, 0x00000000, 0x00000000, 0x00010000 }, /* SPEFSCR_REGS */ \
- { 0xffffffff, 0xffffffff, 0x00000008, 0x00000000 }, /* NON_SPECIAL_REGS */ \
+ { 0xffffffff, 0xffffffff, 0x00000008, 0x00020000 }, /* NON_SPECIAL_REGS */ \
{ 0x00000000, 0x00000000, 0x00000001, 0x00000000 }, /* MQ_REGS */ \
{ 0x00000000, 0x00000000, 0x00000002, 0x00000000 }, /* LINK_REGS */ \
{ 0x00000000, 0x00000000, 0x00000004, 0x00000000 }, /* CTR_REGS */ \
{ 0x00000000, 0x00000000, 0x00000006, 0x00000000 }, /* LINK_OR_CTR_REGS */ \
{ 0x00000000, 0x00000000, 0x00000007, 0x00002000 }, /* SPECIAL_REGS */ \
- { 0xffffffff, 0x00000000, 0x0000000f, 0x00000000 }, /* SPEC_OR_GEN_REGS */ \
+ { 0xffffffff, 0x00000000, 0x0000000f, 0x00022000 }, /* SPEC_OR_GEN_REGS */ \
{ 0x00000000, 0x00000000, 0x00000010, 0x00000000 }, /* CR0_REGS */ \
{ 0x00000000, 0x00000000, 0x00000ff0, 0x00000000 }, /* CR_REGS */ \
- { 0xffffffff, 0x00000000, 0x0000efff, 0x00000000 }, /* NON_FLOAT_REGS */ \
+ { 0xffffffff, 0x00000000, 0x0000efff, 0x00020000 }, /* NON_FLOAT_REGS */ \
{ 0x00000000, 0x00000000, 0x00001000, 0x00000000 }, /* XER_REGS */ \
- { 0xffffffff, 0xffffffff, 0xffffffff, 0x00003fff } /* ALL_REGS */ \
+ { 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff } /* ALL_REGS */ \
}
/* The same information, inverted:
@@ -1356,115 +1067,27 @@ enum reg_class
: (REGNO) == ARG_POINTER_REGNUM ? BASE_REGS \
: (REGNO) == XER_REGNO ? XER_REGS \
: (REGNO) == VRSAVE_REGNO ? VRSAVE_REGS \
- : (REGNO) == VSCR_REGNO ? VRSAVE_REGS \
+ : (REGNO) == VSCR_REGNO ? VRSAVE_REGS \
: (REGNO) == SPE_ACC_REGNO ? SPE_ACC_REGS \
: (REGNO) == SPEFSCR_REGNO ? SPEFSCR_REGS \
+ : (REGNO) == FRAME_POINTER_REGNUM ? BASE_REGS \
: NO_REGS)
/* The class value for index registers, and the one for base regs. */
#define INDEX_REG_CLASS GENERAL_REGS
#define BASE_REG_CLASS BASE_REGS
-/* Get reg_class from a letter such as appears in the machine description. */
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'f' ? FLOAT_REGS \
- : (C) == 'b' ? BASE_REGS \
- : (C) == 'h' ? SPECIAL_REGS \
- : (C) == 'q' ? MQ_REGS \
- : (C) == 'c' ? CTR_REGS \
- : (C) == 'l' ? LINK_REGS \
- : (C) == 'v' ? ALTIVEC_REGS \
- : (C) == 'x' ? CR0_REGS \
- : (C) == 'y' ? CR_REGS \
- : (C) == 'z' ? XER_REGS \
- : NO_REGS)
-
-/* The letters I, J, K, L, M, N, and P in a register constraint string
- can be used to stand for particular ranges of immediate operands.
- This macro defines what the ranges are.
- C is the letter, and VALUE is a constant value.
- Return 1 if VALUE is in the range specified by C.
-
- `I' is a signed 16-bit constant
- `J' is a constant with only the high-order 16 bits nonzero
- `K' is a constant with only the low-order 16 bits nonzero
- `L' is a signed 16-bit constant shifted left 16 bits
- `M' is a constant that is greater than 31
- `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 */
-
-#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- ( (C) == 'I' ? (unsigned HOST_WIDE_INT) ((VALUE) + 0x8000) < 0x10000 \
- : (C) == 'J' ? ((VALUE) & (~ (unsigned HOST_WIDE_INT) 0xffff0000)) == 0 \
- : (C) == 'K' ? ((VALUE) & (~ (HOST_WIDE_INT) 0xffff)) == 0 \
- : (C) == 'L' ? (((VALUE) & 0xffff) == 0 \
- && ((VALUE) >> 31 == -1 || (VALUE) >> 31 == 0)) \
- : (C) == 'M' ? (VALUE) > 31 \
- : (C) == 'N' ? (VALUE) > 0 && exact_log2 (VALUE) >= 0 \
- : (C) == 'O' ? (VALUE) == 0 \
- : (C) == 'P' ? (unsigned HOST_WIDE_INT) ((- (VALUE)) + 0x8000) < 0x10000 \
- : 0)
-
-/* Similar, but for floating constants, and defining letters G and H.
- Here VALUE is the CONST_DOUBLE rtx itself.
-
- We flag for special constants when we can copy the constant into
- a general register in two insns for DF/DI and one insn for SF.
-
- 'H' is used for DI/DF constants that take 3 insns. */
-
-#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ( (C) == 'G' ? (num_insns_constant (VALUE, GET_MODE (VALUE)) \
- == ((GET_MODE (VALUE) == SFmode) ? 1 : 2)) \
- : (C) == 'H' ? (num_insns_constant (VALUE, GET_MODE (VALUE)) == 3) \
- : 0)
-
-/* Optional extra constraints for this machine.
-
- 'Q' means that is a memory operand that is just an offset from a reg.
- 'R' is for AIX TOC entries.
- 'S' is a constant that can be placed into a 64-bit mask operand
- 'T' is a constant that can be placed into a 32-bit mask operand
- 'U' is for V.4 small data references.
- 'W' is a vector constant that can be easily generated (no mem refs).
- 'Y' is a indexed or word-aligned displacement memory operand.
- 't' is for AND masks that can be performed by two rldic{l,r} insns. */
-
-#define EXTRA_CONSTRAINT(OP, C) \
- ((C) == 'Q' ? GET_CODE (OP) == MEM && GET_CODE (XEXP (OP, 0)) == REG \
- : (C) == 'R' ? legitimate_constant_pool_address_p (OP) \
- : (C) == 'S' ? mask64_operand (OP, DImode) \
- : (C) == 'T' ? mask_operand (OP, SImode) \
- : (C) == 'U' ? (DEFAULT_ABI == ABI_V4 \
- && small_data_operand (OP, GET_MODE (OP))) \
- : (C) == 't' ? (mask64_2_operand (OP, DImode) \
- && (fixed_regs[CR0_REGNO] \
- || !logical_operand (OP, DImode)) \
- && !mask64_operand (OP, DImode)) \
- : (C) == 'W' ? (easy_vector_constant (OP, GET_MODE (OP))) \
- : (C) == 'Y' ? (word_offset_memref_operand (OP, GET_MODE (OP))) \
- : 0)
-
-/* Defining, which contraints are memory contraints. Tells reload,
- that any memory address can be reloaded by copying the
- memory address into a base register if required. */
-
-#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
- ((C) == 'Q' || (C) == 'Y')
-
/* Given an rtx X being reloaded into a reg required to be
in class CLASS, return the class of reg to actually use.
In general this is just CLASS; but on some machines
in some cases it is preferable to use a more restrictive class.
On the RS/6000, we have to return NO_REGS when we want to reload a
- floating-point CONST_DOUBLE to force it to be copied to memory.
+ floating-point CONST_DOUBLE to force it to be copied to memory.
We also don't want to reload integer values into floating-point
registers if we can at all help it. In fact, this can
- cause reload to abort, if it tries to generate a reload of CTR
+ cause reload to die, if it tries to generate a reload of CTR
into a FP register and discovers it doesn't have the memory location
required.
@@ -1473,27 +1096,20 @@ enum reg_class
*/
#define PREFERRED_RELOAD_CLASS(X,CLASS) \
- (((GET_CODE (X) == CONST_DOUBLE \
- && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT) \
- ? NO_REGS \
- : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
- && (CLASS) == NON_SPECIAL_REGS) \
- ? GENERAL_REGS \
- : (CLASS)))
-
-#define DISPARAGE_RELOAD_CLASS(X, CLASS) \
- (GET_CODE (X) == REG \
- && REGNO (X) < FIRST_PSEUDO_REGISTER \
- && SECONDARY_MEMORY_NEEDED (GET_MODE_CLASS (GET_MODE (X)), \
- CLASS, GET_MODE (X)) \
- ? 6 : 0)
+ ((CONSTANT_P (X) \
+ && reg_classes_intersect_p ((CLASS), FLOAT_REGS)) \
+ ? NO_REGS \
+ : (GET_MODE_CLASS (GET_MODE (X)) == MODE_INT \
+ && (CLASS) == NON_SPECIAL_REGS) \
+ ? GENERAL_REGS \
+ : (CLASS))
/* Return the register class of a scratch register needed to copy IN into
or out of a register in CLASS in MODE. If it can be done directly,
NO_REGS is returned. */
-#define SECONDARY_RELOAD_CLASS(CLASS, MODE, IN) \
- secondary_reload_class (CLASS, MODE, IN)
+#define SECONDARY_RELOAD_CLASS(CLASS,MODE,IN) \
+ rs6000_secondary_reload_class (CLASS, MODE, IN)
/* If we are copying between FP or AltiVec registers and anything
else, we need a memory location. */
@@ -1512,20 +1128,23 @@ enum reg_class
#define CLASS_MAX_NREGS(CLASS, MODE) \
(((CLASS) == FLOAT_REGS) \
? ((GET_MODE_SIZE (MODE) + UNITS_PER_FP_WORD - 1) / UNITS_PER_FP_WORD) \
+ : (TARGET_E500_DOUBLE && (CLASS) == GENERAL_REGS && (MODE) == DFmode) \
+ ? 1 \
: ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD))
+/* Return nonzero if for CLASS a mode change from FROM to TO is invalid. */
-/* Return a class of registers that cannot change FROM mode to TO mode. */
-
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (((DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) \
- && GET_MODE_SIZE (FROM) >= 8 && GET_MODE_SIZE (TO) >= 8) \
- ? 0 \
- : GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? reg_classes_intersect_p (FLOAT_REGS, CLASS) \
- : (TARGET_SPE && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1) \
- ? reg_classes_intersect_p (GENERAL_REGS, CLASS) \
- : 0)
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? ((GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8 \
+ || TARGET_IEEEQUAD) \
+ && reg_classes_intersect_p (FLOAT_REGS, CLASS)) \
+ : (((TARGET_E500_DOUBLE \
+ && ((((TO) == DFmode) + ((FROM) == DFmode)) == 1 \
+ || (((TO) == DImode) + ((FROM) == DImode)) == 1)) \
+ || (TARGET_SPE \
+ && (SPE_VECTOR_MODE (FROM) + SPE_VECTOR_MODE (TO)) == 1)) \
+ && reg_classes_intersect_p (GENERAL_REGS, CLASS)))
/* Stack layout; function entry, exit and calling. */
@@ -1546,14 +1165,14 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
/* Offsets recorded in opcodes are a multiple of this alignment factor. */
#define DWARF_CIE_DATA_ALIGNMENT (-((int) (TARGET_32BIT ? 4 : 8)))
-/* Define this if the nominal address of the stack frame
+/* Define this to nonzero if the nominal address of the stack frame
is at the high-address end of the local variables;
that is, each additional local variable allocated
goes at a more negative offset in the frame.
On the RS/6000, we grow upwards, from the area after the outgoing
arguments. */
-/* #define FRAME_GROWS_DOWNWARD */
+#define FRAME_GROWS_DOWNWARD (flag_stack_protect != 0)
/* Size of the outgoing register save area */
#define RS6000_REG_SAVE ((DEFAULT_ABI == ABI_AIX \
@@ -1571,16 +1190,9 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
plus_constant (stack_pointer_rtx, \
(TARGET_32BIT ? 20 : 40)))
-/* Size of the V.4 varargs area if needed */
-#define RS6000_VARARGS_AREA 0
-
/* Align an address */
#define RS6000_ALIGN(n,a) (((n) + (a) - 1) & ~((a) - 1))
-/* Size of V.4 varargs area in bytes */
-#define RS6000_VARARGS_SIZE \
- ((GP_ARG_NUM_REG * (TARGET_32BIT ? 4 : 8)) + (FP_ARG_NUM_REG * 8) + 8)
-
/* 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
@@ -1591,10 +1203,11 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
outgoing parameter area. */
#define STARTING_FRAME_OFFSET \
- (RS6000_ALIGN (current_function_outgoing_args_size, \
- TARGET_ALTIVEC ? 16 : 8) \
- + RS6000_VARARGS_AREA \
- + RS6000_SAVE_AREA)
+ (FRAME_GROWS_DOWNWARD \
+ ? 0 \
+ : (RS6000_ALIGN (current_function_outgoing_args_size, \
+ TARGET_ALTIVEC ? 16 : 8) \
+ + RS6000_SAVE_AREA))
/* Offset from the stack pointer register to an item dynamically
allocated on the stack, e.g., by `alloca'.
@@ -1665,7 +1278,7 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
/* DRAFT_V4_STRUCT_RET defaults off. */
#define DRAFT_V4_STRUCT_RET 0
-/* Let RETURN_IN_MEMORY control what happens. */
+/* Let TARGET_RETURN_IN_MEMORY control what happens. */
#define DEFAULT_PCC_STRUCT_RETURN 0
/* Mode of stack savearea.
@@ -1708,13 +1321,17 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
#define CALL_LONG 0x00000008 /* always call indirect */
#define CALL_LIBCALL 0x00000010 /* libcall */
+/* We don't have prologue and epilogue functions to save/restore
+ everything for most ABIs. */
+#define WORLD_SAVE_P(INFO) 0
+
/* 1 if N is a possible register number for a function value
as seen by the caller.
On RS/6000, this is r3, fp1, and v2 (for AltiVec). */
#define FUNCTION_VALUE_REGNO_P(N) \
((N) == GP_ARG_RETURN \
- || ((N) == FP_ARG_RETURN && TARGET_HARD_FLOAT) \
+ || ((N) == FP_ARG_RETURN && TARGET_HARD_FLOAT && TARGET_FPRS) \
|| ((N) == ALTIVEC_ARG_RETURN && TARGET_ALTIVEC && TARGET_ALTIVEC_ABI))
/* 1 if N is a possible register number for function argument passing.
@@ -1725,24 +1342,8 @@ extern enum rs6000_abi rs6000_current_abi; /* available for use by subtarget */
|| ((unsigned) (N) - ALTIVEC_ARG_MIN_REG < ALTIVEC_ARG_NUM_REG \
&& TARGET_ALTIVEC && TARGET_ALTIVEC_ABI) \
|| ((unsigned) (N) - FP_ARG_MIN_REG < FP_ARG_NUM_REG \
- && TARGET_HARD_FLOAT))
+ && TARGET_HARD_FLOAT && TARGET_FPRS))
-/* A C structure for machine-specific, per-function data.
- This is added to the cfun structure. */
-typedef struct machine_function GTY(())
-{
- /* Whether a System V.4 varargs area was created. */
- int sysv_varargs_p;
- /* Flags if __builtin_return_address (n) with n >= 1 was used. */
- int ra_needs_full_frame;
- /* Some local-dynamic symbol. */
- const char *some_ld_name;
- /* Whether the instruction chain has been scanned already. */
- int insn_chain_scanned_p;
- /* Flags if __builtin_return_address (0) was used. */
- int ra_need_lr;
-} machine_function;
-
/* 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
@@ -1771,6 +1372,9 @@ typedef struct rs6000_args
int stdarg; /* Whether function is a stdarg function. */
int call_cookie; /* Do special things for this call */
int sysv_gregno; /* next available GP register */
+ int intoffset; /* running offset in struct (darwin64) */
+ int use_stack; /* any part of struct on stack (darwin64) */
+ int named; /* false for varargs params */
} CUMULATIVE_ARGS;
/* Initialize a variable CUM of type CUMULATIVE_ARGS
@@ -1796,7 +1400,7 @@ typedef struct rs6000_args
(TYPE is null for libcalls where that information may not be available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- function_arg_advance (&CUM, MODE, TYPE, NAMED)
+ function_arg_advance (&CUM, MODE, TYPE, NAMED, 0)
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
@@ -1823,22 +1427,6 @@ typedef struct rs6000_args
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (&CUM, MODE, TYPE, NAMED)
-/* 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) \
- function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED)
-
-/* A C expression that indicates when an argument must be passed by
- reference. If nonzero for an argument, a copy of that argument is
- made in memory and a pointer to the argument is passed instead of
- the argument itself. The pointer is passed in whatever way is
- appropriate for passing a pointer to that type. */
-
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- function_arg_pass_by_reference(&CUM, MODE, TYPE, NAMED)
-
/* If defined, a C expression which determines whether, and in which
direction, to pad out an argument with extra space. The value
should be of type `enum direction': either `upward' to pad above
@@ -1858,17 +1446,9 @@ typedef struct rs6000_args
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
rs6000_va_start (valist, nextarg)
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- rs6000_va_arg (valist, type)
-
#define PAD_VARARGS_DOWN \
(FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
-/* 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
-
/* Output assembler code to FILE to increment profiler label # LABELNO
for profiling a function entry. */
@@ -1951,10 +1531,12 @@ typedef struct rs6000_args
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 ELIMINABLE_REGS \
+{{ HARD_FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
{ RS6000_PIC_OFFSET_TABLE_REGNUM, RS6000_PIC_OFFSET_TABLE_REGNUM } }
/* Given FROM and TO register numbers, say whether this elimination is allowed.
@@ -1994,14 +1576,18 @@ typedef struct rs6000_args
#define REGNO_OK_FOR_INDEX_P(REGNO) \
((REGNO) < FIRST_PSEUDO_REGISTER \
? (REGNO) <= 31 || (REGNO) == 67 \
+ || (REGNO) == FRAME_POINTER_REGNUM \
: (reg_renumber[REGNO] >= 0 \
- && (reg_renumber[REGNO] <= 31 || reg_renumber[REGNO] == 67)))
+ && (reg_renumber[REGNO] <= 31 || reg_renumber[REGNO] == 67 \
+ || reg_renumber[REGNO] == FRAME_POINTER_REGNUM)))
#define REGNO_OK_FOR_BASE_P(REGNO) \
((REGNO) < FIRST_PSEUDO_REGISTER \
? ((REGNO) > 0 && (REGNO) <= 31) || (REGNO) == 67 \
+ || (REGNO) == FRAME_POINTER_REGNUM \
: (reg_renumber[REGNO] > 0 \
- && (reg_renumber[REGNO] <= 31 || reg_renumber[REGNO] == 67)))
+ && (reg_renumber[REGNO] <= 31 || reg_renumber[REGNO] == 67 \
+ || reg_renumber[REGNO] == FRAME_POINTER_REGNUM)))
/* Maximum number of registers that can appear in a valid memory address. */
@@ -2030,6 +1616,11 @@ typedef struct rs6000_args
|| easy_vector_constant (X, GET_MODE (X))) \
&& !rs6000_tls_referenced_p (X))
+#define EASY_VECTOR_15(n) ((n) >= -16 && (n) <= 15)
+#define EASY_VECTOR_15_ADD_SELF(n) (!EASY_VECTOR_15((n)) \
+ && EASY_VECTOR_15((n) >> 1) \
+ && ((n) & 1) == 0)
+
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class.
We have two alternate definitions for each of them.
@@ -2052,16 +1643,14 @@ typedef struct rs6000_args
/* Nonzero if X is a hard reg that can be used as an index
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))))
+ ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER) \
+ || 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 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)))
+ ((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER) \
+ || REGNO_OK_FOR_BASE_P (REGNO (X)))
#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)
@@ -2071,7 +1660,7 @@ typedef struct rs6000_args
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
+ On the RS/6000, there are four valid addresses: 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
@@ -2125,9 +1714,9 @@ typedef struct rs6000_args
operand. If we find one, push the reload and jump to WIN. This
macro is used in only one place: `find_reloads_address' in reload.c.
- Implemented on rs6000 by rs6000_legitimize_reload_address.
+ Implemented on rs6000 by rs6000_legitimize_reload_address.
Note that (X) is evaluated twice; this is safe in current usage. */
-
+
#define LEGITIMIZE_RELOAD_ADDRESS(X,MODE,OPNUM,TYPE,IND_LEVELS,WIN) \
do { \
int win; \
@@ -2165,23 +1754,6 @@ do { \
/* #define PIC_OFFSET_TABLE_REG_CALL_CLOBBERED */
-/* By generating position-independent code, when two different
- programs (A and B) share a common library (libC.a), the text of
- the library can be shared whether or not the library is linked at
- the same address for both programs. In some of these
- environments, position-independent code requires not only the use
- of different addressing modes, but also special code to enable the
- use of these addressing modes.
-
- The `FINALIZE_PIC' macro serves as a hook to emit these special
- codes once the function is being compiled into assembly code, but
- not before. (It is not done before, because in the case of
- compiling an inline function, it would lead to multiple PIC
- prologues being included in functions which used inline functions
- and were compiled to assembly language.) */
-
-/* #define FINALIZE_PIC */
-
/* A C expression that is nonzero if X is a legitimate immediate
operand on the target machine when generating position independent
code. You can assume that X satisfies `CONSTANT_P', so you need
@@ -2215,6 +1787,12 @@ do { \
/* #define FIXUNS_TRUNC_LIKE_FIX_TRUNC */
+/* An integer expression for the size in bits of the largest integer machine
+ mode that should actually be used. */
+
+/* Allow pairs of registers to be used, which is the intent of the default. */
+#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_POWERPC64 ? TImode : DImode)
+
/* Max number of bytes we can move from memory to memory
in one reasonably fast instruction. */
#define MOVE_MAX (! TARGET_POWERPC64 ? 4 : 8)
@@ -2232,7 +1810,7 @@ do { \
/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
will either zero-extend or sign-extend. The value of this macro should
be the code that says which one of the two operations is implicitly
- done, NIL if none. */
+ done, UNKNOWN if none. */
#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
/* Define if loading short immediate values into registers sign extends. */
@@ -2290,9 +1868,9 @@ do { \
comparison. CCmode should be used in all other cases. */
#define SELECT_CC_MODE(OP,X,Y) \
- (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT ? CCFPmode \
+ (SCALAR_FLOAT_MODE_P (GET_MODE (X)) ? CCFPmode \
: (OP) == GTU || (OP) == LTU || (OP) == GEU || (OP) == LEU ? CCUNSmode \
- : (((OP) == EQ || (OP) == NE) && GET_RTX_CLASS (GET_CODE (X)) == '<' \
+ : (((OP) == EQ || (OP) == NE) && COMPARISON_P (X) \
? CCEQmode : CCmode))
/* Can the condition code MODE be safely reversed? This is safe in
@@ -2317,10 +1895,6 @@ extern int rs6000_compare_fp_p;
the end of the line. */
#define ASM_COMMENT_START " #"
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-
-#define TARGET_MEM_FUNCTIONS
-
/* Flag to say the TOC is initialized */
extern int toc_initialized;
@@ -2349,9 +1923,9 @@ extern int toc_initialized;
do \
{ \
fputs ("\t.weak\t", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
- && DEFAULT_ABI == ABI_AIX) \
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
{ \
if (TARGET_XCOFF) \
fputs ("[DS]", (FILE)); \
@@ -2363,7 +1937,7 @@ extern int toc_initialized;
{ \
ASM_OUTPUT_DEF ((FILE), (NAME), (VAL)); \
if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
- && DEFAULT_ABI == ABI_AIX) \
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
{ \
fputs ("\t.set\t.", (FILE)); \
RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
@@ -2376,6 +1950,26 @@ extern int toc_initialized;
while (0)
#endif
+#if HAVE_GAS_WEAKREF
+#define ASM_OUTPUT_WEAKREF(FILE, DECL, NAME, VALUE) \
+ do \
+ { \
+ fputs ("\t.weakref\t", (FILE)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
+ fputs (", ", (FILE)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (VALUE)); \
+ if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
+ { \
+ fputs ("\n\t.weakref\t.", (FILE)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
+ fputs (", .", (FILE)); \
+ RS6000_OUTPUT_BASENAME ((FILE), (VALUE)); \
+ } \
+ fputc ('\n', (FILE)); \
+ } while (0)
+#endif
+
/* This implements the `alias' attribute. */
#undef ASM_OUTPUT_DEF_FROM_DECLS
#define ASM_OUTPUT_DEF_FROM_DECLS(FILE, DECL, TARGET) \
@@ -2384,7 +1978,7 @@ extern int toc_initialized;
const char *alias = XSTR (XEXP (DECL_RTL (DECL), 0), 0); \
const char *name = IDENTIFIER_POINTER (TARGET); \
if (TREE_CODE (DECL) == FUNCTION_DECL \
- && DEFAULT_ABI == ABI_AIX) \
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
{ \
if (TREE_PUBLIC (DECL)) \
{ \
@@ -2548,6 +2142,7 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
&rs6000_reg_names[110][0], /* vscr */ \
&rs6000_reg_names[111][0], /* spe_acc */ \
&rs6000_reg_names[112][0], /* spefscr */ \
+ &rs6000_reg_names[113][0], /* sfp */ \
}
/* Table of additional register names to use in user input. */
@@ -2635,79 +2230,6 @@ extern char rs6000_reg_names[][8]; /* register names (0 vs. %r0). */
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
-/* Define the codes that are matched by predicates in rs6000.c. */
-
-#define PREDICATE_CODES \
- {"any_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
- LABEL_REF, SUBREG, REG, MEM, PARALLEL}}, \
- {"zero_constant", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF, \
- LABEL_REF, SUBREG, REG, MEM}}, \
- {"short_cint_operand", {CONST_INT}}, \
- {"u_short_cint_operand", {CONST_INT}}, \
- {"non_short_cint_operand", {CONST_INT}}, \
- {"exact_log2_cint_operand", {CONST_INT}}, \
- {"gpc_reg_operand", {SUBREG, REG}}, \
- {"cc_reg_operand", {SUBREG, REG}}, \
- {"cc_reg_not_cr0_operand", {SUBREG, REG}}, \
- {"reg_or_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_neg_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"reg_or_aligned_short_operand", {SUBREG, REG, CONST_INT}}, \
- {"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}}, \
- {"easy_vector_constant", {CONST_VECTOR}}, \
- {"easy_vector_constant_add_self", {CONST_VECTOR}}, \
- {"zero_fp_constant", {CONST_DOUBLE}}, \
- {"reg_or_mem_operand", {SUBREG, MEM, REG}}, \
- {"lwa_operand", {SUBREG, MEM, REG}}, \
- {"volatile_mem_operand", {MEM}}, \
- {"offsettable_mem_operand", {MEM}}, \
- {"mem_or_easy_const_operand", {SUBREG, MEM, CONST_DOUBLE}}, \
- {"add_operand", {SUBREG, REG, CONST_INT}}, \
- {"non_add_cint_operand", {CONST_INT}}, \
- {"and_operand", {SUBREG, REG, CONST_INT}}, \
- {"and64_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
- {"and64_2_operand", {SUBREG, REG, CONST_INT}}, \
- {"logical_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
- {"non_logical_cint_operand", {CONST_INT, CONST_DOUBLE}}, \
- {"mask_operand", {CONST_INT}}, \
- {"mask_operand_wrap", {CONST_INT}}, \
- {"mask64_operand", {CONST_INT}}, \
- {"mask64_2_operand", {CONST_INT}}, \
- {"count_register_operand", {REG}}, \
- {"xer_operand", {REG}}, \
- {"symbol_ref_operand", {SYMBOL_REF}}, \
- {"rs6000_tls_symbol_ref", {SYMBOL_REF}}, \
- {"call_operand", {SYMBOL_REF, REG}}, \
- {"current_file_function_operand", {SYMBOL_REF}}, \
- {"input_operand", {SUBREG, MEM, REG, CONST_INT, \
- CONST_DOUBLE, SYMBOL_REF}}, \
- {"load_multiple_operation", {PARALLEL}}, \
- {"store_multiple_operation", {PARALLEL}}, \
- {"vrsave_operation", {PARALLEL}}, \
- {"branch_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU, \
- UNORDERED, ORDERED, \
- UNGE, UNLE }}, \
- {"branch_positive_comparison_operator", {EQ, LT, GT, LTU, GTU, \
- UNORDERED }}, \
- {"scc_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU, \
- UNORDERED, ORDERED, \
- UNGE, UNLE }}, \
- {"trap_comparison_operator", {EQ, NE, LE, LT, GE, \
- GT, LEU, LTU, GEU, GTU}}, \
- {"boolean_operator", {AND, IOR, XOR}}, \
- {"boolean_or_operator", {IOR, XOR}}, \
- {"altivec_register_operand", {REG}}, \
- {"min_max_operator", {SMIN, SMAX, UMIN, UMAX}},
-
/* uncomment for disabling the corresponding default options */
/* #define MACHINE_no_sched_interblock */
/* #define MACHINE_no_sched_speculative */
@@ -2923,7 +2445,237 @@ enum rs6000_builtins
ALTIVEC_BUILTIN_ABS_V4SF,
ALTIVEC_BUILTIN_ABS_V8HI,
ALTIVEC_BUILTIN_ABS_V16QI,
- ALTIVEC_BUILTIN_COMPILETIME_ERROR,
+ ALTIVEC_BUILTIN_MASK_FOR_LOAD,
+ ALTIVEC_BUILTIN_MASK_FOR_STORE,
+ ALTIVEC_BUILTIN_VEC_INIT_V4SI,
+ ALTIVEC_BUILTIN_VEC_INIT_V8HI,
+ ALTIVEC_BUILTIN_VEC_INIT_V16QI,
+ ALTIVEC_BUILTIN_VEC_INIT_V4SF,
+ ALTIVEC_BUILTIN_VEC_SET_V4SI,
+ ALTIVEC_BUILTIN_VEC_SET_V8HI,
+ ALTIVEC_BUILTIN_VEC_SET_V16QI,
+ ALTIVEC_BUILTIN_VEC_SET_V4SF,
+ ALTIVEC_BUILTIN_VEC_EXT_V4SI,
+ ALTIVEC_BUILTIN_VEC_EXT_V8HI,
+ ALTIVEC_BUILTIN_VEC_EXT_V16QI,
+ ALTIVEC_BUILTIN_VEC_EXT_V4SF,
+
+ /* Altivec overloaded builtins. */
+ ALTIVEC_BUILTIN_VCMPEQ_P,
+ ALTIVEC_BUILTIN_OVERLOADED_FIRST = ALTIVEC_BUILTIN_VCMPEQ_P,
+ ALTIVEC_BUILTIN_VCMPGT_P,
+ ALTIVEC_BUILTIN_VCMPGE_P,
+ ALTIVEC_BUILTIN_VEC_ABS,
+ ALTIVEC_BUILTIN_VEC_ABSS,
+ ALTIVEC_BUILTIN_VEC_ADD,
+ ALTIVEC_BUILTIN_VEC_ADDC,
+ ALTIVEC_BUILTIN_VEC_ADDS,
+ ALTIVEC_BUILTIN_VEC_AND,
+ ALTIVEC_BUILTIN_VEC_ANDC,
+ ALTIVEC_BUILTIN_VEC_AVG,
+ ALTIVEC_BUILTIN_VEC_CEIL,
+ ALTIVEC_BUILTIN_VEC_CMPB,
+ ALTIVEC_BUILTIN_VEC_CMPEQ,
+ ALTIVEC_BUILTIN_VEC_CMPEQUB,
+ ALTIVEC_BUILTIN_VEC_CMPEQUH,
+ ALTIVEC_BUILTIN_VEC_CMPEQUW,
+ ALTIVEC_BUILTIN_VEC_CMPGE,
+ ALTIVEC_BUILTIN_VEC_CMPGT,
+ ALTIVEC_BUILTIN_VEC_CMPLE,
+ ALTIVEC_BUILTIN_VEC_CMPLT,
+ ALTIVEC_BUILTIN_VEC_CTF,
+ ALTIVEC_BUILTIN_VEC_CTS,
+ ALTIVEC_BUILTIN_VEC_CTU,
+ ALTIVEC_BUILTIN_VEC_DST,
+ ALTIVEC_BUILTIN_VEC_DSTST,
+ ALTIVEC_BUILTIN_VEC_DSTSTT,
+ ALTIVEC_BUILTIN_VEC_DSTT,
+ ALTIVEC_BUILTIN_VEC_EXPTE,
+ ALTIVEC_BUILTIN_VEC_FLOOR,
+ ALTIVEC_BUILTIN_VEC_LD,
+ ALTIVEC_BUILTIN_VEC_LDE,
+ ALTIVEC_BUILTIN_VEC_LDL,
+ ALTIVEC_BUILTIN_VEC_LOGE,
+ ALTIVEC_BUILTIN_VEC_LVEBX,
+ ALTIVEC_BUILTIN_VEC_LVEHX,
+ ALTIVEC_BUILTIN_VEC_LVEWX,
+ ALTIVEC_BUILTIN_VEC_LVSL,
+ ALTIVEC_BUILTIN_VEC_LVSR,
+ ALTIVEC_BUILTIN_VEC_MADD,
+ ALTIVEC_BUILTIN_VEC_MADDS,
+ ALTIVEC_BUILTIN_VEC_MAX,
+ ALTIVEC_BUILTIN_VEC_MERGEH,
+ ALTIVEC_BUILTIN_VEC_MERGEL,
+ ALTIVEC_BUILTIN_VEC_MIN,
+ ALTIVEC_BUILTIN_VEC_MLADD,
+ ALTIVEC_BUILTIN_VEC_MPERM,
+ ALTIVEC_BUILTIN_VEC_MRADDS,
+ ALTIVEC_BUILTIN_VEC_MRGHB,
+ ALTIVEC_BUILTIN_VEC_MRGHH,
+ ALTIVEC_BUILTIN_VEC_MRGHW,
+ ALTIVEC_BUILTIN_VEC_MRGLB,
+ ALTIVEC_BUILTIN_VEC_MRGLH,
+ ALTIVEC_BUILTIN_VEC_MRGLW,
+ ALTIVEC_BUILTIN_VEC_MSUM,
+ ALTIVEC_BUILTIN_VEC_MSUMS,
+ ALTIVEC_BUILTIN_VEC_MTVSCR,
+ ALTIVEC_BUILTIN_VEC_MULE,
+ ALTIVEC_BUILTIN_VEC_MULO,
+ ALTIVEC_BUILTIN_VEC_NMSUB,
+ ALTIVEC_BUILTIN_VEC_NOR,
+ ALTIVEC_BUILTIN_VEC_OR,
+ ALTIVEC_BUILTIN_VEC_PACK,
+ ALTIVEC_BUILTIN_VEC_PACKPX,
+ ALTIVEC_BUILTIN_VEC_PACKS,
+ ALTIVEC_BUILTIN_VEC_PACKSU,
+ ALTIVEC_BUILTIN_VEC_PERM,
+ ALTIVEC_BUILTIN_VEC_RE,
+ ALTIVEC_BUILTIN_VEC_RL,
+ ALTIVEC_BUILTIN_VEC_ROUND,
+ ALTIVEC_BUILTIN_VEC_RSQRTE,
+ ALTIVEC_BUILTIN_VEC_SEL,
+ ALTIVEC_BUILTIN_VEC_SL,
+ ALTIVEC_BUILTIN_VEC_SLD,
+ ALTIVEC_BUILTIN_VEC_SLL,
+ ALTIVEC_BUILTIN_VEC_SLO,
+ ALTIVEC_BUILTIN_VEC_SPLAT,
+ ALTIVEC_BUILTIN_VEC_SPLAT_S16,
+ ALTIVEC_BUILTIN_VEC_SPLAT_S32,
+ ALTIVEC_BUILTIN_VEC_SPLAT_S8,
+ ALTIVEC_BUILTIN_VEC_SPLAT_U16,
+ ALTIVEC_BUILTIN_VEC_SPLAT_U32,
+ ALTIVEC_BUILTIN_VEC_SPLAT_U8,
+ ALTIVEC_BUILTIN_VEC_SPLTB,
+ ALTIVEC_BUILTIN_VEC_SPLTH,
+ ALTIVEC_BUILTIN_VEC_SPLTW,
+ ALTIVEC_BUILTIN_VEC_SR,
+ ALTIVEC_BUILTIN_VEC_SRA,
+ ALTIVEC_BUILTIN_VEC_SRL,
+ ALTIVEC_BUILTIN_VEC_SRO,
+ ALTIVEC_BUILTIN_VEC_ST,
+ ALTIVEC_BUILTIN_VEC_STE,
+ ALTIVEC_BUILTIN_VEC_STL,
+ ALTIVEC_BUILTIN_VEC_STVEBX,
+ ALTIVEC_BUILTIN_VEC_STVEHX,
+ ALTIVEC_BUILTIN_VEC_STVEWX,
+ ALTIVEC_BUILTIN_VEC_SUB,
+ ALTIVEC_BUILTIN_VEC_SUBC,
+ ALTIVEC_BUILTIN_VEC_SUBS,
+ ALTIVEC_BUILTIN_VEC_SUM2S,
+ ALTIVEC_BUILTIN_VEC_SUM4S,
+ ALTIVEC_BUILTIN_VEC_SUMS,
+ ALTIVEC_BUILTIN_VEC_TRUNC,
+ ALTIVEC_BUILTIN_VEC_UNPACKH,
+ ALTIVEC_BUILTIN_VEC_UNPACKL,
+ ALTIVEC_BUILTIN_VEC_VADDFP,
+ ALTIVEC_BUILTIN_VEC_VADDSBS,
+ ALTIVEC_BUILTIN_VEC_VADDSHS,
+ ALTIVEC_BUILTIN_VEC_VADDSWS,
+ ALTIVEC_BUILTIN_VEC_VADDUBM,
+ ALTIVEC_BUILTIN_VEC_VADDUBS,
+ ALTIVEC_BUILTIN_VEC_VADDUHM,
+ ALTIVEC_BUILTIN_VEC_VADDUHS,
+ ALTIVEC_BUILTIN_VEC_VADDUWM,
+ ALTIVEC_BUILTIN_VEC_VADDUWS,
+ ALTIVEC_BUILTIN_VEC_VAVGSB,
+ ALTIVEC_BUILTIN_VEC_VAVGSH,
+ ALTIVEC_BUILTIN_VEC_VAVGSW,
+ ALTIVEC_BUILTIN_VEC_VAVGUB,
+ ALTIVEC_BUILTIN_VEC_VAVGUH,
+ ALTIVEC_BUILTIN_VEC_VAVGUW,
+ ALTIVEC_BUILTIN_VEC_VCFSX,
+ ALTIVEC_BUILTIN_VEC_VCFUX,
+ ALTIVEC_BUILTIN_VEC_VCMPEQFP,
+ ALTIVEC_BUILTIN_VEC_VCMPEQUB,
+ ALTIVEC_BUILTIN_VEC_VCMPEQUH,
+ ALTIVEC_BUILTIN_VEC_VCMPEQUW,
+ ALTIVEC_BUILTIN_VEC_VCMPGTFP,
+ ALTIVEC_BUILTIN_VEC_VCMPGTSB,
+ ALTIVEC_BUILTIN_VEC_VCMPGTSH,
+ ALTIVEC_BUILTIN_VEC_VCMPGTSW,
+ ALTIVEC_BUILTIN_VEC_VCMPGTUB,
+ ALTIVEC_BUILTIN_VEC_VCMPGTUH,
+ ALTIVEC_BUILTIN_VEC_VCMPGTUW,
+ ALTIVEC_BUILTIN_VEC_VMAXFP,
+ ALTIVEC_BUILTIN_VEC_VMAXSB,
+ ALTIVEC_BUILTIN_VEC_VMAXSH,
+ ALTIVEC_BUILTIN_VEC_VMAXSW,
+ ALTIVEC_BUILTIN_VEC_VMAXUB,
+ ALTIVEC_BUILTIN_VEC_VMAXUH,
+ ALTIVEC_BUILTIN_VEC_VMAXUW,
+ ALTIVEC_BUILTIN_VEC_VMINFP,
+ ALTIVEC_BUILTIN_VEC_VMINSB,
+ ALTIVEC_BUILTIN_VEC_VMINSH,
+ ALTIVEC_BUILTIN_VEC_VMINSW,
+ ALTIVEC_BUILTIN_VEC_VMINUB,
+ ALTIVEC_BUILTIN_VEC_VMINUH,
+ ALTIVEC_BUILTIN_VEC_VMINUW,
+ ALTIVEC_BUILTIN_VEC_VMRGHB,
+ ALTIVEC_BUILTIN_VEC_VMRGHH,
+ ALTIVEC_BUILTIN_VEC_VMRGHW,
+ ALTIVEC_BUILTIN_VEC_VMRGLB,
+ ALTIVEC_BUILTIN_VEC_VMRGLH,
+ ALTIVEC_BUILTIN_VEC_VMRGLW,
+ ALTIVEC_BUILTIN_VEC_VMSUMMBM,
+ ALTIVEC_BUILTIN_VEC_VMSUMSHM,
+ ALTIVEC_BUILTIN_VEC_VMSUMSHS,
+ ALTIVEC_BUILTIN_VEC_VMSUMUBM,
+ ALTIVEC_BUILTIN_VEC_VMSUMUHM,
+ ALTIVEC_BUILTIN_VEC_VMSUMUHS,
+ ALTIVEC_BUILTIN_VEC_VMULESB,
+ ALTIVEC_BUILTIN_VEC_VMULESH,
+ ALTIVEC_BUILTIN_VEC_VMULEUB,
+ ALTIVEC_BUILTIN_VEC_VMULEUH,
+ ALTIVEC_BUILTIN_VEC_VMULOSB,
+ ALTIVEC_BUILTIN_VEC_VMULOSH,
+ ALTIVEC_BUILTIN_VEC_VMULOUB,
+ ALTIVEC_BUILTIN_VEC_VMULOUH,
+ ALTIVEC_BUILTIN_VEC_VPKSHSS,
+ ALTIVEC_BUILTIN_VEC_VPKSHUS,
+ ALTIVEC_BUILTIN_VEC_VPKSWSS,
+ ALTIVEC_BUILTIN_VEC_VPKSWUS,
+ ALTIVEC_BUILTIN_VEC_VPKUHUM,
+ ALTIVEC_BUILTIN_VEC_VPKUHUS,
+ ALTIVEC_BUILTIN_VEC_VPKUWUM,
+ ALTIVEC_BUILTIN_VEC_VPKUWUS,
+ ALTIVEC_BUILTIN_VEC_VRLB,
+ ALTIVEC_BUILTIN_VEC_VRLH,
+ ALTIVEC_BUILTIN_VEC_VRLW,
+ ALTIVEC_BUILTIN_VEC_VSLB,
+ ALTIVEC_BUILTIN_VEC_VSLH,
+ ALTIVEC_BUILTIN_VEC_VSLW,
+ ALTIVEC_BUILTIN_VEC_VSPLTB,
+ ALTIVEC_BUILTIN_VEC_VSPLTH,
+ ALTIVEC_BUILTIN_VEC_VSPLTW,
+ ALTIVEC_BUILTIN_VEC_VSRAB,
+ ALTIVEC_BUILTIN_VEC_VSRAH,
+ ALTIVEC_BUILTIN_VEC_VSRAW,
+ ALTIVEC_BUILTIN_VEC_VSRB,
+ ALTIVEC_BUILTIN_VEC_VSRH,
+ ALTIVEC_BUILTIN_VEC_VSRW,
+ ALTIVEC_BUILTIN_VEC_VSUBFP,
+ ALTIVEC_BUILTIN_VEC_VSUBSBS,
+ ALTIVEC_BUILTIN_VEC_VSUBSHS,
+ ALTIVEC_BUILTIN_VEC_VSUBSWS,
+ ALTIVEC_BUILTIN_VEC_VSUBUBM,
+ ALTIVEC_BUILTIN_VEC_VSUBUBS,
+ ALTIVEC_BUILTIN_VEC_VSUBUHM,
+ ALTIVEC_BUILTIN_VEC_VSUBUHS,
+ ALTIVEC_BUILTIN_VEC_VSUBUWM,
+ ALTIVEC_BUILTIN_VEC_VSUBUWS,
+ ALTIVEC_BUILTIN_VEC_VSUM4SBS,
+ ALTIVEC_BUILTIN_VEC_VSUM4SHS,
+ ALTIVEC_BUILTIN_VEC_VSUM4UBS,
+ ALTIVEC_BUILTIN_VEC_VUPKHPX,
+ ALTIVEC_BUILTIN_VEC_VUPKHSB,
+ ALTIVEC_BUILTIN_VEC_VUPKHSH,
+ ALTIVEC_BUILTIN_VEC_VUPKLPX,
+ ALTIVEC_BUILTIN_VEC_VUPKLSB,
+ ALTIVEC_BUILTIN_VEC_VUPKLSH,
+ ALTIVEC_BUILTIN_VEC_XOR,
+ ALTIVEC_BUILTIN_VEC_STEP,
+ ALTIVEC_BUILTIN_OVERLOADED_LAST = ALTIVEC_BUILTIN_VEC_STEP,
+
/* SPE builtins. */
SPE_BUILTIN_EVADDW,
SPE_BUILTIN_EVAND,
@@ -3157,5 +2909,84 @@ enum rs6000_builtins
SPE_BUILTIN_EVMWHGUMIAN,
SPE_BUILTIN_MTSPEFSCR,
SPE_BUILTIN_MFSPEFSCR,
- SPE_BUILTIN_BRINC
+ SPE_BUILTIN_BRINC,
+
+ RS6000_BUILTIN_COUNT
};
+
+enum rs6000_builtin_type_index
+{
+ RS6000_BTI_NOT_OPAQUE,
+ RS6000_BTI_opaque_V2SI,
+ RS6000_BTI_opaque_V2SF,
+ RS6000_BTI_opaque_p_V2SI,
+ RS6000_BTI_opaque_V4SI,
+ RS6000_BTI_V16QI,
+ RS6000_BTI_V2SI,
+ RS6000_BTI_V2SF,
+ RS6000_BTI_V4HI,
+ RS6000_BTI_V4SI,
+ RS6000_BTI_V4SF,
+ RS6000_BTI_V8HI,
+ RS6000_BTI_unsigned_V16QI,
+ RS6000_BTI_unsigned_V8HI,
+ RS6000_BTI_unsigned_V4SI,
+ RS6000_BTI_bool_char, /* __bool char */
+ RS6000_BTI_bool_short, /* __bool short */
+ RS6000_BTI_bool_int, /* __bool int */
+ RS6000_BTI_pixel, /* __pixel */
+ RS6000_BTI_bool_V16QI, /* __vector __bool char */
+ RS6000_BTI_bool_V8HI, /* __vector __bool short */
+ RS6000_BTI_bool_V4SI, /* __vector __bool int */
+ RS6000_BTI_pixel_V8HI, /* __vector __pixel */
+ RS6000_BTI_long, /* long_integer_type_node */
+ RS6000_BTI_unsigned_long, /* long_unsigned_type_node */
+ RS6000_BTI_INTQI, /* intQI_type_node */
+ RS6000_BTI_UINTQI, /* unsigned_intQI_type_node */
+ RS6000_BTI_INTHI, /* intHI_type_node */
+ RS6000_BTI_UINTHI, /* unsigned_intHI_type_node */
+ RS6000_BTI_INTSI, /* intSI_type_node */
+ RS6000_BTI_UINTSI, /* unsigned_intSI_type_node */
+ RS6000_BTI_float, /* float_type_node */
+ RS6000_BTI_void, /* void_type_node */
+ RS6000_BTI_MAX
+};
+
+
+#define opaque_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V2SI])
+#define opaque_V2SF_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V2SF])
+#define opaque_p_V2SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_p_V2SI])
+#define opaque_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_opaque_V4SI])
+#define V16QI_type_node (rs6000_builtin_types[RS6000_BTI_V16QI])
+#define V2SI_type_node (rs6000_builtin_types[RS6000_BTI_V2SI])
+#define V2SF_type_node (rs6000_builtin_types[RS6000_BTI_V2SF])
+#define V4HI_type_node (rs6000_builtin_types[RS6000_BTI_V4HI])
+#define V4SI_type_node (rs6000_builtin_types[RS6000_BTI_V4SI])
+#define V4SF_type_node (rs6000_builtin_types[RS6000_BTI_V4SF])
+#define V8HI_type_node (rs6000_builtin_types[RS6000_BTI_V8HI])
+#define unsigned_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V16QI])
+#define unsigned_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V8HI])
+#define unsigned_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_unsigned_V4SI])
+#define bool_char_type_node (rs6000_builtin_types[RS6000_BTI_bool_char])
+#define bool_short_type_node (rs6000_builtin_types[RS6000_BTI_bool_short])
+#define bool_int_type_node (rs6000_builtin_types[RS6000_BTI_bool_int])
+#define pixel_type_node (rs6000_builtin_types[RS6000_BTI_pixel])
+#define bool_V16QI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V16QI])
+#define bool_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V8HI])
+#define bool_V4SI_type_node (rs6000_builtin_types[RS6000_BTI_bool_V4SI])
+#define pixel_V8HI_type_node (rs6000_builtin_types[RS6000_BTI_pixel_V8HI])
+
+#define long_integer_type_internal_node (rs6000_builtin_types[RS6000_BTI_long])
+#define long_unsigned_type_internal_node (rs6000_builtin_types[RS6000_BTI_unsigned_long])
+#define intQI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTQI])
+#define uintQI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTQI])
+#define intHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTHI])
+#define uintHI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTHI])
+#define intSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_INTSI])
+#define uintSI_type_internal_node (rs6000_builtin_types[RS6000_BTI_UINTSI])
+#define float_type_internal_node (rs6000_builtin_types[RS6000_BTI_float])
+#define void_type_internal_node (rs6000_builtin_types[RS6000_BTI_void])
+
+extern GTY(()) tree rs6000_builtin_types[RS6000_BTI_MAX];
+extern GTY(()) tree rs6000_builtin_decls[RS6000_BUILTIN_COUNT];
+
diff --git a/contrib/gcc/config/rs6000/rs6000.md b/contrib/gcc/config/rs6000/rs6000.md
index 0e242d4..21cc207 100644
--- a/contrib/gcc/config/rs6000/rs6000.md
+++ b/contrib/gcc/config/rs6000/rs6000.md
@@ -1,6 +1,7 @@
;; Machine description for IBM RISC System 6000 (POWER) for GNU C compiler
;; Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+;; Free Software Foundation, Inc.
;; Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu)
;; This file is part of GCC.
@@ -17,8 +18,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
@@ -34,6 +35,10 @@
(UNSPEC_MOVSI_GOT 8)
(UNSPEC_MV_CR_OV 9) ; move_from_CR_ov_bit
(UNSPEC_FCTIWZ 10)
+ (UNSPEC_FRIM 11)
+ (UNSPEC_FRIN 12)
+ (UNSPEC_FRIP 13)
+ (UNSPEC_FRIZ 14)
(UNSPEC_LD_MPIC 15) ; load_macho_picbase
(UNSPEC_MPIC_CORRECT 16) ; macho_correct_pic
(UNSPEC_TLSGD 17)
@@ -50,7 +55,23 @@
(UNSPEC_TLSGOTTPREL 28)
(UNSPEC_TLSTLS 29)
(UNSPEC_FIX_TRUNC_TF 30) ; fadd, rounding towards zero
- (UNSPEC_MV_CR_EQ 31) ; move_from_CR_eq_bit
+ (UNSPEC_MV_CR_GT 31) ; move_from_CR_gt_bit
+ (UNSPEC_STFIWX 32)
+ (UNSPEC_POPCNTB 33)
+ (UNSPEC_FRES 34)
+ (UNSPEC_SP_SET 35)
+ (UNSPEC_SP_TEST 36)
+ (UNSPEC_SYNC 37)
+ (UNSPEC_LWSYNC 38)
+ (UNSPEC_ISYNC 39)
+ (UNSPEC_SYNC_OP 40)
+ (UNSPEC_ATOMIC 41)
+ (UNSPEC_CMPXCHG 42)
+ (UNSPEC_XCHG 43)
+ (UNSPEC_AND 44)
+ (UNSPEC_DLMZB 45)
+ (UNSPEC_DLMZB_CR 46)
+ (UNSPEC_DLMZB_STRLEN 47)
])
;;
@@ -59,16 +80,18 @@
(define_constants
[(UNSPECV_BLOCK 0)
+ (UNSPECV_LL 1) ; load-locked
+ (UNSPECV_SC 2) ; store-conditional
(UNSPECV_EH_RR 9) ; eh_reg_restore
])
;; Define an insn type attribute. This is used in function unit delay
;; computations.
-(define_attr "type" "integer,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv"
+(define_attr "type" "integer,two,three,load,load_ext,load_ext_u,load_ext_ux,load_ux,load_u,store,store_ux,store_u,fpload,fpload_ux,fpload_u,fpstore,fpstore_ux,fpstore_u,vecload,vecstore,imul,imul2,imul3,lmul,idiv,ldiv,insert_word,branch,cmp,fast_compare,compare,delayed_compare,imul_compare,lmul_compare,fpcompare,cr_logical,delayed_cr,mfcr,mfcrf,mtcr,mfjmpr,mtjmpr,fp,fpsimple,dmul,sdiv,ddiv,ssqrt,dsqrt,jmpreg,brinc,vecsimple,veccomplex,vecdiv,veccmp,veccmpsimple,vecperm,vecfloat,vecfdiv,isync,sync,load_l,store_c"
(const_string "integer"))
;; Length (in bytes).
-; '(pc)' in the following doesn't include the instruction itself; it is
+; '(pc)' in the following doesn't include the instruction itself; it is
; calculated as if the instruction had zero size.
(define_attr "length" ""
(if_then_else (eq_attr "type" "branch")
@@ -102,40 +125,81 @@
(include "power4.md")
(include "power5.md")
+(include "predicates.md")
+(include "constraints.md")
+
+(include "darwin.md")
+
+
+;; Mode macros
+
+; This mode macro allows :GPR to be used to indicate the allowable size
+; of whole values in GPRs.
+(define_mode_macro GPR [SI (DI "TARGET_POWERPC64")])
+
+; Any supported integer mode.
+(define_mode_macro INT [QI HI SI DI TI])
+
+; Any supported integer mode that fits in one register.
+(define_mode_macro INT1 [QI HI SI (DI "TARGET_POWERPC64")])
+
+; extend modes for DImode
+(define_mode_macro QHSI [QI HI SI])
+
+; SImode or DImode, even if DImode doesn't fit in GPRs.
+(define_mode_macro SDI [SI DI])
+
+; The size of a pointer. Also, the size of the value that a record-condition
+; (one with a '.') will compare.
+(define_mode_macro P [(SI "TARGET_32BIT") (DI "TARGET_64BIT")])
+
+; Any hardware-supported floating-point mode
+(define_mode_macro FP [(SF "TARGET_HARD_FLOAT")
+ (DF "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)")
+ (TF "!TARGET_IEEEQUAD
+ && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")])
+
+; Various instructions that come in SI and DI forms.
+; A generic w/d attribute, for things like cmpw/cmpd.
+(define_mode_attr wd [(QI "b") (HI "h") (SI "w") (DI "d")])
+
+; DImode bits
+(define_mode_attr dbits [(QI "56") (HI "48") (SI "32")])
+
;; Start with fixed-point load and store insns. Here we put only the more
;; complex forms. Basic data transfer is done later.
-(define_expand "zero_extendqidi2"
+(define_expand "zero_extend<mode>di2"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
- (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "")))]
+ (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "")))]
"TARGET_POWERPC64"
"")
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal1"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (zero_extend:DI (match_operand:QI 1 "reg_or_mem_operand" "m,r")))]
+ (zero_extend:DI (match_operand:QHSI 1 "reg_or_mem_operand" "m,r")))]
"TARGET_POWERPC64"
"@
- lbz%U1%X1 %0,%1
- rldicl %0,%1,0,56"
+ l<wd>z%U1%X1 %0,%1
+ rldicl %0,%1,0,<dbits>"
[(set_attr "type" "load,*")])
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(clobber (match_scratch:DI 2 "=r,r"))]
"TARGET_64BIT"
"@
- rldicl. %2,%1,0,56
+ rldicl. %2,%1,0,<dbits>
#"
[(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+ (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
(const_int 0)))
(clobber (match_scratch:DI 2 ""))]
"TARGET_POWERPC64 && reload_completed"
@@ -146,22 +210,22 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "*zero_extend<mode>di2_internal3"
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
(zero_extend:DI (match_dup 1)))]
"TARGET_64BIT"
"@
- rldicl. %0,%1,0,56
+ rldicl. %0,%1,0,<dbits>
#"
[(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
[(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:QI 1 "gpc_reg_operand" ""))
+ (compare:CC (zero_extend:DI (match_operand:QHSI 1 "gpc_reg_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(zero_extend:DI (match_dup 1)))]
@@ -231,73 +295,6 @@
(const_int 0)))]
"")
-(define_expand "zero_extendhidi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
- "TARGET_POWERPC64"
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (zero_extend:DI (match_operand:HI 1 "reg_or_mem_operand" "m,r")))]
- "TARGET_POWERPC64"
- "@
- lhz%U1%X1 %0,%1
- rldicl %0,%1,0,48"
- [(set_attr "type" "load,*")])
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (clobber (match_scratch:DI 2 "=r,r"))]
- "TARGET_64BIT"
- "@
- rldicl. %2,%1,0,48
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 2)
- (zero_extend:DI (match_dup 1)))
- (set (match_dup 0)
- (compare:CC (match_dup 2)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (zero_extend:DI (match_dup 1)))]
- "TARGET_64BIT"
- "@
- rldicl. %0,%1,0,48
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:HI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (zero_extend:DI (match_dup 1)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (match_dup 1)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
(define_expand "extendhidi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(sign_extend:DI (match_operand:HI 1 "gpc_reg_operand" "")))]
@@ -365,73 +362,6 @@
(const_int 0)))]
"")
-(define_expand "zero_extendsidi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
- "TARGET_POWERPC64"
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (zero_extend:DI (match_operand:SI 1 "reg_or_mem_operand" "m,r")))]
- "TARGET_POWERPC64"
- "@
- lwz%U1%X1 %0,%1
- rldicl %0,%1,0,32"
- [(set_attr "type" "load,*")])
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (clobber (match_scratch:DI 2 "=r,r"))]
- "TARGET_64BIT"
- "@
- rldicl. %2,%1,0,32
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 2)
- (zero_extend:DI (match_dup 1)))
- (set (match_dup 0)
- (compare:CC (match_dup 2)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (zero_extend:DI (match_dup 1)))]
- "TARGET_64BIT"
- "@
- rldicl. %0,%1,0,32
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (zero_extend:DI (match_operand:SI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (zero_extend:DI (match_dup 1)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (zero_extend:DI (match_dup 1)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
(define_expand "extendsidi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
(sign_extend:DI (match_operand:SI 1 "gpc_reg_operand" "")))]
@@ -953,6 +883,537 @@
[(set_attr "type" "compare")
(set_attr "length" "4,8")])
+;; IBM 405 and 440 half-word multiplication operations.
+
+(define_insn "*macchwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16))
+ (sign_extend:SI
+ (match_dup 1)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "macchw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*macchw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "macchw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*macchwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (lshiftrt:SI
+ (match_dup 2)
+ (const_int 16))
+ (zero_extend:SI
+ (match_dup 1)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "macchwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*macchwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "macchwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*machhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (ashiftrt:SI
+ (match_dup 1)
+ (const_int 16))
+ (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "machhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*machhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "machhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*machhwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (lshiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (lshiftrt:SI
+ (match_dup 1)
+ (const_int 16))
+ (lshiftrt:SI
+ (match_dup 2)
+ (const_int 16)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "machhwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*machhwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (lshiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "machhwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (sign_extend:SI
+ (match_dup 1))
+ (sign_extend:SI
+ (match_dup 2)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "maclhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*maclhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "maclhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (plus:SI (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (zero_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (match_operand:SI 4 "gpc_reg_operand" "0"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (zero_extend:SI
+ (match_dup 1))
+ (zero_extend:SI
+ (match_dup 2)))
+ (match_dup 4)))]
+ "TARGET_MULHW"
+ "maclhwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*maclhwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (plus:SI (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (zero_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (match_operand:SI 3 "gpc_reg_operand" "0")))]
+ "TARGET_MULHW"
+ "maclhwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmacchwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r"))))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_dup 4)
+ (mult:SI (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16))
+ (sign_extend:SI
+ (match_dup 1)))))]
+ "TARGET_MULHW"
+ "nmacchw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmacchw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))))]
+ "TARGET_MULHW"
+ "nmacchw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmachhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_dup 4)
+ (mult:SI (ashiftrt:SI
+ (match_dup 1)
+ (const_int 16))
+ (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16)))))]
+ "TARGET_MULHW"
+ "nmachhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmachhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))))]
+ "TARGET_MULHW"
+ "nmachhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmaclhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (minus:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r"))))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_dup 4)
+ (mult:SI (sign_extend:SI
+ (match_dup 1))
+ (sign_extend:SI
+ (match_dup 2)))))]
+ "TARGET_MULHW"
+ "nmaclhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*nmaclhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (minus:SI (match_operand:SI 3 "gpc_reg_operand" "0")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))))]
+ "TARGET_MULHW"
+ "nmaclhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16))
+ (sign_extend:SI
+ (match_dup 1))))]
+ "TARGET_MULHW"
+ "mulchw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulchw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r"))))]
+ "TARGET_MULHW"
+ "mulchw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (lshiftrt:SI
+ (match_dup 2)
+ (const_int 16))
+ (zero_extend:SI
+ (match_dup 1))))]
+ "TARGET_MULHW"
+ "mulchwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulchwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))
+ (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "r"))))]
+ "TARGET_MULHW"
+ "mulchwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_dup 1)
+ (const_int 16))
+ (ashiftrt:SI
+ (match_dup 2)
+ (const_int 16))))]
+ "TARGET_MULHW"
+ "mulhhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (ashiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (ashiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))))]
+ "TARGET_MULHW"
+ "mulhhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (lshiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16)))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (lshiftrt:SI
+ (match_dup 1)
+ (const_int 16))
+ (lshiftrt:SI
+ (match_dup 2)
+ (const_int 16))))]
+ "TARGET_MULHW"
+ "mulhhwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mulhhwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (lshiftrt:SI
+ (match_operand:SI 1 "gpc_reg_operand" "%r")
+ (const_int 16))
+ (lshiftrt:SI
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (const_int 16))))]
+ "TARGET_MULHW"
+ "mulhhwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (sign_extend:SI
+ (match_dup 1))
+ (sign_extend:SI
+ (match_dup 2))))]
+ "TARGET_MULHW"
+ "mullhw. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mullhw"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (sign_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_MULHW"
+ "mullhw %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwuc"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (compare:CC (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (zero_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r")))
+ (const_int 0)))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (zero_extend:SI
+ (match_dup 1))
+ (zero_extend:SI
+ (match_dup 2))))]
+ "TARGET_MULHW"
+ "mullhwu. %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+(define_insn "*mullhwu"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (mult:SI (zero_extend:SI
+ (match_operand:HI 1 "gpc_reg_operand" "%r"))
+ (zero_extend:SI
+ (match_operand:HI 2 "gpc_reg_operand" "r"))))]
+ "TARGET_MULHW"
+ "mullhwu %0, %1, %2"
+ [(set_attr "type" "imul3")])
+
+;; IBM 405 and 440 string-search dlmzb instruction support.
+(define_insn "dlmzb"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x")
+ (unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "gpc_reg_operand" "r")]
+ UNSPEC_DLMZB_CR))
+ (set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_dup 1)
+ (match_dup 2)]
+ UNSPEC_DLMZB))]
+ "TARGET_DLMZB"
+ "dlmzb. %0, %1, %2")
+
+(define_expand "strlensi"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ (unspec:SI [(match_operand:BLK 1 "general_operand" "")
+ (match_operand:QI 2 "const_int_operand" "")
+ (match_operand 3 "const_int_operand" "")]
+ UNSPEC_DLMZB_STRLEN))
+ (clobber (match_scratch:CC 4 "=x"))]
+ "TARGET_DLMZB && WORDS_BIG_ENDIAN && !optimize_size"
+{
+ rtx result = operands[0];
+ rtx src = operands[1];
+ rtx search_char = operands[2];
+ rtx align = operands[3];
+ rtx addr, scratch_string, word1, word2, scratch_dlmzb;
+ rtx loop_label, end_label, mem, cr0, cond;
+ if (search_char != const0_rtx
+ || GET_CODE (align) != CONST_INT
+ || INTVAL (align) < 8)
+ FAIL;
+ word1 = gen_reg_rtx (SImode);
+ word2 = gen_reg_rtx (SImode);
+ scratch_dlmzb = gen_reg_rtx (SImode);
+ scratch_string = gen_reg_rtx (Pmode);
+ loop_label = gen_label_rtx ();
+ end_label = gen_label_rtx ();
+ addr = force_reg (Pmode, XEXP (src, 0));
+ emit_move_insn (scratch_string, addr);
+ emit_label (loop_label);
+ mem = change_address (src, SImode, scratch_string);
+ emit_move_insn (word1, mem);
+ emit_move_insn (word2, adjust_address (mem, SImode, 4));
+ cr0 = gen_rtx_REG (CCmode, CR0_REGNO);
+ emit_insn (gen_dlmzb (scratch_dlmzb, word1, word2, cr0));
+ cond = gen_rtx_NE (VOIDmode, cr0, const0_rtx);
+ emit_jump_insn (gen_rtx_SET (VOIDmode,
+ pc_rtx,
+ gen_rtx_IF_THEN_ELSE (VOIDmode,
+ cond,
+ gen_rtx_LABEL_REF
+ (VOIDmode,
+ end_label),
+ pc_rtx)));
+ emit_insn (gen_addsi3 (scratch_string, scratch_string, GEN_INT (8)));
+ emit_jump_insn (gen_rtx_SET (VOIDmode,
+ pc_rtx,
+ gen_rtx_LABEL_REF (VOIDmode, loop_label)));
+ emit_barrier ();
+ emit_label (end_label);
+ emit_insn (gen_addsi3 (scratch_string, scratch_string, scratch_dlmzb));
+ emit_insn (gen_subsi3 (result, scratch_string, addr));
+ emit_insn (gen_subsi3 (result, result, const1_rtx));
+ DONE;
+})
+
(define_split
[(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
(compare:CC (sign_extend:SI (match_operand:HI 1 "gpc_reg_operand" ""))
@@ -969,38 +1430,45 @@
;; Fixed-point arithmetic insns.
-;; Discourage ai/addic because of carry but provide it in an alternative
-;; allowing register zero as source.
-(define_expand "addsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_arith_cint_operand" "")))]
+(define_expand "add<mode>3"
+ [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+ (plus:SDI (match_operand:SDI 1 "gpc_reg_operand" "")
+ (match_operand:SDI 2 "reg_or_add_cint_operand" "")))]
""
- "
{
- if (GET_CODE (operands[2]) == CONST_INT
- && ! add_operand (operands[2], SImode))
+ if (<MODE>mode == DImode && ! TARGET_POWERPC64)
+ {
+ if (non_short_cint_operand (operands[2], DImode))
+ FAIL;
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && ! add_operand (operands[2], <MODE>mode))
{
rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
- ? operands[0] : gen_reg_rtx (SImode));
+ ? operands[0] : gen_reg_rtx (<MODE>mode));
HOST_WIDE_INT val = INTVAL (operands[2]);
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
- HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
+
+ if (<MODE>mode == DImode && !satisfies_constraint_L (GEN_INT (rest)))
+ FAIL;
/* 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 (rest)));
- emit_insn (gen_addsi3 (operands[0], tmp, GEN_INT (low)));
+ emit_insn (gen_add<mode>3 (tmp, operands[1], GEN_INT (rest)));
+ emit_insn (gen_add<mode>3 (operands[0], tmp, GEN_INT (low)));
DONE;
}
-}")
+})
-(define_insn "*addsi3_internal1"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,?r,r")
- (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,b,r,b")
- (match_operand:SI 2 "add_operand" "r,I,I,L")))]
+;; Discourage ai/addic because of carry but provide it in an alternative
+;; allowing register zero as source.
+(define_insn "*add<mode>3_internal1"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r,?r,r")
+ (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "%r,b,r,b")
+ (match_operand:GPR 2 "add_operand" "r,I,I,L")))]
""
"@
{cax|add} %0,%1,%2
@@ -1017,13 +1485,13 @@
"{cau|addis} %0,%1,ha16(%2)"
[(set_attr "length" "4")])
-(define_insn "*addsi3_internal2"
+(define_insn "*add<mode>3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:SI 2 "reg_or_short_operand" "r,I,r,I"))
+ (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
+ (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
(const_int 0)))
- (clobber (match_scratch:SI 3 "=r,r,r,r"))]
- "TARGET_32BIT"
+ (clobber (match_scratch:P 3 "=r,r,r,r"))]
+ ""
"@
{cax.|add.} %3,%1,%2
{ai.|addic.} %3,%1,%2
@@ -1034,28 +1502,28 @@
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
+ (compare:CC (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "reg_or_short_operand" ""))
(const_int 0)))
- (clobber (match_scratch:SI 3 ""))]
- "TARGET_32BIT && reload_completed"
+ (clobber (match_scratch:GPR 3 ""))]
+ "reload_completed"
[(set (match_dup 3)
- (plus:SI (match_dup 1)
+ (plus:GPR (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
"")
-(define_insn "*addsi3_internal3"
+(define_insn "*add<mode>3_internal3"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:SI 2 "reg_or_short_operand" "r,I,r,I"))
+ (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "%r,r,r,r")
+ (match_operand:P 2 "reg_or_short_operand" "r,I,r,I"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
- (plus:SI (match_dup 1)
- (match_dup 2)))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+ (plus:P (match_dup 1)
+ (match_dup 2)))]
+ ""
"@
{cax.|add.} %0,%1,%2
{ai.|addic.} %0,%1,%2
@@ -1066,15 +1534,15 @@
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
+ (compare:CC (plus:P (match_operand:P 1 "gpc_reg_operand" "")
+ (match_operand:P 2 "reg_or_short_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (plus:P (match_dup 1) (match_dup 2)))]
+ "reload_completed"
[(set (match_dup 0)
- (plus:SI (match_dup 1)
- (match_dup 2)))
+ (plus:P (match_dup 1)
+ (match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
@@ -1085,34 +1553,43 @@
;; add should be last in case the result gets used in an address.
(define_split
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "non_add_cint_operand" "")))]
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (plus:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "non_add_cint_operand" "")))]
""
- [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 4)))]
-"
+ [(set (match_dup 0) (plus:GPR (match_dup 1) (match_dup 3)))
+ (set (match_dup 0) (plus:GPR (match_dup 0) (match_dup 4)))]
{
HOST_WIDE_INT val = INTVAL (operands[2]);
HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
- HOST_WIDE_INT rest = trunc_int_for_mode (val - low, SImode);
+ HOST_WIDE_INT rest = trunc_int_for_mode (val - low, <MODE>mode);
- operands[3] = GEN_INT (rest);
operands[4] = GEN_INT (low);
-}")
+ if (<MODE>mode == SImode || satisfies_constraint_L (GEN_INT (rest)))
+ 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_cmplsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (not:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_insn "one_cmpl<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (not:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"nor %0,%1,%1")
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (clobber (match_scratch:SI 2 "=r,r"))]
- "TARGET_32BIT"
+ (clobber (match_scratch:P 2 "=r,r"))]
+ ""
"@
nor. %2,%1,%1
#"
@@ -1121,12 +1598,12 @@
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+ (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" ""))
(const_int 0)))
- (clobber (match_scratch:SI 2 ""))]
- "TARGET_32BIT && reload_completed"
+ (clobber (match_scratch:P 2 ""))]
+ "reload_completed"
[(set (match_dup 2)
- (not:SI (match_dup 1)))
+ (not:P (match_dup 1)))
(set (match_dup 0)
(compare:CC (match_dup 2)
(const_int 0)))]
@@ -1134,11 +1611,11 @@
(define_insn ""
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (not:SI (match_dup 1)))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (not:P (match_dup 1)))]
+ ""
"@
nor. %0,%1,%1
#"
@@ -1147,13 +1624,13 @@
(define_split
[(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (not:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+ (compare:CC (not:P (match_operand:P 1 "gpc_reg_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (not:SI (match_dup 1)))]
- "TARGET_32BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (not:P (match_dup 1)))]
+ "reload_completed"
[(set (match_dup 0)
- (not:SI (match_dup 1)))
+ (not:P (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
@@ -1167,9 +1644,9 @@
"{sf%I1|subf%I1c} %0,%2,%1")
(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (minus:SI (match_operand:SI 1 "reg_or_short_operand" "r,I")
- (match_operand:SI 2 "gpc_reg_operand" "r,r")))]
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r,r")
+ (minus:GPR (match_operand:GPR 1 "reg_or_short_operand" "r,I")
+ (match_operand:GPR 2 "gpc_reg_operand" "r,r")))]
"TARGET_POWERPC"
"@
subf %0,%2,%1
@@ -1190,11 +1667,11 @@
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+ (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (clobber (match_scratch:SI 3 "=r,r"))]
- "TARGET_POWERPC && TARGET_32BIT"
+ (clobber (match_scratch:P 3 "=r,r"))]
+ "TARGET_POWERPC"
"@
subf. %3,%2,%1
#"
@@ -1203,13 +1680,13 @@
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "gpc_reg_operand" ""))
+ (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "")
+ (match_operand:P 2 "gpc_reg_operand" ""))
(const_int 0)))
- (clobber (match_scratch:SI 3 ""))]
- "TARGET_32BIT && reload_completed"
+ (clobber (match_scratch:P 3 ""))]
+ "reload_completed"
[(set (match_dup 3)
- (minus:SI (match_dup 1)
+ (minus:P (match_dup 1)
(match_dup 2)))
(set (match_dup 0)
(compare:CC (match_dup 3)
@@ -1232,13 +1709,13 @@
(define_insn ""
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "gpc_reg_operand" "r,r"))
+ (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (minus:SI (match_dup 1)
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (minus:P (match_dup 1)
(match_dup 2)))]
- "TARGET_POWERPC && TARGET_32BIT"
+ "TARGET_POWERPC"
"@
subf. %0,%2,%1
#"
@@ -1247,32 +1724,32 @@
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (minus:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "gpc_reg_operand" ""))
+ (compare:CC (minus:P (match_operand:P 1 "gpc_reg_operand" "")
+ (match_operand:P 2 "gpc_reg_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (minus:SI (match_dup 1)
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (minus:P (match_dup 1)
(match_dup 2)))]
- "TARGET_32BIT && reload_completed"
+ "reload_completed"
[(set (match_dup 0)
- (minus:SI (match_dup 1)
+ (minus:P (match_dup 1)
(match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-(define_expand "subsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (minus:SI (match_operand:SI 1 "reg_or_short_operand" "")
- (match_operand:SI 2 "reg_or_arith_cint_operand" "")))]
+(define_expand "sub<mode>3"
+ [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+ (minus:SDI (match_operand:SDI 1 "reg_or_short_operand" "")
+ (match_operand:SDI 2 "reg_or_sub_cint_operand" "")))]
""
"
{
if (GET_CODE (operands[2]) == CONST_INT)
{
- emit_insn (gen_addsi3 (operands[0], operands[1],
- negate_rtx (SImode, operands[2])));
+ emit_insn (gen_add<mode>3 (operands[0], operands[1],
+ negate_rtx (<MODE>mode, operands[2])));
DONE;
}
}")
@@ -1555,18 +2032,24 @@
(set (match_dup 0) (minus:SI (match_dup 2) (match_dup 0)))]
"")
-(define_insn "negsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_expand "neg<mode>2"
+ [(set (match_operand:SDI 0 "gpc_reg_operand" "")
+ (neg:SDI (match_operand:SDI 1 "gpc_reg_operand" "")))]
+ ""
+ "")
+
+(define_insn "*neg<mode>2_internal"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
"neg %0,%1")
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (clobber (match_scratch:SI 2 "=r,r"))]
- "TARGET_32BIT"
+ (clobber (match_scratch:P 2 "=r,r"))]
+ ""
"@
neg. %2,%1
#"
@@ -1575,12 +2058,12 @@
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+ (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
(const_int 0)))
- (clobber (match_scratch:SI 2 ""))]
- "TARGET_32BIT && reload_completed"
+ (clobber (match_scratch:P 2 ""))]
+ "reload_completed"
[(set (match_dup 2)
- (neg:SI (match_dup 1)))
+ (neg:P (match_dup 1)))
(set (match_dup 0)
(compare:CC (match_dup 2)
(const_int 0)))]
@@ -1588,11 +2071,11 @@
(define_insn ""
[(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r,r"))
+ (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" "r,r"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (neg:SI (match_dup 1)))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (neg:P (match_dup 1)))]
+ ""
"@
neg. %0,%1
#"
@@ -1601,56 +2084,85 @@
(define_split
[(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (neg:SI (match_operand:SI 1 "gpc_reg_operand" ""))
+ (compare:CC (neg:P (match_operand:P 1 "gpc_reg_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (neg:SI (match_dup 1)))]
- "TARGET_32BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (neg:P (match_dup 1)))]
+ "reload_completed"
[(set (match_dup 0)
- (neg:SI (match_dup 1)))
+ (neg:P (match_dup 1)))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-(define_insn "clzsi2"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (clz:SI (match_operand:SI 1 "gpc_reg_operand" "r")))]
+(define_insn "clz<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (clz:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))]
""
- "{cntlz|cntlzw} %0,%1")
+ "{cntlz|cntlz<wd>} %0,%1")
-(define_expand "ctzsi2"
+(define_expand "ctz<mode>2"
[(set (match_dup 2)
- (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
- (parallel [(set (match_dup 3) (and:SI (match_dup 1)
- (match_dup 2)))
+ (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+ (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
+ (match_dup 2)))
(clobber (scratch:CC))])
- (set (match_dup 4) (clz:SI (match_dup 3)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (minus:SI (const_int 31) (match_dup 4)))]
+ (set (match_dup 4) (clz:GPR (match_dup 3)))
+ (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (minus:GPR (match_dup 5) (match_dup 4)))]
""
{
- operands[2] = gen_reg_rtx (SImode);
- operands[3] = gen_reg_rtx (SImode);
- operands[4] = gen_reg_rtx (SImode);
+ operands[2] = gen_reg_rtx (<MODE>mode);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+ operands[4] = gen_reg_rtx (<MODE>mode);
+ operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 1);
})
-
-(define_expand "ffssi2"
+
+(define_expand "ffs<mode>2"
[(set (match_dup 2)
- (neg:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
- (parallel [(set (match_dup 3) (and:SI (match_dup 1)
- (match_dup 2)))
+ (neg:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")))
+ (parallel [(set (match_dup 3) (and:GPR (match_dup 1)
+ (match_dup 2)))
(clobber (scratch:CC))])
- (set (match_dup 4) (clz:SI (match_dup 3)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (minus:SI (const_int 32) (match_dup 4)))]
+ (set (match_dup 4) (clz:GPR (match_dup 3)))
+ (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (minus:GPR (match_dup 5) (match_dup 4)))]
""
{
- operands[2] = gen_reg_rtx (SImode);
- operands[3] = gen_reg_rtx (SImode);
- operands[4] = gen_reg_rtx (SImode);
+ operands[2] = gen_reg_rtx (<MODE>mode);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+ operands[4] = gen_reg_rtx (<MODE>mode);
+ operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode));
})
-
+
+(define_expand "popcount<mode>2"
+ [(set (match_dup 2)
+ (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
+ UNSPEC_POPCNTB))
+ (set (match_dup 3)
+ (mult:GPR (match_dup 2) (match_dup 4)))
+ (set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (lshiftrt:GPR (match_dup 3) (match_dup 5)))]
+ "TARGET_POPCNTB"
+ {
+ operands[2] = gen_reg_rtx (<MODE>mode);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+ operands[4] = force_reg (<MODE>mode,
+ <MODE>mode == SImode
+ ? GEN_INT (0x01010101)
+ : GEN_INT ((HOST_WIDE_INT)
+ 0x01010101 << 32 | 0x01010101));
+ operands[5] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - 8);
+ })
+
+(define_insn "popcntb<mode>2"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (unspec:GPR [(match_operand:GPR 1 "gpc_reg_operand" "r")]
+ UNSPEC_POPCNTB))]
+ "TARGET_POPCNTB"
+ "popcntb %0,%1")
+
(define_expand "mulsi3"
[(use (match_operand:SI 0 "gpc_reg_operand" ""))
(use (match_operand:SI 1 "gpc_reg_operand" ""))
@@ -1674,10 +2186,10 @@
"@
{muls|mullw} %0,%1,%2
{muli|mulli} %0,%1,%2"
- [(set (attr "type")
+ [(set (attr "type")
(cond [(match_operand:SI 2 "s8bit_cint_operand" "")
(const_string "imul3")
- (match_operand:SI 2 "short_cint_operand" "")
+ (match_operand:SI 2 "short_cint_operand" "")
(const_string "imul2")]
(const_string "imul")))])
@@ -1689,10 +2201,10 @@
"@
{muls|mullw} %0,%1,%2
{muli|mulli} %0,%1,%2"
- [(set (attr "type")
+ [(set (attr "type")
(cond [(match_operand:SI 2 "s8bit_cint_operand" "")
(const_string "imul3")
- (match_operand:SI 2 "short_cint_operand" "")
+ (match_operand:SI 2 "short_cint_operand" "")
(const_string "imul2")]
(const_string "imul")))])
@@ -1848,10 +2360,10 @@
"divs %0,%1,%2"
[(set_attr "type" "idiv")])
-(define_expand "udivsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "gpc_reg_operand" "")))]
+(define_expand "udiv<mode>3"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "gpc_reg_operand" "")))]
"TARGET_POWERPC || (! TARGET_POWER && ! TARGET_POWERPC)"
"
{
@@ -1880,21 +2392,21 @@
[(set_attr "type" "idiv")])
(define_insn "*udivsi3_no_mq"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (udiv:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "gpc_reg_operand" "r")))]
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (udiv:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "gpc_reg_operand" "r")))]
"TARGET_POWERPC && ! TARGET_POWER"
- "divwu %0,%1,%2"
+ "div<wd>u %0,%1,%2"
[(set_attr "type" "idiv")])
;; For powers of two we can do srai/aze for divide and then adjust for
;; modulus. If it isn't a power of two, FAIL on POWER so divmodsi4 will be
;; used; for PowerPC, force operands into register and do a normal divide;
;; for AIX common-mode, use quoss call on register operands.
-(define_expand "divsi3"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_cint_operand" "")))]
+(define_expand "div<mode>3"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "reg_or_cint_operand" "")))]
""
"
{
@@ -1904,7 +2416,7 @@
;
else if (TARGET_POWERPC)
{
- operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = force_reg (<MODE>mode, operands[2]);
if (TARGET_POWER)
{
emit_insn (gen_divsi3_mq (operands[0], operands[1], operands[2]));
@@ -1932,18 +2444,18 @@
"divw %0,%1,%2"
[(set_attr "type" "idiv")])
-(define_insn "*divsi3_no_mq"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "gpc_reg_operand" "r")))]
+(define_insn "*div<mode>3_no_mq"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "gpc_reg_operand" "r")))]
"TARGET_POWERPC && ! TARGET_POWER"
- "divw %0,%1,%2"
+ "div<wd> %0,%1,%2"
[(set_attr "type" "idiv")])
-(define_expand "modsi3"
- [(use (match_operand:SI 0 "gpc_reg_operand" ""))
- (use (match_operand:SI 1 "gpc_reg_operand" ""))
- (use (match_operand:SI 2 "reg_or_cint_operand" ""))]
+(define_expand "mod<mode>3"
+ [(use (match_operand:GPR 0 "gpc_reg_operand" ""))
+ (use (match_operand:GPR 1 "gpc_reg_operand" ""))
+ (use (match_operand:GPR 2 "reg_or_cint_operand" ""))]
""
"
{
@@ -1956,45 +2468,47 @@
|| (i = exact_log2 (INTVAL (operands[2]))) < 0)
FAIL;
- temp1 = gen_reg_rtx (SImode);
- temp2 = gen_reg_rtx (SImode);
+ temp1 = gen_reg_rtx (<MODE>mode);
+ temp2 = gen_reg_rtx (<MODE>mode);
- emit_insn (gen_divsi3 (temp1, operands[1], operands[2]));
- emit_insn (gen_ashlsi3 (temp2, temp1, GEN_INT (i)));
- emit_insn (gen_subsi3 (operands[0], operands[1], temp2));
+ emit_insn (gen_div<mode>3 (temp1, operands[1], operands[2]));
+ emit_insn (gen_ashl<mode>3 (temp2, temp1, GEN_INT (i)));
+ emit_insn (gen_sub<mode>3 (operands[0], operands[1], temp2));
DONE;
}")
(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (div:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "exact_log2_cint_operand" "N")))]
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "exact_log2_cint_operand" "N")))]
""
- "{srai|srawi} %0,%1,%p2\;{aze|addze} %0,%0"
- [(set_attr "length" "8")])
+ "{srai|sra<wd>i} %0,%1,%p2\;{aze|addze} %0,%0"
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
+ (compare:CC (div:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "exact_log2_cint_operand" "N,N"))
(const_int 0)))
- (clobber (match_scratch:SI 3 "=r,r"))]
+ (clobber (match_scratch:P 3 "=r,r"))]
""
"@
- {srai|srawi} %3,%1,%p2\;{aze.|addze.} %3,%3
+ {srai|sra<wd>i} %3,%1,%p2\;{aze.|addze.} %3,%3
#"
[(set_attr "type" "compare")
(set_attr "length" "8,12")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "exact_log2_cint_operand" ""))
+ (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "exact_log2_cint_operand"
+ ""))
(const_int 0)))
- (clobber (match_scratch:SI 3 ""))]
+ (clobber (match_scratch:GPR 3 ""))]
"reload_completed"
[(set (match_dup 3)
- (div:SI (match_dup 1) (match_dup 2)))
+ (div:<MODE> (match_dup 1) (match_dup 2)))
(set (match_dup 0)
(compare:CC (match_dup 3)
(const_int 0)))]
@@ -2002,28 +2516,29 @@
(define_insn ""
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "exact_log2_cint_operand" "N,N"))
+ (compare:CC (div:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "exact_log2_cint_operand" "N,N"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (div:SI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (div:P (match_dup 1) (match_dup 2)))]
""
"@
- {srai|srawi} %0,%1,%p2\;{aze.|addze.} %0,%0
+ {srai|sra<wd>i} %0,%1,%p2\;{aze.|addze.} %0,%0
#"
[(set_attr "type" "compare")
(set_attr "length" "8,12")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (div:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "exact_log2_cint_operand" ""))
+ (compare:CC (div:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "exact_log2_cint_operand"
+ ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (div:SI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:GPR 0 "gpc_reg_operand" "")
+ (div:GPR (match_dup 1) (match_dup 2)))]
"reload_completed"
[(set (match_dup 0)
- (div:SI (match_dup 1) (match_dup 2)))
+ (div:<MODE> (match_dup 1) (match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
@@ -2215,7 +2730,8 @@
and %0,%1,%2
{rlinm|rlwinm} %0,%1,0,%m2,%M2
{andil.|andi.} %0,%1,%b2
- {andiu.|andis.} %0,%1,%u2")
+ {andiu.|andis.} %0,%1,%u2"
+ [(set_attr "type" "*,*,compare,compare")])
;; Note to set cr's other than cr0 we do the and immediate and then
;; the test again -- this avoids a mfcr which on the higher end
@@ -2263,15 +2779,15 @@
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (and:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "and_operand" ""))
+ (compare:CC (and:GPR (match_operand:GPR 1 "gpc_reg_operand" "")
+ (match_operand:GPR 2 "and_operand" ""))
(const_int 0)))
- (clobber (match_scratch:SI 3 ""))
+ (clobber (match_scratch:GPR 3 ""))
(clobber (match_scratch:CC 4 ""))]
"reload_completed"
[(parallel [(set (match_dup 3)
- (and:SI (match_dup 1)
- (match_dup 2)))
+ (and:<MODE> (match_dup 1)
+ (match_dup 2)))
(clobber (match_dup 4))])
(set (match_dup 0)
(compare:CC (match_dup 3)
@@ -2515,7 +3031,7 @@
(const_int 0)))]
"")
-;; Split a logical operation that we can't do in one insn into two insns,
+;; Split a logical operation that we can't do in one insn into two insns,
;; each of which does one 16-bit part. This is used by combine.
(define_split
@@ -2530,11 +3046,11 @@
{
rtx i;
i = GEN_INT (INTVAL (operands[2]) & (~ (HOST_WIDE_INT) 0xffff));
- operands[4] = gen_rtx (GET_CODE (operands[3]), SImode,
- operands[1], i);
+ operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
+ operands[1], i);
i = GEN_INT (INTVAL (operands[2]) & 0xffff);
- operands[5] = gen_rtx (GET_CODE (operands[3]), SImode,
- operands[0], i);
+ operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
+ operands[0], i);
}")
(define_insn "*boolcsi3_internal1"
@@ -2873,9 +3389,12 @@
{
/* Do not handle 16/8 bit structures that fit in HI/QI modes directly, since
the (SUBREG:SI (REG:HI xxx)) that is otherwise generated can confuse the
- compiler if the address of the structure is taken later. */
+ compiler if the address of the structure is taken later. Likewise, do
+ not handle invalid E500 subregs. */
if (GET_CODE (operands[0]) == SUBREG
- && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD))
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (operands[0]))) < UNITS_PER_WORD
+ || ((TARGET_E500_DOUBLE || TARGET_SPE)
+ && invalid_e500_subreg (operands[0], GET_MODE (operands[0])))))
FAIL;
if (TARGET_POWERPC64 && GET_MODE (operands[0]) == DImode)
@@ -2906,7 +3425,7 @@
[(set (zero_extract:SI (match_operand:SI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
(match_operand:SI 2 "const_int_operand" "i"))
- (ashift:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+ (rotate:SI (match_operand:SI 3 "gpc_reg_operand" "r")
(match_operand:SI 4 "const_int_operand" "i")))]
"(32 - (INTVAL (operands[4]) & 31)) >= INTVAL (operands[1])"
"*
@@ -2981,6 +3500,45 @@
}"
[(set_attr "type" "insert_word")])
+;; combine patterns for rlwimi
+(define_insn "*insvsi_internal5"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (ior:SI (and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+ (match_operand:SI 1 "mask_operand" "i"))
+ (and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (match_operand:SI 5 "mask_operand" "i"))))]
+ "TARGET_POWERPC && INTVAL(operands[1]) == ~INTVAL(operands[5])"
+ "*
+{
+ int me = extract_ME(operands[5]);
+ int mb = extract_MB(operands[5]);
+ operands[4] = GEN_INT(32 - INTVAL(operands[2]));
+ operands[2] = GEN_INT(mb);
+ operands[1] = GEN_INT(me);
+ return \"{rlimi|rlwimi} %0,%3,%h4,%h2,%h1\";
+}"
+ [(set_attr "type" "insert_word")])
+
+(define_insn "*insvsi_internal6"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (ior:SI (and:SI (lshiftrt:SI (match_operand:SI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (match_operand:SI 5 "mask_operand" "i"))
+ (and:SI (match_operand:SI 4 "gpc_reg_operand" "0")
+ (match_operand:SI 1 "mask_operand" "i"))))]
+ "TARGET_POWERPC && INTVAL(operands[1]) == ~INTVAL(operands[5])"
+ "*
+{
+ int me = extract_ME(operands[5]);
+ int mb = extract_MB(operands[5]);
+ operands[4] = GEN_INT(32 - INTVAL(operands[2]));
+ operands[2] = GEN_INT(mb);
+ operands[1] = GEN_INT(me);
+ return \"{rlimi|rlwimi} %0,%3,%h4,%h2,%h1\";
+}"
+ [(set_attr "type" "insert_word")])
+
(define_insn "insvdi"
[(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
(match_operand:SI 1 "const_int_operand" "i")
@@ -2996,6 +3554,46 @@
return \"rldimi %0,%3,%H1,%H2\";
}")
+(define_insn "*insvdi_internal2"
+ [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "i")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (ashiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 4 "const_int_operand" "i")))]
+ "TARGET_POWERPC64
+ && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+ "*
+{
+ int shift = INTVAL (operands[4]) & 63;
+ int start = (INTVAL (operands[2]) & 63) - 32;
+ int size = INTVAL (operands[1]) & 63;
+
+ operands[4] = GEN_INT (64 - shift - start - size);
+ operands[2] = GEN_INT (start);
+ operands[1] = GEN_INT (start + size - 1);
+ return \"rlwimi %0,%3,%h4,%h2,%h1\";
+}")
+
+(define_insn "*insvdi_internal3"
+ [(set (zero_extract:DI (match_operand:DI 0 "gpc_reg_operand" "+r")
+ (match_operand:SI 1 "const_int_operand" "i")
+ (match_operand:SI 2 "const_int_operand" "i"))
+ (lshiftrt:DI (match_operand:DI 3 "gpc_reg_operand" "r")
+ (match_operand:SI 4 "const_int_operand" "i")))]
+ "TARGET_POWERPC64
+ && insvdi_rshift_rlwimi_p (operands[1], operands[2], operands[4])"
+ "*
+{
+ int shift = INTVAL (operands[4]) & 63;
+ int start = (INTVAL (operands[2]) & 63) - 32;
+ int size = INTVAL (operands[1]) & 63;
+
+ operands[4] = GEN_INT (64 - shift - start - size);
+ operands[2] = GEN_INT (start);
+ operands[1] = GEN_INT (start + size - 1);
+ return \"rlwimi %0,%3,%h4,%h2,%h1\";
+}")
+
(define_expand "extzv"
[(set (match_operand 0 "gpc_reg_operand" "")
(zero_extract (match_operand 1 "gpc_reg_operand" "")
@@ -3183,7 +3781,8 @@
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl. %4,%1,%3,%2\";
-}")
+}"
+ [(set_attr "type" "compare")])
(define_insn "*extzvdi_internal2"
[(set (match_operand:CC 4 "gpc_reg_operand" "=x")
@@ -3205,7 +3804,8 @@
operands[3] = GEN_INT (start + size);
operands[2] = GEN_INT (64 - size);
return \"rldicl. %0,%1,%3,%2\";
-}")
+}"
+ [(set_attr "type" "compare")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -3650,7 +4250,7 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "rlwinm"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(and:SI (ashift:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "const_int_operand" "i"))
@@ -4317,20 +4917,35 @@
;; this case, we just lose precision that we would have otherwise gotten but
;; is not guaranteed. Perhaps this should be tightened up at some point.
-(define_insn "extendsfdf2"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
- (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "f")))]
+(define_expand "extendsfdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (float_extend:DF (match_operand:SF 1 "reg_or_none500mem_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn_and_split "*extendsfdf2_fpr"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f,f")
+ (float_extend:DF (match_operand:SF 1 "reg_or_mem_operand" "0,f,m")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
- "*
+ "@
+ #
+ fmr %0,%1
+ lfs%U1%X1 %0,%1"
+ "&& reload_completed && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])"
+ [(const_int 0)]
{
- if (REGNO (operands[0]) == REGNO (operands[1]))
- return \"\";
- else
- return \"fmr %0,%1\";
-}"
- [(set_attr "type" "fp")])
+ emit_note (NOTE_INSN_DELETED);
+ DONE;
+}
+ [(set_attr "type" "fp,fp,fpload")])
+
+(define_expand "truncdfsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
-(define_insn "truncdfsf2"
+(define_insn "*truncdfsf2_fpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
@@ -4446,12 +5061,26 @@
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")])
+(define_insn "fres"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+ "TARGET_PPC_GFXOPT && flag_finite_math_only"
+ "fres %0,%1"
+ [(set_attr "type" "fp")])
+
(define_expand "divsf3"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(div:SF (match_operand:SF 1 "gpc_reg_operand" "")
(match_operand:SF 2 "gpc_reg_operand" "")))]
"TARGET_HARD_FLOAT"
- "")
+{
+ if (swdiv && !optimize_size && TARGET_PPC_GFXOPT
+ && flag_finite_math_only && !flag_trapping_math)
+ {
+ rs6000_emit_swdivsf (operands[0], operands[1], operands[2]);
+ DONE;
+ }
+})
(define_insn ""
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
@@ -4581,7 +5210,7 @@
"! TARGET_POWERPC && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
&& ! HONOR_SIGNED_ZEROS (SFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
- [(set_attr "type" "fp")])
+ [(set_attr "type" "dmul")])
(define_expand "sqrtsf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -4603,26 +5232,62 @@
"fsqrt %0,%1"
[(set_attr "type" "dsqrt")])
+(define_expand "copysignsf3"
+ [(set (match_dup 3)
+ (abs:SF (match_operand:SF 1 "gpc_reg_operand" "")))
+ (set (match_dup 4)
+ (neg:SF (abs:SF (match_dup 1))))
+ (set (match_operand:SF 0 "gpc_reg_operand" "")
+ (if_then_else:SF (ge (match_operand:SF 2 "gpc_reg_operand" "")
+ (match_dup 5))
+ (match_dup 3)
+ (match_dup 4)))]
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
+ && !HONOR_NANS (SFmode) && !HONOR_SIGNED_ZEROS (SFmode)"
+ {
+ operands[3] = gen_reg_rtx (SFmode);
+ operands[4] = gen_reg_rtx (SFmode);
+ operands[5] = CONST0_RTX (SFmode);
+ })
+
+(define_expand "copysigndf3"
+ [(set (match_dup 3)
+ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))
+ (set (match_dup 4)
+ (neg:DF (abs:DF (match_dup 1))))
+ (set (match_operand:DF 0 "gpc_reg_operand" "")
+ (if_then_else:DF (ge (match_operand:DF 2 "gpc_reg_operand" "")
+ (match_dup 5))
+ (match_dup 3)
+ (match_dup 4)))]
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS
+ && !HONOR_NANS (DFmode) && !HONOR_SIGNED_ZEROS (DFmode)"
+ {
+ operands[3] = gen_reg_rtx (DFmode);
+ operands[4] = gen_reg_rtx (DFmode);
+ operands[5] = CONST0_RTX (DFmode);
+ })
+
;; 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.
-(define_expand "maxsf3"
+(define_expand "smaxsf3"
[(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 1)
(match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
"{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
-(define_expand "minsf3"
+(define_expand "sminsf3"
[(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 && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
"{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
@@ -4630,10 +5295,10 @@
(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 && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
[(const_int 0)]
"
-{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
operands[1], operands[2]);
DONE;
}")
@@ -4720,28 +5385,47 @@
"fsel %0,%1,%2,%3"
[(set_attr "type" "fp")])
-(define_insn "negdf2"
+(define_expand "negdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (neg:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn "*negdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(neg:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
"fneg %0,%1"
[(set_attr "type" "fp")])
-(define_insn "absdf2"
+(define_expand "absdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn "*absdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(abs:DF (match_operand:DF 1 "gpc_reg_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
"fabs %0,%1"
[(set_attr "type" "fp")])
-(define_insn ""
+(define_insn "*nabsdf2_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "f"))))]
"TARGET_HARD_FLOAT && TARGET_FPRS"
"fnabs %0,%1"
[(set_attr "type" "fp")])
-(define_insn "adddf3"
+(define_expand "adddf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (plus:DF (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn "*adddf3_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(plus:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -4749,7 +5433,14 @@
"{fa|fadd} %0,%1,%2"
[(set_attr "type" "fp")])
-(define_insn "subdf3"
+(define_expand "subdf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (minus:DF (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn "*subdf3_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(minus:DF (match_operand:DF 1 "gpc_reg_operand" "f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -4757,7 +5448,14 @@
"{fs|fsub} %0,%1,%2"
[(set_attr "type" "fp")])
-(define_insn "muldf3"
+(define_expand "muldf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+ "")
+
+(define_insn "*muldf3_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -4765,7 +5463,28 @@
"{fm|fmul} %0,%1,%2"
[(set_attr "type" "dmul")])
-(define_insn "divdf3"
+(define_insn "fred"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRES))]
+ "TARGET_POPCNTB && flag_finite_math_only"
+ "fre %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (div:DF (match_operand:DF 1 "gpc_reg_operand" "")
+ (match_operand:DF 2 "gpc_reg_operand" "")))]
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
+{
+ if (swdiv && !optimize_size && TARGET_POPCNTB
+ && flag_finite_math_only && !flag_trapping_math)
+ {
+ rs6000_emit_swdivdf (operands[0], operands[1], operands[2]);
+ DONE;
+ }
+})
+
+(define_insn "*divdf3_fpr"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(div:DF (match_operand:DF 1 "gpc_reg_operand" "f")
(match_operand:DF 2 "gpc_reg_operand" "f")))]
@@ -4826,7 +5545,7 @@
(minus:DF (match_operand:DF 3 "gpc_reg_operand" "f")
(mult:DF (match_operand:DF 1 "gpc_reg_operand" "%f")
(match_operand:DF 2 "gpc_reg_operand" "f"))))]
- "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
+ "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_FUSED_MADD
&& ! HONOR_SIGNED_ZEROS (DFmode)"
"{fnms|fnmsub} %0,%1,%2,%3"
[(set_attr "type" "dmul")])
@@ -4839,24 +5558,24 @@
[(set_attr "type" "dsqrt")])
;; The conditional move instructions allow us to perform max and min
-;; operations even when
+;; operations even when
-(define_expand "maxdf3"
+(define_expand "smaxdf3"
[(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 1)
(match_dup 2)))]
- "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
"{ rs6000_emit_minmax (operands[0], SMAX, operands[1], operands[2]); DONE;}")
-(define_expand "mindf3"
+(define_expand "smindf3"
[(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 && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
"{ rs6000_emit_minmax (operands[0], SMIN, operands[1], operands[2]); DONE;}")
(define_split
@@ -4864,10 +5583,10 @@
(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 && TARGET_FPRS"
+ "TARGET_PPC_GFXOPT && TARGET_HARD_FLOAT && TARGET_FPRS && !flag_trapping_math"
[(const_int 0)]
"
-{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
+{ rs6000_emit_minmax (operands[0], GET_CODE (operands[3]),
operands[1], operands[2]);
DONE;
}")
@@ -4936,6 +5655,11 @@
"TARGET_HARD_FLOAT && TARGET_FPRS"
"
{
+ if (TARGET_E500_DOUBLE)
+ {
+ emit_insn (gen_spe_floatsidf2 (operands[0], operands[1]));
+ DONE;
+ }
if (TARGET_POWERPC64)
{
rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
@@ -4952,7 +5676,7 @@
operands[6] = gen_reg_rtx (SImode);
}")
-(define_insn "*floatsidf2_internal"
+(define_insn_and_split "*floatsidf2_internal"
[(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
(float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
(use (match_operand:SI 2 "gpc_reg_operand" "r"))
@@ -4962,45 +5686,29 @@
(clobber (match_operand:SI 6 "gpc_reg_operand" "=&r"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
- [(set_attr "length" "24")])
-
-(define_split
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
- (use (match_operand:SI 2 "gpc_reg_operand" ""))
- (use (match_operand:DF 3 "gpc_reg_operand" ""))
- (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
- (clobber (match_operand:DF 5 "gpc_reg_operand" ""))
- (clobber (match_operand:SI 6 "gpc_reg_operand" ""))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
- (use (match_operand:SI 2 "gpc_reg_operand" ""))
- (use (match_operand:DF 3 "gpc_reg_operand" ""))
- (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
- (clobber (match_operand:DF 5 "gpc_reg_operand" ""))
- (clobber (match_operand:SI 6 "gpc_reg_operand" ""))]
+ "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+ [(pc)]
"
{
rtx lowword, highword;
- if (GET_CODE (operands[4]) != MEM)
- abort();
- highword = XEXP (operands[4], 0);
- lowword = plus_constant (highword, 4);
+ gcc_assert (MEM_P (operands[4]));
+ highword = adjust_address (operands[4], SImode, 0);
+ lowword = adjust_address (operands[4], SImode, 4);
if (! WORDS_BIG_ENDIAN)
{
rtx tmp;
tmp = highword; highword = lowword; lowword = tmp;
}
- emit_insn (gen_xorsi3 (operands[6], operands[1],
+ emit_insn (gen_xorsi3 (operands[6], operands[1],
GEN_INT (~ (HOST_WIDE_INT) 0x7fffffff)));
- emit_move_insn (gen_rtx_MEM (SImode, lowword), operands[6]);
- emit_move_insn (gen_rtx_MEM (SImode, highword), operands[2]);
+ emit_move_insn (lowword, operands[6]);
+ emit_move_insn (highword, operands[2]);
emit_move_insn (operands[5], operands[4]);
emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
DONE;
-}")
+}"
+ [(set_attr "length" "24")])
(define_expand "floatunssisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
@@ -5015,9 +5723,14 @@
(use (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])]
- "TARGET_HARD_FLOAT && TARGET_FPRS"
+ "TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
"
{
+ if (TARGET_E500_DOUBLE)
+ {
+ emit_insn (gen_spe_floatunssidf2 (operands[0], operands[1]));
+ DONE;
+ }
if (TARGET_POWERPC64)
{
rtx mem = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
@@ -5034,7 +5747,7 @@
operands[5] = gen_reg_rtx (DFmode);
}")
-(define_insn "*floatunssidf2_internal"
+(define_insn_and_split "*floatunssidf2_internal"
[(set (match_operand:DF 0 "gpc_reg_operand" "=&f")
(unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))
(use (match_operand:SI 2 "gpc_reg_operand" "r"))
@@ -5043,100 +5756,173 @@
(clobber (match_operand:DF 5 "gpc_reg_operand" "=&f"))]
"! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
- [(set_attr "length" "20")])
-
-(define_split
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
- (use (match_operand:SI 2 "gpc_reg_operand" ""))
- (use (match_operand:DF 3 "gpc_reg_operand" ""))
- (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
- (clobber (match_operand:DF 5 "gpc_reg_operand" ""))]
- "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS"
- [(set (match_operand:DF 0 "gpc_reg_operand" "")
- (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "")))
- (use (match_operand:SI 2 "gpc_reg_operand" ""))
- (use (match_operand:DF 3 "gpc_reg_operand" ""))
- (clobber (match_operand:DF 4 "offsettable_mem_operand" ""))
- (clobber (match_operand:DF 5 "gpc_reg_operand" ""))]
+ "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[4]))"
+ [(pc)]
"
{
rtx lowword, highword;
- if (GET_CODE (operands[4]) != MEM)
- abort();
- highword = XEXP (operands[4], 0);
- lowword = plus_constant (highword, 4);
+ gcc_assert (MEM_P (operands[4]));
+ highword = adjust_address (operands[4], SImode, 0);
+ lowword = adjust_address (operands[4], SImode, 4);
if (! WORDS_BIG_ENDIAN)
{
rtx tmp;
tmp = highword; highword = lowword; lowword = tmp;
}
- emit_move_insn (gen_rtx_MEM (SImode, lowword), operands[1]);
- emit_move_insn (gen_rtx_MEM (SImode, highword), operands[2]);
+ emit_move_insn (lowword, operands[1]);
+ emit_move_insn (highword, operands[2]);
emit_move_insn (operands[5], operands[4]);
emit_insn (gen_subdf3 (operands[0], operands[5], operands[3]));
DONE;
-}")
+}"
+ [(set_attr "length" "20")])
(define_expand "fix_truncdfsi2"
- [(parallel [(set (match_operand:SI 0 "gpc_reg_operand" "")
+ [(parallel [(set (match_operand:SI 0 "fix_trunc_dest_operand" "")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
(clobber (match_dup 2))
(clobber (match_dup 3))])]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "(TARGET_POWER2 || TARGET_POWERPC)
+ && TARGET_HARD_FLOAT && (TARGET_FPRS || TARGET_E500_DOUBLE)"
"
{
+ if (TARGET_E500_DOUBLE)
+ {
+ emit_insn (gen_spe_fix_truncdfsi2 (operands[0], operands[1]));
+ DONE;
+ }
operands[2] = gen_reg_rtx (DImode);
+ if (TARGET_PPC_GFXOPT)
+ {
+ rtx orig_dest = operands[0];
+ if (! memory_operand (orig_dest, GET_MODE (orig_dest)))
+ operands[0] = assign_stack_temp (SImode, GET_MODE_SIZE (SImode), 0);
+ emit_insn (gen_fix_truncdfsi2_internal_gfxopt (operands[0], operands[1],
+ operands[2]));
+ if (operands[0] != orig_dest)
+ emit_move_insn (orig_dest, operands[0]);
+ DONE;
+ }
operands[3] = assign_stack_temp (DImode, GET_MODE_SIZE (DImode), 0);
}")
-(define_insn "*fix_truncdfsi2_internal"
+(define_insn_and_split "*fix_truncdfsi2_internal"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
(clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))
(clobber (match_operand:DI 3 "memory_operand" "=o"))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
"#"
- [(set_attr "length" "16")])
-
-(define_split
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
- (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
- (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))]
- "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
- [(set (match_operand:SI 0 "gpc_reg_operand" "")
- (fix:SI (match_operand:DF 1 "gpc_reg_operand" "")))
- (clobber (match_operand:DI 2 "gpc_reg_operand" ""))
- (clobber (match_operand:DI 3 "offsettable_mem_operand" ""))]
+ "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[3]))"
+ [(pc)]
"
{
rtx lowword;
- if (GET_CODE (operands[3]) != MEM)
- abort();
- lowword = XEXP (operands[3], 0);
- if (WORDS_BIG_ENDIAN)
- lowword = plus_constant (lowword, 4);
+ gcc_assert (MEM_P (operands[3]));
+ lowword = adjust_address (operands[3], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
emit_insn (gen_fctiwz (operands[2], operands[1]));
emit_move_insn (operands[3], operands[2]);
- emit_move_insn (operands[0], gen_rtx_MEM (SImode, lowword));
+ emit_move_insn (operands[0], lowword);
DONE;
-}")
+}"
+ [(set_attr "length" "16")])
+
+(define_insn_and_split "fix_truncdfsi2_internal_gfxopt"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "f")))
+ (clobber (match_operand:DI 2 "gpc_reg_operand" "=f"))]
+ "(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS
+ && TARGET_PPC_GFXOPT"
+ "#"
+ "&& 1"
+ [(pc)]
+ "
+{
+ emit_insn (gen_fctiwz (operands[2], operands[1]));
+ emit_insn (gen_stfiwx (operands[0], operands[2]));
+ DONE;
+}"
+ [(set_attr "length" "16")])
; Here, we use (set (reg) (unspec:DI [(fix:SI ...)] UNSPEC_FCTIWZ))
; rather than (set (subreg:SI (reg)) (fix:SI ...))
; because the first makes it clear that operand 0 is not live
; before the instruction.
(define_insn "fctiwz"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=*f")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=f")
(unspec:DI [(fix:SI (match_operand:DF 1 "gpc_reg_operand" "f"))]
UNSPEC_FCTIWZ))]
"(TARGET_POWER2 || TARGET_POWERPC) && TARGET_HARD_FLOAT && TARGET_FPRS"
"{fcirz|fctiwz} %0,%1"
[(set_attr "type" "fp")])
+(define_insn "btruncdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "friz %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "btruncsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIZ))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "friz %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "ceildf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frip %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "ceilsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIP))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frip %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "floordf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frim %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "floorsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIM))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frim %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "rounddf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+ (unspec:DF [(match_operand:DF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frin %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "roundsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=f")
+ (unspec:SF [(match_operand:SF 1 "gpc_reg_operand" "f")] UNSPEC_FRIN))]
+ "TARGET_FPRND && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "frin %0,%1"
+ [(set_attr "type" "fp")])
+
+; An UNSPEC is used so we don't have to support SImode in FP registers.
+(define_insn "stfiwx"
+ [(set (match_operand:SI 0 "memory_operand" "=Z")
+ (unspec:SI [(match_operand:DI 1 "gpc_reg_operand" "f")]
+ UNSPEC_STFIWX))]
+ "TARGET_PPC_GFXOPT"
+ "stfiwx %1,%y0"
+ [(set_attr "type" "fpstore")])
+
(define_expand "floatsisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "")
(float:SF (match_operand:SI 1 "gpc_reg_operand" "")))]
@@ -5275,7 +6061,8 @@
? \"{a|addc} %0,%1,%2\;{ae|adde} %L0,%L1,%L2\"
: \"{ai|addic} %0,%1,%2\;{a%G2e|add%G2e} %L0,%L1\";
}"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn "*subdi3_noppc64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,r,r,r")
@@ -5293,7 +6080,8 @@
? \"{sf|subfc} %0,%2,%1\;{sfe|subfe} %L0,%L2,%L1\"
: \"{sfi|subfic} %0,%2,%1\;{sf%G1e|subf%G1e} %L0,%L2\";
}"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn "*negdi2_noppc64"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
@@ -5305,7 +6093,8 @@
? \"{sfi|subfic} %L0,%L1,0\;{sfze|subfze} %0,%1\"
: \"{sfi|subfic} %0,%1,0\;{sfze|subfze} %L0,%L1\";
}"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_expand "mulsidi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -5588,11 +6377,12 @@
"@
{srai|srawi} %0,%1,31\;{srai|srawi} %L0,%1,%h2
{sri|srwi} %L0,%L1,%h2\;insrwi %L0,%1,%h2,0\;{srai|srawi} %0,%1,%h2"
- [(set_attr "length" "8,12")])
+ [(set_attr "type" "two,three")
+ (set_attr "length" "8,12")])
(define_insn "*ashrdisi3_noppc64"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (subreg:SI (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
+ (subreg:SI (ashiftrt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(const_int 32)) 4))]
"TARGET_32BIT && !TARGET_POWERPC64"
"*
@@ -5602,289 +6392,11 @@
else
return \"mr %0,%1\";
}"
- [(set_attr "length" "4")])
+ [(set_attr "length" "4")])
;; PowerPC64 DImode operations.
-(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_add_cint64_operand" "")))]
- ""
- "
-{
- if (! TARGET_POWERPC64)
- {
- if (non_short_cint_operand (operands[2], DImode))
- FAIL;
- }
- else
- if (GET_CODE (operands[2]) == CONST_INT
- && ! add_operand (operands[2], DImode))
- {
- rtx tmp = ((no_new_pseudos || rtx_equal_p (operands[0], operands[1]))
- ? operands[0] : gen_reg_rtx (DImode));
-
- HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
- HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
-
- if (!CONST_OK_FOR_LETTER_P (rest, 'L'))
- FAIL;
-
- /* 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;
- }
-}")
-
-;; Discourage ai/addic because of carry but provide it in an alternative
-;; allowing register zero as source.
-
-(define_insn "*adddi3_internal1"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,?r,r")
- (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,b,r,b")
- (match_operand:DI 2 "add_operand" "r,I,I,L")))]
- "TARGET_POWERPC64"
- "@
- add %0,%1,%2
- addi %0,%1,%2
- addic %0,%1,%2
- addis %0,%1,%v2")
-
-(define_insn "*adddi3_internal2"
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I"))
- (const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r,r,r"))]
- "TARGET_64BIT"
- "@
- add. %3,%1,%2
- addic. %3,%1,%2
- #
- #"
- [(set_attr "type" "fast_compare,compare,compare,compare")
- (set_attr "length" "4,4,8,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 3 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 3)
- (plus:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (compare:CC (match_dup 3)
- (const_int 0)))]
- "")
-
-(define_insn "*adddi3_internal3"
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r")
- (match_operand:DI 2 "reg_or_short_operand" "r,I,r,I"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- add. %0,%1,%2
- addic. %0,%1,%2
- #
- #"
- [(set_attr "type" "fast_compare,compare,compare,compare")
- (set_attr "length" "4,4,8,8")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (plus:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-;; Split an add that we can't do in one insn into two insns, each of which
-;; does one 16-bit part. This is used by combine. Note that the low-order
-;; add should be last in case the result gets used in an address.
-
-(define_split
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (plus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "non_add_cint_operand" "")))]
- "TARGET_POWERPC64"
- [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 3)))
- (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 4)))]
-"
-{
- HOST_WIDE_INT val = INTVAL (operands[2]);
- HOST_WIDE_INT low = ((val & 0xffff) ^ 0x8000) - 0x8000;
- HOST_WIDE_INT rest = trunc_int_for_mode (val - low, DImode);
-
- 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"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (not:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
- "TARGET_POWERPC64"
- "nor %0,%1,%1")
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (clobber (match_scratch:DI 2 "=r,r"))]
- "TARGET_64BIT"
- "@
- nor. %2,%1,%1
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 2)
- (not:DI (match_dup 1)))
- (set (match_dup 0)
- (compare:CC (match_dup 2)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (not:DI (match_dup 1)))]
- "TARGET_64BIT"
- "@
- nor. %0,%1,%1
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (not:DI (match_operand:DI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (not:DI (match_dup 1)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (not:DI (match_dup 1)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (minus:DI (match_operand:DI 1 "reg_or_short_operand" "r,I")
- (match_operand:DI 2 "gpc_reg_operand" "r,r")))]
- "TARGET_POWERPC64"
- "@
- subf %0,%2,%1
- subfic %0,%2,%1")
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r"))]
- "TARGET_64BIT"
- "@
- subf. %3,%2,%1
- #"
- [(set_attr "type" "fast_compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 3 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 3)
- (minus:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (compare:CC (match_dup 3)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (minus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- subf. %0,%2,%1
- #"
- [(set_attr "type" "fast_compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (minus:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (minus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (minus:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(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_sub_cint64_operand" "")))]
- ""
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- emit_insn (gen_adddi3 (operands[0], operands[1],
- negate_rtx (DImode, operands[2])));
- DONE;
- }
-}")
-
(define_insn_and_split "absdi2"
[(set (match_operand:DI 0 "gpc_reg_operand" "=&r,r")
(abs:DI (match_operand:DI 1 "gpc_reg_operand" "r,0")))
@@ -5909,115 +6421,20 @@
(set (match_dup 0) (minus:DI (match_dup 2) (match_dup 0)))]
"")
-(define_expand "negdi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (neg:DI (match_operand:DI 1 "gpc_reg_operand" "")))]
- ""
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
- "TARGET_POWERPC64"
- "neg %0,%1")
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (clobber (match_scratch:DI 2 "=r,r"))]
- "TARGET_64BIT"
- "@
- neg. %2,%1
- #"
- [(set_attr "type" "fast_compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 2 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 2)
- (neg:DI (match_dup 1)))
- (set (match_dup 0)
- (compare:CC (match_dup 2)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r,r"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (neg:DI (match_dup 1)))]
- "TARGET_64BIT"
- "@
- neg. %0,%1
- #"
- [(set_attr "type" "fast_compare")
- (set_attr "length" "4,8")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (neg:DI (match_operand:DI 1 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (neg:DI (match_dup 1)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (neg:DI (match_dup 1)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn "clzdi2"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (clz:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
- "TARGET_POWERPC64"
- "cntlzd %0,%1")
-
-(define_expand "ctzdi2"
- [(set (match_dup 2)
- (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
- (parallel [(set (match_dup 3) (and:DI (match_dup 1)
- (match_dup 2)))
- (clobber (scratch:CC))])
- (set (match_dup 4) (clz:DI (match_dup 3)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (minus:DI (const_int 63) (match_dup 4)))]
- "TARGET_POWERPC64"
- {
- operands[2] = gen_reg_rtx (DImode);
- operands[3] = gen_reg_rtx (DImode);
- operands[4] = gen_reg_rtx (DImode);
- })
-
-(define_expand "ffsdi2"
- [(set (match_dup 2)
- (neg:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
- (parallel [(set (match_dup 3) (and:DI (match_dup 1)
- (match_dup 2)))
- (clobber (scratch:CC))])
- (set (match_dup 4) (clz:DI (match_dup 3)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (minus:DI (const_int 64) (match_dup 4)))]
- "TARGET_POWERPC64"
- {
- operands[2] = gen_reg_rtx (DImode);
- operands[3] = gen_reg_rtx (DImode);
- operands[4] = gen_reg_rtx (DImode);
- })
-
(define_insn "muldi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r")
- (match_operand:DI 2 "gpc_reg_operand" "r")))]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
+ (mult:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r")
+ (match_operand:DI 2 "reg_or_short_operand" "r,I")))]
"TARGET_POWERPC64"
- "mulld %0,%1,%2"
- [(set_attr "type" "lmul")])
+ "@
+ mulld %0,%1,%2
+ mulli %0,%1,%2"
+ [(set (attr "type")
+ (cond [(match_operand:SI 2 "s8bit_cint_operand" "")
+ (const_string "imul3")
+ (match_operand:SI 2 "short_cint_operand" "")
+ (const_string "imul2")]
+ (const_string "lmul")))])
(define_insn "*muldi3_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -6099,126 +6516,6 @@
"mulhdu %0,%1,%2"
[(set_attr "type" "lmul")])
-(define_expand "divdi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "")
- (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_cint_operand" "")))]
- "TARGET_POWERPC64"
- "
-{
- if (GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) > 0
- && exact_log2 (INTVAL (operands[2])) >= 0)
- ;
- else
- operands[2] = force_reg (DImode, operands[2]);
-}")
-
-(define_expand "moddi3"
- [(use (match_operand:DI 0 "gpc_reg_operand" ""))
- (use (match_operand:DI 1 "gpc_reg_operand" ""))
- (use (match_operand:DI 2 "reg_or_cint_operand" ""))]
- "TARGET_POWERPC64"
- "
-{
- int i;
- rtx temp1;
- rtx temp2;
-
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) <= 0
- || (i = exact_log2 (INTVAL (operands[2]))) < 0)
- FAIL;
-
- temp1 = gen_reg_rtx (DImode);
- temp2 = gen_reg_rtx (DImode);
-
- emit_insn (gen_divdi3 (temp1, operands[1], operands[2]));
- emit_insn (gen_ashldi3 (temp2, temp1, GEN_INT (i)));
- emit_insn (gen_subdi3 (operands[0], operands[1], temp2));
- DONE;
-}")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "exact_log2_cint_operand" "N")))]
- "TARGET_POWERPC64"
- "sradi %0,%1,%p2\;addze %0,%0"
- [(set_attr "length" "8")])
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
- (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
- (const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r"))]
- "TARGET_64BIT"
- "@
- sradi %3,%1,%p2\;addze. %3,%3
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "exact_log2_cint_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 3 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 3)
- (div:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 0)
- (compare:CC (match_dup 3)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "exact_log2_cint_operand" "N,N"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- sradi %0,%1,%p2\;addze. %0,%0
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC (div:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "exact_log2_cint_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (div:DI (match_dup 1) (match_dup 2)))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0)
- (div:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (div:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "gpc_reg_operand" "r")))]
- "TARGET_POWERPC64"
- "divd %0,%1,%2"
- [(set_attr "type" "ldiv")])
-
-(define_insn "udivdi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (udiv:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "gpc_reg_operand" "r")))]
- "TARGET_POWERPC64"
- "divdu %0,%1,%2"
- [(set_attr "type" "ldiv")])
-
(define_insn "rotldi3"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(rotate:DI (match_operand:DI 1 "gpc_reg_operand" "r")
@@ -6604,9 +6901,8 @@
(ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_cint_operand" "ri")))]
"TARGET_POWERPC64"
- "sld%I2 %0,%1,%H2"
- [(set_attr "length" "8")])
-
+ "sld%I2 %0,%1,%H2")
+
(define_insn "*ashldi3_internal2"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
@@ -6619,7 +6915,7 @@
#"
[(set_attr "type" "delayed_compare")
(set_attr "length" "4,8")])
-
+
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
(compare:CC (ashift:DI (match_operand:DI 1 "gpc_reg_operand" "")
@@ -6683,7 +6979,7 @@
"@
rldic. %4,%1,%H2,%W3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
@@ -6717,7 +7013,7 @@
"@
rldic. %0,%1,%H2,%W3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
@@ -6759,7 +7055,7 @@
"@
rldicr. %4,%1,%H2,%S3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
@@ -6793,7 +7089,7 @@
"@
rldicr. %0,%1,%H2,%S3
#"
- [(set_attr "type" "delayed_compare")
+ [(set_attr "type" "compare")
(set_attr "length" "4,8")])
(define_split
@@ -6984,18 +7280,20 @@
"")
(define_insn "anddi3"
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
- (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:DI 2 "and64_2_operand" "?r,S,K,J,t")))
- (clobber (match_scratch:CC 3 "=X,X,x,x,X"))]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r")
+ (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "?r,S,T,K,J,t")))
+ (clobber (match_scratch:CC 3 "=X,X,X,x,x,X"))]
"TARGET_POWERPC64"
"@
and %0,%1,%2
rldic%B2 %0,%1,0,%S2
+ rlwinm %0,%1,0,%m2,%M2
andi. %0,%1,%b2
andis. %0,%1,%u2
#"
- [(set_attr "length" "4,4,4,4,8")])
+ [(set_attr "type" "*,*,*,compare,compare,*")
+ (set_attr "length" "4,4,4,4,4,8")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -7004,6 +7302,7 @@
(clobber (match_scratch:CC 3 ""))]
"TARGET_POWERPC64
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask_operand (operands[2], DImode)
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
@@ -7013,22 +7312,22 @@
(and:DI (rotate:DI (match_dup 0)
(match_dup 6))
(match_dup 7)))]
- "
{
build_mask64_2_operands (operands[2], &operands[4]);
-}")
+})
(define_insn "*anddi3_internal2"
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
(const_int 0)))
- (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r"))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+ (clobber (match_scratch:DI 3 "=r,r,r,r,r,r,r,r,r,r,r,r"))
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
"TARGET_64BIT"
"@
and. %3,%1,%2
rldic%B2. %3,%1,0,%S2
+ rlwinm. %3,%1,0,%m2,%M2
andi. %3,%1,%b2
andis. %3,%1,%u2
#
@@ -7036,26 +7335,10 @@
#
#
#
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "and64_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 3 ""))
- (clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed"
- [(parallel [(set (match_dup 3)
- (and:DI (match_dup 1)
- (match_dup 2)))
- (clobber (match_dup 4))])
- (set (match_dup 0)
- (compare:CC (match_dup 3)
- (const_int 0)))]
- "")
+ [(set_attr "type" "compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 0 "cc_reg_operand" "")
@@ -7064,8 +7347,9 @@
(const_int 0)))
(clobber (match_scratch:DI 3 ""))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed
+ "TARGET_64BIT && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask_operand (operands[2], DImode)
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 3)
(and:DI (rotate:DI (match_dup 1)
@@ -7083,17 +7367,18 @@
}")
(define_insn "*anddi3_internal3"
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,?y,?y,??y,??y,?y")
- (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "and64_2_operand" "r,S,K,J,t,r,S,K,J,t"))
+ [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,x,x,x,x,?y,?y,?y,??y,??y,?y")
+ (compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r,r,r")
+ (match_operand:DI 2 "and64_2_operand" "r,S,T,K,J,t,r,S,T,K,J,t"))
(const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
+ (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r,r,r")
(and:DI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,x,x,X"))]
+ (clobber (match_scratch:CC 4 "=X,X,X,X,X,X,X,X,X,x,x,X"))]
"TARGET_64BIT"
"@
and. %0,%1,%2
rldic%B2. %0,%1,0,%S2
+ rlwinm. %0,%1,0,%m2,%M2
andi. %0,%1,%b2
andis. %0,%1,%u2
#
@@ -7101,19 +7386,20 @@
#
#
#
+ #
#"
- [(set_attr "type" "compare,delayed_compare,compare,compare,delayed_compare,compare,compare,compare,compare,compare")
- (set_attr "length" "4,4,4,4,8,8,8,8,8,12")])
+ [(set_attr "type" "compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare,compare")
+ (set_attr "length" "4,4,4,4,4,8,8,8,8,8,8,12")])
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC (and:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "and64_operand" ""))
+ (match_operand:DI 2 "and64_2_operand" ""))
(const_int 0)))
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed"
+ "TARGET_64BIT && reload_completed"
[(parallel [(set (match_dup 0)
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_dup 4))])
@@ -7130,8 +7416,9 @@
(set (match_operand:DI 0 "gpc_reg_operand" "")
(and:DI (match_dup 1) (match_dup 2)))
(clobber (match_scratch:CC 4 ""))]
- "TARGET_POWERPC64 && reload_completed
+ "TARGET_64BIT && reload_completed
&& (fixed_regs[CR0_REGNO] || !logical_operand (operands[2], DImode))
+ && !mask_operand (operands[2], DImode)
&& !mask64_operand (operands[2], DImode)"
[(set (match_dup 0)
(and:DI (rotate:DI (match_dup 1)
@@ -7286,7 +7573,7 @@
(const_int 0)))]
"")
-;; Split a logical operation that we can't do in one insn into two insns,
+;; Split a logical operation that we can't do in one insn into two insns,
;; each of which does one 16-bit part. This is used by combine.
(define_split
@@ -7300,7 +7587,7 @@
"
{
rtx i3,i4;
-
+
if (GET_CODE (operands[2]) == CONST_DOUBLE)
{
HOST_WIDE_INT value = CONST_DOUBLE_LOW (operands[2]);
@@ -7314,10 +7601,10 @@
& (~ (HOST_WIDE_INT) 0xffff));
i4 = GEN_INT (INTVAL (operands[2]) & 0xffff);
}
- operands[4] = gen_rtx (GET_CODE (operands[3]), DImode,
- operands[1], i3);
- operands[5] = gen_rtx (GET_CODE (operands[3]), DImode,
- operands[0], i4);
+ operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
+ operands[1], i3);
+ operands[5] = gen_rtx_fmt_ee (GET_CODE (operands[3]), DImode,
+ operands[0], i4);
}")
(define_insn "*boolcdi3_internal1"
@@ -7454,41 +7741,6 @@
;; Now define ways of moving data around.
-;; Elf specific ways of loading addresses for non-PIC code.
-;; The output of this could be r0, but we make a very strong
-;; preference for a base register because it will usually
-;; be needed there.
-(define_insn "elf_high"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
- (high:SI (match_operand 1 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "{liu|lis} %0,%1@ha")
-
-(define_insn "elf_low"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
- (match_operand 2 "" "")))]
- "TARGET_ELF && ! TARGET_64BIT"
- "@
- {cal|la} %0,%2@l(%1)
- {ai|addic} %0,%1,%K2")
-
-;; Mach-O PIC trickery.
-(define_insn "macho_high"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
- (high:SI (match_operand 1 "" "")))]
- "TARGET_MACHO && ! TARGET_64BIT"
- "{liu|lis} %0,ha16(%1)")
-
-(define_insn "macho_low"
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
- (match_operand 2 "" "")))]
- "TARGET_MACHO && ! TARGET_64BIT"
- "@
- {cal %0,%a2@l(%1)|la %0,lo16(%2)(%1)}
- {cal %0,%a2@l(%1)|addic %0,%1,lo16(%2)}")
-
;; Set up a register with a value from the GOT table
(define_expand "movsi_got"
@@ -7528,7 +7780,7 @@
;; Used by sched, shorten_branches and final when the GOT pseudo reg
;; didn't get allocated to a hard register.
-(define_split
+(define_split
[(set (match_operand:SI 0 "gpc_reg_operand" "")
(unspec:SI [(match_operand:SI 1 "got_no_const_operand" "")
(match_operand:SI 2 "memory_operand" "")]
@@ -7545,12 +7797,6 @@
;; do the load 16-bits at a time. We could do this by loading from memory,
;; and this is even supposed to be faster, but it is simpler not to get
;; integers in the TOC.
-(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
- (match_operand:SI 1 "any_operand" ""))]
- ""
- "{ rs6000_emit_move (operands[0], operands[1], SImode); DONE; }")
-
(define_insn "movsi_low"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
@@ -7560,90 +7806,8 @@
[(set_attr "type" "load")
(set_attr "length" "4")])
-(define_insn "movsi_low_st"
- [(set (mem:SI (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
- (match_operand 2 "" "")))
- (match_operand:SI 0 "gpc_reg_operand" "r"))]
- "TARGET_MACHO && ! TARGET_64BIT"
- "{st|stw} %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
-
-(define_insn "movdf_low"
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f,!r")
- (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
- (match_operand 2 "" ""))))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
- "*
-{
- switch (which_alternative)
- {
- case 0:
- return \"lfd %0,lo16(%2)(%1)\";
- case 1:
- {
- rtx operands2[4];
- operands2[0] = operands[0];
- operands2[1] = operands[1];
- operands2[2] = operands[2];
- if (TARGET_POWERPC64 && TARGET_32BIT)
- /* Note, old assemblers didn't support relocation here. */
- return \"ld %0,lo16(%2)(%1)\";
- else
- {
- operands2[3] = gen_rtx_REG (SImode, RS6000_PIC_OFFSET_TABLE_REGNUM);
- output_asm_insn (\"{l|lwz} %0,lo16(%2)(%1)\", operands);
-#if TARGET_MACHO
- if (MACHO_DYNAMIC_NO_PIC_P)
- output_asm_insn (\"{liu|lis} %L0,ha16(%2+4)\", operands);
- else
- /* We cannot rely on ha16(low half)==ha16(high half), alas,
- although in practice it almost always is. */
- output_asm_insn (\"{cau|addis} %L0,%3,ha16(%2+4)\", operands2);
-#endif
- return (\"{l|lwz} %L0,lo16(%2+4)(%L0)\");
- }
- }
- default:
- abort();
- }
-}"
- [(set_attr "type" "load")
- (set_attr "length" "4,12")])
-
-(define_insn "movdf_low_st"
- [(set (mem:DF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
- (match_operand 2 "" "")))
- (match_operand:DF 0 "gpc_reg_operand" "f"))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
- "stfd %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
-
-(define_insn "movsf_low"
- [(set (match_operand:SF 0 "gpc_reg_operand" "=f,!r")
- (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
- (match_operand 2 "" ""))))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
- "@
- lfs %0,lo16(%2)(%1)
- {l|lwz} %0,lo16(%2)(%1)"
- [(set_attr "type" "load")
- (set_attr "length" "4")])
-
-(define_insn "movsf_low_st"
- [(set (mem:SF (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,b")
- (match_operand 2 "" "")))
- (match_operand:SF 0 "gpc_reg_operand" "f,!r"))]
- "TARGET_MACHO && TARGET_HARD_FLOAT && TARGET_FPRS && ! TARGET_64BIT"
- "@
- stfs %0,lo16(%2)(%1)
- {st|stw} %0,lo16(%2)(%1)"
- [(set_attr "type" "store")
- (set_attr "length" "4")])
-
(define_insn "*movsi_internal1"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "=r,r,r,m,r,r,r,r,r,*q,*c*l,*h,*h")
(match_operand:SI 1 "input_operand" "r,U,m,r,I,L,n,R,*h,r,r,r,0"))]
"gpc_reg_operand (operands[0], SImode)
|| gpc_reg_operand (operands[1], SImode)"
@@ -7686,14 +7850,14 @@
FAIL;
}")
-(define_insn "*movsi_internal2"
+(define_insn "*mov<mode>_internal2"
[(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "0,r,r")
+ (compare:CC (match_operand:P 1 "gpc_reg_operand" "0,r,r")
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
+ ""
"@
- {cmpi|cmpwi} %2,%0,0
+ {cmpi|cmp<wd>i} %2,%0,0
mr. %0,%1
#"
[(set_attr "type" "cmp,compare,cmp")
@@ -7701,22 +7865,16 @@
(define_split
[(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
+ (compare:CC (match_operand:P 1 "gpc_reg_operand" "")
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "") (match_dup 1))]
- "TARGET_32BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "") (match_dup 1))]
+ "reload_completed"
[(set (match_dup 0) (match_dup 1))
(set (match_dup 2)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
- (match_operand:HI 1 "any_operand" ""))]
- ""
- "{ rs6000_emit_move (operands[0], operands[1], HImode); DONE; }")
-
(define_insn "*movhi_internal"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
(match_operand:HI 1 "input_operand" "r,m,r,i,*h,r,r,0"))]
@@ -7733,11 +7891,11 @@
{cror 0,0,0|nop}"
[(set_attr "type" "*,load,store,*,mfjmpr,*,mtjmpr,*")])
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "any_operand" ""))]
+(define_expand "mov<mode>"
+ [(set (match_operand:INT 0 "general_operand" "")
+ (match_operand:INT 1 "any_operand" ""))]
""
- "{ rs6000_emit_move (operands[0], operands[1], QImode); DONE; }")
+ "{ rs6000_emit_move (operands[0], operands[1], <MODE>mode); DONE; }")
(define_insn "*movqi_internal"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m,r,r,*q,*c*l,*h")
@@ -7765,42 +7923,44 @@
"")
(define_insn "*movcc_internal1"
- [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,?y,r,r,r,r,q,cl,r,m")
- (match_operand:CC 1 "nonimmediate_operand" "y,r,r,x,y,r,h,r,r,m,r"))]
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=y,x,?y,y,r,r,r,r,r,q,cl,r,m")
+ (match_operand:CC 1 "general_operand" "y,r,r,O,x,y,r,I,h,r,r,m,r"))]
"register_operand (operands[0], CCmode)
|| register_operand (operands[1], CCmode)"
"@
mcrf %0,%1
mtcrf 128,%1
{rlinm|rlwinm} %1,%1,%F0,0xffffffff\;mtcrf %R0,%1\;{rlinm|rlwinm} %1,%1,%f0,0xffffffff
+ crxor %0,%0,%0
mfcr %0%Q1
mfcr %0%Q1\;{rlinm|rlwinm} %0,%0,%f1,0xf0000000
mr %0,%1
+ {lil|li} %0,%1
mf%1 %0
mt%0 %1
mt%0 %1
{l%U1%X1|lwz%U1%X1} %0,%1
{st%U0%U1|stw%U0%U1} %1,%0"
[(set (attr "type")
- (cond [(eq_attr "alternative" "0")
+ (cond [(eq_attr "alternative" "0,3")
(const_string "cr_logical")
(eq_attr "alternative" "1,2")
(const_string "mtcr")
- (eq_attr "alternative" "5,7")
+ (eq_attr "alternative" "6,7,9")
(const_string "integer")
- (eq_attr "alternative" "6")
- (const_string "mfjmpr")
(eq_attr "alternative" "8")
+ (const_string "mfjmpr")
+ (eq_attr "alternative" "10")
(const_string "mtjmpr")
- (eq_attr "alternative" "9")
+ (eq_attr "alternative" "11")
(const_string "load")
- (eq_attr "alternative" "10")
+ (eq_attr "alternative" "12")
(const_string "store")
(ne (symbol_ref "TARGET_MFCRF") (const_int 0))
(const_string "mfcrf")
]
(const_string "mfcr")))
- (set_attr "length" "4,4,12,4,8,4,4,4,4,4,4")])
+ (set_attr "length" "4,4,12,4,4,8,4,4,4,4,4,4,4")])
;; For floating-point, we normally deal with the floating-point registers
;; unless -msoft-float is used. The sole exception is that parameter passing
@@ -7839,7 +7999,7 @@
}")
(define_insn "*movsf_hardfloat"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,!cl,!q,!r,!h,!r,!r")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=!r,!r,m,f,f,m,*c*l,*q,!r,*h,!r,!r")
(match_operand:SF 1 "input_operand" "r,m,r,f,m,f,r,r,h,0,G,Fn"))]
"(gpc_reg_operand (operands[0], SFmode)
|| gpc_reg_operand (operands[1], SFmode))
@@ -7857,7 +8017,7 @@
{cror 0,0,0|nop}
#
#"
- [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,mtjmpr,*,*,*,*")
+ [(set_attr "type" "*,load,store,fp,fpload,fpstore,mtjmpr,*,mfjmpr,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,4,8")])
(define_insn "*movsf_softfloat"
@@ -7879,7 +8039,7 @@
#
#
{cror 0,0,0|nop}"
- [(set_attr "type" "*,mtjmpr,*,*,load,store,*,*,*,*,*,*")
+ [(set_attr "type" "*,mtjmpr,*,mfjmpr,load,store,*,*,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,4,8,4")])
@@ -7941,7 +8101,7 @@
(define_split
[(set (match_operand:DF 0 "gpc_reg_operand" "")
- (match_operand:DF 1 "easy_fp_constant" ""))]
+ (match_operand:DF 1 "const_double_operand" ""))]
"TARGET_POWERPC64 && reload_completed
&& ((GET_CODE (operands[0]) == REG && REGNO (operands[0]) <= 31)
|| (GET_CODE (operands[0]) == SUBREG
@@ -7989,7 +8149,7 @@
switch (which_alternative)
{
default:
- abort ();
+ gcc_unreachable ();
case 0:
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register
@@ -7999,7 +8159,7 @@
else
return \"mr %0,%1\;mr %L0,%L1\";
case 1:
- if (offsettable_memref_p (operands[1])
+ if (rs6000_offsettable_memref_p (operands[1])
|| (GET_CODE (operands[1]) == MEM
&& (GET_CODE (XEXP (operands[1], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[1], 0)) == PRE_INC
@@ -8039,7 +8199,7 @@
}
}
case 2:
- if (offsettable_memref_p (operands[0])
+ if (rs6000_offsettable_memref_p (operands[0])
|| (GET_CODE (operands[0]) == MEM
&& (GET_CODE (XEXP (operands[0], 0)) == LO_SUM
|| GET_CODE (XEXP (operands[0], 0)) == PRE_INC
@@ -8068,13 +8228,13 @@
return \"#\";
}
}"
- [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*")
+ [(set_attr "type" "two,load,store,fp,fpload,fpstore,*,*,*")
(set_attr "length" "8,16,16,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat32"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m,r,r,r")
(match_operand:DF 1 "input_operand" "r,m,r,G,H,F"))]
- "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || !TARGET_FPRS)
+ "! TARGET_POWERPC64 && (TARGET_SOFT_FLOAT || TARGET_E500_SINGLE)
&& (gpc_reg_operand (operands[0], DFmode)
|| gpc_reg_operand (operands[1], DFmode))"
"*
@@ -8082,7 +8242,7 @@
switch (which_alternative)
{
default:
- abort ();
+ gcc_unreachable ();
case 0:
/* We normally copy the low-numbered register first. However, if
the first register operand 0 is the same as the second register of
@@ -8109,13 +8269,13 @@
return \"#\";
}
}"
- [(set_attr "type" "*,load,store,*,*,*")
+ [(set_attr "type" "two,load,store,*,*,*")
(set_attr "length" "8,8,8,8,12,16")])
; ld/std require word-aligned displacements -> 'Y' constraint.
; List Y->r and r->Y before r->r for reload.
(define_insn "*movdf_hardfloat64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,!cl,!r,!h,!r,!r,!r")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,r,!r,f,f,m,*c*l,!r,*h,!r,!r,!r")
(match_operand:DF 1 "input_operand" "r,Y,r,f,m,f,r,h,0,G,H,F"))]
"TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS
&& (gpc_reg_operand (operands[0], DFmode)
@@ -8133,7 +8293,7 @@
#
#
#"
- [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,*,*,*,*,*")
+ [(set_attr "type" "store,load,*,fp,fpload,fpstore,mtjmpr,mfjmpr,*,*,*,*")
(set_attr "length" "4,4,4,4,4,4,4,4,4,8,12,16")])
(define_insn "*movdf_softfloat64"
@@ -8152,23 +8312,22 @@
#
#
{cror 0,0,0|nop}"
- [(set_attr "type" "load,store,*,*,*,*,*,*,*")
+ [(set_attr "type" "load,store,*,mtjmpr,mfjmpr,*,*,*,*")
(set_attr "length" "4,4,4,4,4,8,12,16,4")])
(define_expand "movtf"
[(set (match_operand:TF 0 "general_operand" "")
(match_operand:TF 1 "any_operand" ""))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+ "!TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128"
"{ rs6000_emit_move (operands[0], operands[1], TFmode); DONE; }")
; It's important to list the o->f and f->o moves before f->f because
; otherwise reload, given m->f, will try to pick f->f and reload it,
-; which doesn't make progress.
+; which doesn't make progress. Likewise r->Y must be before r->r.
(define_insn_and_split "*movtf_internal"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,rm,r")
- (match_operand:TF 1 "input_operand" "f,o,f,r,mGHF"))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,f,r,Y,r")
+ (match_operand:TF 1 "input_operand" "f,o,f,YGHF,r,r"))]
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128
&& (gpc_reg_operand (operands[0], TFmode)
|| gpc_reg_operand (operands[1], TFmode))"
@@ -8176,23 +8335,39 @@
"&& reload_completed"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
- [(set_attr "length" "8,8,8,20,20")])
+ [(set_attr "length" "8,8,8,20,20,16")])
+
+(define_insn_and_split "*movtf_softfloat"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=r,Y,r")
+ (match_operand:TF 1 "input_operand" "YGHF,r,r"))]
+ "!TARGET_IEEEQUAD
+ && (TARGET_SOFT_FLOAT || !TARGET_FPRS) && TARGET_LONG_DOUBLE_128
+ && (gpc_reg_operand (operands[0], TFmode)
+ || gpc_reg_operand (operands[1], TFmode))"
+ "#"
+ "&& reload_completed"
+ [(pc)]
+{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; }
+ [(set_attr "length" "20,20,16")])
(define_expand "extenddftf2"
[(parallel [(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:DF 1 "input_operand" "")))
(use (match_dup 2))])]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
{
operands[2] = CONST0_RTX (DFmode);
+ /* Generate GOT reference early for SVR4 PIC. */
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ operands[2] = validize_mem (force_const_mem (DFmode, operands[2]));
})
(define_insn_and_split "*extenddftf2_internal"
[(set (match_operand:TF 0 "nonimmediate_operand" "=o,f,&f,r")
(float_extend:TF (match_operand:DF 1 "input_operand" "fr,mf,mf,rmGHF")))
- (use (match_operand:DF 2 "input_operand" "rf,m,f,n"))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ (use (match_operand:DF 2 "zero_reg_mem_operand" "rf,m,f,n"))]
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
"&& reload_completed"
@@ -8205,12 +8380,12 @@
emit_move_insn (simplify_gen_subreg (DFmode, operands[0], TFmode, lo_word),
operands[2]);
DONE;
-})
+})
(define_expand "extendsftf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
(float_extend:TF (match_operand:SF 1 "gpc_reg_operand" "")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
{
rtx tmp = gen_reg_rtx (DFmode);
@@ -8222,14 +8397,14 @@
(define_expand "trunctfdf2"
[(set (match_operand:DF 0 "gpc_reg_operand" "")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"")
(define_insn_and_split "trunctfdf2_internal1"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f,?f")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "0,f")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && !TARGET_XL_COMPAT
+ "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"@
#
@@ -8245,7 +8420,7 @@
(define_insn "trunctfdf2_internal2"
[(set (match_operand:DF 0 "gpc_reg_operand" "=f")
(float_truncate:DF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && TARGET_XL_COMPAT
+ "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"fadd %0,%1,%L1"
[(set_attr "type" "fp")])
@@ -8254,7 +8429,7 @@
[(set (match_operand:SF 0 "gpc_reg_operand" "=f")
(float_truncate:SF (match_operand:TF 1 "gpc_reg_operand" "f")))
(clobber (match_scratch:DF 2 "=f"))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
"&& reload_completed"
@@ -8265,9 +8440,9 @@
"")
(define_expand "floatsitf2"
- [(set (match_operand:TF 0 "gpc_reg_operand" "=f")
- (float:TF (match_operand:SI 1 "gpc_reg_operand" "r")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ [(set (match_operand:TF 0 "gpc_reg_operand" "")
+ (float:TF (match_operand:SI 1 "gpc_reg_operand" "")))]
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
{
rtx tmp = gen_reg_rtx (DFmode);
@@ -8295,7 +8470,7 @@
(clobber (match_dup 3))
(clobber (match_dup 4))
(clobber (match_dup 5))])]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& (TARGET_POWER2 || TARGET_POWERPC)
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
{
@@ -8312,31 +8487,28 @@
(clobber (match_operand:DF 3 "gpc_reg_operand" "=&f"))
(clobber (match_operand:DI 4 "gpc_reg_operand" "=f"))
(clobber (match_operand:DI 5 "memory_operand" "=o"))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
- "&& reload_completed"
+ "&& (!no_new_pseudos || offsettable_nonstrict_memref_p (operands[5]))"
[(pc)]
{
rtx lowword;
emit_insn (gen_fix_trunc_helper (operands[2], operands[1], operands[3]));
- if (GET_CODE (operands[5]) != MEM)
- abort();
- lowword = XEXP (operands[5], 0);
- if (WORDS_BIG_ENDIAN)
- lowword = plus_constant (lowword, 4);
+ gcc_assert (MEM_P (operands[5]));
+ lowword = adjust_address (operands[5], SImode, WORDS_BIG_ENDIAN ? 4 : 0);
emit_insn (gen_fctiwz (operands[4], operands[2]));
emit_move_insn (operands[5], operands[4]);
- emit_move_insn (operands[0], gen_rtx_MEM (SImode, lowword));
+ emit_move_insn (operands[0], lowword);
DONE;
})
(define_insn "negtf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(neg:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"*
{
@@ -8351,7 +8523,7 @@
(define_expand "abstf2"
[(set (match_operand:TF 0 "gpc_reg_operand" "=f")
(abs:TF (match_operand:TF 1 "gpc_reg_operand" "f")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"
{
@@ -8371,7 +8543,7 @@
(label_ref (match_operand 2 "" ""))
(pc)))
(set (match_dup 6) (neg:DF (match_dup 6)))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
+ "!TARGET_IEEEQUAD
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"
{
@@ -8385,43 +8557,24 @@
;; Next come the multi-word integer load and store and the load and store
;; multiple insns.
-(define_expand "movdi"
- [(set (match_operand:DI 0 "general_operand" "")
- (match_operand:DI 1 "any_operand" ""))]
- ""
- "{ rs6000_emit_move (operands[0], operands[1], DImode); DONE; }")
+; List r->r after r->"o<>", otherwise reload will try to reload a
+; non-offsettable address by using r->r which won't make progress.
(define_insn "*movdi_internal32"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,f,f,m,r,r,r,r,r")
- (match_operand:DI 1 "input_operand" "r,m,r,f,m,f,IJK,n,G,H,F"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=o<>,r,r,*f,*f,m,r")
+ (match_operand:DI 1 "input_operand" "r,r,m,f,m,f,IJKnGHF"))]
"! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
- "*
-{
- switch (which_alternative)
- {
- default:
- abort ();
- case 0:
- case 1:
- case 2:
- return \"#\";
- case 3:
- return \"fmr %0,%1\";
- case 4:
- return \"lfd%U1%X1 %0,%1\";
- case 5:
- return \"stfd%U0%X0 %1,%0\";
- case 6:
- case 7:
- case 8:
- case 9:
- case 10:
- return \"#\";
- }
-}"
- [(set_attr "type" "*,load,store,fp,fpload,fpstore,*,*,*,*,*")])
+ "@
+ #
+ #
+ #
+ fmr %0,%1
+ lfd%U1%X1 %0,%1
+ stfd%U0%X0 %1,%0
+ #"
+ [(set_attr "type" "load,*,store,fp,fpload,fpstore,*")])
(define_split
[(set (match_operand:DI 0 "gpc_reg_operand" "")
@@ -8447,47 +8600,21 @@
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "input_operand" ""))]
- "reload_completed && !TARGET_POWERPC64
+ "reload_completed && !TARGET_POWERPC64
&& gpr_or_gpr_p (operands[0], operands[1])"
[(pc)]
{ rs6000_split_multireg_move (operands[0], operands[1]); DONE; })
-(define_split
- [(set (match_operand:TI 0 "gpc_reg_operand" "")
- (match_operand:TI 1 "const_double_operand" ""))]
- "TARGET_POWERPC64"
- [(set (match_dup 2) (match_dup 4))
- (set (match_dup 3) (match_dup 5))]
- "
-{
- operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
- TImode);
- operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
- TImode);
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
- operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
- }
- else if (GET_CODE (operands[1]) == CONST_INT)
- {
- operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
- operands[5] = operands[1];
- }
- else
- FAIL;
-}")
-
(define_insn "*movdi_internal64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=Y,r,r,r,r,r,r,??f,f,m,r,*h,*h")
- (match_operand:DI 1 "input_operand" "r,Y,r,I,L,nF,R,f,m,f,*h,r,0"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m,r,r,r,r,*f,*f,m,r,*h,*h")
+ (match_operand:DI 1 "input_operand" "r,m,r,I,L,nF,R,f,m,f,*h,r,0"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
"@
- std%U0%X0 %1,%0
- ld%U1%X1 %0,%1
mr %0,%1
+ ld%U1%X1 %0,%1
+ std%U0%X0 %1,%0
li %0,%1
lis %0,%v1
#
@@ -8498,7 +8625,7 @@
mf%1 %0
mt%0 %1
{cror 0,0,0|nop}"
- [(set_attr "type" "store,load,*,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*")
+ [(set_attr "type" "*,load,store,*,*,*,*,fp,fpload,fpstore,mfjmpr,mtjmpr,*")
(set_attr "length" "4,4,4,4,4,20,4,4,4,4,4,4,4")])
;; immediate value valid for a single instruction hiding in a const_double
@@ -8561,41 +8688,10 @@
else
FAIL;
}")
-
-(define_insn "*movdi_internal2"
- [(set (match_operand:CC 2 "cc_reg_operand" "=y,x,?y")
- (compare:CC (match_operand:DI 1 "gpc_reg_operand" "0,r,r")
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r") (match_dup 1))]
- "TARGET_64BIT"
- "@
- cmpdi %2,%0,0
- mr. %0,%1
- #"
- [(set_attr "type" "cmp,compare,cmp")
- (set_attr "length" "4,4,8")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC (match_operand:DI 1 "gpc_reg_operand" "")
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "") (match_dup 1))]
- "TARGET_POWERPC64 && reload_completed"
- [(set (match_dup 0) (match_dup 1))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
;; TImode is similar, except that we usually want to compute the address into
;; a register and use lsi/stsi (the exception is during reload). MQ is also
;; clobbered in stsi for POWER, so we need a SCRATCH for it.
-(define_expand "movti"
- [(parallel [(set (match_operand:TI 0 "general_operand" "")
- (match_operand:TI 1 "general_operand" ""))
- (clobber (scratch:SI))])]
- ""
- "{ rs6000_emit_move (operands[0], operands[1], TImode); DONE; }")
;; We say that MQ is clobbered in the last alternative because the first
;; alternative would never get used otherwise since it would need a reload
@@ -8604,17 +8700,17 @@
;; giving the SCRATCH mq.
(define_insn "*movti_power"
- [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
- (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))
- (clobber (match_scratch:SI 2 "=q,q#X,X,X,X"))]
- "TARGET_POWER && ! TARGET_POWERPC64
+ [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r,r")
+ (match_operand:TI 1 "input_operand" "r,r,r,Q,m,n"))
+ (clobber (match_scratch:SI 2 "=q,q#X,X,X,X,X"))]
+ "TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
{
switch (which_alternative)
{
default:
- abort ();
+ gcc_unreachable ();
case 0:
if (TARGET_STRING)
@@ -8630,14 +8726,15 @@
return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */
case 4:
+ case 5:
return \"#\";
}
}"
- [(set_attr "type" "store,store,*,load,load")])
+ [(set_attr "type" "store,store,*,load,load,*")])
(define_insn "*movti_string"
- [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,m,????r,????r,????r")
- (match_operand:TI 1 "reg_or_mem_operand" "r,r,r,Q,m"))]
+ [(set (match_operand:TI 0 "reg_or_mem_operand" "=Q,o<>,????r,????r,????r,r")
+ (match_operand:TI 1 "input_operand" "r,r,r,Q,m,n"))]
"! TARGET_POWER && ! TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], TImode) || gpc_reg_operand (operands[1], TImode))"
"*
@@ -8645,7 +8742,7 @@
switch (which_alternative)
{
default:
- abort ();
+ gcc_unreachable ();
case 0:
if (TARGET_STRING)
return \"{stsi|stswi} %1,%P0,16\";
@@ -8655,28 +8752,52 @@
case 3:
/* If the address is not used in the output, we can use lsi. Otherwise,
fall through to generating four loads. */
- if (TARGET_STRING
+ if (TARGET_STRING
&& ! reg_overlap_mentioned_p (operands[0], operands[1]))
return \"{lsi|lswi} %0,%P1,16\";
/* ... fall through ... */
case 4:
+ case 5:
return \"#\";
}
}"
- [(set_attr "type" "store,store,*,load,load")])
+ [(set_attr "type" "store_ux,store_ux,*,load_ux,load_ux,*")])
(define_insn "*movti_ppc64"
- [(set (match_operand:TI 0 "nonimmediate_operand" "=r,m,r")
- (match_operand:TI 1 "input_operand" "r,r,o"))]
+ [(set (match_operand:TI 0 "nonimmediate_operand" "=r,o<>,r")
+ (match_operand:TI 1 "input_operand" "r,r,m"))]
"TARGET_POWERPC64 && (gpc_reg_operand (operands[0], TImode)
|| gpc_reg_operand (operands[1], TImode))"
- "@
- #
- #
- #"
+ "#"
[(set_attr "type" "*,load,store")])
(define_split
+ [(set (match_operand:TI 0 "gpc_reg_operand" "")
+ (match_operand:TI 1 "const_double_operand" ""))]
+ "TARGET_POWERPC64"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+ "
+{
+ operands[2] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN == 0,
+ TImode);
+ operands[3] = operand_subword_force (operands[0], WORDS_BIG_ENDIAN != 0,
+ TImode);
+ if (GET_CODE (operands[1]) == CONST_DOUBLE)
+ {
+ operands[4] = GEN_INT (CONST_DOUBLE_HIGH (operands[1]));
+ operands[5] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
+ }
+ else if (GET_CODE (operands[1]) == CONST_INT)
+ {
+ operands[4] = GEN_INT (- (INTVAL (operands[1]) < 0));
+ operands[5] = operands[1];
+ }
+ else
+ FAIL;
+}")
+
+(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
(match_operand:TI 1 "input_operand" ""))]
"reload_completed
@@ -8741,7 +8862,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 8"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_insn "*ldmsi7"
@@ -8763,7 +8884,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 7"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_insn "*ldmsi6"
@@ -8783,7 +8904,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 6"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_insn "*ldmsi5"
@@ -8801,7 +8922,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 5"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_insn "*ldmsi4"
@@ -8817,7 +8938,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 4"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_insn "*ldmsi3"
@@ -8831,7 +8952,7 @@
"TARGET_STRING && XVECLEN (operands[0], 0) == 3"
"*
{ return rs6000_output_load_multiple (operands); }"
- [(set_attr "type" "load")
+ [(set_attr "type" "load_ux")
(set_attr "length" "32")])
(define_expand "store_multiple"
@@ -8878,20 +8999,11 @@
gen_rtx_REG (SImode, regno + i));
}")
-(define_insn "*store_multiple_power"
- [(match_parallel 0 "store_multiple_operation"
- [(set (match_operand:SI 1 "indirect_operand" "=Q")
- (match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "=q"))])]
- "TARGET_STRING && TARGET_POWER"
- "{stsi|stswi} %2,%P1,%O0"
- [(set_attr "type" "store")])
-
(define_insn "*stmsi8"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
@@ -8908,13 +9020,13 @@
(match_operand:SI 10 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 9"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
(define_insn "*stmsi7"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
@@ -8929,13 +9041,13 @@
(match_operand:SI 9 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 8"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
(define_insn "*stmsi6"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
@@ -8948,13 +9060,13 @@
(match_operand:SI 8 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 7"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
(define_insn "*stmsi5"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
@@ -8965,13 +9077,13 @@
(match_operand:SI 7 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 6"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
(define_insn "*stmsi4"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
@@ -8980,28 +9092,154 @@
(match_operand:SI 6 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 5"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
(define_insn "*stmsi3"
[(match_parallel 0 "store_multiple_operation"
[(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
(match_operand:SI 2 "gpc_reg_operand" "r"))
- (clobber (match_scratch:SI 3 "X"))
+ (clobber (match_scratch:SI 3 "=X"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
(match_operand:SI 4 "gpc_reg_operand" "r"))
(set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
(match_operand:SI 5 "gpc_reg_operand" "r"))])]
"TARGET_STRING && !TARGET_POWER && XVECLEN (operands[0], 0) == 4"
"{stsi|stswi} %2,%1,%O0"
- [(set_attr "type" "store")])
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi8_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 6 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 7 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 8 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 9 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 28)))
+ (match_operand:SI 10 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 9"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi7_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 6 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 7 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 8 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 24)))
+ (match_operand:SI 9 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 8"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi6_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 6 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 7 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 20)))
+ (match_operand:SI 8 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 7"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi5_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 6 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 16)))
+ (match_operand:SI 7 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 6"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi4_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 12)))
+ (match_operand:SI 6 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 5"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+
+(define_insn "*stmsi3_power"
+ [(match_parallel 0 "store_multiple_operation"
+ [(set (mem:SI (match_operand:SI 1 "gpc_reg_operand" "b"))
+ (match_operand:SI 2 "gpc_reg_operand" "r"))
+ (clobber (match_scratch:SI 3 "=q"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 4)))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (set (mem:SI (plus:SI (match_dup 1) (const_int 8)))
+ (match_operand:SI 5 "gpc_reg_operand" "r"))])]
+ "TARGET_STRING && TARGET_POWER && XVECLEN (operands[0], 0) == 4"
+ "{stsi|stswi} %2,%1,%O0"
+ [(set_attr "type" "store_ux")])
+(define_expand "setmemsi"
+ [(parallel [(set (match_operand:BLK 0 "" "")
+ (match_operand 2 "const_int_operand" ""))
+ (use (match_operand:SI 1 "" ""))
+ (use (match_operand:SI 3 "" ""))])]
+ ""
+ "
+{
+ /* If value to set is not zero, use the library routine. */
+ if (operands[2] != const0_rtx)
+ FAIL;
+
+ if (expand_block_clear (operands))
+ DONE;
+ else
+ FAIL;
+}")
+
;; String/block move insn.
;; Argument 0 is the destination
;; Argument 1 is the source
;; Argument 2 is the length
;; Argument 3 is the alignment
-(define_expand "movstrsi"
+(define_expand "movmemsi"
[(parallel [(set (match_operand:BLK 0 "" "")
(match_operand:BLK 1 "" ""))
(use (match_operand:SI 2 "" ""))
@@ -9018,7 +9256,7 @@
;; Move up to 32 bytes at a time. The fixed registers are needed because the
;; register allocator doesn't have a clue about allocating 8 word registers.
;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_8reg"
+(define_expand "movmemsi_8reg"
[(parallel [(set (match_operand 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
@@ -9056,12 +9294,12 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
(define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+ [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+ (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
(use (match_operand:SI 2 "immediate_operand" "i"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
@@ -9072,7 +9310,7 @@
(clobber (reg:SI 10))
(clobber (reg:SI 11))
(clobber (reg:SI 12))
- (clobber (match_scratch:SI 5 "X"))]
+ (clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && ! TARGET_POWER
&& ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32)
|| INTVAL (operands[2]) == 0)
@@ -9080,37 +9318,13 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
- (set_attr "length" "8")])
-
-(define_insn ""
- [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
- (use (match_operand:SI 2 "immediate_operand" "i"))
- (use (match_operand:SI 3 "immediate_operand" "i"))
- (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
- (clobber (reg:SI 6))
- (clobber (reg:SI 7))
- (clobber (reg:SI 8))
- (clobber (reg:SI 9))
- (clobber (reg:SI 10))
- (clobber (reg:SI 11))
- (clobber (reg:SI 12))
- (clobber (match_scratch:SI 5 "X"))]
- "TARGET_STRING && TARGET_POWERPC64
- && ((INTVAL (operands[2]) > 24 && INTVAL (operands[2]) < 32)
- || INTVAL (operands[2]) == 0)
- && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 12)
- && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 12)
- && REGNO (operands[4]) == 5"
- "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
;; Move up to 24 bytes at a time. The fixed registers are needed because the
;; register allocator doesn't have a clue about allocating 6 word registers.
;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_6reg"
+(define_expand "movmemsi_6reg"
[(parallel [(set (match_operand 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
@@ -9143,12 +9357,12 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
(define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+ [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+ (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
(use (match_operand:SI 2 "immediate_operand" "i"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
@@ -9157,41 +9371,20 @@
(clobber (reg:SI 8))
(clobber (reg:SI 9))
(clobber (reg:SI 10))
- (clobber (match_scratch:SI 5 "X"))]
+ (clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && ! TARGET_POWER
&& INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 32
&& (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 10)
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
- (set_attr "length" "8")])
-
-(define_insn ""
- [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
- (use (match_operand:SI 2 "immediate_operand" "i"))
- (use (match_operand:SI 3 "immediate_operand" "i"))
- (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
- (clobber (reg:SI 6))
- (clobber (reg:SI 7))
- (clobber (reg:SI 8))
- (clobber (reg:SI 9))
- (clobber (reg:SI 10))
- (clobber (match_scratch:SI 5 "X"))]
- "TARGET_STRING && TARGET_POWERPC64
- && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 32
- && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 10)
- && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 10)
- && REGNO (operands[4]) == 5"
- "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
;; Move up to 16 bytes at a time, using 4 fixed registers to avoid spill
;; problems with TImode.
;; rD/rS = r5 is preferred, efficient form.
-(define_expand "movstrsi_4reg"
+(define_expand "movmemsi_4reg"
[(parallel [(set (match_operand 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
@@ -9220,49 +9413,30 @@
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
(define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+ [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+ (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
(use (match_operand:SI 2 "immediate_operand" "i"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
(clobber (reg:SI 6))
(clobber (reg:SI 7))
(clobber (reg:SI 8))
- (clobber (match_scratch:SI 5 "X"))]
+ (clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && ! TARGET_POWER
&& INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16
&& (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 8)
&& (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
&& REGNO (operands[4]) == 5"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
- (set_attr "length" "8")])
-
-(define_insn ""
- [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
- (use (match_operand:SI 2 "immediate_operand" "i"))
- (use (match_operand:SI 3 "immediate_operand" "i"))
- (clobber (match_operand:SI 4 "gpc_reg_operand" "=r"))
- (clobber (reg:SI 6))
- (clobber (reg:SI 7))
- (clobber (reg:SI 8))
- (clobber (match_scratch:SI 5 "X"))]
- "TARGET_STRING && TARGET_POWERPC64
- && INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16
- && (REGNO (operands[0]) < 5 || REGNO (operands[0]) > 8)
- && (REGNO (operands[1]) < 5 || REGNO (operands[1]) > 8)
- && REGNO (operands[4]) == 5"
- "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
;; Move up to 8 bytes at a time.
-(define_expand "movstrsi_2reg"
+(define_expand "movmemsi_2reg"
[(parallel [(set (match_operand 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
@@ -9282,7 +9456,7 @@
"TARGET_STRING && TARGET_POWER && ! TARGET_POWERPC64
&& INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
(define_insn ""
@@ -9291,15 +9465,15 @@
(use (match_operand:SI 2 "immediate_operand" "i"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_scratch:DI 4 "=&r"))
- (clobber (match_scratch:SI 5 "X"))]
+ (clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && ! TARGET_POWER && ! TARGET_POWERPC64
&& INTVAL (operands[2]) > 4 && INTVAL (operands[2]) <= 8"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
;; Move up to 4 bytes at a time.
-(define_expand "movstrsi_1reg"
+(define_expand "movmemsi_1reg"
[(parallel [(set (match_operand 0 "" "")
(match_operand 1 "" ""))
(use (match_operand 2 "" ""))
@@ -9319,35 +9493,21 @@
"TARGET_STRING && TARGET_POWER
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
(define_insn ""
- [(set (mem:BLK (match_operand:SI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:SI 1 "gpc_reg_operand" "b")))
+ [(set (mem:BLK (match_operand:P 0 "gpc_reg_operand" "b"))
+ (mem:BLK (match_operand:P 1 "gpc_reg_operand" "b")))
(use (match_operand:SI 2 "immediate_operand" "i"))
(use (match_operand:SI 3 "immediate_operand" "i"))
(clobber (match_scratch:SI 4 "=&r"))
- (clobber (match_scratch:SI 5 "X"))]
+ (clobber (match_scratch:SI 5 "=X"))]
"TARGET_STRING && ! TARGET_POWER
&& INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
"{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
+ [(set_attr "type" "store_ux")
(set_attr "length" "8")])
-
-(define_insn ""
- [(set (mem:BLK (match_operand:DI 0 "gpc_reg_operand" "b"))
- (mem:BLK (match_operand:DI 1 "gpc_reg_operand" "b")))
- (use (match_operand:SI 2 "immediate_operand" "i"))
- (use (match_operand:SI 3 "immediate_operand" "i"))
- (clobber (match_scratch:SI 4 "=&r"))
- (clobber (match_scratch:SI 5 "X"))]
- "TARGET_STRING && TARGET_POWERPC64
- && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 4"
- "{lsi|lswi} %4,%1,%2\;{stsi|stswi} %4,%0,%2"
- [(set_attr "type" "load")
- (set_attr "length" "8")])
-
;; Define insns that do load or store with update. Some of these we can
;; get by using pre-decrement or pre-increment, but the hardware can also
@@ -9370,12 +9530,12 @@
ldu %3,%2(%0)"
[(set_attr "type" "load_ux,load_u")])
-(define_insn "movdi_update"
- [(set (mem:DI (plus:DI (match_operand:DI 1 "gpc_reg_operand" "0,0")
- (match_operand:DI 2 "reg_or_aligned_short_operand" "r,I")))
+(define_insn "movdi_<mode>_update"
+ [(set (mem:DI (plus:P (match_operand:P 1 "gpc_reg_operand" "0,0")
+ (match_operand:P 2 "reg_or_aligned_short_operand" "r,I")))
(match_operand:DI 3 "gpc_reg_operand" "r,r"))
- (set (match_operand:DI 0 "gpc_reg_operand" "=b,b")
- (plus:DI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=b,b")
+ (plus:P (match_dup 1) (match_dup 2)))]
"TARGET_POWERPC64 && TARGET_UPDATE"
"@
stdux %3,%0,%2
@@ -9578,170 +9738,214 @@
;; Peephole to convert two consecutive FP loads or stores into lfq/stfq.
-(define_peephole
- [(set (match_operand:DF 0 "gpc_reg_operand" "=f")
+(define_insn "*lfq_power2"
+ [(set (match_operand:V2DF 0 "gpc_reg_operand" "=f")
+ (match_operand:V2DF 1 "memory_operand" ""))]
+ "TARGET_POWER2
+ && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "lfq%U1%X1 %0,%1")
+
+(define_peephole2
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
(match_operand:DF 1 "memory_operand" ""))
- (set (match_operand:DF 2 "gpc_reg_operand" "=f")
+ (set (match_operand:DF 2 "gpc_reg_operand" "")
(match_operand:DF 3 "memory_operand" ""))]
"TARGET_POWER2
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& registers_ok_for_quad_peep (operands[0], operands[2])
- && ! MEM_VOLATILE_P (operands[1]) && ! MEM_VOLATILE_P (operands[3])
- && addrs_ok_for_quad_peep (XEXP (operands[1], 0), XEXP (operands[3], 0))"
- "lfq%U1%X1 %0,%1")
+ && mems_ok_for_quad_peep (operands[1], operands[3])"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[1] = widen_memory_access (operands[1], V2DFmode, 0);
+ operands[0] = gen_rtx_REG (V2DFmode, REGNO (operands[0]));")
-(define_peephole
+(define_insn "*stfq_power2"
+ [(set (match_operand:V2DF 0 "memory_operand" "")
+ (match_operand:V2DF 1 "gpc_reg_operand" "f"))]
+ "TARGET_POWER2
+ && TARGET_HARD_FLOAT && TARGET_FPRS"
+ "stfq%U0%X0 %1,%0")
+
+
+(define_peephole2
[(set (match_operand:DF 0 "memory_operand" "")
- (match_operand:DF 1 "gpc_reg_operand" "f"))
+ (match_operand:DF 1 "gpc_reg_operand" ""))
(set (match_operand:DF 2 "memory_operand" "")
- (match_operand:DF 3 "gpc_reg_operand" "f"))]
+ (match_operand:DF 3 "gpc_reg_operand" ""))]
"TARGET_POWER2
&& TARGET_HARD_FLOAT && TARGET_FPRS
&& registers_ok_for_quad_peep (operands[1], operands[3])
- && ! MEM_VOLATILE_P (operands[0]) && ! MEM_VOLATILE_P (operands[2])
- && addrs_ok_for_quad_peep (XEXP (operands[0], 0), XEXP (operands[2], 0))"
- "stfq%U0%X0 %1,%0")
+ && mems_ok_for_quad_peep (operands[0], operands[2])"
+ [(set (match_dup 0)
+ (match_dup 1))]
+ "operands[0] = widen_memory_access (operands[0], V2DFmode, 0);
+ operands[1] = gen_rtx_REG (V2DFmode, REGNO (operands[1]));")
+
+;; After inserting conditional returns we can sometimes have
+;; unnecessary register moves. Unfortunately we cannot have a
+;; modeless peephole here, because some single SImode sets have early
+;; clobber outputs. Although those sets expand to multi-ppc-insn
+;; sequences, using get_attr_length here will smash the operands
+;; array. Neither is there an early_cobbler_p predicate.
+;; Disallow subregs for E500 so we don't munge frob_di_df_2.
+(define_peephole2
+ [(set (match_operand:DF 0 "gpc_reg_operand" "")
+ (match_operand:DF 1 "any_operand" ""))
+ (set (match_operand:DF 2 "gpc_reg_operand" "")
+ (match_dup 0))]
+ "!(TARGET_E500_DOUBLE && GET_CODE (operands[2]) == SUBREG)
+ && peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 2) (match_dup 1))])
+
+(define_peephole2
+ [(set (match_operand:SF 0 "gpc_reg_operand" "")
+ (match_operand:SF 1 "any_operand" ""))
+ (set (match_operand:SF 2 "gpc_reg_operand" "")
+ (match_dup 0))]
+ "peep2_reg_dead_p (2, operands[0])"
+ [(set (match_dup 2) (match_dup 1))])
+
;; TLS support.
;; "b" output constraint here and on tls_ld to support tls linker optimization.
(define_insn "tls_gd_32"
- [(set (match_operand:SI 0 "register_operand" "=b")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%2@got@tlsgd")
(define_insn "tls_gd_64"
- [(set (match_operand:DI 0 "register_operand" "=b")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGD))]
"HAVE_AS_TLS && TARGET_64BIT"
"addi %0,%1,%2@got@tlsgd")
(define_insn "tls_ld_32"
- [(set (match_operand:SI 0 "register_operand" "=b")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")]
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%&@got@tlsld")
(define_insn "tls_ld_64"
- [(set (match_operand:DI 0 "register_operand" "=b")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")]
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")]
UNSPEC_TLSLD))]
"HAVE_AS_TLS && TARGET_64BIT"
"addi %0,%1,%&@got@tlsld")
(define_insn "tls_dtprel_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPREL))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%2@dtprel")
(define_insn "tls_dtprel_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPREL))]
"HAVE_AS_TLS && TARGET_64BIT"
"addi %0,%1,%2@dtprel")
(define_insn "tls_dtprel_ha_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPRELHA))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addis %0,%1,%2@dtprel@ha")
(define_insn "tls_dtprel_ha_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPRELHA))]
"HAVE_AS_TLS && TARGET_64BIT"
"addis %0,%1,%2@dtprel@ha")
(define_insn "tls_dtprel_lo_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPRELLO))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%2@dtprel@l")
(define_insn "tls_dtprel_lo_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSDTPRELLO))]
"HAVE_AS_TLS && TARGET_64BIT"
"addi %0,%1,%2@dtprel@l")
(define_insn "tls_got_dtprel_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL))]
"HAVE_AS_TLS && !TARGET_64BIT"
"lwz %0,%2@got@dtprel(%1)")
(define_insn "tls_got_dtprel_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTDTPREL))]
"HAVE_AS_TLS && TARGET_64BIT"
"ld %0,%2@got@dtprel(%1)")
(define_insn "tls_tprel_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPREL))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%2@tprel")
(define_insn "tls_tprel_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPREL))]
"HAVE_AS_TLS && TARGET_64BIT"
"addi %0,%1,%2@tprel")
(define_insn "tls_tprel_ha_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPRELHA))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addis %0,%1,%2@tprel@ha")
(define_insn "tls_tprel_ha_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPRELHA))]
"HAVE_AS_TLS && TARGET_64BIT"
"addis %0,%1,%2@tprel@ha")
(define_insn "tls_tprel_lo_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPRELLO))]
"HAVE_AS_TLS && !TARGET_64BIT"
"addi %0,%1,%2@tprel@l")
(define_insn "tls_tprel_lo_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTPRELLO))]
"HAVE_AS_TLS && TARGET_64BIT"
@@ -9751,32 +9955,32 @@
;; optimization. The linker may edit the instructions emitted by a
;; tls_got_tprel/tls_tls pair to addis,addi.
(define_insn "tls_got_tprel_32"
- [(set (match_operand:SI 0 "register_operand" "=b")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL))]
"HAVE_AS_TLS && !TARGET_64BIT"
"lwz %0,%2@got@tprel(%1)")
(define_insn "tls_got_tprel_64"
- [(set (match_operand:DI 0 "register_operand" "=b")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=b")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSGOTTPREL))]
"HAVE_AS_TLS && TARGET_64BIT"
"ld %0,%2@got@tprel(%1)")
(define_insn "tls_tls_32"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (unspec:SI [(match_operand:SI 1 "register_operand" "b")
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "b")
(match_operand:SI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTLS))]
"HAVE_AS_TLS && !TARGET_64BIT"
"add %0,%1,%2@tls")
(define_insn "tls_tls_64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (unspec:DI [(match_operand:DI 1 "register_operand" "b")
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "b")
(match_operand:DI 2 "rs6000_tls_symbol_ref" "")]
UNSPEC_TLSTLS))]
"HAVE_AS_TLS && TARGET_64BIT"
@@ -9804,7 +10008,7 @@
if (current_function_limit_stack)
{
rtx available;
- available = expand_binop (Pmode, sub_optab,
+ available = expand_binop (Pmode, sub_optab,
stack_pointer_rtx, stack_limit_rtx,
NULL_RTX, 1, OPTAB_WIDEN);
emit_insn (gen_cond_trap (LTU, available, operands[1], const0_rtx));
@@ -9824,7 +10028,7 @@
neg_op0 = GEN_INT (- INTVAL (operands[1]));
if (TARGET_UPDATE)
- emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_update))
+ emit_insn ((* ((TARGET_32BIT) ? gen_movsi_update : gen_movdi_di_update))
(stack_pointer_rtx, stack_pointer_rtx, neg_op0, chain));
else
@@ -9859,52 +10063,58 @@
""
"DONE;")
+;; Adjust stack pointer (op0) to a new value (op1).
+;; First copy old stack backchain to new location, and ensure that the
+;; scheduler won't reorder the sp assignment before the backchain write.
(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))]
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 4) (match_dup 2))
+ (set (match_dup 5) (unspec:BLK [(match_dup 5)] UNSPEC_TIE))
+ (set (match_operand 0 "register_operand" "")
+ (match_operand 1 "register_operand" ""))]
""
"
{
operands[2] = gen_reg_rtx (Pmode);
- operands[3] = gen_rtx_MEM (Pmode, operands[0]);
+ operands[3] = gen_frame_mem (Pmode, operands[0]);
+ operands[4] = gen_frame_mem (Pmode, operands[1]);
+ operands[5] = gen_frame_mem (BLKmode, operands[0]);
}")
(define_expand "save_stack_nonlocal"
- [(match_operand 0 "memory_operand" "")
- (match_operand 1 "register_operand" "")]
+ [(set (match_dup 3) (match_dup 4))
+ (set (match_operand 0 "memory_operand" "") (match_dup 3))
+ (set (match_dup 2) (match_operand 1 "register_operand" ""))]
""
"
{
- rtx temp = gen_reg_rtx (Pmode);
+ int units_per_word = (TARGET_32BIT) ? 4 : 8;
/* 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_32BIT ? DImode : TImode)),
- temp);
- emit_move_insn (operand_subword (operands[0], 1, 0, (TARGET_32BIT ? DImode : TImode)),
- operands[1]);
- DONE;
+ operands[0] = adjust_address_nv (operands[0], Pmode, 0);
+ operands[2] = adjust_address_nv (operands[0], Pmode, units_per_word);
+ operands[3] = gen_reg_rtx (Pmode);
+ operands[4] = gen_frame_mem (Pmode, operands[1]);
}")
(define_expand "restore_stack_nonlocal"
- [(match_operand 0 "register_operand" "")
- (match_operand 1 "memory_operand" "")]
+ [(set (match_dup 2) (match_operand 1 "memory_operand" ""))
+ (set (match_dup 3) (match_dup 4))
+ (set (match_dup 5) (match_dup 2))
+ (set (match_dup 6) (unspec:BLK [(match_dup 6)] UNSPEC_TIE))
+ (set (match_operand 0 "register_operand" "") (match_dup 3))]
""
"
{
- rtx temp = gen_reg_rtx (Pmode);
+ int units_per_word = (TARGET_32BIT) ? 4 : 8;
/* Restore the backchain from the first word, sp from the second. */
- emit_move_insn (temp,
- operand_subword (operands[1], 0, 0, (TARGET_32BIT ? DImode : TImode)));
- emit_move_insn (operands[0],
- operand_subword (operands[1], 1, 0,
- (TARGET_32BIT ? DImode : TImode)));
- emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp);
- DONE;
+ operands[2] = gen_reg_rtx (Pmode);
+ operands[3] = gen_reg_rtx (Pmode);
+ operands[1] = adjust_address_nv (operands[1], Pmode, 0);
+ operands[4] = adjust_address_nv (operands[1], Pmode, units_per_word);
+ operands[5] = gen_frame_mem (Pmode, operands[3]);
+ operands[6] = gen_frame_mem (BLKmode, operands[0]);
}")
;; TOC register handling.
@@ -9960,7 +10170,8 @@
[(set (match_operand:SI 0 "register_operand" "=l")
(match_operand:SI 1 "immediate_operand" "s"))
(use (unspec [(match_dup 1)] UNSPEC_TOC))]
- "TARGET_ELF && DEFAULT_ABI != ABI_AIX && flag_pic == 2"
+ "TARGET_ELF && DEFAULT_ABI != ABI_AIX
+ && (flag_pic == 2 || (flag_pic && TARGET_SECURE_PLT))"
"bcl 20,31,%1\\n%1:"
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -9983,24 +10194,22 @@
"{l|lwz} %0,%2-%3(%1)"
[(set_attr "type" "load")])
-(define_insn "load_macho_picbase"
- [(set (match_operand:SI 0 "register_operand" "=l")
- (unspec:SI [(match_operand:SI 1 "immediate_operand" "s")]
- UNSPEC_LD_MPIC))]
- "(DEFAULT_ABI == ABI_DARWIN) && flag_pic"
- "bcl 20,31,%1\\n%1:"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+(define_insn "load_toc_v4_PIC_3b"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b")
+ (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
+ (high:SI
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s")))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cau|addis} %0,%1,%2-%3@ha")
-(define_insn "macho_correct_pic"
+(define_insn "load_toc_v4_PIC_3c"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (plus:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (unspec:SI [(match_operand:SI 2 "immediate_operand" "s")
- (match_operand:SI 3 "immediate_operand" "s")]
- UNSPEC_MPIC_CORRECT)))]
- "DEFAULT_ABI == ABI_DARWIN"
- "addis %0,%1,ha16(%2-%3)\n\taddi %0,%0,lo16(%2-%3)"
- [(set_attr "length" "8")])
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b")
+ (minus:SI (match_operand:SI 2 "symbol_ref_operand" "s")
+ (match_operand:SI 3 "symbol_ref_operand" "s"))))]
+ "TARGET_ELF && TARGET_SECURE_PLT && DEFAULT_ABI != ABI_AIX && flag_pic"
+ "{cal|addi} %0,%1,%2-%3@l")
;; If the TOC is shared over a translation unit, as happens with all
;; the kinds of PIC that we support, we need to restore the TOC
@@ -10035,6 +10244,25 @@
rs6000_emit_load_toc_table (FALSE);
DONE;
}")
+
+;; Elf specific ways of loading addresses for non-PIC code.
+;; The output of this could be r0, but we make a very strong
+;; preference for a base register because it will usually
+;; be needed there.
+(define_insn "elf_high"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=b*r")
+ (high:SI (match_operand 1 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "{liu|lis} %0,%1@ha")
+
+(define_insn "elf_low"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
+ (lo_sum:SI (match_operand:SI 1 "gpc_reg_operand" "b,!*r")
+ (match_operand 2 "" "")))]
+ "TARGET_ELF && ! TARGET_64BIT"
+ "@
+ {cal|la} %0,%2@l(%1)
+ {ai|addic} %0,%1,%K2")
;; A function pointer under AIX is a pointer to a data area whose first word
;; contains the actual address of the function, whose second word contains a
@@ -10146,11 +10374,30 @@
operands[0] = machopic_indirect_call_target (operands[0]);
#endif
- if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == MEM);
+ gcc_assert (GET_CODE (operands[1]) == CONST_INT);
operands[0] = XEXP (operands[0], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[0]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[0]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode, operands[0]),
+ operands[1]),
+ gen_rtx_USE (VOIDmode, operands[2]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[0]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[0]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[2]) & CALL_LONG) != 0))
@@ -10158,12 +10405,14 @@
if (INTVAL (operands[2]) & CALL_LONG)
operands[0] = rs6000_longcall_ref (operands[0]);
- if (DEFAULT_ABI == ABI_V4
- || DEFAULT_ABI == ABI_DARWIN)
- operands[0] = force_reg (Pmode, operands[0]);
+ switch (DEFAULT_ABI)
+ {
+ case ABI_V4:
+ case ABI_DARWIN:
+ operands[0] = force_reg (Pmode, operands[0]);
+ break;
- else if (DEFAULT_ABI == ABI_AIX)
- {
+ case ABI_AIX:
/* AIX function pointers are really pointers to a three word
area. */
emit_call_insn (TARGET_32BIT
@@ -10174,9 +10423,10 @@
operands[0]),
operands[1]));
DONE;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
}
}")
@@ -10194,11 +10444,33 @@
operands[1] = machopic_indirect_call_target (operands[1]);
#endif
- if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
operands[1] = XEXP (operands[1], 0);
+ if (DEFAULT_ABI == ABI_V4 && TARGET_SECURE_PLT
+ && flag_pic
+ && GET_CODE (operands[1]) == SYMBOL_REF
+ && !SYMBOL_REF_LOCAL_P (operands[1]))
+ {
+ rtx call;
+ rtvec tmp;
+
+ tmp = gen_rtvec (3,
+ gen_rtx_SET (VOIDmode,
+ operands[0],
+ gen_rtx_CALL (VOIDmode,
+ gen_rtx_MEM (SImode,
+ operands[1]),
+ operands[2])),
+ gen_rtx_USE (VOIDmode, operands[3]),
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (SImode)));
+ call = emit_call_insn (gen_rtx_PARALLEL (VOIDmode, tmp));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (call), pic_offset_table_rtx);
+ DONE;
+ }
+
if (GET_CODE (operands[1]) != SYMBOL_REF
|| (DEFAULT_ABI == ABI_AIX && !SYMBOL_REF_FUNCTION_P (operands[1]))
|| (DEFAULT_ABI != ABI_DARWIN && (INTVAL (operands[3]) & CALL_LONG) != 0))
@@ -10206,12 +10478,14 @@
if (INTVAL (operands[3]) & CALL_LONG)
operands[1] = rs6000_longcall_ref (operands[1]);
- if (DEFAULT_ABI == ABI_V4
- || DEFAULT_ABI == ABI_DARWIN)
- operands[1] = force_reg (Pmode, operands[1]);
+ switch (DEFAULT_ABI)
+ {
+ case ABI_V4:
+ case ABI_DARWIN:
+ operands[1] = force_reg (Pmode, operands[1]);
+ break;
- else if (DEFAULT_ABI == ABI_AIX)
- {
+ case ABI_AIX:
/* AIX function pointers are really pointers to a three word
area. */
emit_call_insn (TARGET_32BIT
@@ -10224,9 +10498,10 @@
operands[1]),
operands[2]));
DONE;
+
+ default:
+ gcc_unreachable ();
}
- else
- abort ();
}
}")
@@ -10323,13 +10598,13 @@
;; and < 0 if they were not.
(define_insn "*call_indirect_nonlocal_aix32"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "cl"))
- (match_operand 1 "" "g"))
+ [(call (mem:SI (match_operand:SI 0 "register_operand" "c,*l"))
+ (match_operand 1 "" "g,g"))
(use (reg:SI 2))
(use (reg:SI 11))
(set (reg:SI 2)
(mem:SI (plus:SI (reg:SI 1) (const_int 20))))
- (clobber (match_scratch:SI 2 "=l"))]
+ (clobber (match_scratch:SI 2 "=l,l"))]
"TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
"b%T0l\;{l|lwz} 2,20(1)"
[(set_attr "type" "jmpreg")
@@ -10348,13 +10623,13 @@
(set_attr "length" "8")])
(define_insn "*call_indirect_nonlocal_aix64"
- [(call (mem:SI (match_operand:DI 0 "register_operand" "cl"))
- (match_operand 1 "" "g"))
+ [(call (mem:SI (match_operand:DI 0 "register_operand" "c,*l"))
+ (match_operand 1 "" "g,g"))
(use (reg:DI 2))
(use (reg:DI 11))
(set (reg:DI 2)
(mem:DI (plus:DI (reg:DI 1) (const_int 40))))
- (clobber (match_scratch:SI 2 "=l"))]
+ (clobber (match_scratch:SI 2 "=l,l"))]
"TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
"b%T0l\;ld 2,40(1)"
[(set_attr "type" "jmpreg")
@@ -10365,7 +10640,7 @@
(match_operand 1 "" "g"))
(use (match_operand:SI 2 "immediate_operand" "O"))
(clobber (match_scratch:SI 3 "=l"))]
- "TARGET_64BIT
+ "TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"bl %z0\;%."
@@ -10374,13 +10649,13 @@
(define_insn "*call_value_indirect_nonlocal_aix32"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" "cl"))
- (match_operand 2 "" "g")))
+ (call (mem:SI (match_operand:SI 1 "register_operand" "c,*l"))
+ (match_operand 2 "" "g,g")))
(use (reg:SI 2))
(use (reg:SI 11))
(set (reg:SI 2)
(mem:SI (plus:SI (reg:SI 1) (const_int 20))))
- (clobber (match_scratch:SI 3 "=l"))]
+ (clobber (match_scratch:SI 3 "=l,l"))]
"TARGET_32BIT && DEFAULT_ABI == ABI_AIX"
"b%T1l\;{l|lwz} 2,20(1)"
[(set_attr "type" "jmpreg")
@@ -10401,13 +10676,13 @@
(define_insn "*call_value_indirect_nonlocal_aix64"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:DI 1 "register_operand" "cl"))
- (match_operand 2 "" "g")))
+ (call (mem:SI (match_operand:DI 1 "register_operand" "c,*l"))
+ (match_operand 2 "" "g,g")))
(use (reg:DI 2))
(use (reg:DI 11))
(set (reg:DI 2)
(mem:DI (plus:DI (reg:DI 1) (const_int 40))))
- (clobber (match_scratch:SI 3 "=l"))]
+ (clobber (match_scratch:SI 3 "=l,l"))]
"TARGET_64BIT && DEFAULT_ABI == ABI_AIX"
"b%T1l\;ld 2,40(1)"
[(set_attr "type" "jmpreg")
@@ -10419,7 +10694,7 @@
(match_operand 2 "" "g")))
(use (match_operand:SI 3 "immediate_operand" "O"))
(clobber (match_scratch:SI 4 "=l"))]
- "TARGET_64BIT
+ "TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"bl %z1\;%."
@@ -10432,11 +10707,11 @@
;; operands[2] is the value FUNCTION_ARG returns for the VOID argument
;; which indicates how to set cr1
-(define_insn "*call_indirect_nonlocal_sysv"
- [(call (mem:SI (match_operand:SI 0 "register_operand" "cl,cl"))
- (match_operand 1 "" "g,g"))
- (use (match_operand:SI 2 "immediate_operand" "O,n"))
- (clobber (match_scratch:SI 3 "=l,l"))]
+(define_insn "*call_indirect_nonlocal_sysv<mode>"
+ [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l,c,*l"))
+ (match_operand 1 "" "g,g,g,g"))
+ (use (match_operand:SI 2 "immediate_operand" "O,O,n,n"))
+ (clobber (match_scratch:SI 3 "=l,l,l,l"))]
"DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN"
{
@@ -10448,11 +10723,11 @@
return "b%T0l";
}
- [(set_attr "type" "jmpreg,jmpreg")
- (set_attr "length" "4,8")])
+ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+ (set_attr "length" "4,4,8,8")])
-(define_insn "*call_nonlocal_sysv"
- [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
+(define_insn "*call_nonlocal_sysv<mode>"
+ [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
(match_operand 1 "" "g,g"))
(use (match_operand:SI 2 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 3 "=l,l"))]
@@ -10469,18 +10744,29 @@
#if TARGET_MACHO
return output_call(insn, operands, 0, 2);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z0@plt" : "bl %z0";
-#endif
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ /* The magic 32768 offset here and in the other sysv call insns
+ corresponds to the offset of r30 in .got2, as given by LCTOC1.
+ See sysv4.h:toc_section. */
+ return "bl %z0+32768@plt";
+ else
+ return "bl %z0@plt";
+ }
+ else
+ return "bl %z0";
+#endif
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
-(define_insn "*call_value_indirect_nonlocal_sysv"
+(define_insn "*call_value_indirect_nonlocal_sysv<mode>"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "register_operand" "cl,cl"))
- (match_operand 2 "" "g,g")))
- (use (match_operand:SI 3 "immediate_operand" "O,n"))
- (clobber (match_scratch:SI 4 "=l,l"))]
+ (call (mem:SI (match_operand:P 1 "register_operand" "c,*l,c,*l"))
+ (match_operand 2 "" "g,g,g,g")))
+ (use (match_operand:SI 3 "immediate_operand" "O,O,n,n"))
+ (clobber (match_scratch:SI 4 "=l,l,l,l"))]
"DEFAULT_ABI == ABI_V4
|| DEFAULT_ABI == ABI_DARWIN"
{
@@ -10492,12 +10778,12 @@
return "b%T1l";
}
- [(set_attr "type" "jmpreg,jmpreg")
- (set_attr "length" "4,8")])
+ [(set_attr "type" "jmpreg,jmpreg,jmpreg,jmpreg")
+ (set_attr "length" "4,4,8,8")])
-(define_insn "*call_value_nonlocal_sysv"
+(define_insn "*call_value_nonlocal_sysv<mode>"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+ (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
(match_operand 2 "" "g,g")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(clobber (match_scratch:SI 4 "=l,l"))]
@@ -10514,8 +10800,16 @@
#if TARGET_MACHO
return output_call(insn, operands, 1, 3);
#else
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? "bl %z1@plt" : "bl %z1";
-#endif
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return "bl %z1+32768@plt";
+ else
+ return "bl %z1@plt";
+ }
+ else
+ return "bl %z1";
+#endif
}
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10563,8 +10857,8 @@
operands[0] = machopic_indirect_call_target (operands[0]);
#endif
- if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[0]) == MEM);
+ gcc_assert (GET_CODE (operands[1]) == CONST_INT);
operands[0] = XEXP (operands[0], 0);
operands[3] = gen_reg_rtx (SImode);
@@ -10677,7 +10971,7 @@
(use (match_operand:SI 2 "immediate_operand" "O"))
(use (match_operand:SI 3 "register_operand" "l"))
(return)]
- "TARGET_64BIT
+ "TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[2]) & CALL_LONG) == 0"
"b %z0"
@@ -10705,15 +10999,15 @@
(use (match_operand:SI 3 "immediate_operand" "O"))
(use (match_operand:SI 4 "register_operand" "l"))
(return)]
- "TARGET_64BIT
+ "TARGET_64BIT
&& DEFAULT_ABI == ABI_AIX
&& (INTVAL (operands[3]) & CALL_LONG) == 0"
"b %z1"
[(set_attr "type" "branch")
(set_attr "length" "4")])
-(define_insn "*sibcall_nonlocal_sysv"
- [(call (mem:SI (match_operand:SI 0 "symbol_ref_operand" "s,s"))
+(define_insn "*sibcall_nonlocal_sysv<mode>"
+ [(call (mem:SI (match_operand:P 0 "symbol_ref_operand" "s,s"))
(match_operand 1 "" ""))
(use (match_operand 2 "immediate_operand" "O,n"))
(use (match_operand:SI 3 "register_operand" "l,l"))
@@ -10729,7 +11023,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z0@plt\" : \"b %z0\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z0+32768@plt\";
+ else
+ return \"b %z0@plt\";
+ }
+ else
+ return \"b %z0\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10749,17 +11051,17 @@
operands[1] = machopic_indirect_call_target (operands[1]);
#endif
- if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != CONST_INT)
- abort ();
+ gcc_assert (GET_CODE (operands[1]) == MEM);
+ gcc_assert (GET_CODE (operands[2]) == CONST_INT);
operands[1] = XEXP (operands[1], 0);
operands[4] = gen_reg_rtx (SImode);
}")
-(define_insn "*sibcall_value_nonlocal_sysv"
+(define_insn "*sibcall_value_nonlocal_sysv<mode>"
[(set (match_operand 0 "" "")
- (call (mem:SI (match_operand:SI 1 "symbol_ref_operand" "s,s"))
+ (call (mem:SI (match_operand:P 1 "symbol_ref_operand" "s,s"))
(match_operand 2 "" "")))
(use (match_operand:SI 3 "immediate_operand" "O,n"))
(use (match_operand:SI 4 "register_operand" "l,l"))
@@ -10775,7 +11077,15 @@
else if (INTVAL (operands[2]) & CALL_V4_CLEAR_FP_ARGS)
output_asm_insn (\"creqv 6,6,6\", operands);
- return (DEFAULT_ABI == ABI_V4 && flag_pic) ? \"b %z1@plt\" : \"b %z1\";
+ if (DEFAULT_ABI == ABI_V4 && flag_pic)
+ {
+ if (TARGET_SECURE_PLT && flag_pic == 2)
+ return \"b %z1+32768@plt\";
+ else
+ return \"b %z1@plt\";
+ }
+ else
+ return \"b %z1\";
}"
[(set_attr "type" "branch,branch")
(set_attr "length" "4,8")])
@@ -10803,10 +11113,10 @@
;; Start with the DEFINE_EXPANDs to generate the rtl for compares, scc
;; insns, and branches. We store the operands of compares until we see
;; how it is used.
-(define_expand "cmpsi"
+(define_expand "cmp<mode>"
[(set (cc0)
- (compare (match_operand:SI 0 "gpc_reg_operand" "")
- (match_operand:SI 1 "reg_or_short_operand" "")))]
+ (compare (match_operand:GPR 0 "gpc_reg_operand" "")
+ (match_operand:GPR 1 "reg_or_short_operand" "")))]
""
"
{
@@ -10814,26 +11124,7 @@
this might be a logical operation. That insn doesn't exist. */
if (GET_CODE (operands[1]) == CONST_INT
&& INTVAL (operands[1]) < 0)
- operands[1] = force_reg (SImode, operands[1]);
-
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 0;
- DONE;
-}")
-
-(define_expand "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "gpc_reg_operand" "")
- (match_operand:DI 1 "reg_or_short_operand" "")))]
- "TARGET_POWERPC64"
- "
-{
- /* Take care of the possibility that operands[1] might be negative but
- this might be a logical operation. That insn doesn't exist. */
- if (GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) < 0)
- operands[1] = force_reg (DImode, operands[1]);
+ operands[1] = force_reg (<MODE>mode, operands[1]);
rs6000_compare_op0 = operands[0];
rs6000_compare_op1 = operands[1];
@@ -10841,35 +11132,10 @@
DONE;
}")
-(define_expand "cmpsf"
- [(set (cc0) (compare (match_operand:SF 0 "gpc_reg_operand" "")
- (match_operand:SF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT"
- "
-{
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 1;
- DONE;
-}")
-
-(define_expand "cmpdf"
- [(set (cc0) (compare (match_operand:DF 0 "gpc_reg_operand" "")
- (match_operand:DF 1 "gpc_reg_operand" "")))]
- "TARGET_HARD_FLOAT && TARGET_FPRS"
- "
-{
- rs6000_compare_op0 = operands[0];
- rs6000_compare_op1 = operands[1];
- rs6000_compare_fp_p = 1;
- DONE;
-}")
-
-(define_expand "cmptf"
- [(set (cc0) (compare (match_operand:TF 0 "gpc_reg_operand" "")
- (match_operand:TF 1 "gpc_reg_operand" "")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
- && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
+(define_expand "cmp<mode>"
+ [(set (cc0) (compare (match_operand:FP 0 "gpc_reg_operand" "")
+ (match_operand:FP 1 "gpc_reg_operand" "")))]
+ ""
"
{
rs6000_compare_op0 = operands[0];
@@ -10930,12 +11196,12 @@
(define_expand "bunordered"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNORDERED, operands[0]); DONE; }")
(define_expand "bordered"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (ORDERED, operands[0]); DONE; }")
(define_expand "buneq"
@@ -10982,11 +11248,11 @@
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
""
"
-{
+{
if (! rs6000_compare_fp_p)
FAIL;
- rs6000_emit_sCOND (NE, operands[0]);
+ rs6000_emit_sCOND (NE, operands[0]);
DONE;
}")
@@ -10996,8 +11262,7 @@
""
"
{
- if (! rs6000_compare_fp_p
- && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+ if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
FAIL;
rs6000_emit_sCOND (GE, operands[0]);
@@ -11010,11 +11275,10 @@
""
"
{
- if (! rs6000_compare_fp_p
- && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+ if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
FAIL;
- rs6000_emit_sCOND (GT, operands[0]);
+ rs6000_emit_sCOND (GT, operands[0]);
DONE;
}")
@@ -11024,11 +11288,10 @@
""
"
{
- if (! rs6000_compare_fp_p
- && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+ if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
FAIL;
- rs6000_emit_sCOND (LE, operands[0]);
+ rs6000_emit_sCOND (LE, operands[0]);
DONE;
}")
@@ -11038,11 +11301,10 @@
""
"
{
- if (! rs6000_compare_fp_p
- && (! TARGET_POWER || rs6000_compare_op1 == const0_rtx))
+ if (! rs6000_compare_fp_p && rs6000_compare_op1 == const0_rtx)
FAIL;
- rs6000_emit_sCOND (LT, operands[0]);
+ rs6000_emit_sCOND (LT, operands[0]);
DONE;
}")
@@ -11068,12 +11330,12 @@
(define_expand "sunordered"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNORDERED, operands[0]); DONE; }")
(define_expand "sordered"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && TARGET_E500 && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (ORDERED, operands[0]); DONE; }")
(define_expand "suneq"
@@ -11106,51 +11368,138 @@
""
"{ rs6000_emit_sCOND (LTGT, operands[0]); DONE; }")
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "stack_protect_setsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))]
+ "TARGET_32BIT"
+ "{l%U1%X1|lwz%U1%X1} %2,%1\;{st%U0%X0|stw%U0%X0} %2,%0\;{lil|li} %2,0"
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
+
+(define_insn "stack_protect_setdi"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))]
+ "TARGET_64BIT"
+ "ld%U1%X1 %2,%1\;std%U0%X0 %2,%0\;{lil|li} %2,0"
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
+
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, TARGET_64BIT ? 13 : 2);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ rs6000_compare_op0 = operands[0];
+ rs6000_compare_op1 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, operands[1]),
+ UNSPEC_SP_TEST);
+ rs6000_compare_fp_p = 0;
+ emit_jump_insn (gen_beq (operands[2]));
+ DONE;
+})
+
+(define_insn "stack_protect_testsi"
+ [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
+ (unspec:CCEQ [(match_operand:SI 1 "memory_operand" "m,m")
+ (match_operand:SI 2 "memory_operand" "m,m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:SI 4 "=r,r") (const_int 0))
+ (clobber (match_scratch:SI 3 "=&r,&r"))]
+ "TARGET_32BIT"
+ "@
+ {l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0
+ {l%U1%X1|lwz%U1%X1} %3,%1\;{l%U2%X2|lwz%U2%X2} %4,%2\;{cmpl|cmplw} %0,%3,%4\;{lil|li} %3,0\;{lil|li} %4,0"
+ [(set_attr "length" "16,20")])
+
+(define_insn "stack_protect_testdi"
+ [(set (match_operand:CCEQ 0 "cc_reg_operand" "=x,?y")
+ (unspec:CCEQ [(match_operand:DI 1 "memory_operand" "m,m")
+ (match_operand:DI 2 "memory_operand" "m,m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:DI 4 "=r,r") (const_int 0))
+ (clobber (match_scratch:DI 3 "=&r,&r"))]
+ "TARGET_64BIT"
+ "@
+ ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;xor. %3,%3,%4\;{lil|li} %4,0
+ ld%U1%X1 %3,%1\;ld%U2%X2 %4,%2\;cmpld %0,%3,%4\;{lil|li} %3,0\;{lil|li} %4,0"
+ [(set_attr "length" "16,20")])
+
;; Here are the actual compare insns.
-(define_insn "*cmpsi_internal1"
+(define_insn "*cmp<mode>_internal1"
[(set (match_operand:CC 0 "cc_reg_operand" "=y")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI")))]
+ (compare:CC (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "reg_or_short_operand" "rI")))]
""
- "{cmp%I2|cmpw%I2} %0,%1,%2"
- [(set_attr "type" "cmp")])
-
-(define_insn "*cmpdi_internal1"
- [(set (match_operand:CC 0 "cc_reg_operand" "=y")
- (compare:CC (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "reg_or_short_operand" "rI")))]
- "TARGET_POWERPC64"
- "cmpd%I2 %0,%1,%2"
+ "{cmp%I2|cmp<wd>%I2} %0,%1,%2"
[(set_attr "type" "cmp")])
;; If we are comparing a register for equality with a large constant,
-;; we can do this with an XOR followed by a compare. But we need a scratch
-;; register for the result of the XOR.
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_operand" "")
- (compare:CC (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "non_short_cint_operand" "")))
- (clobber (match_operand:SI 3 "gpc_reg_operand" ""))]
- "find_single_use (operands[0], insn, 0)
- && (GET_CODE (*find_single_use (operands[0], insn, 0)) == EQ
- || GET_CODE (*find_single_use (operands[0], insn, 0)) == NE)"
- [(set (match_dup 3) (xor:SI (match_dup 1) (match_dup 4)))
- (set (match_dup 0) (compare:CC (match_dup 3) (match_dup 5)))]
- "
+;; we can do this with an XOR followed by a compare. But this is profitable
+;; only if the large constant is only used for the comparison (and in this
+;; case we already have a register to reuse as scratch).
+;;
+;; For 64-bit registers, we could only do so if the constant's bit 15 is clear:
+;; otherwise we'd need to XOR with FFFFFFFF????0000 which is not available.
+
+(define_peephole2
+ [(set (match_operand:SI 0 "register_operand")
+ (match_operand:SI 1 "logical_const_operand" ""))
+ (set (match_dup 0) (match_operator:SI 3 "boolean_or_operator"
+ [(match_dup 0)
+ (match_operand:SI 2 "logical_const_operand" "")]))
+ (set (match_operand:CC 4 "cc_reg_operand" "")
+ (compare:CC (match_operand:SI 5 "gpc_reg_operand" "")
+ (match_dup 0)))
+ (set (pc)
+ (if_then_else (match_operator 6 "equality_operator"
+ [(match_dup 4) (const_int 0)])
+ (match_operand 7 "" "")
+ (match_operand 8 "" "")))]
+ "peep2_reg_dead_p (3, operands[0])
+ && peep2_reg_dead_p (4, operands[4])"
+ [(set (match_dup 0) (xor:SI (match_dup 5) (match_dup 9)))
+ (set (match_dup 4) (compare:CC (match_dup 0) (match_dup 10)))
+ (set (pc) (if_then_else (match_dup 6) (match_dup 7) (match_dup 8)))]
+
{
- /* Get the constant we are comparing against, C, and see what it looks like
- sign-extended to 16 bits. Then see what constant could be XOR'ed
- with C to get the sign-extended value. */
-
- HOST_WIDE_INT c = INTVAL (operands[2]);
+ /* Get the constant we are comparing against, and see what it looks like
+ when sign-extended from 16 to 32 bits. Then see what constant we could
+ XOR with SEXTC to get the sign-extended value. */
+ rtx cnst = simplify_const_binary_operation (GET_CODE (operands[3]),
+ SImode,
+ operands[1], operands[2]);
+ HOST_WIDE_INT c = INTVAL (cnst);
HOST_WIDE_INT sextc = ((c & 0xffff) ^ 0x8000) - 0x8000;
HOST_WIDE_INT xorv = c ^ sextc;
- operands[4] = GEN_INT (xorv);
- operands[5] = GEN_INT (sextc);
-}")
+ operands[9] = GEN_INT (xorv);
+ operands[10] = GEN_INT (sextc);
+})
(define_insn "*cmpsi_internal2"
[(set (match_operand:CCUNS 0 "cc_reg_operand" "=y")
@@ -11234,7 +11583,7 @@
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
(compare:CCFP (match_operand:TF 1 "gpc_reg_operand" "f")
(match_operand:TF 2 "gpc_reg_operand" "f")))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && !TARGET_XL_COMPAT
+ "!TARGET_IEEEQUAD && !TARGET_XL_COMPAT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"fcmpu %0,%1,%2\;bne %0,$+8\;fcmpu %0,%L1,%L2"
[(set_attr "type" "fpcompare")
@@ -11252,7 +11601,7 @@
(clobber (match_scratch:DF 8 "=f"))
(clobber (match_scratch:DF 9 "=f"))
(clobber (match_scratch:DF 10 "=f"))]
- "(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN) && TARGET_XL_COMPAT
+ "!TARGET_IEEEQUAD && TARGET_XL_COMPAT
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
"#"
"&& reload_completed"
@@ -11290,14 +11639,12 @@
DFmode));
if (TARGET_TOC)
{
- operands[13] = gen_rtx_MEM (DFmode,
- create_TOC_reference (XEXP (operands[13], 0)));
- operands[14] = gen_rtx_MEM (DFmode,
- create_TOC_reference (XEXP (operands[14], 0)));
+ operands[13] = gen_const_mem (DFmode,
+ create_TOC_reference (XEXP (operands[13], 0)));
+ operands[14] = gen_const_mem (DFmode,
+ create_TOC_reference (XEXP (operands[14], 0)));
set_mem_alias_set (operands[13], get_TOC_alias_set ());
set_mem_alias_set (operands[14], get_TOC_alias_set ());
- RTX_UNCHANGING_P (operands[13]) = 1;
- RTX_UNCHANGING_P (operands[14]) = 1;
}
})
@@ -11320,16 +11667,16 @@
(const_string "mfcrf")
]
(const_string "mfcr")))
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
-;; Same as above, but get the EQ bit.
-(define_insn "move_from_CR_eq_bit"
+;; Same as above, but get the GT bit.
+(define_insn "move_from_CR_gt_bit"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_EQ))]
+ (unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
"TARGET_E500"
- "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,1"
+ "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,31,31"
[(set_attr "type" "mfcr")
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
;; Same as above, but get the OV/ORDERED bit.
(define_insn "move_from_CR_ov_bit"
@@ -11338,7 +11685,7 @@
"TARGET_ISEL"
"mfcr %0\;{rlinm|rlwinm} %0,%0,%t1,1"
[(set_attr "type" "mfcr")
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -11352,7 +11699,7 @@
(const_string "mfcrf")
]
(const_string "mfcr")))
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -11367,7 +11714,7 @@
mfcr %3%Q2\;{rlinm.|rlwinm.} %3,%3,%J1,1
#"
[(set_attr "type" "delayed_compare")
- (set_attr "length" "12,16")])
+ (set_attr "length" "8,16")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
@@ -11413,7 +11760,7 @@
(const_string "mfcrf")
]
(const_string "mfcr")))
- (set_attr "length" "12")])
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -11448,7 +11795,7 @@
return \"mfcr %4%Q2\;{rlinm.|rlwinm.} %4,%4,%5,%6,%6\";
}"
[(set_attr "type" "delayed_compare")
- (set_attr "length" "12,16")])
+ (set_attr "length" "8,16")])
(define_split
[(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
@@ -11485,7 +11832,7 @@
"REGNO (operands[2]) != REGNO (operands[5])"
"mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
[(set_attr "type" "mfcr")
- (set_attr "length" "20")])
+ (set_attr "length" "12")])
(define_peephole
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
@@ -11499,7 +11846,7 @@
"TARGET_POWERPC64 && REGNO (operands[2]) != REGNO (operands[5])"
"mfcr %3\;{rlinm|rlwinm} %0,%3,%J1,1\;{rlinm|rlwinm} %3,%3,%J4,1"
[(set_attr "type" "mfcr")
- (set_attr "length" "20")])
+ (set_attr "length" "12")])
;; There are some scc insns that can be done directly, without a compare.
;; These are faster because they don't involve the communications between
@@ -11515,117 +11862,96 @@
;; otherwise won't accept constants. We do this because it is faster than
;; the cmp/mfcr sequence we would otherwise generate.
-(define_insn ""
+(define_mode_attr scc_eq_op2 [(SI "rKLI")
+ (DI "rKJI")])
+
+(define_insn_and_split "*eq<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (eq:GPR (match_operand:GPR 1 "gpc_reg_operand" "r")
+ (match_operand:GPR 2 "scc_eq_operand" "<scc_eq_op2>")))]
+ "!TARGET_POWER"
+ "#"
+ "!TARGET_POWER"
+ [(set (match_dup 0)
+ (clz:GPR (match_dup 3)))
+ (set (match_dup 0)
+ (lshiftrt:GPR (match_dup 0) (match_dup 4)))]
+ {
+ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+ {
+ /* Use output operand as intermediate. */
+ operands[3] = operands[0];
+
+ if (logical_operand (operands[2], <MODE>mode))
+ emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+ gen_rtx_XOR (<MODE>mode,
+ operands[1], operands[2])));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+ gen_rtx_PLUS (<MODE>mode, operands[1],
+ negate_rtx (<MODE>mode,
+ operands[2]))));
+ }
+ else
+ operands[3] = operands[1];
+
+ operands[4] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+ })
+
+(define_insn_and_split "*eq<mode>_compare"
+ [(set (match_operand:CC 3 "cc_reg_operand" "=y")
+ (compare:CC
+ (eq:P (match_operand:P 1 "gpc_reg_operand" "=r")
+ (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))
+ (const_int 0)))
+ (set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (eq:P (match_dup 1) (match_dup 2)))]
+ "!TARGET_POWER && optimize_size"
+ "#"
+ "!TARGET_POWER && optimize_size"
+ [(set (match_dup 0)
+ (clz:P (match_dup 4)))
+ (parallel [(set (match_dup 3)
+ (compare:CC (lshiftrt:P (match_dup 0) (match_dup 5))
+ (const_int 0)))
+ (set (match_dup 0)
+ (lshiftrt:P (match_dup 0) (match_dup 5)))])]
+ {
+ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+ {
+ /* Use output operand as intermediate. */
+ operands[4] = operands[0];
+
+ if (logical_operand (operands[2], <MODE>mode))
+ emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+ gen_rtx_XOR (<MODE>mode,
+ operands[1], operands[2])));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[4],
+ gen_rtx_PLUS (<MODE>mode, operands[1],
+ negate_rtx (<MODE>mode,
+ operands[2]))));
+ }
+ else
+ operands[4] = operands[1];
+
+ operands[5] = GEN_INT (exact_log2 (GET_MODE_BITSIZE (<MODE>mode)));
+ })
+
+(define_insn "*eqsi_power"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
(match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I")))
(clobber (match_scratch:SI 3 "=r,&r,r,r,r"))]
- "TARGET_32BIT"
+ "TARGET_POWER"
"@
xor %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
{sfi|subfic} %3,%1,0\;{ae|adde} %0,%3,%1
{xoril|xori} %0,%1,%b2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
{xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0
{sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae|adde} %0,%3,%0"
- [(set_attr "length" "12,8,12,12,12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
- (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I")))
- (clobber (match_scratch:DI 3 "=r,&r,r,r,r"))]
- "TARGET_64BIT"
- "@
- xor %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0
- subfic %3,%1,0\;adde %0,%3,%1
- xori %0,%1,%b2\;subfic %3,%0,0\;adde %0,%3,%0
- xoris %0,%1,%u2\;subfic %3,%0,0\;adde %0,%3,%0
- subfic %0,%1,%2\;subfic %3,%0,0\;adde %0,%3,%0"
- [(set_attr "length" "12,8,12,12,12")])
-
-(define_insn ""
- [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
- (compare:CC
- (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
- (eq:SI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:SI 3 "=r,&r,r,r,r,r,&r,r,r,r"))]
- "TARGET_32BIT"
- "@
- xor %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
- {sfi|subfic} %3,%1,0\;{ae.|adde.} %0,%3,%1
- {xoril|xori} %0,%1,%b2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
- {xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
- {sfi|subfic} %0,%1,%2\;{sfi|subfic} %3,%0,0\;{ae.|adde.} %0,%3,%0
- #
- #
- #
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
-
-(define_split
- [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_cint_operand" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (eq:SI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:SI 3 ""))]
- "TARGET_32BIT && reload_completed"
- [(parallel [(set (match_dup 0)
- (eq:SI (match_dup 1) (match_dup 2)))
- (clobber (match_dup 3))])
- (set (match_dup 4)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
- (compare:CC
- (eq:DI (match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:DI 2 "reg_or_cint_operand" "r,O,K,J,I,r,O,K,J,I"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r,r,r,r,r,r")
- (eq:DI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:DI 3 "=r,&r,r,r,r,r,&r,r,r,r"))]
- "TARGET_64BIT"
- "@
- xor %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0
- subfic %3,%1,0\;adde. %0,%3,%1
- xori %0,%1,%b2\;subfic %3,%0,0\;adde. %0,%3,%0
- xoris %0,%1,%u2\;subfic %3,%0,0\;adde. %0,%3,%0
- subfic %0,%1,%2\;subfic %3,%0,0\;adde. %0,%3,%0
- #
- #
- #
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,8,12,12,12,16,12,16,16,16")])
-
-(define_split
- [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (eq:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_cint_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (eq:DI (match_dup 1) (match_dup 2)))
- (clobber (match_scratch:DI 3 ""))]
- "TARGET_64BIT && reload_completed"
- [(parallel [(set (match_dup 0)
- (eq:DI (match_dup 1) (match_dup 2)))
- (clobber (match_dup 3))])
- (set (match_dup 4)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
+ [(set_attr "type" "three,two,three,three,three")
+ (set_attr "length" "12,8,12,12,12")])
;; We have insns of the form shown by the first define_insn below. If
;; there is something inside the comparison operation, we must split it.
@@ -11642,10 +11968,10 @@
(set (match_dup 2) (plus:SI (match_op_dup 1 [(match_dup 2) (match_dup 3)])
(match_dup 4)))])
-(define_insn ""
+(define_insn "*plus_eqsi"
[(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r")
(plus:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))
+ (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I"))
(match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r")))]
"TARGET_32BIT"
"@
@@ -11654,18 +11980,19 @@
{xoril|xori} %0,%1,%b2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3
{xoriu|xoris} %0,%1,%u2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3
{sfi|subfic} %0,%1,%2\;{sfi|subfic} %0,%0,0\;{aze|addze} %0,%3"
- [(set_attr "length" "12,8,12,12,12")])
+ [(set_attr "type" "three,two,three,three,three")
+ (set_attr "length" "12,8,12,12,12")])
-(define_insn ""
+(define_insn "*compare_plus_eqsi"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
(compare:CC
(plus:SI
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
+ (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
(match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
(const_int 0)))
(clobber (match_scratch:SI 4 "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r"))]
- "TARGET_32BIT"
+ "TARGET_32BIT && optimize_size"
"@
xor %4,%1,%2\;{sfi|subfic} %4,%4,0\;{aze.|addze.} %4,%3
{sfi|subfic} %4,%1,0\;{aze.|addze.} %4,%3
@@ -11685,11 +12012,11 @@
(compare:CC
(plus:SI
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_cint_operand" ""))
+ (match_operand:SI 2 "scc_eq_operand" ""))
(match_operand:SI 3 "gpc_reg_operand" ""))
(const_int 0)))
(clobber (match_scratch:SI 4 ""))]
- "TARGET_32BIT && reload_completed"
+ "TARGET_32BIT && optimize_size && reload_completed"
[(set (match_dup 4)
(plus:SI (eq:SI (match_dup 1)
(match_dup 2))
@@ -11699,17 +12026,17 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "*plus_eqsi_compare"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,x,x,x,x,?y,?y,?y,?y,?y")
(compare:CC
(plus:SI
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r,r,r,r,r,r")
- (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I,r,O,K,L,I"))
+ (match_operand:SI 2 "scc_eq_operand" "r,O,K,L,I,r,O,K,L,I"))
(match_operand:SI 3 "gpc_reg_operand" "r,r,r,r,r,r,r,r,r,r"))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r,&r,&r,&r,&r,&r,&r")
(plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT"
+ "TARGET_32BIT && optimize_size"
"@
xor %0,%1,%2\;{sfi|subfic} %0,%0,0\;{aze.|addze.} %0,%3
{sfi|subfic} %0,%1,0\;{aze.|addze.} %0,%3
@@ -11729,12 +12056,12 @@
(compare:CC
(plus:SI
(eq:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_cint_operand" ""))
+ (match_operand:SI 2 "scc_eq_operand" ""))
(match_operand:SI 3 "gpc_reg_operand" ""))
(const_int 0)))
(set (match_operand:SI 0 "gpc_reg_operand" "")
(plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT && reload_completed"
+ "TARGET_32BIT && optimize_size && reload_completed"
[(set (match_dup 0)
(plus:SI (eq:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
(set (match_dup 4)
@@ -11742,41 +12069,67 @@
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r,r")
- (neg:SI (eq:SI (match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r,r")
- (match_operand:SI 2 "reg_or_cint_operand" "r,O,K,L,I"))))]
- "TARGET_32BIT"
- "@
- xor %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
- {ai|addic} %0,%1,-1\;{sfe|subfe} %0,%0,%0
- {xoril|xori} %0,%1,%b2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
- {xoriu|xoris} %0,%1,%u2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0
- {sfi|subfic} %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0"
- [(set_attr "length" "12,8,12,12,12")])
+(define_insn "*neg_eq0<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (const_int 0))))]
+ ""
+ "{ai|addic} %0,%1,-1\;{sfe|subfe} %0,%0,%0"
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
+
+(define_insn_and_split "*neg_eq<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (neg:P (eq:P (match_operand:P 1 "gpc_reg_operand" "%r")
+ (match_operand:P 2 "scc_eq_operand" "<scc_eq_op2>"))))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0) (neg:P (eq:P (match_dup 3) (const_int 0))))]
+ {
+ if (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)
+ {
+ /* Use output operand as intermediate. */
+ operands[3] = operands[0];
+
+ if (logical_operand (operands[2], <MODE>mode))
+ emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+ gen_rtx_XOR (<MODE>mode,
+ operands[1], operands[2])));
+ else
+ emit_insn (gen_rtx_SET (VOIDmode, operands[3],
+ gen_rtx_PLUS (<MODE>mode, operands[1],
+ negate_rtx (<MODE>mode,
+ operands[2]))));
+ }
+ else
+ operands[3] = operands[1];
+ })
;; Simplify (ne X (const_int 0)) on the PowerPC. No need to on the Power,
;; since it nabs/sr is just as fast.
-(define_insn "*ne0"
+(define_insn "*ne0si"
[(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
(lshiftrt:SI (neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
(const_int 31)))
(clobber (match_scratch:SI 2 "=&r"))]
"! TARGET_POWER && TARGET_32BIT && !TARGET_ISEL"
"{ai|addic} %2,%1,-1\;{sfe|subfe} %0,%2,%1"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
-(define_insn ""
+(define_insn "*ne0di"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(lshiftrt:DI (neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
(const_int 63)))
(clobber (match_scratch:DI 2 "=&r"))]
"TARGET_64BIT"
"addic %2,%1,-1\;subfe %0,%2,%1"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
;; This is what (plus (ne X (const_int 0)) Y) looks like.
-(define_insn ""
+(define_insn "*plus_ne0si"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(plus:SI (lshiftrt:SI
(neg:SI (abs:SI (match_operand:SI 1 "gpc_reg_operand" "r")))
@@ -11785,9 +12138,10 @@
(clobber (match_scratch:SI 3 "=&r"))]
"TARGET_32BIT"
"{ai|addic} %3,%1,-1\;{aze|addze} %0,%2"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
-(define_insn ""
+(define_insn "*plus_ne0di"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
(plus:DI (lshiftrt:DI
(neg:DI (abs:DI (match_operand:DI 1 "gpc_reg_operand" "r")))
@@ -11796,9 +12150,10 @@
(clobber (match_scratch:DI 3 "=&r"))]
"TARGET_64BIT"
"addic %3,%1,-1\;addze %0,%2"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
-(define_insn ""
+(define_insn "*compare_plus_ne0si"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC
(plus:SI (lshiftrt:SI
@@ -11836,7 +12191,7 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "*compare_plus_ne0di"
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
(compare:CC
(plus:DI (lshiftrt:DI
@@ -11871,7 +12226,7 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "*plus_ne0si_compare"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC
(plus:SI (lshiftrt:SI
@@ -11912,7 +12267,7 @@
(const_int 0)))]
"")
-(define_insn ""
+(define_insn "*plus_ne0di_compare"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,?y")
(compare:CC
(plus:DI (lshiftrt:DI
@@ -12090,62 +12445,24 @@
{ai|addic} %0,%1,-1\;{aze|addze} %0,%0\;{srai|srawi} %0,%0,31"
[(set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI")))]
- "TARGET_32BIT"
+(define_insn "*leu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI")))]
+ ""
"{sf%I2|subf%I2c} %0,%1,%2\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (leu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "reg_or_short_operand" "rI")))]
- "TARGET_64BIT"
- "subf%I2c %0,%1,%2\;li %0,0\;adde %0,%0,%0"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC
- (leu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_short_operand" "rI,rI"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (leu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- subf%I2c %0,%1,%2\;li %0,0\;adde. %0,%0,%0
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,16")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (leu:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (leu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (leu:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
-(define_insn ""
+(define_insn "*leu<mode>_compare"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC
- (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
+ (leu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (leu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (leu:P (match_dup 1) (match_dup 2)))]
+ ""
"@
{sf%I2|subf%I2c} %0,%1,%2\;{cal %0,0(0)|li %0,0}\;{ae.|adde.} %0,%0,%0
#"
@@ -12155,27 +12472,28 @@
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC
- (leu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
+ (leu:P (match_operand:P 1 "gpc_reg_operand" "")
+ (match_operand:P 2 "reg_or_short_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (leu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (leu:P (match_dup 1) (match_dup 2)))]
+ "reload_completed"
[(set (match_dup 0)
- (leu:SI (match_dup 1) (match_dup 2)))
+ (leu:P (match_dup 1) (match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (plus:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI"))
- (match_operand:SI 3 "gpc_reg_operand" "r")))]
- "TARGET_32BIT"
+(define_insn "*plus_leu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+ (plus:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI"))
+ (match_operand:P 3 "gpc_reg_operand" "r")))]
+ ""
"{sf%I2|subf%I2c} %0,%1,%2\;{aze|addze} %0,%3"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -12242,23 +12560,25 @@
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (neg:SI (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
- "TARGET_32BIT"
+(define_insn "*neg_leu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (neg:P (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI"))))]
+ ""
"{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;nand %0,%0,%0"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (and:SI (neg:SI
- (leu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI")))
- (match_operand:SI 3 "gpc_reg_operand" "r")))]
- "TARGET_32BIT"
+(define_insn "*and_neg_leu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+ (and:P (neg:P
+ (leu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI")))
+ (match_operand:P 3 "gpc_reg_operand" "r")))]
+ ""
"{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -12451,138 +12771,75 @@
"doz%I2 %0,%1,%2\;nabs %0,%0\;{srai|srawi} %0,%0,31"
[(set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P")))]
- "TARGET_32BIT"
- "@
- {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;neg %0,%0
- {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;neg %0,%0"
- [(set_attr "length" "12")])
+(define_insn_and_split "*ltu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+ (set (match_dup 0) (neg:P (match_dup 0)))]
+ "")
-(define_insn ""
+(define_insn_and_split "*ltu<mode>_compare"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC
- (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
+ (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
- (ltu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT"
- "@
- {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;neg. %0,%0
- {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;neg. %0,%0
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,12,16,16")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_neg_short_operand" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (ltu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (ltu:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+ (ltu:P (match_dup 1) (match_dup 2)))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+ (parallel [(set (match_dup 3)
+ (compare:CC (neg:P (match_dup 0)) (const_int 0)))
+ (set (match_dup 0) (neg:P (match_dup 0)))])]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
- (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P"))
- (match_operand:SI 3 "reg_or_short_operand" "rI,rI")))]
- "TARGET_32BIT"
- "@
- {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3
- {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC
- (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
- (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
- (const_int 0)))
- (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
- "TARGET_32BIT"
- "@
- {sf|subfc} %4,%2,%1\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
- {ai|addic} %4,%1,%n2\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,12,16,16")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_neg_short_operand" ""))
- (match_operand:SI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:SI 4 ""))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 4)
- (plus:SI (ltu:SI (match_dup 1) (match_dup 2))
- (match_dup 3)))
- (set (match_dup 0)
- (compare:CC (match_dup 4)
- (const_int 0)))]
+(define_insn_and_split "*plus_ltu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r,r")
+ (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
+ (match_operand:P 3 "reg_or_short_operand" "rI,rI")))]
+ ""
+ "#"
+ "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+ (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
"")
-(define_insn ""
+(define_insn_and_split "*plus_ltu<mode>_compare"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC
- (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
- (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
+ (plus:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
+ (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
- (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT"
- "@
- {sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
- {ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,12,16,16")])
-
-(define_split
- [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_neg_short_operand" ""))
- (match_operand:SI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (plus:SI (ltu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
- (set (match_dup 4)
- (compare:CC (match_dup 0)
- (const_int 0)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
+ (plus:P (ltu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ ""
+ "#"
+ "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(set (match_dup 0) (neg:P (ltu:P (match_dup 1) (match_dup 2))))
+ (parallel [(set (match_dup 4)
+ (compare:CC (minus:P (match_dup 3) (match_dup 0))
+ (const_int 0)))
+ (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (neg:SI (ltu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P"))))]
- "TARGET_32BIT"
+(define_insn "*neg_ltu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (neg:P (ltu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0
{ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
@@ -12709,35 +12966,26 @@
"doz%I2 %0,%1,%2\;{ai|addic} %0,%0,-1\;{sfe|subfe} %0,%0,%0"
[(set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P")))]
- "TARGET_32BIT"
+(define_insn "*geu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0
{ai|addic} %0,%1,%n2\;{cal %0,0(0)|li %0,0}\;{ae|adde} %0,%0,%0"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (geu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_neg_short_operand" "r,P")))]
- "TARGET_64BIT"
- "@
- subfc %0,%2,%1\;li %0,0\;adde %0,%0,%0
- addic %0,%1,%n2\;li %0,0\;adde %0,%0,%0"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
-(define_insn ""
+(define_insn "*geu<mode>_compare"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC
- (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P,r,P"))
+ (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P,r,P"))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
- (geu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT"
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r,r,r")
+ (geu:P (match_dup 1) (match_dup 2)))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{cal %0,0(0)|li %0,0}\;{ae.|adde.} %0,%0,%0
{ai|addic} %0,%1,%n2\;{cal %0,0(0)|li %0,0}\;{ae.|adde.} %0,%0,%0
@@ -12749,62 +12997,30 @@
(define_split
[(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
(compare:CC
- (geu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_neg_short_operand" ""))
+ (geu:P (match_operand:P 1 "gpc_reg_operand" "")
+ (match_operand:P 2 "reg_or_neg_short_operand" ""))
(const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (geu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (geu:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC
- (geu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:DI 2 "reg_or_neg_short_operand" "r,P,r,P"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r")
- (geu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- subfc %0,%2,%1\;li %0,0\;adde. %0,%0,%0
- addic %0,%1,%n2\;li %0,0\;adde. %0,%0,%0
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,12,16,16")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (geu:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_neg_short_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (geu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT && reload_completed"
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (geu:P (match_dup 1) (match_dup 2)))]
+ "reload_completed"
[(set (match_dup 0)
- (geu:DI (match_dup 1) (match_dup 2)))
+ (geu:P (match_dup 1) (match_dup 2)))
(set (match_dup 3)
(compare:CC (match_dup 0)
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
- (plus:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P"))
- (match_operand:SI 3 "gpc_reg_operand" "r,r")))]
- "TARGET_32BIT"
+(define_insn "*plus_geu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
+ (plus:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P"))
+ (match_operand:P 3 "gpc_reg_operand" "r,r")))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{aze|addze} %0,%3
{ai|addic} %0,%1,%n2\;{aze|addze} %0,%3"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -12875,27 +13091,29 @@
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (neg:SI (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_short_operand" "r,I"))))]
- "TARGET_32BIT"
+(define_insn "*neg_geu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (neg:P (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_short_operand" "r,I"))))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;nand %0,%0,%0
{sfi|subfic} %0,%1,-1\;{a%I2|add%I2c} %0,%0,%2\;{sfe|subfe} %0,%0,%0"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
- (and:SI (neg:SI
- (geu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_neg_short_operand" "r,P")))
- (match_operand:SI 3 "gpc_reg_operand" "r,r")))]
- "TARGET_32BIT"
+(define_insn "*and_neg_geu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r,&r")
+ (and:P (neg:P
+ (geu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_neg_short_operand" "r,P")))
+ (match_operand:P 3 "gpc_reg_operand" "r,r")))]
+ ""
"@
{sf|subfc} %0,%2,%1\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0
{ai|addic} %0,%1,%n2\;{sfe|subfe} %0,%0,%0\;andc %0,%3,%0"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
@@ -12973,84 +13191,6 @@
(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (const_int 0)))]
- "TARGET_32BIT"
- "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{sri|srwi} %0,%0,31"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (const_int 0)))]
- "TARGET_64BIT"
- "subfic %0,%1,0\;addme %0,%0\;srdi %0,%0,63"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC
- (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (const_int 0))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (gt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT"
- "@
- {sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{sri.|srwi.} %0,%0,31
- #"
- [(set_attr "type" "delayed_compare")
- (set_attr "length" "12,16")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (gt:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (const_int 0))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (gt:SI (match_dup 1) (const_int 0)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (gt:SI (match_dup 1) (const_int 0)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 2 "cc_reg_operand" "=x,?y")
- (compare:CC
- (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (const_int 0))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (gt:DI (match_dup 1) (const_int 0)))]
- "TARGET_64BIT"
- "@
- subfic %0,%1,0\;addme %0,%0\;srdi. %0,%0,63
- #"
- [(set_attr "type" "delayed_compare")
- (set_attr "length" "12,16")])
-
-(define_split
- [(set (match_operand:CC 2 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (gt:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (const_int 0))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (gt:DI (match_dup 1) (const_int 0)))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (gt:DI (match_dup 1) (const_int 0)))
- (set (match_dup 2)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_short_operand" "r")))]
"TARGET_POWER"
"doz %0,%2,%1\;nabs %0,%0\;{sri|srwi} %0,%0,31"
@@ -13087,23 +13227,15 @@
(const_int 0)))]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
- (plus:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (const_int 0))
- (match_operand:SI 2 "gpc_reg_operand" "r")))]
- "TARGET_32BIT"
+(define_insn "*plus_gt0<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+ (plus:P (gt:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (const_int 0))
+ (match_operand:P 2 "gpc_reg_operand" "r")))]
+ ""
"{a|addc} %0,%1,%1\;{sfe|subfe} %0,%1,%0\;{aze|addze} %0,%2"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
- (plus:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (const_int 0))
- (match_operand:DI 2 "gpc_reg_operand" "r")))]
- "TARGET_64BIT"
- "addc %0,%1,%1\;subfe %0,%1,%0\;addze %0,%2"
- [(set_attr "length" "12")])
+ [(set_attr "type" "three")
+ (set_attr "length" "12")])
(define_insn ""
[(set (match_operand:CC 0 "cc_reg_operand" "=x,?y")
@@ -13311,280 +13443,79 @@
(define_insn ""
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (const_int 0))))]
- "TARGET_32BIT"
- "{sfi|subfic} %0,%1,0\;{ame|addme} %0,%0\;{srai|srawi} %0,%0,31"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (neg:DI (gt:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (const_int 0))))]
- "TARGET_64BIT"
- "subfic %0,%1,0\;addme %0,%0\;sradi %0,%0,63"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (neg:SI (gt:SI (match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand:SI 2 "reg_or_short_operand" "r"))))]
"TARGET_POWER"
"doz %0,%2,%1\;nabs %0,%0\;{srai|srawi} %0,%0,31"
[(set_attr "length" "12")])
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI")))]
- "TARGET_32BIT"
- "{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;neg %0,%0"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "reg_or_short_operand" "rI")))]
- "TARGET_64BIT"
- "subf%I2c %0,%1,%2\;subfe %0,%0,%0\;neg %0,%0"
- [(set_attr "length" "12")])
-
-(define_insn ""
- [(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
- (compare:CC
- (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_short_operand" "rI,rI"))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=r,r")
- (gtu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT"
- "@
- {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;neg. %0,%0
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,16")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (gtu:SI (match_dup 1) (match_dup 2)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (gtu:SI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
+(define_insn_and_split "*gtu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI")))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+ (set (match_dup 0) (neg:P (match_dup 0)))]
"")
-(define_insn ""
+(define_insn_and_split "*gtu<mode>_compare"
[(set (match_operand:CC 3 "cc_reg_operand" "=x,?y")
(compare:CC
- (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_short_operand" "rI,rI"))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=r,r")
- (gtu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT"
- "@
- subf%I2c %0,%1,%2\;subfe %0,%0,%0\;neg. %0,%0
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "12,16")])
-
-(define_split
- [(set (match_operand:CC 3 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (gtu:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (gtu:DI (match_dup 1) (match_dup 2)))
- (set (match_dup 3)
- (compare:CC (match_dup 0)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r")
- (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r")
- (match_operand:SI 2 "reg_or_short_operand" "I,rI"))
- (match_operand:SI 3 "reg_or_short_operand" "r,rI")))]
- "TARGET_32BIT"
- "@
- {ai|addic} %0,%1,%k2\;{aze|addze} %0,%3
- {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf%I3|subf%I3c} %0,%0,%3"
- [(set_attr "length" "8,12")])
-
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r")
- (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r")
- (match_operand:DI 2 "reg_or_short_operand" "I,rI"))
- (match_operand:DI 3 "reg_or_short_operand" "r,rI")))]
- "TARGET_64BIT"
- "@
- addic %0,%1,%k2\;addze %0,%3
- subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subf%I3c %0,%0,%3"
- [(set_attr "length" "8,12")])
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC
- (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_short_operand" "I,r,I,r"))
- (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
- (const_int 0)))
- (clobber (match_scratch:SI 4 "=&r,&r,&r,&r"))]
- "TARGET_32BIT"
- "@
- {ai|addic} %4,%1,%k2\;{aze.|addze.} %4,%3
- {sf%I2|subf%I2c} %4,%1,%2\;{sfe|subfe} %4,%4,%4\;{sf.|subfc.} %4,%4,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12,12,16")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
- (match_operand:SI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:SI 4 ""))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 4)
- (plus:SI (gtu:SI (match_dup 1) (match_dup 2))
- (match_dup 3)))
- (set (match_dup 0)
- (compare:CC (match_dup 4)
- (const_int 0)))]
- "")
-
-(define_insn ""
- [(set (match_operand:CC 0 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC
- (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:DI 2 "reg_or_short_operand" "I,r,I,r"))
- (match_operand:DI 3 "gpc_reg_operand" "r,r,r,r"))
+ (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r")
+ (match_operand:P 2 "reg_or_short_operand" "rI,rI"))
(const_int 0)))
- (clobber (match_scratch:DI 4 "=&r,&r,&r,&r"))]
- "TARGET_64BIT"
- "@
- addic %4,%1,%k2\;addze. %4,%3
- subf%I2c %4,%1,%2\;subfe %4,%4,%4\;subfc. %4,%4,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12,12,16")])
-
-(define_split
- [(set (match_operand:CC 0 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (match_operand:DI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (clobber (match_scratch:DI 4 ""))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 4)
- (plus:DI (gtu:DI (match_dup 1) (match_dup 2))
- (match_dup 3)))
- (set (match_dup 0)
- (compare:CC (match_dup 4)
- (const_int 0)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=r,r")
+ (gtu:P (match_dup 1) (match_dup 2)))]
+ ""
+ "#"
+ ""
+ [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+ (parallel [(set (match_dup 3)
+ (compare:CC (neg:P (match_dup 0)) (const_int 0)))
+ (set (match_dup 0) (neg:P (match_dup 0)))])]
"")
-(define_insn ""
- [(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
- (compare:CC
- (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:SI 2 "reg_or_short_operand" "I,r,I,r"))
- (match_operand:SI 3 "gpc_reg_operand" "r,r,r,r"))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
- (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT"
- "@
- {ai|addic} %0,%1,%k2\;{aze.|addze.} %0,%3
- {sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0\;{sf.|subfc.} %0,%0,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12,12,16")])
-
-(define_split
- [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "")
- (match_operand:SI 2 "reg_or_short_operand" ""))
- (match_operand:SI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_32BIT && reload_completed"
- [(set (match_dup 0)
- (plus:SI (gtu:SI (match_dup 1) (match_dup 2)) (match_dup 3)))
- (set (match_dup 4)
- (compare:CC (match_dup 0)
- (const_int 0)))]
+(define_insn_and_split "*plus_gtu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=&r")
+ (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI"))
+ (match_operand:P 3 "reg_or_short_operand" "rI")))]
+ ""
+ "#"
+ "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+ (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))]
"")
-(define_insn ""
+(define_insn_and_split "*plus_gtu<mode>_compare"
[(set (match_operand:CC 4 "cc_reg_operand" "=x,x,?y,?y")
(compare:CC
- (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r,r,r,r")
- (match_operand:DI 2 "reg_or_short_operand" "I,r,I,r"))
- (match_operand:DI 3 "gpc_reg_operand" "r,r,r,r"))
+ (plus:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r,r,r,r")
+ (match_operand:P 2 "reg_or_short_operand" "I,r,I,r"))
+ (match_operand:P 3 "gpc_reg_operand" "r,r,r,r"))
(const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "=&r,&r,&r,&r")
- (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_64BIT"
- "@
- addic %0,%1,%k2\;addze. %0,%3
- subf%I2c %0,%1,%2\;subfe %0,%0,%0\;subfc. %0,%0,%3
- #
- #"
- [(set_attr "type" "compare")
- (set_attr "length" "8,12,12,16")])
-
-(define_split
- [(set (match_operand:CC 4 "cc_reg_not_cr0_operand" "")
- (compare:CC
- (plus:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "")
- (match_operand:DI 2 "reg_or_short_operand" ""))
- (match_operand:DI 3 "gpc_reg_operand" ""))
- (const_int 0)))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (plus:DI (gtu:DI (match_dup 1) (match_dup 2)) (match_dup 3)))
- (set (match_dup 4)
- (compare:CC (match_dup 0)
- (const_int 0)))]
+ (set (match_operand:P 0 "gpc_reg_operand" "=&r,&r,&r,&r")
+ (plus:P (gtu:P (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ ""
+ "#"
+ "&& !reg_overlap_mentioned_p (operands[0], operands[3])"
+ [(set (match_dup 0) (neg:P (gtu:P (match_dup 1) (match_dup 2))))
+ (parallel [(set (match_dup 4)
+ (compare:CC (minus:P (match_dup 3) (match_dup 0))
+ (const_int 0)))
+ (set (match_dup 0) (minus:P (match_dup 3) (match_dup 0)))])]
"")
-(define_insn ""
- [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (neg:SI (gtu:SI (match_operand:SI 1 "gpc_reg_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI"))))]
- "TARGET_32BIT"
+(define_insn "*neg_gtu<mode>"
+ [(set (match_operand:P 0 "gpc_reg_operand" "=r")
+ (neg:P (gtu:P (match_operand:P 1 "gpc_reg_operand" "r")
+ (match_operand:P 2 "reg_or_short_operand" "rI"))))]
+ ""
"{sf%I2|subf%I2c} %0,%1,%2\;{sfe|subfe} %0,%0,%0"
- [(set_attr "length" "8")])
+ [(set_attr "type" "two")
+ (set_attr "length" "8")])
-(define_insn ""
- [(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (neg:DI (gtu:DI (match_operand:DI 1 "gpc_reg_operand" "r")
- (match_operand:DI 2 "reg_or_short_operand" "rI"))))]
- "TARGET_64BIT"
- "subf%I2c %0,%1,%2\;subfe %0,%0,%0"
- [(set_attr "length" "8")])
;; Define both directions of branch and return. If we need a reload
;; register, we'd rather use CR0 since it is much easier to copy a
@@ -13618,7 +13549,7 @@
{
return output_cbranch (operands[0], NULL, 0, insn);
}"
- [(set_attr "type" "branch")
+ [(set_attr "type" "jmpreg")
(set_attr "length" "4")])
(define_insn ""
@@ -13649,7 +13580,7 @@
{
return output_cbranch (operands[0], NULL, 1, insn);
}"
- [(set_attr "type" "branch")
+ [(set_attr "type" "jmpreg")
(set_attr "length" "4")])
;; Logic on condition register values.
@@ -13731,28 +13662,28 @@
{
int positive_1, positive_2;
- positive_1 = branch_positive_comparison_operator (operands[1], CCEQmode);
- positive_2 = branch_positive_comparison_operator (operands[3], CCEQmode);
+ positive_1 = branch_positive_comparison_operator (operands[1],
+ GET_MODE (operands[1]));
+ positive_2 = branch_positive_comparison_operator (operands[3],
+ GET_MODE (operands[3]));
if (! positive_1)
- operands[1] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[2]),
- GET_CODE (operands[1])),
- SImode,
- operands[2], const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE (operands[2]),
+ GET_CODE (operands[1])),
+ SImode,
+ operands[2], const0_rtx);
else if (GET_MODE (operands[1]) != SImode)
- operands[1] = gen_rtx (GET_CODE (operands[1]),
- SImode,
- operands[2], const0_rtx);
+ operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), SImode,
+ operands[2], const0_rtx);
if (! positive_2)
- operands[3] = gen_rtx (rs6000_reverse_condition (GET_MODE (operands[4]),
- GET_CODE (operands[3])),
- SImode,
- operands[4], const0_rtx);
+ operands[3] = gen_rtx_fmt_ee (rs6000_reverse_condition (GET_MODE (operands[4]),
+ GET_CODE (operands[3])),
+ SImode,
+ operands[4], const0_rtx);
else if (GET_MODE (operands[3]) != SImode)
- operands[3] = gen_rtx (GET_CODE (operands[3]),
- SImode,
- operands[4], const0_rtx);
+ operands[3] = gen_rtx_fmt_ee (GET_CODE (operands[3]), SImode,
+ operands[4], const0_rtx);
if (positive_1 == positive_2)
{
@@ -13781,33 +13712,16 @@
[(set_attr "type" "jmpreg")])
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "register_operand" ""))]
- ""
- "
-{
- if (TARGET_32BIT)
- emit_jump_insn (gen_indirect_jumpsi (operands[0]));
- else
- emit_jump_insn (gen_indirect_jumpdi (operands[0]));
- DONE;
-}")
+ [(set (pc) (match_operand 0 "register_operand" ""))])
-(define_insn "indirect_jumpsi"
- [(set (pc) (match_operand:SI 0 "register_operand" "c,*l"))]
- "TARGET_32BIT"
+(define_insn "*indirect_jump<mode>"
+ [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))]
+ ""
"@
bctr
{br|blr}"
[(set_attr "type" "jmpreg")])
-(define_insn "indirect_jumpdi"
- [(set (pc) (match_operand:DI 0 "register_operand" "c,*l"))]
- "TARGET_64BIT"
- "@
- bctr
- blr"
- [(set_attr "type" "jmpreg")])
-
;; Table jump for switch statements:
(define_expand "tablejump"
[(use (match_operand 0 "" ""))
@@ -13836,7 +13750,7 @@
}")
(define_expand "tablejumpdi"
- [(set (match_dup 4)
+ [(set (match_dup 4)
(sign_extend:DI (match_operand:SI 0 "lwa_operand" "rm")))
(set (match_dup 3)
(plus:DI (match_dup 4)
@@ -13850,26 +13764,16 @@
operands[4] = gen_reg_rtx (DImode);
}")
-(define_insn ""
+(define_insn "*tablejump<mode>_internal1"
[(set (pc)
- (match_operand:SI 0 "register_operand" "c,*l"))
+ (match_operand:P 0 "register_operand" "c,*l"))
(use (label_ref (match_operand 1 "" "")))]
- "TARGET_32BIT"
+ ""
"@
bctr
{br|blr}"
[(set_attr "type" "jmpreg")])
-(define_insn ""
- [(set (pc)
- (match_operand:DI 0 "register_operand" "c,*l"))
- (use (label_ref (match_operand 1 "" "")))]
- "TARGET_64BIT"
- "@
- bctr
- blr"
- [(set_attr "type" "jmpreg")])
-
(define_insn "nop"
[(const_int 0)]
""
@@ -13905,32 +13809,18 @@
DONE;
}")
-(define_expand "ctrsi"
+(define_expand "ctr<mode>"
[(parallel [(set (pc)
- (if_then_else (ne (match_operand:SI 0 "register_operand" "")
+ (if_then_else (ne (match_operand:P 0 "register_operand" "")
(const_int 1))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:SI (match_dup 0)
+ (plus:P (match_dup 0)
(const_int -1)))
(clobber (match_scratch:CC 2 ""))
- (clobber (match_scratch:SI 3 ""))])]
- "TARGET_32BIT"
- "")
-
-(define_expand "ctrdi"
- [(parallel [(set (pc)
- (if_then_else (ne (match_operand:DI 0 "register_operand" "")
- (const_int 1))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:DI (match_dup 0)
- (const_int -1)))
- (clobber (match_scratch:CC 2 ""))
- (clobber (match_scratch:DI 3 ""))])]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 3 ""))])]
+ ""
"")
;; We need to be able to do this for any operand, including MEM, or we
@@ -13939,66 +13829,18 @@
;; For the length attribute to be calculated correctly, the
;; label MUST be operand 0.
-(define_insn "*ctrsi_internal1"
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"{bdn|bdnz} %l0\";
- else
- return \"bdz $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal2"
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
- (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"bdz %l0\";
- else
- return \"{bdn|bdnz} $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal1"
+(define_insn "*ctr<mode>_internal1"
[(set (pc)
- (if_then_else (ne (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+ (if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
(const_int 1))
(label_ref (match_operand 0 "" ""))
(pc)))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+ (plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+ ""
"*
{
if (which_alternative != 0)
@@ -14011,116 +13853,18 @@
[(set_attr "type" "branch")
(set_attr "length" "*,12,16,16")])
-(define_insn "*ctrdi_internal2"
+(define_insn "*ctr<mode>_internal2"
[(set (pc)
- (if_then_else (ne (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+ (if_then_else (ne (match_operand:P 1 "register_operand" "c,*r,*r,*r")
(const_int 1))
(pc)
(label_ref (match_operand 0 "" ""))))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+ (plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"bdz %l0\";
- else
- return \"{bdn|bdnz} $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-;; Similar, but we can use GE since we have a REG_NONNEG.
-
-(define_insn "*ctrsi_internal3"
- [(set (pc)
- (if_then_else (ge (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT && find_reg_note (insn, REG_NONNEG, 0)"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"{bdn|bdnz} %l0\";
- else
- return \"bdz $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal4"
- [(set (pc)
- (if_then_else (ge (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT && find_reg_note (insn, REG_NONNEG, 0)"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"bdz %l0\";
- else
- return \"{bdn|bdnz} $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal3"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT && find_reg_note (insn, REG_NONNEG, 0)"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"{bdn|bdnz} %l0\";
- else
- return \"bdz $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal4"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT && find_reg_note (insn, REG_NONNEG, 0)"
+ (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+ ""
"*
{
if (which_alternative != 0)
@@ -14135,66 +13879,18 @@
;; Similar but use EQ
-(define_insn "*ctrsi_internal5"
+(define_insn "*ctr<mode>_internal5"
[(set (pc)
- (if_then_else (eq (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
+ (if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
(const_int 1))
(label_ref (match_operand 0 "" ""))
(pc)))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+ (plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"bdz %l0\";
- else
- return \"{bdn|bdnz} $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrsi_internal6"
- [(set (pc)
- (if_then_else (eq (match_operand:SI 1 "register_operand" "c,*r,*r,*r")
- (const_int 1))
- (pc)
- (label_ref (match_operand 0 "" ""))))
- (set (match_operand:SI 2 "register_operand" "=1,*r,m,*q*c*l")
- (plus:SI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:SI 4 "=X,X,&r,r"))]
- "TARGET_32BIT"
- "*
-{
- if (which_alternative != 0)
- return \"#\";
- else if (get_attr_length (insn) == 4)
- return \"{bdn|bdnz} %l0\";
- else
- return \"bdz $+8\;b %l0\";
-}"
- [(set_attr "type" "branch")
- (set_attr "length" "*,12,16,16")])
-
-(define_insn "*ctrdi_internal5"
- [(set (pc)
- (if_then_else (eq (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
- (const_int 1))
- (label_ref (match_operand 0 "" ""))
- (pc)))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+ ""
"*
{
if (which_alternative != 0)
@@ -14207,18 +13903,18 @@
[(set_attr "type" "branch")
(set_attr "length" "*,12,16,16")])
-(define_insn "*ctrdi_internal6"
+(define_insn "*ctr<mode>_internal6"
[(set (pc)
- (if_then_else (eq (match_operand:DI 1 "register_operand" "c,*r,*r,*r")
+ (if_then_else (eq (match_operand:P 1 "register_operand" "c,*r,*r,*r")
(const_int 1))
(pc)
(label_ref (match_operand 0 "" ""))))
- (set (match_operand:DI 2 "register_operand" "=1,*r,m,*c*l")
- (plus:DI (match_dup 1)
+ (set (match_operand:P 2 "nonimmediate_operand" "=1,*r,m,*q*c*l")
+ (plus:P (match_dup 1)
(const_int -1)))
(clobber (match_scratch:CC 3 "=X,&x,&x,&x"))
- (clobber (match_scratch:DI 4 "=X,X,&r,r"))]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 4 "=X,X,&r,r"))]
+ ""
"*
{
if (which_alternative != 0)
@@ -14236,104 +13932,47 @@
(define_split
[(set (pc)
(if_then_else (match_operator 2 "comparison_operator"
- [(match_operand:SI 1 "gpc_reg_operand" "")
+ [(match_operand:P 1 "gpc_reg_operand" "")
(const_int 1)])
(match_operand 5 "" "")
(match_operand 6 "" "")))
- (set (match_operand:SI 0 "gpc_reg_operand" "")
- (plus:SI (match_dup 1)
- (const_int -1)))
+ (set (match_operand:P 0 "gpc_reg_operand" "")
+ (plus:P (match_dup 1) (const_int -1)))
(clobber (match_scratch:CC 3 ""))
- (clobber (match_scratch:SI 4 ""))]
- "TARGET_32BIT && reload_completed"
- [(parallel [(set (match_dup 3)
- (compare:CC (plus:SI (match_dup 1)
- (const_int -1))
- (const_int 0)))
- (set (match_dup 0)
- (plus:SI (match_dup 1)
- (const_int -1)))])
- (set (pc) (if_then_else (match_dup 7)
- (match_dup 5)
- (match_dup 6)))]
- "
-{ operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
- const0_rtx); }")
-
-(define_split
- [(set (pc)
- (if_then_else (match_operator 2 "comparison_operator"
- [(match_operand:SI 1 "gpc_reg_operand" "")
- (const_int 1)])
- (match_operand 5 "" "")
- (match_operand 6 "" "")))
- (set (match_operand:SI 0 "nonimmediate_operand" "")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:CC 3 ""))
- (clobber (match_scratch:SI 4 ""))]
- "TARGET_32BIT && reload_completed
- && ! gpc_reg_operand (operands[0], SImode)"
- [(parallel [(set (match_dup 3)
- (compare:CC (plus:SI (match_dup 1)
- (const_int -1))
- (const_int 0)))
- (set (match_dup 4)
- (plus:SI (match_dup 1)
- (const_int -1)))])
- (set (match_dup 0)
- (match_dup 4))
- (set (pc) (if_then_else (match_dup 7)
- (match_dup 5)
- (match_dup 6)))]
- "
-{ operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
- const0_rtx); }")
-(define_split
- [(set (pc)
- (if_then_else (match_operator 2 "comparison_operator"
- [(match_operand:DI 1 "gpc_reg_operand" "")
- (const_int 1)])
- (match_operand 5 "" "")
- (match_operand 6 "" "")))
- (set (match_operand:DI 0 "gpc_reg_operand" "")
- (plus:DI (match_dup 1)
- (const_int -1)))
- (clobber (match_scratch:CC 3 ""))
- (clobber (match_scratch:DI 4 ""))]
- "TARGET_64BIT && reload_completed"
+ (clobber (match_scratch:P 4 ""))]
+ "reload_completed"
[(parallel [(set (match_dup 3)
- (compare:CC (plus:DI (match_dup 1)
+ (compare:CC (plus:P (match_dup 1)
(const_int -1))
(const_int 0)))
(set (match_dup 0)
- (plus:DI (match_dup 1)
+ (plus:P (match_dup 1)
(const_int -1)))])
(set (pc) (if_then_else (match_dup 7)
(match_dup 5)
(match_dup 6)))]
"
-{ operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
- const0_rtx); }")
+{ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
+ operands[3], const0_rtx); }")
(define_split
[(set (pc)
(if_then_else (match_operator 2 "comparison_operator"
- [(match_operand:DI 1 "gpc_reg_operand" "")
+ [(match_operand:P 1 "gpc_reg_operand" "")
(const_int 1)])
(match_operand 5 "" "")
(match_operand 6 "" "")))
- (set (match_operand:DI 0 "nonimmediate_operand" "")
- (plus:DI (match_dup 1) (const_int -1)))
+ (set (match_operand:P 0 "nonimmediate_operand" "")
+ (plus:P (match_dup 1) (const_int -1)))
(clobber (match_scratch:CC 3 ""))
- (clobber (match_scratch:DI 4 ""))]
- "TARGET_64BIT && reload_completed
- && ! gpc_reg_operand (operands[0], DImode)"
+ (clobber (match_scratch:P 4 ""))]
+ "reload_completed && ! gpc_reg_operand (operands[0], SImode)"
[(parallel [(set (match_dup 3)
- (compare:CC (plus:DI (match_dup 1)
+ (compare:CC (plus:P (match_dup 1)
(const_int -1))
(const_int 0)))
(set (match_dup 4)
- (plus:DI (match_dup 1)
+ (plus:P (match_dup 1)
(const_int -1)))])
(set (match_dup 0)
(match_dup 4))
@@ -14341,8 +13980,8 @@
(match_dup 5)
(match_dup 6)))]
"
-{ operands[7] = gen_rtx (GET_CODE (operands[2]), VOIDmode, operands[3],
- const0_rtx); }")
+{ operands[7] = gen_rtx_fmt_ee (GET_CODE (operands[2]), VOIDmode,
+ operands[3], const0_rtx); }")
(define_insn "trap"
[(trap_if (const_int 1) (const_int 0))]
@@ -14360,19 +13999,11 @@
(define_insn ""
[(trap_if (match_operator 0 "trap_comparison_operator"
- [(match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "reg_or_short_operand" "rI")])
+ [(match_operand:GPR 1 "register_operand" "r")
+ (match_operand:GPR 2 "reg_or_short_operand" "rI")])
(const_int 0))]
""
- "{t|tw}%V0%I2 %1,%2")
-
-(define_insn ""
- [(trap_if (match_operator 0 "trap_comparison_operator"
- [(match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "reg_or_short_operand" "rI")])
- (const_int 0))]
- "TARGET_POWERPC64"
- "td%V0%I2 %1,%2")
+ "{t|t<wd>}%V0%I2 %1,%2")
;; Insns related to generating the function prologue and epilogue.
@@ -14408,7 +14039,7 @@
(define_insn "movesi_from_cr"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
- (unspec:SI [(reg:CC 68) (reg:CC 69) (reg:CC 70) (reg:CC 71)
+ (unspec:SI [(reg:CC 68) (reg:CC 69) (reg:CC 70) (reg:CC 71)
(reg:CC 72) (reg:CC 73) (reg:CC 74) (reg:CC 75)]
UNSPEC_MOVESI_FROM_CR))]
""
@@ -14420,26 +14051,16 @@
[(set (match_operand:SI 1 "memory_operand" "=m")
(match_operand:SI 2 "gpc_reg_operand" "r"))])]
"TARGET_MULTIPLE"
- "{stm|stmw} %2,%1")
-
-(define_insn "*save_fpregs_si"
- [(match_parallel 0 "any_operand"
- [(clobber (match_operand:SI 1 "register_operand" "=l"))
- (use (match_operand:SI 2 "call_operand" "s"))
- (set (match_operand:DF 3 "memory_operand" "=m")
- (match_operand:DF 4 "gpc_reg_operand" "f"))])]
- "TARGET_32BIT"
- "bl %z2"
- [(set_attr "type" "branch")
- (set_attr "length" "4")])
+ "{stm|stmw} %2,%1"
+ [(set_attr "type" "store_ux")])
-(define_insn "*save_fpregs_di"
- [(match_parallel 0 "any_operand"
- [(clobber (match_operand:DI 1 "register_operand" "=l"))
- (use (match_operand:DI 2 "call_operand" "s"))
+(define_insn "*save_fpregs_<mode>"
+ [(match_parallel 0 "any_parallel_operand"
+ [(clobber (match_operand:P 1 "register_operand" "=l"))
+ (use (match_operand:P 2 "call_operand" "s"))
(set (match_operand:DF 3 "memory_operand" "=m")
(match_operand:DF 4 "gpc_reg_operand" "f"))])]
- "TARGET_64BIT"
+ ""
"bl %z2"
[(set_attr "type" "branch")
(set_attr "length" "4")])
@@ -14497,7 +14118,7 @@
(unspec:CC [(match_operand:SI 1 "gpc_reg_operand" "r")
(match_operand 2 "immediate_operand" "n")]
UNSPEC_MOVESI_TO_CR))]
- "GET_CODE (operands[0]) == REG
+ "GET_CODE (operands[0]) == REG
&& CR_REGNO_P (REGNO (operands[0]))
&& GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) == 1 << (75 - REGNO (operands[0]))"
@@ -14506,50 +14127,34 @@
; The load-multiple instructions have similar properties.
; Note that "load_multiple" is a name known to the machine-independent
-; code that actually corresponds to the powerpc load-string.
+; code that actually corresponds to the PowerPC load-string.
(define_insn "*lmw"
[(match_parallel 0 "lmw_operation"
[(set (match_operand:SI 1 "gpc_reg_operand" "=r")
(match_operand:SI 2 "memory_operand" "m"))])]
"TARGET_MULTIPLE"
- "{lm|lmw} %1,%2")
-
-(define_insn "*return_internal_si"
- [(return)
- (use (match_operand:SI 0 "register_operand" "lc"))]
- "TARGET_32BIT"
- "b%T0"
- [(set_attr "type" "jmpreg")])
+ "{lm|lmw} %1,%2"
+ [(set_attr "type" "load_ux")])
-(define_insn "*return_internal_di"
+(define_insn "*return_internal_<mode>"
[(return)
- (use (match_operand:DI 0 "register_operand" "lc"))]
- "TARGET_64BIT"
+ (use (match_operand:P 0 "register_operand" "lc"))]
+ ""
"b%T0"
[(set_attr "type" "jmpreg")])
; FIXME: This would probably be somewhat simpler if the Cygnus sibcall
-; stuff was in GCC. Oh, and "any_operand" is a bit flexible...
-
-(define_insn "*return_and_restore_fpregs_si"
- [(match_parallel 0 "any_operand"
- [(return)
- (use (match_operand:SI 1 "register_operand" "l"))
- (use (match_operand:SI 2 "call_operand" "s"))
- (set (match_operand:DF 3 "gpc_reg_operand" "=f")
- (match_operand:DF 4 "memory_operand" "m"))])]
- "TARGET_32BIT"
- "b %z2")
+; stuff was in GCC. Oh, and "any_parallel_operand" is a bit flexible...
-(define_insn "*return_and_restore_fpregs_di"
- [(match_parallel 0 "any_operand"
+(define_insn "*return_and_restore_fpregs_<mode>"
+ [(match_parallel 0 "any_parallel_operand"
[(return)
- (use (match_operand:DI 1 "register_operand" "l"))
- (use (match_operand:DI 2 "call_operand" "s"))
+ (use (match_operand:P 1 "register_operand" "l"))
+ (use (match_operand:P 2 "call_operand" "s"))
(set (match_operand:DF 3 "gpc_reg_operand" "=f")
(match_operand:DF 4 "memory_operand" "m"))])]
- "TARGET_64BIT"
+ ""
"b %z2")
; This is used in compiling the unwind routines.
@@ -14566,18 +14171,11 @@
}")
; 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")]
+(define_insn "eh_set_lr_<mode>"
+ [(unspec_volatile [(match_operand:P 0 "register_operand" "r")]
UNSPECV_EH_RR)
- (clobber (match_scratch:SI 1 "=&b"))]
- "TARGET_32BIT"
- "#")
-
-(define_insn "eh_set_lr_di"
- [(unspec_volatile [(match_operand:DI 0 "register_operand" "r")]
- UNSPECV_EH_RR)
- (clobber (match_scratch:DI 1 "=&b"))]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 1 "=&b"))]
+ ""
"#")
(define_split
@@ -14592,7 +14190,7 @@
}")
(define_insn "prefetch"
- [(prefetch (match_operand:V4SI 0 "address_operand" "p")
+ [(prefetch (match_operand 0 "indexed_or_indirect_address" "a")
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))]
"TARGET_POWERPC"
@@ -14603,6 +14201,8 @@
return INTVAL (operands[1]) ? \"dcbtst %a0\" : \"dcbt %a0\";
}"
[(set_attr "type" "load")])
+
+(include "sync.md")
(include "altivec.md")
(include "spe.md")
diff --git a/contrib/gcc/config/rs6000/rs6000.opt b/contrib/gcc/config/rs6000/rs6000.opt
new file mode 100644
index 0000000..8ff390d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/rs6000.opt
@@ -0,0 +1,247 @@
+; Options for the rs6000 port of the compiler
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mpower
+Target Report RejectNegative Mask(POWER)
+Use POWER instruction set
+
+mno-power
+Target Report RejectNegative
+Do not use POWER instruction set
+
+mpower2
+Target Report Mask(POWER2)
+Use POWER2 instruction set
+
+mpowerpc
+Target Report RejectNegative Mask(POWERPC)
+Use PowerPC instruction set
+
+mno-powerpc
+Target Report RejectNegative
+Do not use PowerPC instruction set
+
+mpowerpc64
+Target Report Mask(POWERPC64)
+Use PowerPC-64 instruction set
+
+mpowerpc-gpopt
+Target Report Mask(PPC_GPOPT)
+Use PowerPC General Purpose group optional instructions
+
+mpowerpc-gfxopt
+Target Report Mask(PPC_GFXOPT)
+Use PowerPC Graphics group optional instructions
+
+mmfcrf
+Target Report Mask(MFCRF)
+Use PowerPC V2.01 single field mfcr instruction
+
+mpopcntb
+Target Report Mask(POPCNTB)
+Use PowerPC V2.02 popcntb instruction
+
+mfprnd
+Target Report Mask(FPRND)
+Use PowerPC V2.02 floating point rounding instructions
+
+maltivec
+Target Report Mask(ALTIVEC)
+Use AltiVec instructions
+
+mmulhw
+Target Report Mask(MULHW)
+Use 4xx half-word multiply instructions
+
+mdlmzb
+Target Report Mask(DLMZB)
+Use 4xx string-search dlmzb instruction
+
+mmultiple
+Target Report Mask(MULTIPLE)
+Generate load/store multiple instructions
+
+mstring
+Target Report Mask(STRING)
+Generate string instructions for block moves
+
+mnew-mnemonics
+Target Report RejectNegative Mask(NEW_MNEMONICS)
+Use new mnemonics for PowerPC architecture
+
+mold-mnemonics
+Target Report RejectNegative InverseMask(NEW_MNEMONICS)
+Use old mnemonics for PowerPC architecture
+
+msoft-float
+Target Report RejectNegative Mask(SOFT_FLOAT)
+Do not use hardware floating point
+
+mhard-float
+Target Report RejectNegative InverseMask(SOFT_FLOAT, HARD_FLOAT)
+Use hardware floating point
+
+mno-update
+Target Report RejectNegative Mask(NO_UPDATE)
+Do not generate load/store with update instructions
+
+mupdate
+Target Report RejectNegative InverseMask(NO_UPDATE, UPDATE)
+Generate load/store with update instructions
+
+mno-fused-madd
+Target Report RejectNegative Mask(NO_FUSED_MADD)
+Do not generate fused multiply/add instructions
+
+mfused-madd
+Target Report RejectNegative InverseMask(NO_FUSED_MADD, FUSED_MADD)
+Generate fused multiply/add instructions
+
+msched-prolog
+Target Report Var(TARGET_SCHED_PROLOG) Init(1)
+Schedule the start and end of the procedure
+
+msched-epilog
+Target Undocumented Var(TARGET_SCHED_PROLOG) VarExists
+
+maix-struct-return
+Target Report RejectNegative Var(aix_struct_return)
+Return all structures in memory (AIX default)
+
+msvr4-struct-return
+Target Report RejectNegative Var(aix_struct_return,0) VarExists
+Return small structures in registers (SVR4 default)
+
+mxl-compat
+Target Report Var(TARGET_XL_COMPAT)
+Conform more closely to IBM XLC semantics
+
+mswdiv
+Target Report Var(swdiv)
+Generate software floating point divide for better throughput
+
+mno-fp-in-toc
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC)
+Do not place floating point constants in TOC
+
+mfp-in-toc
+Target Report RejectNegative Var(TARGET_NO_FP_IN_TOC,0)
+Place floating point constants in TOC
+
+mno-sum-in-toc
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC)
+Do not place symbol+offset constants in TOC
+
+msum-in-toc
+Target RejectNegative Var(TARGET_NO_SUM_IN_TOC,0) VarExists
+Place symbol+offset constants in TOC
+
+; Output only one TOC entry per module. Normally linking fails if
+; there are more than 16K unique variables/constants in an executable. With
+; this option, linking fails only if there are more than 16K modules, or
+; if there are more than 16K unique variables/constant in a single module.
+;
+; This is at the cost of having 2 extra loads and one extra store per
+; function, and one less allocable register.
+mminimal-toc
+Target Report Mask(MINIMAL_TOC)
+Use only one TOC entry per procedure
+
+mfull-toc
+Target Report
+Put everything in the regular TOC
+
+mvrsave
+Target Report Var(TARGET_ALTIVEC_VRSAVE)
+Generate VRSAVE instructions when generating AltiVec code
+
+mvrsave=
+Target RejectNegative Joined
+-mvrsave=yes/no Deprecated option. Use -mvrsave/-mno-vrsave instead
+
+misel
+Target Var(rs6000_isel)
+Generate isel instructions
+
+misel=
+Target RejectNegative Joined
+-misel=yes/no Deprecated option. Use -misel/-mno-isel instead
+
+mspe
+Target Var(rs6000_spe)
+Generate SPE SIMD instructions on E500
+
+mspe=
+Target RejectNegative Joined
+-mspe=yes/no Deprecated option. Use -mspe/-mno-spe instead
+
+mdebug=
+Target RejectNegative Joined
+-mdebug= Enable debug output
+
+mabi=
+Target RejectNegative Joined
+-mabi= Specify ABI to use
+
+mcpu=
+Target RejectNegative Joined
+-mcpu= Use features of and schedule code for given CPU
+
+mtune=
+Target RejectNegative Joined
+-mtune= Schedule code for given CPU
+
+mtraceback=
+Target RejectNegative Joined
+-mtraceback= Select full, part, or no traceback table
+
+mlongcall
+Target Report Var(rs6000_default_long_calls)
+Avoid all range limits on call instructions
+
+mwarn-altivec-long
+Target Var(rs6000_warn_altivec_long) Init(1)
+Warn about deprecated 'vector long ...' AltiVec type usage
+
+mfloat-gprs=
+Target RejectNegative Joined
+-mfloat-gprs= Select GPR floating point method
+
+mlong-double-
+Target RejectNegative Joined UInteger
+-mlong-double-<n> Specify size of long double (64 or 128 bits)
+
+msched-costly-dep=
+Target RejectNegative Joined
+Determine which dependences between insns are considered costly
+
+minsert-sched-nops=
+Target RejectNegative Joined
+Specify which post scheduling nop insertion scheme to apply
+
+malign-
+Target RejectNegative Joined
+Specify alignment of structure fields default/natural
+
+mprioritize-restricted-insns=
+Target RejectNegative Joined UInteger Var(rs6000_sched_restricted_insns_priority)
+Specify scheduling priority for dispatch slot restricted insns
diff --git a/contrib/gcc/config/rs6000/rs64.md b/contrib/gcc/config/rs6000/rs64.md
index 4d99875..71ec61d 100644
--- a/contrib/gcc/config/rs6000/rs64.md
+++ b/contrib/gcc/config/rs6000/rs64.md
@@ -1,5 +1,5 @@
;; Scheduling description for IBM RS64 processors.
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -15,8 +15,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_automaton "rs64,rs64fp")
(define_cpu_unit "iu_rs64" "rs64")
@@ -31,7 +31,7 @@
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
-(define_insn_reservation "rs64a-store" 1
+(define_insn_reservation "rs64a-store" 2
(and (eq_attr "type" "store,store_ux,store_u,fpstore,fpstore_ux,fpstore_u")
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
@@ -41,11 +41,26 @@
(eq_attr "cpu" "rs64a"))
"lsu_rs64")
+(define_insn_reservation "rs64a-llsc" 2
+ (and (eq_attr "type" "load_l,store_c")
+ (eq_attr "cpu" "rs64a"))
+ "lsu_rs64")
+
(define_insn_reservation "rs64a-integer" 1
(and (eq_attr "type" "integer,insert_word")
(eq_attr "cpu" "rs64a"))
"iu_rs64")
+(define_insn_reservation "rs64a-two" 1
+ (and (eq_attr "type" "two")
+ (eq_attr "cpu" "rs64a"))
+ "iu_rs64,iu_rs64")
+
+(define_insn_reservation "rs64a-three" 1
+ (and (eq_attr "type" "three")
+ (eq_attr "cpu" "rs64a"))
+ "iu_rs64,iu_rs64,iu_rs64")
+
(define_insn_reservation "rs64a-imul" 20
(and (eq_attr "type" "imul,imul_compare")
(eq_attr "cpu" "rs64a"))
@@ -126,3 +141,13 @@
(eq_attr "cpu" "rs64a"))
"bpu_rs64")
+(define_insn_reservation "rs64a-isync" 6
+ (and (eq_attr "type" "isync")
+ (eq_attr "cpu" "rs64a"))
+ "bpu_rs64")
+
+(define_insn_reservation "rs64a-sync" 1
+ (and (eq_attr "type" "sync")
+ (eq_attr "cpu" "rs64a"))
+ "lsu_rs64")
+
diff --git a/contrib/gcc/config/rs6000/rtems.h b/contrib/gcc/config/rs6000/rtems.h
index d83e1eb..7c49186 100644
--- a/contrib/gcc/config/rs6000/rtems.h
+++ b/contrib/gcc/config/rs6000/rtems.h
@@ -1,5 +1,5 @@
/* Definitions for rtems targeting a PowerPC using elf.
- Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2005
+ Copyright (C) 1996, 1997, 2000, 2001, 2002, 2003, 2004, 2005
Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Specify predefined symbols in preprocessor. */
diff --git a/contrib/gcc/config/rs6000/secureplt.h b/contrib/gcc/config/rs6000/secureplt.h
new file mode 100644
index 0000000..a02af8d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/secureplt.h
@@ -0,0 +1,21 @@
+/* Default to -msecure-plt.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#define CC1_SECURE_PLT_DEFAULT_SPEC "-msecure-plt"
diff --git a/contrib/gcc/config/rs6000/sfp-machine.h b/contrib/gcc/config/rs6000/sfp-machine.h
new file mode 100644
index 0000000..29173e2
--- /dev/null
+++ b/contrib/gcc/config/rs6000/sfp-machine.h
@@ -0,0 +1,63 @@
+#define _FP_W_TYPE_SIZE 32
+#define _FP_W_TYPE unsigned long
+#define _FP_WS_TYPE signed long
+#define _FP_I_TYPE long
+
+#define _FP_MUL_MEAT_S(R,X,Y) \
+ _FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_D(R,X,Y) \
+ _FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
+#define _FP_MUL_MEAT_Q(R,X,Y) \
+ _FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
+
+#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
+#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
+#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
+
+#define _FP_NANFRAC_S ((_FP_QNANBIT_S << 1) - 1)
+#define _FP_NANFRAC_D ((_FP_QNANBIT_D << 1) - 1), -1
+#define _FP_NANFRAC_Q ((_FP_QNANBIT_Q << 1) - 1), -1, -1, -1
+#define _FP_NANSIGN_S 0
+#define _FP_NANSIGN_D 0
+#define _FP_NANSIGN_Q 0
+
+#define _FP_KEEPNANFRACP 1
+
+/* Someone please check this. */
+#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
+ do { \
+ if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
+ { \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R,Y); \
+ } \
+ else \
+ { \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R,X); \
+ } \
+ R##_c = FP_CLS_NAN; \
+ } while (0)
+
+#define __LITTLE_ENDIAN 1234
+#define __BIG_ENDIAN 4321
+
+#if defined __BIG_ENDIAN__ || defined _BIG_ENDIAN
+# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
+# error "Both BIG_ENDIAN and LITTLE_ENDIAN defined!"
+# endif
+# define __BYTE_ORDER __BIG_ENDIAN
+#else
+# if defined __LITTLE_ENDIAN__ || defined _LITTLE_ENDIAN
+# define __BYTE_ORDER __LITTLE_ENDIAN
+# else
+# error "Cannot determine current byte order"
+# endif
+#endif
+
+
+/* Define ALIASNAME as a strong alias for NAME. */
+# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
+# define _strong_alias(name, aliasname) \
+ extern __typeof (name) aliasname __attribute__ ((alias (#name)));
diff --git a/contrib/gcc/config/rs6000/sol-ci.asm b/contrib/gcc/config/rs6000/sol-ci.asm
index cc97b0a..35e3b8e 100644
--- a/contrib/gcc/config/rs6000/sol-ci.asm
+++ b/contrib/gcc/config/rs6000/sol-ci.asm
@@ -23,8 +23,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/sol-cn.asm b/contrib/gcc/config/rs6000/sol-cn.asm
index 673540f..8546834 100644
--- a/contrib/gcc/config/rs6000/sol-cn.asm
+++ b/contrib/gcc/config/rs6000/sol-cn.asm
@@ -23,8 +23,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program; see the file COPYING. If not, write to
-# the Free Software Foundation, 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston, MA 02110-1301, USA.
#
# As a special exception, if you link this library with files
# compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/rs6000/spe.h b/contrib/gcc/config/rs6000/spe.h
index 878fc72..4e2d7f6 100644
--- a/contrib/gcc/config/rs6000/spe.h
+++ b/contrib/gcc/config/rs6000/spe.h
@@ -1,5 +1,5 @@
/* PowerPC E500 user include file.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
Contributed by Aldy Hernandez (aldyh@redhat.com).
This file is part of GCC.
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* As a special exception, if you include this header file into source
files compiled by GCC, this header file does not by itself cause
diff --git a/contrib/gcc/config/rs6000/spe.md b/contrib/gcc/config/rs6000/spe.md
index 306accd..7d05e08 100644
--- a/contrib/gcc/config/rs6000/spe.md
+++ b/contrib/gcc/config/rs6000/spe.md
@@ -1,5 +1,5 @@
;; e500 SPE description
-;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Aldy Hernandez (aldy@quesejoda.com)
;; This file is part of GCC.
@@ -16,12 +16,24 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the
-;; Free Software Foundation, 59 Temple Place - Suite 330, Boston,
-;; MA 02111-1307, USA.
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
(define_constants
[(SPE_ACC_REGNO 111)
- (SPEFSCR_REGNO 112)])
+ (SPEFSCR_REGNO 112)
+
+ (CMPDFEQ_GPR 1006)
+ (TSTDFEQ_GPR 1007)
+ (CMPDFGT_GPR 1008)
+ (TSTDFGT_GPR 1009)
+ (CMPDFLT_GPR 1010)
+ (TSTDFLT_GPR 1011)
+ (E500_CR_IOR_COMPARE 1012)
+ ])
+
+;; Modes using a 64-bit register.
+(define_mode_macro SPE64 [DF V4HI V2SF V1DI V2SI])
(define_insn "*negsf2_gpr"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
@@ -76,6 +88,22 @@
"efsdiv %0,%1,%2"
[(set_attr "type" "vecfdiv")])
+;; Floating point conversion instructions.
+
+(define_insn "fixuns_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (unsigned_fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdctuiz %0,%1"
+ [(set_attr "type" "fp")])
+
+(define_insn "spe_extendsfdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (float_extend:DF (match_operand:SF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdcfs %0,%1"
+ [(set_attr "type" "fp")])
+
(define_insn "spe_fixuns_truncsfsi2"
[(set (match_operand:SI 0 "gpc_reg_operand" "=r")
(unsigned_fix:SI (match_operand:SF 1 "gpc_reg_operand" "r")))]
@@ -90,6 +118,13 @@
"efsctsiz %0,%1"
[(set_attr "type" "fp")])
+(define_insn "spe_fix_truncdfsi2"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
+ (fix:SI (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdctsiz %0,%1"
+ [(set_attr "type" "fp")])
+
(define_insn "spe_floatunssisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
(unsigned_float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
@@ -97,6 +132,13 @@
"efscfui %0,%1"
[(set_attr "type" "fp")])
+(define_insn "spe_floatunssidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (unsigned_float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdcfui %0,%1"
+ [(set_attr "type" "fp")])
+
(define_insn "spe_floatsisf2"
[(set (match_operand:SF 0 "gpc_reg_operand" "=r")
(float:SF (match_operand:SI 1 "gpc_reg_operand" "r")))]
@@ -104,6 +146,12 @@
"efscfsi %0,%1"
[(set_attr "type" "fp")])
+(define_insn "spe_floatsidf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (float:DF (match_operand:SI 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdcfsi %0,%1"
+ [(set_attr "type" "fp")])
;; SPE SIMD instructions
@@ -2147,6 +2195,165 @@
[(set_attr "type" "vecstore")
(set_attr "length" "4")])
+;; Double-precision floating point instructions.
+
+;; FIXME: Add o=r option.
+(define_insn "*frob_df_di"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=r,r")
+ (subreg:DF (match_operand:DI 1 "input_operand" "r,m") 0))]
+ "TARGET_E500_DOUBLE"
+ "@
+ evmergelo %0,%1,%L1
+ evldd%X1 %0,%y1")
+
+(define_insn "*frob_di_df"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=&r")
+ (subreg:DI (match_operand:DF 1 "input_operand" "r") 0))]
+ "TARGET_E500_DOUBLE"
+ "evmergehi %0,%1,%1\;mr %L0,%1"
+ [(set_attr "length" "8")])
+
+(define_insn "*frob_di_df_2"
+ [(set (subreg:DF (match_operand:DI 0 "register_operand" "=&r,r") 0)
+ (match_operand:DF 1 "input_operand" "r,m"))]
+ "TARGET_E500_DOUBLE"
+ "*
+{
+ switch (which_alternative)
+ {
+ default:
+ gcc_unreachable ();
+ case 0:
+ return \"evmergehi %0,%1,%1\;mr %L0,%1\";
+ case 1:
+ /* If the address is not offsettable we need to load the whole
+ doubleword into a 64-bit register and then copy the high word
+ to form the correct output layout. */
+ if (!offsettable_nonstrict_memref_p (operands[1]))
+ return \"evldd%X1 %L0,%y1\;evmergehi %0,%L0,%L0\";
+ /* If the low-address word is used in the address, we must load
+ it last. Otherwise, load it first. Note that we cannot have
+ auto-increment in that case since the address register is
+ known to be dead. */
+ if (refers_to_regno_p (REGNO (operands[0]), REGNO (operands[0]) + 1,
+ operands[1], 0))
+ return \"{l|lwz} %L0,%L1\;{l|lwz} %0,%1\";
+ else
+ return \"{l%U1%X1|lwz%U1%X1} %0,%1\;{l|lwz} %L0,%L1\";
+ }
+}"
+ [(set_attr "length" "8,8")])
+
+(define_insn "*mov_si<mode>_e500_subreg0"
+ [(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,&r") 0)
+ (match_operand:SI 1 "input_operand" "r,m"))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ evmergelo %0,%1,%0
+ evmergelohi %0,%0,%0\;{l%U1%X1|lwz%U1%X1} %0,%1\;evmergelohi %0,%0,%0")
+
+;; ??? Could use evstwwe for memory stores in some cases, depending on
+;; the offset.
+(define_insn "*mov_si<mode>_e500_subreg0_2"
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+ (subreg:SI (match_operand:SPE64 1 "register_operand" "+r,&r") 0))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ evmergehi %0,%0,%1
+ evmergelohi %1,%1,%1\;{st%U0%X0|stw%U0%X0} %1,%0")
+
+(define_insn "*mov_si<mode>_e500_subreg4"
+ [(set (subreg:SI (match_operand:SPE64 0 "register_operand" "+r,r") 4)
+ (match_operand:SI 1 "input_operand" "r,m"))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ mr %0,%1
+ {l%U1%X1|lwz%U1%X1} %0,%1")
+
+(define_insn "*mov_si<mode>_e500_subreg4_2"
+ [(set (match_operand:SI 0 "rs6000_nonimmediate_operand" "+r,m")
+ (subreg:SI (match_operand:SPE64 1 "register_operand" "r,r") 4))]
+ "(TARGET_E500_DOUBLE && <MODE>mode == DFmode) || (TARGET_SPE && <MODE>mode != DFmode)"
+ "@
+ mr %0,%1
+ {st%U0%X0|stw%U0%X0} %1,%0")
+
+;; FIXME: Allow r=CONST0.
+(define_insn "*movdf_e500_double"
+ [(set (match_operand:DF 0 "rs6000_nonimmediate_operand" "=r,r,m")
+ (match_operand:DF 1 "input_operand" "r,m,r"))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE
+ && (gpc_reg_operand (operands[0], DFmode)
+ || gpc_reg_operand (operands[1], DFmode))"
+ "*
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return \"evor %0,%1,%1\";
+ case 1:
+ return \"evldd%X1 %0,%y1\";
+ case 2:
+ return \"evstdd%X0 %1,%y0\";
+ default:
+ gcc_unreachable ();
+ }
+ }"
+ [(set_attr "type" "*,vecload,vecstore")
+ (set_attr "length" "*,*,*")])
+
+(define_insn "spe_truncdfsf2"
+ [(set (match_operand:SF 0 "gpc_reg_operand" "=r")
+ (float_truncate:SF (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efscfd %0,%1")
+
+(define_insn "spe_absdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (abs:DF (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdabs %0,%1")
+
+(define_insn "spe_nabsdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (neg:DF (abs:DF (match_operand:DF 1 "gpc_reg_operand" "r"))))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdnabs %0,%1")
+
+(define_insn "spe_negdf2"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (neg:DF (match_operand:DF 1 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdneg %0,%1")
+
+(define_insn "spe_adddf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (plus:DF (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdadd %0,%1,%2")
+
+(define_insn "spe_subdf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (minus:DF (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdsub %0,%1,%2")
+
+(define_insn "spe_muldf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (mult:DF (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efdmul %0,%1,%2")
+
+(define_insn "spe_divdf3"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=r")
+ (div:DF (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r")))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE"
+ "efddiv %0,%1,%2")
+
;; Vector move instructions.
(define_expand "movv2si"
@@ -2169,7 +2376,7 @@
case 1: return \"evldd%X1 %0,%y1\";
case 2: return \"evor %0,%1,%1\";
case 3: return output_vec_const_move (operands);
- default: abort ();
+ default: gcc_unreachable ();
}
}"
[(set_attr "type" "vecload,vecstore,*,*")
@@ -2210,15 +2417,16 @@
"{ rs6000_emit_move (operands[0], operands[1], V4HImode); DONE; }")
(define_insn "*movv4hi_internal"
- [(set (match_operand:V4HI 0 "nonimmediate_operand" "=m,r,r")
- (match_operand:V4HI 1 "input_operand" "r,m,r"))]
+ [(set (match_operand:V4HI 0 "nonimmediate_operand" "=m,r,r,r")
+ (match_operand:V4HI 1 "input_operand" "r,m,r,W"))]
"TARGET_SPE
&& (gpc_reg_operand (operands[0], V4HImode)
|| gpc_reg_operand (operands[1], V4HImode))"
"@
evstdd%X0 %1,%y0
evldd%X1 %0,%y1
- evor %0,%1,%1"
+ evor %0,%1,%1
+ evxor %0,%0,%0"
[(set_attr "type" "vecload")])
(define_expand "movv2sf"
@@ -2458,14 +2666,14 @@
;; FP comparison stuff.
;; Flip the GT bit.
-(define_insn "e500_flip_eq_bit"
+(define_insn "e500_flip_gt_bit"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
+ (unspec:CCFP
+ [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
"!TARGET_FPRS && TARGET_HARD_FLOAT"
"*
{
- return output_e500_flip_eq_bit (operands[0], operands[1]);
+ return output_e500_flip_gt_bit (operands[0], operands[1]);
}"
[(set_attr "type" "cr_logical")])
@@ -2475,60 +2683,132 @@
(define_insn "cmpsfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1000))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1000))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmpeq %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsfeq_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1001))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1001))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststeq %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmpsfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1002))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1002))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmpgt %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsfgt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1003))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1003))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststgt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
(define_insn "cmpsflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1004))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1004))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && !flag_unsafe_math_optimizations"
"efscmplt %0,%1,%2"
[(set_attr "type" "veccmp")])
(define_insn "tstsflt_gpr"
[(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
- (unspec:CCFP
- [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
- (match_operand:SF 2 "gpc_reg_operand" "r"))]
- 1005))]
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:SF 1 "gpc_reg_operand" "r")
+ (match_operand:SF 2 "gpc_reg_operand" "r"))]
+ 1005))]
"TARGET_HARD_FLOAT && !TARGET_FPRS && flag_unsafe_math_optimizations"
"efststlt %0,%1,%2"
[(set_attr "type" "veccmpsimple")])
+
+;; Same thing, but for double-precision.
+
+(define_insn "cmpdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpeq %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfeq_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFEQ_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtsteq %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmpgt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdfgt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFGT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstgt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+(define_insn "cmpdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ CMPDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && !flag_unsafe_math_optimizations"
+ "efdcmplt %0,%1,%2"
+ [(set_attr "type" "veccmp")])
+
+(define_insn "tstdflt_gpr"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP
+ [(compare:CCFP (match_operand:DF 1 "gpc_reg_operand" "r")
+ (match_operand:DF 2 "gpc_reg_operand" "r"))]
+ TSTDFLT_GPR))]
+ "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
+ "efdtstlt %0,%1,%2"
+ [(set_attr "type" "veccmpsimple")])
+
+;; Like cceq_ior_compare, but compare the GT bits.
+(define_insn "e500_cr_ior_compare"
+ [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ (unspec:CCFP [(match_operand 1 "cc_reg_operand" "y")
+ (match_operand 2 "cc_reg_operand" "y")]
+ E500_CR_IOR_COMPARE))]
+ "TARGET_E500"
+ "cror 4*%0+gt,4*%1+gt,4*%2+gt"
+ [(set_attr "type" "cr_logical")])
diff --git a/contrib/gcc/config/rs6000/sync.md b/contrib/gcc/config/rs6000/sync.md
new file mode 100644
index 0000000..b716647
--- /dev/null
+++ b/contrib/gcc/config/rs6000/sync.md
@@ -0,0 +1,625 @@
+;; Machine description for PowerPC synchronization instructions.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;; Contributed by Geoffrey Keating.
+
+;; This file is part of GCC.
+
+;; GCC is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published
+;; by the Free Software Foundation; either version 2, or (at your
+;; option) any later version.
+
+;; GCC is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the
+;; Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+(define_mode_attr larx [(SI "lwarx") (DI "ldarx")])
+(define_mode_attr stcx [(SI "stwcx.") (DI "stdcx.")])
+
+(define_code_macro FETCHOP [plus minus ior xor and])
+(define_code_attr fetchop_name
+ [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")])
+(define_code_attr fetchop_pred
+ [(plus "add_operand") (minus "gpc_reg_operand")
+ (ior "logical_operand") (xor "logical_operand") (and "and_operand")])
+(define_code_attr fetchopsi_constr
+ [(plus "rIL") (minus "r") (ior "rKL") (xor "rKL") (and "rTKL")])
+(define_code_attr fetchopdi_constr
+ [(plus "rIL") (minus "r") (ior "rKJF") (xor "rKJF") (and "rSTKJ")])
+
+(define_expand "memory_barrier"
+ [(set (mem:BLK (match_dup 0))
+ (unspec:BLK [(mem:BLK (match_dup 0))] UNSPEC_SYNC))]
+ ""
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*sync_internal"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec:BLK [(match_operand:BLK 1 "" "")] UNSPEC_SYNC))]
+ ""
+ "{dcs|sync}"
+ [(set_attr "type" "sync")])
+
+(define_insn "load_locked_<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=r")
+ (unspec_volatile:GPR
+ [(match_operand:GPR 1 "memory_operand" "Z")] UNSPECV_LL))]
+ "TARGET_POWERPC"
+ "<larx> %0,%y1"
+ [(set_attr "type" "load_l")])
+
+(define_insn "store_conditional_<mode>"
+ [(set (match_operand:CC 0 "cc_reg_operand" "=x")
+ (unspec_volatile:CC [(const_int 0)] UNSPECV_SC))
+ (set (match_operand:GPR 1 "memory_operand" "=Z")
+ (match_operand:GPR 2 "gpc_reg_operand" "r"))]
+ "TARGET_POWERPC"
+ "<stcx> %2,%y1"
+ [(set_attr "type" "store_c")])
+
+(define_insn_and_split "sync_compare_and_swap<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (match_operand:GPR 1 "memory_operand" "+Z"))
+ (set (match_dup 1)
+ (unspec:GPR
+ [(match_operand:GPR 2 "reg_or_short_operand" "rI")
+ (match_operand:GPR 3 "gpc_reg_operand" "r")]
+ UNSPEC_CMPXCHG))
+ (clobber (match_scratch:GPR 4 "=&r"))
+ (clobber (match_scratch:CC 5 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_compare_and_swap (operands[0], operands[1], operands[2],
+ operands[3], operands[4]);
+ DONE;
+})
+
+(define_expand "sync_compare_and_swaphi"
+ [(match_operand:HI 0 "gpc_reg_operand" "")
+ (match_operand:HI 1 "memory_operand" "")
+ (match_operand:HI 2 "gpc_reg_operand" "")
+ (match_operand:HI 3 "gpc_reg_operand" "")]
+ "TARGET_POWERPC"
+{
+ rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
+ operands[2], operands[3]);
+ DONE;
+})
+
+(define_expand "sync_compare_and_swapqi"
+ [(match_operand:QI 0 "gpc_reg_operand" "")
+ (match_operand:QI 1 "memory_operand" "")
+ (match_operand:QI 2 "gpc_reg_operand" "")
+ (match_operand:QI 3 "gpc_reg_operand" "")]
+ "TARGET_POWERPC"
+{
+ rs6000_expand_compare_and_swapqhi (operands[0], operands[1],
+ operands[2], operands[3]);
+ DONE;
+})
+
+(define_insn_and_split "sync_compare_and_swapqhi_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+ (match_operand:SI 4 "memory_operand" "+Z"))
+ (set (match_dup 4)
+ (unspec:SI
+ [(match_operand:SI 1 "gpc_reg_operand" "r")
+ (match_operand:SI 2 "gpc_reg_operand" "r")
+ (match_operand:SI 3 "gpc_reg_operand" "r")]
+ UNSPEC_CMPXCHG))
+ (clobber (match_scratch:SI 5 "=&r"))
+ (clobber (match_scratch:CC 6 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_compare_and_swapqhi (operands[0], operands[1],
+ operands[2], operands[3], operands[4],
+ operands[5]);
+ DONE;
+})
+
+(define_insn_and_split "sync_lock_test_and_set<mode>"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (match_operand:GPR 1 "memory_operand" "+Z"))
+ (set (match_dup 1)
+ (unspec:GPR
+ [(match_operand:GPR 2 "reg_or_short_operand" "rL")]
+ UNSPEC_XCHG))
+ (clobber (match_scratch:GPR 3 "=&r"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_lock_test_and_set (operands[0], operands[1], operands[2],
+ operands[3]);
+ DONE;
+})
+
+(define_expand "sync_<fetchop_name><mode>"
+ [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
+ (unspec:INT1
+ [(FETCHOP:INT1 (match_dup 0)
+ (match_operand:INT1 1 "<fetchop_pred>" ""))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (<CODE>, <MODE>mode, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_<fetchop_name>si_internal"
+ [(set (match_operand:SI 0 "memory_operand" "+Z")
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 0)
+ (match_operand:SI 1 "<fetchop_pred>" "<fetchopsi_constr>"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 2 "=&b"))
+ (clobber (match_scratch:CC 3 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, operands[2]);
+ DONE;
+})
+
+(define_insn_and_split "*sync_<fetchop_name>di_internal"
+ [(set (match_operand:DI 0 "memory_operand" "+Z")
+ (unspec:DI
+ [(FETCHOP:DI (match_dup 0)
+ (match_operand:DI 1 "<fetchop_pred>" "<fetchopdi_constr>"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:DI 2 "=&b"))
+ (clobber (match_scratch:CC 3 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, operands[2]);
+ DONE;
+})
+
+(define_expand "sync_nand<mode>"
+ [(parallel [(set (match_operand:INT1 0 "memory_operand" "")
+ (unspec:INT1
+ [(and:INT1 (not:INT1 (match_dup 0))
+ (match_operand:INT1 1 "gpc_reg_operand" ""))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (AND, <MODE>mode,
+ gen_rtx_NOT (<MODE>mode, operands[0]),
+ operands[1],
+ NULL_RTX, NULL_RTX, true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_nand<mode>_internal"
+ [(set (match_operand:GPR 0 "memory_operand" "+Z")
+ (unspec:GPR
+ [(and:GPR (not:GPR (match_dup 0))
+ (match_operand:GPR 1 "gpc_reg_operand" "r"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:GPR 2 "=&r"))
+ (clobber (match_scratch:CC 3 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (NOT, operands[0], operands[1],
+ NULL_RTX, NULL_RTX, operands[2]);
+ DONE;
+})
+
+(define_expand "sync_old_<fetchop_name><mode>"
+ [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
+ (match_operand:INT1 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec:INT1
+ [(FETCHOP:INT1 (match_dup 1)
+ (match_operand:INT1 2 "<fetchop_pred>" ""))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
+ operands[0], NULL_RTX, true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_old_<fetchop_name>si_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+ (match_operand:SI 1 "memory_operand" "+Z"))
+ (set (match_dup 1)
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 1)
+ (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 3 "=&b"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
+ operands[0], NULL_RTX, operands[3]);
+ DONE;
+})
+
+(define_insn_and_split "*sync_old_<fetchop_name>di_internal"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
+ (match_operand:DI 1 "memory_operand" "+Z"))
+ (set (match_dup 1)
+ (unspec:DI
+ [(FETCHOP:DI (match_dup 1)
+ (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:DI 3 "=&b"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
+ operands[0], NULL_RTX, operands[3]);
+ DONE;
+})
+
+(define_expand "sync_old_nand<mode>"
+ [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
+ (match_operand:INT1 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec:INT1
+ [(and:INT1 (not:INT1 (match_dup 1))
+ (match_operand:INT1 2 "gpc_reg_operand" ""))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (AND, <MODE>mode,
+ gen_rtx_NOT (<MODE>mode, operands[1]),
+ operands[2],
+ operands[0], NULL_RTX, true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_old_nand<mode>_internal"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (match_operand:GPR 1 "memory_operand" "+Z"))
+ (set (match_dup 1)
+ (unspec:GPR
+ [(and:GPR (not:GPR (match_dup 1))
+ (match_operand:GPR 2 "gpc_reg_operand" "r"))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:GPR 3 "=&r"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (NOT, operands[1], operands[2],
+ operands[0], NULL_RTX, operands[3]);
+ DONE;
+})
+
+(define_expand "sync_new_<fetchop_name><mode>"
+ [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
+ (FETCHOP:INT1
+ (match_operand:INT1 1 "memory_operand" "")
+ (match_operand:INT1 2 "<fetchop_pred>" "")))
+ (set (match_dup 1)
+ (unspec:INT1
+ [(FETCHOP:INT1 (match_dup 1) (match_dup 2))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (<CODE>, <MODE>mode, operands[1], operands[2],
+ NULL_RTX, operands[0], true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_new_<fetchop_name>si_internal"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=&r")
+ (FETCHOP:SI
+ (match_operand:SI 1 "memory_operand" "+Z")
+ (match_operand:SI 2 "<fetchop_pred>" "<fetchopsi_constr>")))
+ (set (match_dup 1)
+ (unspec:SI
+ [(FETCHOP:SI (match_dup 1) (match_dup 2))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:SI 3 "=&b"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
+ NULL_RTX, operands[0], operands[3]);
+ DONE;
+})
+
+(define_insn_and_split "*sync_new_<fetchop_name>di_internal"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=&r")
+ (FETCHOP:DI
+ (match_operand:DI 1 "memory_operand" "+Z")
+ (match_operand:DI 2 "<fetchop_pred>" "<fetchopdi_constr>")))
+ (set (match_dup 1)
+ (unspec:DI
+ [(FETCHOP:DI (match_dup 1) (match_dup 2))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:DI 3 "=&b"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (<CODE>, operands[1], operands[2],
+ NULL_RTX, operands[0], operands[3]);
+ DONE;
+})
+
+(define_expand "sync_new_nand<mode>"
+ [(parallel [(set (match_operand:INT1 0 "gpc_reg_operand" "")
+ (and:INT1
+ (not:INT1 (match_operand:INT1 1 "memory_operand" ""))
+ (match_operand:INT1 2 "gpc_reg_operand" "")))
+ (set (match_dup 1)
+ (unspec:INT1
+ [(and:INT1 (not:INT1 (match_dup 1)) (match_dup 2))]
+ UNSPEC_ATOMIC))
+ (clobber (scratch:INT1))
+ (clobber (scratch:CC))])]
+ "TARGET_POWERPC"
+ "
+{
+ if (<MODE>mode != SImode && <MODE>mode != DImode)
+ {
+ if (PPC405_ERRATUM77)
+ FAIL;
+ rs6000_emit_sync (AND, <MODE>mode,
+ gen_rtx_NOT (<MODE>mode, operands[1]),
+ operands[2],
+ NULL_RTX, operands[0], true);
+ DONE;
+ }
+}")
+
+(define_insn_and_split "*sync_new_nand<mode>_internal"
+ [(set (match_operand:GPR 0 "gpc_reg_operand" "=&r")
+ (and:GPR
+ (not:GPR (match_operand:GPR 1 "memory_operand" "+Z"))
+ (match_operand:GPR 2 "gpc_reg_operand" "r")))
+ (set (match_dup 1)
+ (unspec:GPR
+ [(and:GPR (not:GPR (match_dup 1)) (match_dup 2))]
+ UNSPEC_ATOMIC))
+ (clobber (match_scratch:GPR 3 "=&r"))
+ (clobber (match_scratch:CC 4 "=&x"))]
+ "TARGET_POWERPC"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rs6000_split_atomic_op (NOT, operands[1], operands[2],
+ NULL_RTX, operands[0], operands[3]);
+ DONE;
+})
+
+; and<mode> without cr0 clobber to avoid generation of additional clobber
+; in atomic splitters causing internal consistency failure.
+; cr0 already clobbered by larx/stcx.
+(define_insn "*atomic_andsi"
+ [(set (match_operand:SI 0 "gpc_reg_operand" "=r,r,r,r")
+ (unspec:SI [(match_operand:SI 1 "gpc_reg_operand" "%r,r,r,r")
+ (match_operand:SI 2 "and_operand" "?r,T,K,L")]
+ UNSPEC_AND))]
+ ""
+ "@
+ and %0,%1,%2
+ {rlinm|rlwinm} %0,%1,0,%m2,%M2
+ {andil.|andi.} %0,%1,%b2
+ {andiu.|andis.} %0,%1,%u2"
+ [(set_attr "type" "*,*,compare,compare")])
+
+(define_insn "*atomic_anddi"
+ [(set (match_operand:DI 0 "gpc_reg_operand" "=r,r,r,r,r")
+ (unspec:DI [(match_operand:DI 1 "gpc_reg_operand" "%r,r,r,r,r")
+ (match_operand:DI 2 "and_operand" "?r,S,T,K,J")]
+ UNSPEC_AND))]
+ "TARGET_POWERPC64"
+ "@
+ and %0,%1,%2
+ rldic%B2 %0,%1,0,%S2
+ rlwinm %0,%1,0,%m2,%M2
+ andi. %0,%1,%b2
+ andis. %0,%1,%u2"
+ [(set_attr "type" "*,*,*,compare,compare")
+ (set_attr "length" "4,4,4,4,4")])
+
+; the sync_*_internal patterns all have these operands:
+; 0 - memory location
+; 1 - operand
+; 2 - value in memory after operation
+; 3 - value in memory immediately before operation
+
+(define_insn "*sync_addshort_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
+ (ior:SI (and:SI (plus:SI (match_operand:SI 0 "memory_operand" "+Z")
+ (match_operand:SI 1 "add_operand" "rI"))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (and:SI (not:SI (match_dup 4)) (match_dup 0))))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
+ (set (match_dup 0)
+ (unspec:SI [(ior:SI (and:SI (plus:SI (match_dup 0) (match_dup 1))
+ (match_dup 4))
+ (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
+ UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 5 "=&x"))
+ (clobber (match_scratch:SI 6 "=&r"))]
+ "TARGET_POWERPC && !PPC405_ERRATUM77"
+ "lwarx %3,%y0\n\tadd%I1 %2,%3,%1\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
+ [(set_attr "length" "28")])
+
+(define_insn "*sync_subshort_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
+ (ior:SI (and:SI (minus:SI (match_operand:SI 0 "memory_operand" "+Z")
+ (match_operand:SI 1 "add_operand" "rI"))
+ (match_operand:SI 4 "gpc_reg_operand" "r"))
+ (and:SI (not:SI (match_dup 4)) (match_dup 0))))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
+ (set (match_dup 0)
+ (unspec:SI [(ior:SI (and:SI (minus:SI (match_dup 0) (match_dup 1))
+ (match_dup 4))
+ (and:SI (not:SI (match_dup 4)) (match_dup 0)))]
+ UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 5 "=&x"))
+ (clobber (match_scratch:SI 6 "=&r"))]
+ "TARGET_POWERPC && !PPC405_ERRATUM77"
+ "lwarx %3,%y0\n\tsubf %2,%1,%3\n\tandc %6,%3,%4\n\tand %2,%2,%4\n\tor %2,%2,%6\n\tstwcx. %2,%y0\n\tbne- $-24"
+ [(set_attr "length" "28")])
+
+(define_insn "*sync_andsi_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r,&r")
+ (and:SI (match_operand:SI 0 "memory_operand" "+Z,Z,Z,Z")
+ (match_operand:SI 1 "and_operand" "r,T,K,L")))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b,&b") (match_dup 0))
+ (set (match_dup 0)
+ (unspec:SI [(and:SI (match_dup 0) (match_dup 1))]
+ UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 4 "=&x,&x,&x,&x"))]
+ "TARGET_POWERPC && !PPC405_ERRATUM77"
+ "@
+ lwarx %3,%y0\n\tand %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
+ lwarx %3,%y0\n\trlwinm %2,%3,0,%m1,%M1\n\tstwcx. %2,%y0\n\tbne- $-12
+ lwarx %3,%y0\n\tandi. %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
+ lwarx %3,%y0\n\tandis. %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
+ [(set_attr "length" "16,16,16,16")])
+
+(define_insn "*sync_boolsi_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r,&r,&r")
+ (match_operator:SI 4 "boolean_or_operator"
+ [(match_operand:SI 0 "memory_operand" "+Z,Z,Z")
+ (match_operand:SI 1 "logical_operand" "r,K,L")]))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b,&b,&b") (match_dup 0))
+ (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 5 "=&x,&x,&x"))]
+ "TARGET_POWERPC && !PPC405_ERRATUM77"
+ "@
+ lwarx %3,%y0\n\t%q4 %2,%3,%1\n\tstwcx. %2,%y0\n\tbne- $-12
+ lwarx %3,%y0\n\t%q4i %2,%3,%b1\n\tstwcx. %2,%y0\n\tbne- $-12
+ lwarx %3,%y0\n\t%q4is %2,%3,%u1\n\tstwcx. %2,%y0\n\tbne- $-12"
+ [(set_attr "length" "16,16,16")])
+
+; This pattern could also take immediate values of operand 1,
+; since the non-NOT version of the operator is used; but this is not
+; very useful, since in practice operand 1 is a full 32-bit value.
+; Likewise, operand 5 is in practice either <= 2^16 or it is a register.
+(define_insn "*sync_boolcshort_internal"
+ [(set (match_operand:SI 2 "gpc_reg_operand" "=&r")
+ (match_operator:SI 4 "boolean_operator"
+ [(xor:SI (match_operand:SI 0 "memory_operand" "+Z")
+ (match_operand:SI 5 "logical_operand" "rK"))
+ (match_operand:SI 1 "gpc_reg_operand" "r")]))
+ (set (match_operand:SI 3 "gpc_reg_operand" "=&b") (match_dup 0))
+ (set (match_dup 0) (unspec:SI [(match_dup 4)] UNSPEC_SYNC_OP))
+ (clobber (match_scratch:CC 6 "=&x"))]
+ "TARGET_POWERPC && !PPC405_ERRATUM77"
+ "lwarx %3,%y0\n\txor%I2 %2,%3,%5\n\t%q4 %2,%2,%1\n\tstwcx. %2,%y0\n\tbne- $-16"
+ [(set_attr "length" "20")])
+
+(define_insn "isync"
+ [(set (mem:BLK (match_scratch 0 "X"))
+ (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_ISYNC))]
+ ""
+ "{ics|isync}"
+ [(set_attr "type" "isync")])
+
+(define_expand "sync_lock_release<mode>"
+ [(set (match_operand:INT 0 "memory_operand")
+ (match_operand:INT 1 "any_operand"))]
+ ""
+ "
+{
+ emit_insn (gen_lwsync ());
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+}")
+
+; Some AIX assemblers don't accept lwsync, so we use a .long.
+(define_insn "lwsync"
+ [(set (mem:BLK (match_scratch 0 "X"))
+ (unspec_volatile:BLK [(mem:BLK (match_scratch 1 "X"))] UNSPEC_LWSYNC))]
+ ""
+{
+ if (TARGET_NO_LWSYNC)
+ return "sync";
+ else
+ return ".long 0x7c2004ac";
+}
+ [(set_attr "type" "sync")])
+
diff --git a/contrib/gcc/config/rs6000/sysv4.h b/contrib/gcc/config/rs6000/sysv4.h
index d367aa8..0adde2b 100644
--- a/contrib/gcc/config/rs6000/sysv4.h
+++ b/contrib/gcc/config/rs6000/sysv4.h
@@ -1,6 +1,6 @@
/* Target definitions for GNU compiler for PowerPC running System V.4
Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2005 Free Software Foundation, Inc.
+ 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
Contributed by Cygnus Support.
This file is part of GCC.
@@ -17,10 +17,11 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
/* Header files should be C++ aware in general. */
+#undef NO_IMPLICIT_EXTERN_C
#define NO_IMPLICIT_EXTERN_C
/* Yes! We are ELF. */
@@ -46,24 +47,6 @@ enum rs6000_sdata_type {
extern enum rs6000_sdata_type rs6000_sdata;
-/* V.4/eabi switches. */
-#define MASK_NO_BITFIELD_TYPE 0x40000000 /* Set PCC_BITFIELD_TYPE_MATTERS to 0. */
-#define MASK_STRICT_ALIGN 0x20000000 /* Set STRICT_ALIGNMENT to 1. */
-#define MASK_RELOCATABLE 0x10000000 /* GOT pointers are PC relative. */
-#define MASK_EABI 0x08000000 /* Adhere to eabi, not System V spec. */
-#define MASK_LITTLE_ENDIAN 0x04000000 /* Target is little endian. */
-#define MASK_REGNAMES 0x02000000 /* Use alternate register names. */
-#define MASK_PROTOTYPE 0x01000000 /* Only prototyped fcns pass variable args. */
-#define MASK_NO_BITFIELD_WORD 0x00800000 /* Bitfields cannot cross word boundaries */
-
-#define TARGET_NO_BITFIELD_TYPE (target_flags & MASK_NO_BITFIELD_TYPE)
-#define TARGET_STRICT_ALIGN (target_flags & MASK_STRICT_ALIGN)
-#define TARGET_RELOCATABLE (target_flags & MASK_RELOCATABLE)
-#define TARGET_EABI (target_flags & MASK_EABI)
-#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
-#define TARGET_REGNAMES (target_flags & MASK_REGNAMES)
-#define TARGET_PROTOTYPE (target_flags & MASK_PROTOTYPE)
-#define TARGET_NO_BITFIELD_WORD (target_flags & MASK_NO_BITFIELD_WORD)
#define TARGET_TOC ((target_flags & MASK_64BIT) \
|| ((target_flags & (MASK_RELOCATABLE \
| MASK_MINIMAL_TOC)) \
@@ -76,91 +59,17 @@ extern enum rs6000_sdata_type rs6000_sdata;
#define TARGET_NO_TOC (! TARGET_TOC)
#define TARGET_NO_EABI (! TARGET_EABI)
-/* Strings provided by SUBTARGET_OPTIONS */
+#ifdef HAVE_AS_REL16
+#undef TARGET_SECURE_PLT
+#define TARGET_SECURE_PLT secure_plt
+#endif
+
extern const char *rs6000_abi_name;
extern const char *rs6000_sdata_name;
extern const char *rs6000_tls_size_string; /* For -mtls-size= */
-/* Override rs6000.h definition. */
-#undef SUBTARGET_OPTIONS
-#define SUBTARGET_OPTIONS \
- { "call-", &rs6000_abi_name, N_("Select ABI calling convention"), 0}, \
- { "sdata=", &rs6000_sdata_name, N_("Select method for sdata handling"), 0}, \
- { "tls-size=", &rs6000_tls_size_string, \
- N_("Specify bit size of immediate TLS offsets"), 0 }
-
#define SDATA_DEFAULT_SIZE 8
-/* Note, V.4 no longer uses a normal TOC, so make -mfull-toc, be just
- the same as -mminimal-toc. */
-/* Override rs6000.h definition. */
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- { "bit-align", -MASK_NO_BITFIELD_TYPE, \
- N_("Align to the base type of the bit-field") }, \
- { "no-bit-align", MASK_NO_BITFIELD_TYPE, \
- N_("Don't align to the base type of the bit-field") }, \
- { "strict-align", MASK_STRICT_ALIGN, \
- N_("Don't assume that unaligned accesses are handled by the system") }, \
- { "no-strict-align", -MASK_STRICT_ALIGN, \
- N_("Assume that unaligned accesses are handled by the system") }, \
- { "relocatable", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC, \
- N_("Produce code relocatable at runtime") }, \
- { "no-relocatable", -MASK_RELOCATABLE, \
- N_("Don't produce code relocatable at runtime") }, \
- { "relocatable-lib", MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC, \
- N_("Produce code relocatable at runtime") }, \
- { "no-relocatable-lib", -MASK_RELOCATABLE, \
- N_("Don't produce code relocatable at runtime") }, \
- { "little-endian", MASK_LITTLE_ENDIAN, \
- N_("Produce little endian code") }, \
- { "little", MASK_LITTLE_ENDIAN, \
- N_("Produce little endian code") }, \
- { "big-endian", -MASK_LITTLE_ENDIAN, \
- N_("Produce big endian code") }, \
- { "big", -MASK_LITTLE_ENDIAN, \
- N_("Produce big endian code") }, \
- { "no-toc", 0, N_("no description yet") }, \
- { "toc", MASK_MINIMAL_TOC, N_("no description yet") }, \
- { "full-toc", MASK_MINIMAL_TOC, N_("no description yet") }, \
- { "prototype", MASK_PROTOTYPE, \
- N_("Assume all variable arg functions are prototyped") }, \
- { "no-prototype", -MASK_PROTOTYPE, \
- N_("Non-prototyped functions might take a variable number of args") }, \
- { "no-traceback", 0, N_("no description yet") }, \
- { "eabi", MASK_EABI, N_("Use EABI") }, \
- { "no-eabi", -MASK_EABI, N_("Don't use EABI") }, \
- { "bit-word", -MASK_NO_BITFIELD_WORD, "" }, \
- { "no-bit-word", MASK_NO_BITFIELD_WORD, \
- N_("Do not allow bit-fields to cross word boundaries") }, \
- { "regnames", MASK_REGNAMES, \
- N_("Use alternate register names") }, \
- { "no-regnames", -MASK_REGNAMES, \
- N_("Don't use alternate register names") }, \
- { "sdata", 0, N_("no description yet") }, \
- { "no-sdata", 0, N_("no description yet") }, \
- { "sim", 0, \
- N_("Link with libsim.a, libc.a and sim-crt0.o") }, \
- { "ads", 0, \
- N_("Link with libads.a, libc.a and crt0.o") }, \
- { "yellowknife", 0, \
- N_("Link with libyk.a, libc.a and crt0.o") }, \
- { "mvme", 0, \
- N_("Link with libmvme.a, libc.a and crt0.o") }, \
- { "emb", 0, \
- N_("Set the PPC_EMB bit in the ELF flags header") }, \
- { "windiss", 0, N_("Use the WindISS simulator") }, \
- { "shlib", 0, N_("no description yet") }, \
- { "64", MASK_64BIT | MASK_POWERPC64 | MASK_POWERPC, \
- N_("Generate 64-bit code") }, \
- { "32", - (MASK_64BIT | MASK_POWERPC64), \
- N_("Generate 32-bit code") }, \
- EXTRA_SUBTARGET_SWITCHES \
- { "newlib", 0, N_("no description yet") },
-
-/* This is meant to be redefined in the host dependent files. */
-#define EXTRA_SUBTARGET_SWITCHES
-
/* Sometimes certain combinations of command options do not make sense
on a particular target machine. You can define a macro
`OVERRIDE_OPTIONS' to take account of this. This macro, if
@@ -196,7 +105,12 @@ do { \
else if (!strcmp (rs6000_abi_name, "freebsd")) \
rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "linux")) \
- rs6000_current_abi = ABI_V4; \
+ { \
+ if (TARGET_64BIT) \
+ rs6000_current_abi = ABI_AIX; \
+ else \
+ rs6000_current_abi = ABI_V4; \
+ } \
else if (!strcmp (rs6000_abi_name, "gnu")) \
rs6000_current_abi = ABI_V4; \
else if (!strcmp (rs6000_abi_name, "netbsd")) \
@@ -296,9 +210,17 @@ do { \
error ("-mcall-aixdesc must be big endian"); \
} \
\
+ if (TARGET_SECURE_PLT != secure_plt) \
+ { \
+ error ("-msecure-plt not supported by your assembler"); \
+ } \
+ \
/* Treat -fPIC the same as -mrelocatable. */ \
if (flag_pic > 1 && DEFAULT_ABI != ABI_AIX) \
- target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC | MASK_NO_FP_IN_TOC; \
+ { \
+ target_flags |= MASK_RELOCATABLE | MASK_MINIMAL_TOC; \
+ TARGET_NO_FP_IN_TOC = 1; \
+ } \
\
else if (TARGET_RELOCATABLE) \
flag_pic = 2; \
@@ -321,16 +243,15 @@ do { \
#undef PROCESSOR_DEFAULT
#define PROCESSOR_DEFAULT PROCESSOR_PPC750
+/* SVR4 only defined for PowerPC, so short-circuit POWER patterns. */
+#undef TARGET_POWER
+#define TARGET_POWER 0
+
#define FIXED_R2 1
/* System V.4 uses register 13 as a pointer to the small data area,
so it is not available to the normal user. */
#define FIXED_R13 1
-/* Size of the V.4 varargs area if needed. */
-/* Override rs6000.h definition. */
-#undef RS6000_VARARGS_AREA
-#define RS6000_VARARGS_AREA ((cfun->machine->sysv_varargs_p) ? RS6000_VARARGS_SIZE : 0)
-
/* Override default big endianism definitions in rs6000.h. */
#undef BYTES_BIG_ENDIAN
#undef WORDS_BIG_ENDIAN
@@ -412,15 +333,6 @@ do { \
((TARGET_ALTIVEC && TREE_CODE (TREE_TYPE (FIELD)) == VECTOR_TYPE) \
? 128 : COMPUTED)
-/* Define this macro as an expression for the alignment of a type
- (given by TYPE as a tree node) if the alignment computed in the
- usual way is COMPUTED and the alignment explicitly specified was
- SPECIFIED. */
-#define ROUND_TYPE_ALIGN(TYPE, COMPUTED, SPECIFIED) \
- ((TARGET_ALTIVEC && TREE_CODE (TYPE) == VECTOR_TYPE) \
- ? MAX (MAX ((COMPUTED), (SPECIFIED)), 128) \
- : MAX (COMPUTED, SPECIFIED))
-
#undef BIGGEST_FIELD_ALIGNMENT
/* Use ELF style section commands. */
@@ -450,131 +362,12 @@ do { \
#define SDATA2_SECTION_ASM_OP "\t.section\t\".sdata2\",\"a\""
#define SBSS_SECTION_ASM_OP "\t.section\t\".sbss\",\"aw\",@nobits"
-/* Besides the usual ELF sections, we need a toc section. */
-/* Override elfos.h definition. */
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_toc, in_sdata, in_sdata2, in_sbss, in_init, in_fini
-
-/* Override elfos.h definition. */
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- TOC_SECTION_FUNCTION \
- SDATA_SECTION_FUNCTION \
- SDATA2_SECTION_FUNCTION \
- SBSS_SECTION_FUNCTION \
- INIT_SECTION_FUNCTION \
- FINI_SECTION_FUNCTION
-
-#define TOC_SECTION_FUNCTION \
-void \
-toc_section (void) \
-{ \
- if (in_section != in_toc) \
- { \
- in_section = in_toc; \
- if (DEFAULT_ABI == ABI_AIX \
- && TARGET_MINIMAL_TOC \
- && !TARGET_RELOCATABLE) \
- { \
- if (! toc_initialized) \
- { \
- toc_initialized = 1; \
- fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
- (*targetm.asm_out.internal_label) (asm_out_file, "LCTOC", 0); \
- fprintf (asm_out_file, "\t.tc "); \
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1[TC],"); \
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
- fprintf (asm_out_file, "\n"); \
- \
- fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
- fprintf (asm_out_file, " = .+32768\n"); \
- } \
- else \
- fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
- } \
- else if (DEFAULT_ABI == ABI_AIX && !TARGET_RELOCATABLE) \
- fprintf (asm_out_file, "%s\n", TOC_SECTION_ASM_OP); \
- else \
- { \
- fprintf (asm_out_file, "%s\n", MINIMAL_TOC_SECTION_ASM_OP); \
- if (! toc_initialized) \
- { \
- ASM_OUTPUT_INTERNAL_LABEL_PREFIX (asm_out_file, "LCTOC1"); \
- fprintf (asm_out_file, " = .+32768\n"); \
- toc_initialized = 1; \
- } \
- } \
- } \
-} \
- \
-extern int in_toc_section (void); \
-int in_toc_section (void) \
-{ \
- return in_section == in_toc; \
-}
-
-#define SDATA_SECTION_FUNCTION \
-void \
-sdata_section (void) \
-{ \
- if (in_section != in_sdata) \
- { \
- in_section = in_sdata; \
- fprintf (asm_out_file, "%s\n", SDATA_SECTION_ASM_OP); \
- } \
-}
-
-#define SDATA2_SECTION_FUNCTION \
-void \
-sdata2_section (void) \
-{ \
- if (in_section != in_sdata2) \
- { \
- in_section = in_sdata2; \
- fprintf (asm_out_file, "%s\n", SDATA2_SECTION_ASM_OP); \
- } \
-}
-
-#define SBSS_SECTION_FUNCTION \
-void \
-sbss_section (void) \
-{ \
- if (in_section != in_sbss) \
- { \
- in_section = in_sbss; \
- fprintf (asm_out_file, "%s\n", SBSS_SECTION_ASM_OP); \
- } \
-}
-
-#define INIT_SECTION_FUNCTION \
-void \
-init_section (void) \
-{ \
- if (in_section != in_init) \
- { \
- in_section = in_init; \
- fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \
- } \
-}
-
-#define FINI_SECTION_FUNCTION \
-void \
-fini_section (void) \
-{ \
- if (in_section != in_fini) \
- { \
- in_section = in_fini; \
- fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \
- } \
-}
-
/* Override default elf definitions. */
+#define TARGET_ASM_INIT_SECTIONS rs6000_elf_asm_init_sections
+#undef TARGET_ASM_RELOC_RW_MASK
+#define TARGET_ASM_RELOC_RW_MASK rs6000_elf_reloc_rw_mask
#undef TARGET_ASM_SELECT_RTX_SECTION
#define TARGET_ASM_SELECT_RTX_SECTION rs6000_elf_select_rtx_section
-#undef TARGET_ASM_SELECT_SECTION
-#define TARGET_ASM_SELECT_SECTION rs6000_elf_select_section
-#define TARGET_ASM_UNIQUE_SECTION rs6000_elf_unique_section
/* Return nonzero if this entry is to be written into the constant pool
in a special way. We do so if this is a SYMBOL_REF, LABEL_REF or a CONST
@@ -599,7 +392,7 @@ fini_section (void) \
|| (!TARGET_NO_FP_IN_TOC \
&& !TARGET_RELOCATABLE \
&& GET_CODE (X) == CONST_DOUBLE \
- && GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ && SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
&& BITS_PER_WORD == HOST_BITS_PER_INT)))
/* These macros generate the special .type and .size directives which
@@ -641,14 +434,12 @@ extern int rs6000_pic_labelno;
#define LCOMM_ASM_OP "\t.lcomm\t"
-/* Override elfos.h definition. */
-#undef ASM_OUTPUT_ALIGNED_LOCAL
-#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+/* Describe how to emit uninitialized local items. */
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- if (rs6000_sdata != SDATA_NONE && (SIZE) > 0 \
- && (SIZE) <= g_switch_value) \
+ if ((DECL) && rs6000_elf_in_small_data_p (DECL)) \
{ \
- sbss_section (); \
+ switch_to_section (sbss_section); \
ASM_OUTPUT_ALIGN (FILE, exact_log2 (ALIGN / BITS_PER_UNIT)); \
ASM_OUTPUT_LABEL (FILE, NAME); \
ASM_OUTPUT_SKIP (FILE, SIZE); \
@@ -668,7 +459,7 @@ do { \
/* Describe how to emit uninitialized external linkage items. */
#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- ASM_OUTPUT_ALIGNED_LOCAL (FILE, NAME, SIZE, ALIGN); \
+ ASM_OUTPUT_ALIGNED_DECL_LOCAL (FILE, DECL, NAME, SIZE, ALIGN); \
} while (0)
#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
@@ -739,23 +530,8 @@ extern int fixuplabelno;
/* Historically we have also supported stabs debugging. */
#define DBX_DEBUGGING_INFO 1
-#define DBX_REGISTER_NUMBER(REGNO) rs6000_dbx_register_number (REGNO)
-
-/* Map register numbers held in the call frame info that gcc has
- collected using DWARF_FRAME_REGNUM to those that should be output in
- .debug_frame and .eh_frame. We continue to use gcc hard reg numbers
- for .eh_frame, but use the numbers mandated by the various ABIs for
- .debug_frame. rs6000_emit_prologue has translated any combination of
- CR2, CR3, CR4 saves to a save of CR2. The actual code emitted saves
- the whole of CR, so we map CR2_REGNO to the DWARF reg for CR. */
-#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) \
- ((FOR_EH) ? (REGNO) \
- : (REGNO) == CR2_REGNO ? 64 \
- : DBX_REGISTER_NUMBER (REGNO))
-
#define TARGET_ENCODE_SECTION_INFO rs6000_elf_encode_section_info
#define TARGET_IN_SMALL_DATA_P rs6000_elf_in_small_data_p
-#define TARGET_SECTION_TYPE_FLAGS rs6000_elf_section_type_flags
/* The ELF version doesn't encode [DS] or whatever at the end of symbols. */
@@ -773,38 +549,28 @@ extern int fixuplabelno;
#define TARGET_VERSION fprintf (stderr, " (PowerPC System V.4)");
#endif
-#define TARGET_OS_SYSV_CPP_BUILTINS() \
- do \
- { \
- if (flag_pic == 1) \
- { \
- builtin_define ("__pic__=1"); \
- builtin_define ("__PIC__=1"); \
- } \
- else if (flag_pic == 2) \
- { \
- builtin_define ("__pic__=2"); \
- builtin_define ("__PIC__=2"); \
- } \
- if (target_flags_explicit \
- & MASK_RELOCATABLE) \
- builtin_define ("_RELOCATABLE"); \
- } \
+#define TARGET_OS_SYSV_CPP_BUILTINS() \
+ do \
+ { \
+ if (target_flags_explicit \
+ & MASK_RELOCATABLE) \
+ builtin_define ("_RELOCATABLE"); \
+ } \
while (0)
#ifndef TARGET_OS_CPP_BUILTINS
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("PPC"); \
- builtin_define_std ("unix"); \
- builtin_define ("__svr4__"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=svr4"); \
- builtin_assert ("cpu=powerpc"); \
- builtin_assert ("machine=powerpc"); \
- TARGET_OS_SYSV_CPP_BUILTINS (); \
- } \
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("PPC"); \
+ builtin_define_std ("unix"); \
+ builtin_define ("__svr4__"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=svr4"); \
+ builtin_assert ("cpu=powerpc"); \
+ builtin_assert ("machine=powerpc"); \
+ TARGET_OS_SYSV_CPP_BUILTINS (); \
+ } \
while (0)
#endif
@@ -837,6 +603,10 @@ extern int fixuplabelno;
#define CC1_ENDIAN_DEFAULT_SPEC "%(cc1_endian_big)"
+#ifndef CC1_SECURE_PLT_DEFAULT_SPEC
+#define CC1_SECURE_PLT_DEFAULT_SPEC ""
+#endif
+
/* Pass -G xxx to the compiler and set correct endian mode. */
#define CC1_SPEC "%{G*} \
%{mlittle|mlittle-endian: %(cc1_endian_little); \
@@ -849,7 +619,6 @@ extern int fixuplabelno;
mcall-gnu : -mbig %(cc1_endian_big); \
mcall-i960-old : -mlittle %(cc1_endian_little); \
: %(cc1_endian_default)} \
-%{mno-sdata: -msdata=none } \
%{meabi: %{!mcall-*: -mcall-sysv }} \
%{!meabi: %{!mno-eabi: \
%{mrelocatable: -meabi } \
@@ -861,6 +630,7 @@ extern int fixuplabelno;
%{mcall-openbsd: -mno-eabi }}} \
%{msdata: -msdata=default} \
%{mno-sdata: -msdata=none} \
+%{!mbss-plt: %{!msecure-plt: %(cc1_secure_plt_default)}} \
%{profile: -p}"
/* Don't put -Y P,<path> for cross compilers. */
@@ -1089,7 +859,6 @@ extern int fixuplabelno;
#define LINK_OS_FREEBSD_SPEC "\
%{p:%nconsider using `-pg' instead of `-p' with gprof(1)} \
- %{Wl,*:%*} \
%{v:-V} \
%{assert*} %{R*} %{rpath*} %{defsym*} \
%{shared:-Bshareable %{h*} %{soname*}} \
@@ -1107,12 +876,12 @@ extern int fixuplabelno;
#ifdef HAVE_LD_PIE
#define STARTFILE_LINUX_SPEC "\
-%{!shared: %{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
+%{!shared: %{pg|p|profile:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}} \
%{mnewlib:ecrti.o%s;:crti.o%s} \
%{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
#else
#define STARTFILE_LINUX_SPEC "\
-%{!shared: %{pg|p:gcrt1.o%s;:crt1.o%s}} \
+%{!shared: %{pg|p|profile:gcrt1.o%s;:crt1.o%s}} \
%{mnewlib:ecrti.o%s;:crti.o%s} \
%{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
#endif
@@ -1123,9 +892,19 @@ extern int fixuplabelno;
#define LINK_START_LINUX_SPEC ""
+#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+#if UCLIBC_DEFAULT
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+#else
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}" U ";:" G "}"
+#endif
+#define LINUX_DYNAMIC_LINKER \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER)
+
#define LINK_OS_LINUX_SPEC "-m elf32ppclinux %{!shared: %{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld.so.1}}}"
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "}}}"
#if defined(HAVE_LD_EH_FRAME_HDR)
# define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
@@ -1237,7 +1016,7 @@ ncrtn.o%s"
/* Override rs6000.h definition. */
#undef SUBTARGET_EXTRA_SPECS
#define SUBTARGET_EXTRA_SPECS \
- { "crtsavres_default", CRTSAVRES_DEFAULT_SPEC }, \
+ { "crtsavres_default", CRTSAVRES_DEFAULT_SPEC }, \
{ "lib_ads", LIB_ADS_SPEC }, \
{ "lib_yellowknife", LIB_YELLOWKNIFE_SPEC }, \
{ "lib_mvme", LIB_MVME_SPEC }, \
@@ -1247,7 +1026,7 @@ ncrtn.o%s"
{ "lib_linux", LIB_LINUX_SPEC }, \
{ "lib_netbsd", LIB_NETBSD_SPEC }, \
{ "lib_openbsd", LIB_OPENBSD_SPEC }, \
- { "lib_windiss", LIB_WINDISS_SPEC }, \
+ { "lib_windiss", LIB_WINDISS_SPEC }, \
{ "lib_default", LIB_DEFAULT_SPEC }, \
{ "startfile_ads", STARTFILE_ADS_SPEC }, \
{ "startfile_yellowknife", STARTFILE_YELLOWKNIFE_SPEC }, \
@@ -1258,7 +1037,7 @@ ncrtn.o%s"
{ "startfile_linux", STARTFILE_LINUX_SPEC }, \
{ "startfile_netbsd", STARTFILE_NETBSD_SPEC }, \
{ "startfile_openbsd", STARTFILE_OPENBSD_SPEC }, \
- { "startfile_windiss", STARTFILE_WINDISS_SPEC }, \
+ { "startfile_windiss", STARTFILE_WINDISS_SPEC }, \
{ "startfile_default", STARTFILE_DEFAULT_SPEC }, \
{ "endfile_ads", ENDFILE_ADS_SPEC }, \
{ "endfile_yellowknife", ENDFILE_YELLOWKNIFE_SPEC }, \
@@ -1269,7 +1048,7 @@ ncrtn.o%s"
{ "endfile_linux", ENDFILE_LINUX_SPEC }, \
{ "endfile_netbsd", ENDFILE_NETBSD_SPEC }, \
{ "endfile_openbsd", ENDFILE_OPENBSD_SPEC }, \
- { "endfile_windiss", ENDFILE_WINDISS_SPEC }, \
+ { "endfile_windiss", ENDFILE_WINDISS_SPEC }, \
{ "endfile_default", ENDFILE_DEFAULT_SPEC }, \
{ "link_path", LINK_PATH_SPEC }, \
{ "link_shlib", LINK_SHLIB_SPEC }, \
@@ -1301,6 +1080,7 @@ ncrtn.o%s"
{ "cc1_endian_big", CC1_ENDIAN_BIG_SPEC }, \
{ "cc1_endian_little", CC1_ENDIAN_LITTLE_SPEC }, \
{ "cc1_endian_default", CC1_ENDIAN_DEFAULT_SPEC }, \
+ { "cc1_secure_plt_default", CC1_SECURE_PLT_DEFAULT_SPEC }, \
{ "cpp_os_ads", CPP_OS_ADS_SPEC }, \
{ "cpp_os_yellowknife", CPP_OS_YELLOWKNIFE_SPEC }, \
{ "cpp_os_mvme", CPP_OS_MVME_SPEC }, \
@@ -1310,7 +1090,7 @@ ncrtn.o%s"
{ "cpp_os_linux", CPP_OS_LINUX_SPEC }, \
{ "cpp_os_netbsd", CPP_OS_NETBSD_SPEC }, \
{ "cpp_os_openbsd", CPP_OS_OPENBSD_SPEC }, \
- { "cpp_os_windiss", CPP_OS_WINDISS_SPEC }, \
+ { "cpp_os_windiss", CPP_OS_WINDISS_SPEC }, \
{ "cpp_os_default", CPP_OS_DEFAULT_SPEC }, \
{ "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }, \
SUBSUBTARGET_EXTRA_SPECS
@@ -1360,3 +1140,6 @@ ncrtn.o%s"
/* Generate entries in .fixup for relocatable addresses. */
#define RELOCATABLE_NEEDS_FIXUP 1
+
+/* This target uses the sysv4.opt file. */
+#define TARGET_USES_SYSV4_OPT 1
diff --git a/contrib/gcc/config/rs6000/sysv4.opt b/contrib/gcc/config/rs6000/sysv4.opt
new file mode 100644
index 0000000..c483ea5
--- /dev/null
+++ b/contrib/gcc/config/rs6000/sysv4.opt
@@ -0,0 +1,149 @@
+; SYSV4 options for PPC port.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by Aldy Hernandez <aldy@quesejoda.com>.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mcall-
+Target RejectNegative Joined
+Select ABI calling convention
+
+msdata=
+Target RejectNegative Joined
+Select method for sdata handling
+
+mtls-size=
+Target RejectNegative Joined
+Specify bit size of immediate TLS offsets
+
+mbit-align
+Target Report Mask(NO_BITFIELD_TYPE)
+Align to the base type of the bit-field
+
+mstrict-align
+Target Report Mask(STRICT_ALIGN)
+Align to the base type of the bit-field
+Don't assume that unaligned accesses are handled by the system
+
+mrelocatable
+Target Report Mask(RELOCATABLE)
+Produce code relocatable at runtime
+
+mrelocatable-lib
+Target
+Produce code relocatable at runtime
+
+mlittle-endian
+Target Report RejectNegative Mask(LITTLE_ENDIAN)
+Produce little endian code
+
+mlittle
+Target Report RejectNegative Mask(LITTLE_ENDIAN) MaskExists
+Produce little endian code
+
+mbig-endian
+Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
+Produce big endian code
+
+mbig
+Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
+Produce big endian code
+
+;; FIXME: This does nothing. What should be done?
+mno-toc
+Target RejectNegative
+no description yet
+
+mtoc
+Target RejectNegative
+no description yet
+
+mprototype
+Target Mask(PROTOTYPE)
+Assume all variable arg functions are prototyped
+
+;; FIXME: Does nothing.
+mno-traceback
+Target RejectNegative
+no description yet
+
+meabi
+Target Report Mask(EABI)
+Use EABI
+
+mbit-word
+Target Report Mask(NO_BITFIELD_WORD)
+Allow bit-fields to cross word boundaries
+
+mregnames
+Target Mask(REGNAMES)
+Use alternate register names
+
+;; FIXME: Does nothing.
+msdata
+Target
+no description yet
+
+msim
+Target RejectNegative
+Link with libsim.a, libc.a and sim-crt0.o
+
+mads
+Target RejectNegative
+Link with libads.a, libc.a and crt0.o
+
+myellowknife
+Target RejectNegative
+Link with libyk.a, libc.a and crt0.o
+
+mmvme
+Target RejectNegative
+Link with libmvme.a, libc.a and crt0.o
+
+memb
+Target RejectNegative
+Set the PPC_EMB bit in the ELF flags header
+
+mwindiss
+Target RejectNegative
+Use the WindISS simulator
+
+mshlib
+Target RejectNegative
+no description yet
+
+m64
+Target Report RejectNegative Mask(64BIT)
+Generate 64-bit code
+
+m32
+Target Report RejectNegative InverseMask(64BIT)
+Generate 32-bit code
+
+mnewlib
+Target RejectNegative
+no description yet
+
+msecure-plt
+Target Report RejectNegative Var(secure_plt, 1)
+Generate code to use a non-exec PLT and GOT
+
+mbss-plt
+Target Report RejectNegative Var(secure_plt, 0)
+Generate code for old exec BSS PLT
diff --git a/contrib/gcc/config/rs6000/sysv4le.h b/contrib/gcc/config/rs6000/sysv4le.h
index 38be8a6..b6964bc 100644
--- a/contrib/gcc/config/rs6000/sysv4le.h
+++ b/contrib/gcc/config/rs6000/sysv4le.h
@@ -17,8 +17,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_LITTLE_ENDIAN)
diff --git a/contrib/gcc/config/rs6000/t-aix43 b/contrib/gcc/config/rs6000/t-aix43
index 8c2592f..6a73cdd 100644
--- a/contrib/gcc/config/rs6000/t-aix43
+++ b/contrib/gcc/config/rs6000/t-aix43
@@ -46,29 +46,31 @@ SHLIB_EXT = .a
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
@multilib_flags@ @shlib_objs@ -lc \
- `case @shlib_base_name@ in \
+ `case @multilib_dir@ in \
*pthread*) echo -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
- rm -f tmp-@shlib_base_name@.a ; \
- $(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a @multilib_dir@/shr.o ; \
- mv tmp-@shlib_base_name@.a @shlib_base_name@.a ; \
+ rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
+ $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/shr.o ; \
+ mv @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/@shlib_base_name@.a ; \
rm -f @multilib_dir@/shr.o
# $(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@.a $$(DESTDIR)$$(slibdir)/
-SHLIB_LIBS = -lc `case @shlib_base_name@ in *pthread*) echo -lpthread ;; esac`
+SHLIB_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
+ $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/
+SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/rs6000/libgcc-ppc64.ver
SHLIB_NM_FLAGS = -Bpg -X32_64
# GCC 128-bit long double support routines.
-LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-ldouble.c
+LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/ppc64-fp.c \
+ $(srcdir)/config/rs6000/darwin-ldouble.c
+TARGET_LIBGCC2_CFLAGS = -mlong-double-128
# Either 32-bit and 64-bit objects in archives.
AR_FLAGS_FOR_TARGET = -X32_64
-# Compile Ada files with minimal-toc. The primary focus is gnatlib, so
-# that the library does not use nearly the entire TOC of applications
-# until gnatlib is built as a shared library on AIX. Compiling the
-# compiler with -mminimal-toc does not cause any harm.
-T_ADAFLAGS = -mminimal-toc
diff --git a/contrib/gcc/config/rs6000/t-aix52 b/contrib/gcc/config/rs6000/t-aix52
index 839bd0a..37a5d83 100644
--- a/contrib/gcc/config/rs6000/t-aix52
+++ b/contrib/gcc/config/rs6000/t-aix52
@@ -27,29 +27,31 @@ SHLIB_EXT = .a
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
@multilib_flags@ @shlib_objs@ -lc \
- `case @shlib_base_name@ in \
+ `case @multilib_dir@ in \
*pthread*) echo -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
- rm -f tmp-@shlib_base_name@.a ; \
- $(AR_CREATE_FOR_TARGET) tmp-@shlib_base_name@.a @multilib_dir@/shr.o ; \
- mv tmp-@shlib_base_name@.a @shlib_base_name@.a ; \
+ rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
+ $(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/shr.o ; \
+ mv @multilib_dir@/tmp-@shlib_base_name@.a \
+ @multilib_dir@/@shlib_base_name@.a ; \
rm -f @multilib_dir@/shr.o
# $(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@.a $$(DESTDIR)$$(slibdir)/
-SHLIB_LIBS = -lc `case @shlib_base_name@ in *pthread*) echo -lpthread ;; esac`
+SHLIB_INSTALL = \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@; \
+ $(INSTALL_DATA) @multilib_dir@/@shlib_base_name@.a \
+ $$(DESTDIR)$$(slibdir)@shlib_slibdir_qual@/
+SHLIB_LIBS = -lc `case @multilib_dir@ in *pthread*) echo -lpthread ;; esac`
SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/rs6000/libgcc-ppc64.ver
SHLIB_NM_FLAGS = -Bpg -X32_64
# GCC 128-bit long double support routines.
-LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-ldouble.c
+LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/ppc64-fp.c \
+ $(srcdir)/config/rs6000/darwin-ldouble.c
+TARGET_LIBGCC2_CFLAGS = -mlong-double-128
# Either 32-bit and 64-bit objects in archives.
AR_FLAGS_FOR_TARGET = -X32_64
-# Compile Ada files with minimal-toc. The primary focus is gnatlib, so
-# that the library does not use nearly the entire TOC of applications
-# until gnatlib is built as a shared library on AIX. Compiling the
-# compiler with -mminimal-toc does not cause any harm.
-T_ADAFLAGS = -mminimal-toc
diff --git a/contrib/gcc/config/rs6000/t-beos b/contrib/gcc/config/rs6000/t-beos
index badffef..dc3b89d 100644
--- a/contrib/gcc/config/rs6000/t-beos
+++ b/contrib/gcc/config/rs6000/t-beos
@@ -28,6 +28,3 @@ EXTRA_PARTS = milli.exp
milli.exp: $(srcdir)/config/rs6000/milli.exp
rm -f milli.exp
cp $(srcdir)/config/rs6000/milli.exp ./milli.exp
-
-# Don't use collect.
-USE_COLLECT2 =
diff --git a/contrib/gcc/config/rs6000/t-darwin b/contrib/gcc/config/rs6000/t-darwin
index 185bb00..5ef2872 100644
--- a/contrib/gcc/config/rs6000/t-darwin
+++ b/contrib/gcc/config/rs6000/t-darwin
@@ -1,7 +1,37 @@
-# Add trampoline and long double support to libgcc.
LIB2FUNCS_EXTRA = $(srcdir)/config/rs6000/darwin-tramp.asm \
- $(srcdir)/config/rs6000/darwin-ldouble.c
+ $(srcdir)/config/rs6000/ppc64-fp.c \
+ $(srcdir)/config/darwin-64.c \
+ $(srcdir)/config/rs6000/darwin-ldouble.c \
+ $(srcdir)/config/rs6000/darwin-world.asm
-# For libgcc, we always want 128-bit long double, since a libgcc built with
-# that will work without it.
-TARGET_LIBGCC2_CFLAGS = -mlong-double-128
+LIB2FUNCS_STATIC_EXTRA = \
+ $(srcdir)/config/rs6000/darwin-fpsave.asm \
+ $(srcdir)/config/rs6000/darwin-vecsave.asm
+
+DARWIN_EXTRA_CRT_BUILD_CFLAGS = -mlongcall
+
+# The .asm files above are designed to run on all processors,
+# even though they use AltiVec instructions. -Wa is used because
+# -force_cpusubtype_ALL doesn't work with -dynamiclib.
+#
+# -pipe because there's an assembler bug, 4077127, which causes
+# it to not properly process the first # directive, causing temporary
+# file names to appear in stabs, causing the bootstrap to fail. Using -pipe
+# works around this by not having any temporary file names.
+TARGET_LIBGCC2_CFLAGS = -Wa,-force_cpusubtype_ALL -pipe -mmacosx-version-min=10.4
+
+# Export the _xlq* symbols from darwin-ldouble.c.
+SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver
+
+SHLIB_VERPFX = $(srcdir)/config/rs6000/darwin-libgcc
+
+LIB2ADDEH += $(srcdir)/config/rs6000/darwin-fallback.c
+
+darwin-fpsave.o: $(srcdir)/config/rs6000/darwin-asm.h
+darwin-tramp.o: $(srcdir)/config/rs6000/darwin-asm.h
+
+# Explain how to build crt2.o
+$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \
+ $(TCONFIG_H) stmp-int-hdrs tsystem.h
+ $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
+ -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext)
diff --git a/contrib/gcc/config/rs6000/t-darwin8 b/contrib/gcc/config/rs6000/t-darwin8
new file mode 100644
index 0000000..2f3bb32
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-darwin8
@@ -0,0 +1,3 @@
+# 64-bit libraries can only be built in Darwin 8.x or later.
+MULTILIB_OPTIONS = m64
+MULTILIB_DIRNAMES = ppc64
diff --git a/contrib/gcc/config/rs6000/t-fprules b/contrib/gcc/config/rs6000/t-fprules
index 4fb09a2..aa686c1 100644
--- a/contrib/gcc/config/rs6000/t-fprules
+++ b/contrib/gcc/config/rs6000/t-fprules
@@ -1,18 +1,7 @@
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-FPBIT = fp-bit.c
-DPBIT = dp-bit.c
-
-dp-bit.c: $(srcdir)/config/fp-bit.c
- cat $(srcdir)/config/fp-bit.c > dp-bit.c
-
-fp-bit.c: $(srcdir)/config/fp-bit.c
- echo '#define FLOAT' > fp-bit.c
- cat $(srcdir)/config/fp-bit.c >> fp-bit.c
-
MULTILIB_MATCHES_FLOAT = msoft-float=mcpu?401 \
msoft-float=mcpu?403 \
msoft-float=mcpu?405 \
+ msoft-float=mcpu?440 \
msoft-float=mcpu?ec603e \
msoft-float=mcpu?801 \
msoft-float=mcpu?821 \
diff --git a/contrib/gcc/config/rs6000/t-fprules-fpbit b/contrib/gcc/config/rs6000/t-fprules-fpbit
new file mode 100644
index 0000000..a80c1cf
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-fprules-fpbit
@@ -0,0 +1,11 @@
+# We want fine grained libraries, so use the new code to build the
+# floating point emulation libraries.
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
diff --git a/contrib/gcc/config/rs6000/t-fprules-softfp b/contrib/gcc/config/rs6000/t-fprules-softfp
new file mode 100644
index 0000000..10b271f
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-fprules-softfp
@@ -0,0 +1,6 @@
+softfp_float_modes := sf df
+softfp_int_modes := si di
+softfp_extensions := sfdf
+softfp_truncations := dfsf
+softfp_machine_header := rs6000/sfp-machine.h
+softfp_exclude_libgcc2 := y
diff --git a/contrib/gcc/config/rs6000/t-linux64 b/contrib/gcc/config/rs6000/t-linux64
index 6d1e6f4..a2c04f9 100644
--- a/contrib/gcc/config/rs6000/t-linux64
+++ b/contrib/gcc/config/rs6000/t-linux64
@@ -1,13 +1,11 @@
#rs6000/t-linux64
-LIB2FUNCS_EXTRA = tramp.S $(srcdir)/config/rs6000/ppc64-fp.c
-LIB2FUNCS_STATIC_EXTRA = eabi.S $(srcdir)/config/rs6000/darwin-ldouble.c
-LIB2FUNCS_SHARED_EXTRA = $(srcdir)/config/rs6000/darwin-ldouble-shared.c
+LIB2FUNCS_EXTRA += tramp.S $(srcdir)/config/rs6000/ppc64-fp.c \
+ $(srcdir)/config/rs6000/darwin-ldouble.c
+LIB2FUNCS_EXTRA := $(sort $(LIB2FUNCS_EXTRA))
-TARGET_LIBGCC2_CFLAGS = -mno-minimal-toc -fPIC -specs=bispecs
-
-SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc64.ver
+TARGET_LIBGCC2_CFLAGS += -mno-minimal-toc
MULTILIB_OPTIONS = m64/m32 msoft-float
MULTILIB_DIRNAMES = 64 32 nof
@@ -17,29 +15,5 @@ MULTILIB_EXCLUSIONS = m64/!m32/msoft-float
MULTILIB_OSDIRNAMES = ../lib64 ../lib nof
MULTILIB_MATCHES = $(MULTILIB_MATCHES_FLOAT)
-# We want fine grained libraries, so use the new code to build the
-# floating point emulation libraries.
-# fp-bit is only to be used by 32-bit multilibs
-FPBIT = fp-bit32.c
-DPBIT = dp-bit32.c
-
-dp-bit32.c: $(srcdir)/config/fp-bit.c
- ( echo '#ifndef __powerpc64__'; \
- cat $(srcdir)/config/fp-bit.c; \
- echo '#endif' ) > dp-bit32.c
-
-fp-bit32.c: $(srcdir)/config/fp-bit.c
- ( echo '#ifndef __powerpc64__'; \
- echo '#define FLOAT'; \
- cat $(srcdir)/config/fp-bit.c; \
- echo '#endif' ) > fp-bit32.c
-
-# Hack to use -mlong-double-128 just for compiling 64 bit libgcc
-mklibgcc: bispecs
-
-bispecs: specs
- if [ x`$(GCC_FOR_TARGET) -print-multi-os-directory` = x../lib ]; then \
- sed -e '/cc1_options/{ n; s/$$/ %{m64:-mlong-double-128}/; }' < specs > $@; \
- else \
- sed -e '/cc1_options/{ n; s/$$/ %{!m32:-mlong-double-128}/; }' < specs > $@; \
- fi
+softfp_wrap_start := '\#ifndef __powerpc64__'
+softfp_wrap_end := '\#endif'
diff --git a/contrib/gcc/config/rs6000/t-lynx b/contrib/gcc/config/rs6000/t-lynx
new file mode 100644
index 0000000..429f641
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-lynx
@@ -0,0 +1,38 @@
+LIB2FUNCS_EXTRA = tramp.S
+
+tramp.S: $(srcdir)/config/rs6000/tramp.asm
+ cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
+
+FPBIT = fp-bit.c
+DPBIT = dp-bit.c
+
+dp-bit.c: $(srcdir)/config/fp-bit.c
+ cat $(srcdir)/config/fp-bit.c > dp-bit.c
+
+fp-bit.c: $(srcdir)/config/fp-bit.c
+ echo '#define FLOAT' > fp-bit.c
+ cat $(srcdir)/config/fp-bit.c >> fp-bit.c
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+MULTILIB_OPTIONS += msoft-float
+MULTILIB_DIRNAMES += soft-float
+
+MULTILIB_OPTIONS += maltivec
+MULTILIB_DIRNAMES += altivec
+
+MULTILIB_EXCEPTIONS = *msoft-float/*maltivec*
+
+EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
+
+# If .sdata is enabled __CTOR_{LIST,END}__ go into .sdata instead of
+# .ctors.
+CRTSTUFF_T_CFLAGS = -mno-sdata
+
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC -mno-sdata
+
+Local Variables:
+mode: makefile
+End:
diff --git a/contrib/gcc/config/rs6000/t-ppccomm b/contrib/gcc/config/rs6000/t-ppccomm
index eaa3252..b4950f1 100644
--- a/contrib/gcc/config/rs6000/t-ppccomm
+++ b/contrib/gcc/config/rs6000/t-ppccomm
@@ -1,6 +1,6 @@
# Common support for PowerPC ELF targets (both EABI and SVR4).
-LIB2FUNCS_EXTRA = tramp.S
+LIB2FUNCS_EXTRA += tramp.S $(srcdir)/config/rs6000/darwin-ldouble.c
# This one can't end up in shared libgcc
LIB2FUNCS_STATIC_EXTRA = eabi.S
@@ -11,6 +11,14 @@ eabi.S: $(srcdir)/config/rs6000/eabi.asm
tramp.S: $(srcdir)/config/rs6000/tramp.asm
cat $(srcdir)/config/rs6000/tramp.asm > tramp.S
+ifneq (,$(findstring gnu,$(target)))
+ifeq (,$(findstring spe,$(target)))
+TARGET_LIBGCC2_CFLAGS += -mlong-double-128
+
+SHLIB_MAPFILES += $(srcdir)/config/rs6000/libgcc-ppc-glibc.ver
+endif
+endif
+
# Switch synonyms
MULTILIB_MATCHES_ENDIAN = mlittle=mlittle-endian mbig=mbig-endian
MULTILIB_MATCHES_SYSV = mcall-sysv=mcall-sysv-eabi mcall-sysv=mcall-sysv-noeabi mcall-sysv=mcall-linux mcall-sysv=mcall-netbsd
diff --git a/contrib/gcc/config/rs6000/t-rtems b/contrib/gcc/config/rs6000/t-rtems
index 05d9a26..b3db949 100644
--- a/contrib/gcc/config/rs6000/t-rtems
+++ b/contrib/gcc/config/rs6000/t-rtems
@@ -1,87 +1,66 @@
# Multilibs for powerpc RTEMS targets.
MULTILIB_OPTIONS = \
-mcpu=403/mcpu=505/mcpu=601/mcpu=602/mcpu=603/mcpu=603e/mcpu=604/mcpu=750/mcpu=821/mcpu=860 \
-Dmpc509/Dmpc8260 \
-D_OLD_EXCEPTIONS \
+mcpu=403/mcpu=505/mcpu=601/mcpu=603e/mcpu=604/mcpu=860/mcpu=7400 \
+Dmpc8260 \
msoft-float
MULTILIB_DIRNAMES = \
-m403 m505 m601 m602 m603 m603e m604 m750 m821 m860 \
-mpc509 \
+m403 m505 m601 m603e m604 m860 m7400 \
mpc8260 \
-roe \
nof
MULTILIB_EXTRA_OPTS = mrelocatable-lib mno-eabi mstrict-align
# MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT}
-MULTILIB_MATCHES = ${MULTILIB_MATCHES_ENDIAN} \
- ${MULTILIB_MATCHES_SYSV} \
- mcpu?505/Dmpc505=mcpu?505/Dmpc509
+MULTILIB_MATCHES =
+MULTILIB_MATCHES += ${MULTILIB_MATCHES_ENDIAN}
+MULTILIB_MATCHES += ${MULTILIB_MATCHES_SYSV}
+# Map 405 to 403
+MULTILIB_MATCHES += mcpu?403=mcpu?405
+# Map 602, 603e, 603 to 603e
+MULTILIB_MATCHES += mcpu?603e=mcpu?602
+MULTILIB_MATCHES += mcpu?603e=mcpu?603
+# Map 801, 821, 823 to 860
+MULTILIB_MATCHES += mcpu?860=mcpu?801
+MULTILIB_MATCHES += mcpu?860=mcpu?821
+MULTILIB_MATCHES += mcpu?860=mcpu?823
+# Map 7450 to 7400
+MULTILIB_MATCHES += mcpu?7400=mcpu?7450
-#
-# RTEMS old/new-exceptions handling
-#
-# old-exception processing is depredicated, therefore
-#
-# * Cpu-variants supporting new exception processing are build
-# with new exception processing only
-# * Cpu-variants not having been ported to new exception processing are
-# build with old and new exception processing
-#
-
-# Cpu-variants supporting new exception processing only
-MULTILIB_NEW_EXCEPTIONS_ONLY = \
-*mcpu=505*/*D_OLD_EXCEPTIONS* \
-*mcpu=604*/*D_OLD_EXCEPTIONS* \
-*mcpu=750*/*D_OLD_EXCEPTIONS* \
-*mcpu=821*/*D_OLD_EXCEPTIONS* \
-*Dmpc8260*/*D_OLD_EXCEPTIONS* \
-*mcpu=860*/*D_OLD_EXCEPTIONS*
+# Map 750 to .
+MULTILIB_MATCHES += mcpu?750=
# Soft-float only, default implies msoft-float
# NOTE: Must match with MULTILIB_MATCHES_FLOAT and MULTILIB_MATCHES
MULTILIB_SOFTFLOAT_ONLY = \
-mcpu=403/*msoft-float* \
-mcpu=821/*msoft-float* \
-mcpu=860/*msoft-float*
+*mcpu=401/*msoft-float* \
+*mcpu=403/*msoft-float* \
+*mcpu=405/*msoft-float* \
+*mcpu=801/*msoft-float* \
+*mcpu=821/*msoft-float* \
+*mcpu=823/*msoft-float* \
+*mcpu=860/*msoft-float*
# Hard-float only, take out msoft-float
MULTILIB_HARDFLOAT_ONLY = \
-mcpu=505/*msoft-float*
+*mcpu=505/*msoft-float*
MULTILIB_EXCEPTIONS =
-# Disallow -D_OLD_EXCEPTIONS without other options
-MULTILIB_EXCEPTIONS += D_OLD_EXCEPTIONS*
-
# Disallow -Dppc and -Dmpc without other options
MULTILIB_EXCEPTIONS += Dppc* Dmpc*
MULTILIB_EXCEPTIONS += \
-${MULTILIB_NEW_EXCEPTIONS_ONLY} \
${MULTILIB_SOFTFLOAT_ONLY} \
${MULTILIB_HARDFLOAT_ONLY}
# Special rules
# Take out all variants we don't want
-MULTILIB_EXCEPTIONS += mcpu=403/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=403/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=505/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=505/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=601/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=601/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=602/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=602/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=603/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=603/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=603e/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=604/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=604/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=750/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=750/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=821/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=821/Dmpc8260*
-MULTILIB_EXCEPTIONS += mcpu=860/Dmpc509*
-MULTILIB_EXCEPTIONS += mcpu=860/Dmpc8260*
+MULTILIB_EXCEPTIONS += *mcpu=403/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=505/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=601/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=604/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=750/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=860/Dmpc*
+MULTILIB_EXCEPTIONS += *mcpu=7400/Dmpc*
diff --git a/contrib/gcc/config/rs6000/t-vxworks b/contrib/gcc/config/rs6000/t-vxworks
index e89e47b..fe65a39 100644
--- a/contrib/gcc/config/rs6000/t-vxworks
+++ b/contrib/gcc/config/rs6000/t-vxworks
@@ -1,10 +1,11 @@
# Multilibs for VxWorks.
-MULTILIB_OPTIONS = t403/t405/t440/t603/t604/t860
-MULTILIB_DIRNAMES = PPC403gnu PPC405gnu PPC440gnu \
- PPC603gnu PPC604gnu PPC860gnu
+# The base multilib is -mhard-float.
+MULTILIB_OPTIONS = mrtp fPIC msoft-float
+MULTILIB_DIRNAMES =
+MULTILIB_MATCHES = fPIC=fpic
+MULTILIB_EXCEPTIONS = fPIC*
-MULTILIB_MATCHES = t604=
-
-# Put vxlib.c back in LIB2FUNCS_EXTRA (t-ppccomm clobbers it).
-LIB2FUNCS_EXTRA += $(srcdir)/config/vxlib.c
+# Restore some variables from t-vxworks clobbered by t-ppccomm.
+EXTRA_MULTILIB_PARTS =
+LIB2FUNCS_EXTRA = $(srcdir)/config/vxlib.c
diff --git a/contrib/gcc/config/rs6000/t-vxworksae b/contrib/gcc/config/rs6000/t-vxworksae
new file mode 100644
index 0000000..5f68262
--- /dev/null
+++ b/contrib/gcc/config/rs6000/t-vxworksae
@@ -0,0 +1,5 @@
+# Multilibs for VxWorks AE.
+
+MULTILIB_OPTIONS = mvthreads msoft-float
+MULTILIB_MATCHES =
+MULTILIB_EXCEPTIONS =
diff --git a/contrib/gcc/config/rs6000/tramp.asm b/contrib/gcc/config/rs6000/tramp.asm
index 284f938..63dacc0 100644
--- a/contrib/gcc/config/rs6000/tramp.asm
+++ b/contrib/gcc/config/rs6000/tramp.asm
@@ -23,8 +23,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause
@@ -44,7 +44,7 @@
.align 2
trampoline_initial:
mflr r0
- bl 1f
+ bcl 20,31,1f
.Lfunc = .-trampoline_initial
.long 0 /* will be replaced with function address */
.Lchain = .-trampoline_initial
@@ -67,7 +67,7 @@ trampoline_size = .-trampoline_initial
FUNC_START(__trampoline_setup)
mflr r0 /* save return address */
- bl .LCF0 /* load up __trampoline_initial into r7 */
+ bcl 20,31,.LCF0 /* load up __trampoline_initial into r7 */
.LCF0:
mflr r11
addi r7,r11,trampoline_initial-4-.LCF0 /* trampoline address -4 */
@@ -105,6 +105,12 @@ FUNC_START(__trampoline_setup)
blr
.Labort:
+#if defined SHARED && defined HAVE_AS_REL16
+ bcl 20,31,1f
+1: mflr r30
+ addis r30,r30,_GLOBAL_OFFSET_TABLE_-1b@ha
+ addi r30,r30,_GLOBAL_OFFSET_TABLE_-1b@l
+#endif
bl JUMP_TARGET(abort)
FUNC_END(__trampoline_setup)
diff --git a/contrib/gcc/config/rs6000/vxworks.h b/contrib/gcc/config/rs6000/vxworks.h
index e7a7092..273a435 100644
--- a/contrib/gcc/config/rs6000/vxworks.h
+++ b/contrib/gcc/config/rs6000/vxworks.h
@@ -1,32 +1,56 @@
/* Definitions of target machine for GNU compiler. Vxworks PowerPC version.
- Copyright (C) 1996, 2000, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1996, 2000, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
- This file is part of GCC.
+This file is part of GCC.
- GCC is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published
- by the Free Software Foundation; either version 2, or (at your
- option) any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
-#undef TARGET_OS_CPP_BUILTINS
+/* Note to future editors: VxWorks is mostly an EABI target. We do
+ not use rs6000/eabi.h because we would have to override most of
+ it anyway. However, if you change that file, consider making
+ analogous changes here too. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC VxWorks)");
+
+/* CPP predefined macros. */
+
+#undef TARGET_OS_CPP_BUILTINS
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
+ builtin_define ("__ppc"); \
+ builtin_define ("__EABI__"); \
+ builtin_define ("__ELF__"); \
builtin_define ("__vxworks"); \
- builtin_define ("__vxworks__"); \
+ builtin_define ("__VXWORKS__"); \
+ if (!TARGET_SOFT_FLOAT) \
+ builtin_define ("__hardfp"); \
+ \
+ /* C89 namespace violation! */ \
+ builtin_define ("CPU_FAMILY=PPC"); \
} \
while (0)
+/* Only big endian PPC is supported by VxWorks. */
+#undef BYTES_BIG_ENDIAN
+#define BYTES_BIG_ENDIAN 1
+
/* We have to kill off the entire specs set created by rs6000/sysv4.h
and substitute our own set. The top level vxworks.h has done some
of this for us. */
@@ -38,45 +62,92 @@
#define SUBTARGET_EXTRA_SPECS /* none needed */
+/* FIXME: The only reason we allow no -mcpu switch at all is because
+ config-ml.in insists on a "." multilib. */
#define CPP_SPEC \
-"-DCPU_FAMILY=PPC -D__ppc -D__EABI__ \
- %{t403: -DCPU=PPC403 -D_SOFT_FLOAT ; \
- t405: -DCPU=PPC405 -D_SOFT_FLOAT ; \
- t440: -DCPU=PPC440 -D_SOFT_FLOAT ; \
- t603: -DCPU=PPC603 ; \
- t604: -DCPU=PPC604 ; \
- t860: -DCPU=PPC860 -D_SOFT_FLOAT ; \
- : -DCPU=PPC604} \
- %{!msoft-float:-D__hardfp} \
- %{fpic|fpie: -D__PIC__=1 -D__pic__=1 ; \
- fPIC|fPIE: -D__PIC__=2 -D__pic__=2 } \
- %(cpp_cpu)"
-
-#define CC1_SPEC \
-"%{t403: -mcpu=403 -mstrict-align ; \
- t405: -mcpu=405 -mstrict-align ; \
- t440: -mcpu=440 -mstrict-align ; \
- t603: -mcpu=603 -mstrict-align ; \
- t604: -mcpu=604 -mstrict-align ; \
- t860: -mcpu=860 ; \
- : -mcpu=604 -mstrict-align } \
- %{G*} %{mno-sdata:-msdata=none} %{msdata:-msdata=default} \
+"%{!DCPU=*: \
+ %{mcpu=403 : -DCPU=PPC403 ; \
+ mcpu=405 : -DCPU=PPC405 ; \
+ mcpu=440 : -DCPU=PPC440 ; \
+ mcpu=603 : -DCPU=PPC603 ; \
+ mcpu=604 : -DCPU=PPC604 ; \
+ mcpu=860 : -DCPU=PPC860 ; \
+ mcpu=8540: -DCPU=PPC85XX ; \
+ : -DCPU=PPC604 }}" \
+VXWORKS_ADDITIONAL_CPP_SPEC
+
+#define CC1_SPEC \
+"%{G*} %{mno-sdata:-msdata=none} %{msdata:-msdata=default} \
%{mlittle|mlittle-endian:-mstrict-align} \
- %{profile: -p} \
+ %{profile: -p} \
%{fvec:-maltivec} %{fvec-eabi:-maltivec -mabi=altivec}"
-
-#define ASM_SPEC "%(asm_cpu) \
-%{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
-%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
-%{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} -mbig"
-
-#undef MULTILIB_DEFAULTS
-#define MULTILIB_DEFAULTS { "t604" }
-
-/* We can't use .ctors/.dtors sections. */
-#undef TARGET_ASM_OUTPUT_CONSTRUCTOR
-#undef TARGET_ASM_OUTPUT_DESTRUCTOR
-
-/* Nor sdata. */
-#undef SDATA_DEFAULT_SIZE
-#define SDATA_DEFAULT_SIZE 0
+
+#define ASM_SPEC \
+"%(asm_cpu) \
+ %{.s: %{mregnames} %{mno-regnames}} %{.S: %{mregnames} %{mno-regnames}} \
+ %{v:-v} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Yd,*} %{Wa,*:%*} \
+ %{mrelocatable} %{mrelocatable-lib} %{fpic:-K PIC} %{fPIC:-K PIC} -mbig"
+
+#undef LIB_SPEC
+#define LIB_SPEC VXWORKS_LIB_SPEC
+#undef LINK_SPEC
+#define LINK_SPEC VXWORKS_LINK_SPEC
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC VXWORKS_STARTFILE_SPEC
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC VXWORKS_ENDFILE_SPEC
+
+/* There is no default multilib. */
+#undef MULTILIB_DEFAULTS
+
+#undef TARGET_DEFAULT
+#define TARGET_DEFAULT \
+ (MASK_POWERPC | MASK_NEW_MNEMONICS | MASK_EABI | MASK_STRICT_ALIGN)
+
+#undef PROCESSOR_DEFAULT
+#define PROCESSOR_DEFAULT PROCESSOR_PPC604
+
+/* Nor sdata, for kernel mode. We use this in
+ SUBSUBTARGET_INITIALIZE_OPTIONS, after rs6000_rtp has been initialized. */
+#undef SDATA_DEFAULT_SIZE
+#define SDATA_DEFAULT_SIZE (TARGET_VXWORKS_RTP ? 8 : 0)
+
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY (16*BITS_PER_UNIT)
+/* Override sysv4.h, reset to the default. */
+#undef PREFERRED_STACK_BOUNDARY
+
+/* Enable SPE */
+#undef TARGET_SPE_ABI
+#undef TARGET_SPE
+#undef TARGET_E500
+#undef TARGET_ISEL
+#undef TARGET_FPRS
+
+#define TARGET_SPE_ABI rs6000_spe_abi
+#define TARGET_SPE rs6000_spe
+#define TARGET_E500 (rs6000_cpu == PROCESSOR_PPC8540)
+#define TARGET_ISEL rs6000_isel
+#define TARGET_FPRS (!rs6000_float_gprs)
+
+/* Make -mcpu=8540 imply SPE. ISEL is automatically enabled, the
+ others must be done by hand. Handle -mrtp. Disable -fPIC
+ for -mrtp - the VxWorks PIC model is not compatible with it. */
+#undef SUBSUBTARGET_OVERRIDE_OPTIONS
+#define SUBSUBTARGET_OVERRIDE_OPTIONS \
+ do { \
+ if (TARGET_E500) \
+ { \
+ rs6000_spe = 1; \
+ rs6000_spe_abi = 1; \
+ rs6000_float_gprs = 1; \
+ } \
+ \
+ if (!g_switch_set) \
+ g_switch_value = SDATA_DEFAULT_SIZE; \
+ VXWORKS_OVERRIDE_OPTIONS; \
+ } while (0)
+
+/* No _mcount profiling on VxWorks. */
+#undef FUNCTION_PROFILER
+#define FUNCTION_PROFILER(FILE,LABELNO) VXWORKS_FUNCTION_PROFILER(FILE,LABELNO)
diff --git a/contrib/gcc/config/rs6000/vxworksae.h b/contrib/gcc/config/rs6000/vxworksae.h
new file mode 100644
index 0000000..814b969
--- /dev/null
+++ b/contrib/gcc/config/rs6000/vxworksae.h
@@ -0,0 +1,24 @@
+/* PowerPC VxWorks AE target definitions for GNU compiler.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (PowerPC VxWorks AE)");
+
diff --git a/contrib/gcc/config/rs6000/windiss.h b/contrib/gcc/config/rs6000/windiss.h
index e66d128..f4f1665 100644
--- a/contrib/gcc/config/rs6000/windiss.h
+++ b/contrib/gcc/config/rs6000/windiss.h
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (PowerPC WindISS)");
diff --git a/contrib/gcc/config/rs6000/x-darwin b/contrib/gcc/config/rs6000/x-darwin
index f7242a7..033ab6b 100644
--- a/contrib/gcc/config/rs6000/x-darwin
+++ b/contrib/gcc/config/rs6000/x-darwin
@@ -1,4 +1,4 @@
-host-darwin.o : $(srcdir)/config/rs6000/host-darwin.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h hosthooks.h hosthooks-def.h toplev.h diagnostic.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $(srcdir)/config/rs6000/host-darwin.c
+host-ppc-darwin.o : $(srcdir)/config/rs6000/host-darwin.c \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
+ config/host-darwin.h $(DIAGNOSTIC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< -o $@
diff --git a/contrib/gcc/config/rs6000/x-darwin64 b/contrib/gcc/config/rs6000/x-darwin64
new file mode 100644
index 0000000..3cb423d
--- /dev/null
+++ b/contrib/gcc/config/rs6000/x-darwin64
@@ -0,0 +1,4 @@
+host-ppc64-darwin.o : $(srcdir)/config/rs6000/host-ppc64-darwin.c \
+ $(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
+ config/host-darwin.h $(DIAGNOSTIC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< -o $@
diff --git a/contrib/gcc/config/rs6000/xcoff.h b/contrib/gcc/config/rs6000/xcoff.h
index d4e056b..ebf79b5 100644
--- a/contrib/gcc/config/rs6000/xcoff.h
+++ b/contrib/gcc/config/rs6000/xcoff.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler,
for some generic XCOFF file format
- Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2001, 2002, 2003, 2004, 2007 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the
- Free Software Foundation, 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA. */
+ Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
#define TARGET_OBJECT_FORMAT OBJECT_XCOFF
@@ -56,92 +56,10 @@
#define DOLLARS_IN_IDENTIFIERS 0
-/* Define the extra sections we need. We define three: one is the read-only
- data section which is used for constants. This is a csect whose name is
- derived from the name of the input file. The second is for initialized
- global variables. This is a csect whose name is that of the variable.
- The third is the TOC. */
-
-#define EXTRA_SECTIONS \
- read_only_data, private_data, read_only_private_data, toc, bss
-
-/* Define the routines to implement these extra sections.
- BIGGEST_ALIGNMENT is 64, so align the sections that much. */
-
-#define EXTRA_SECTION_FUNCTIONS \
- READ_ONLY_DATA_SECTION_FUNCTION \
- PRIVATE_DATA_SECTION_FUNCTION \
- READ_ONLY_PRIVATE_DATA_SECTION_FUNCTION \
- TOC_SECTION_FUNCTION
-
-#define READ_ONLY_DATA_SECTION_FUNCTION \
-void \
-read_only_data_section (void) \
-{ \
- if (in_section != read_only_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
- xcoff_read_only_section_name); \
- in_section = read_only_data; \
- } \
-}
+/* AIX .align pseudo-op accept value from 0 to 12, corresponding to
+ log base 2 of the alignment in bytes; 12 = 4096 bytes = 32768 bits. */
-#define PRIVATE_DATA_SECTION_FUNCTION \
-void \
-private_data_section (void) \
-{ \
- if (in_section != private_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RW],3\n", \
- xcoff_private_data_section_name); \
- in_section = private_data; \
- } \
-}
-
-#define READ_ONLY_PRIVATE_DATA_SECTION_FUNCTION \
-void \
-read_only_private_data_section (void) \
-{ \
- if (in_section != read_only_private_data) \
- { \
- fprintf (asm_out_file, "\t.csect %s[RO],3\n", \
- xcoff_private_data_section_name); \
- in_section = read_only_private_data; \
- } \
-}
-
-#define TOC_SECTION_FUNCTION \
-void \
-toc_section (void) \
-{ \
- if (TARGET_MINIMAL_TOC) \
- { \
- /* toc_section is always called at least once \
- from rs6000_xcoff_file_start, so this is \
- guaranteed to always be defined once and \
- only once in each file. */ \
- if (! toc_initialized) \
- { \
- fputs ("\t.toc\nLCTOC..1:\n", asm_out_file); \
- fputs ("\t.tc toc_table[TC],toc_table[RW]\n", asm_out_file); \
- toc_initialized = 1; \
- } \
- \
- if (in_section != toc) \
- fprintf (asm_out_file, "\t.csect toc_table[RW]%s\n", \
- (TARGET_32BIT ? "" : ",3")); \
- } \
- else \
- { \
- if (in_section != toc) \
- fputs ("\t.toc\n", asm_out_file); \
- } \
- in_section = toc; \
-}
-
-/* Define the name of our readonly data section. */
-
-#define READONLY_DATA_SECTION read_only_data_section
+#define MAX_OFILE_ALIGNMENT 32768
/* Return nonzero if this entry is to be written into the constant
pool in a special way. We do so if this is a SYMBOL_REF, LABEL_REF
@@ -164,14 +82,18 @@ toc_section (void) \
|| (GET_CODE (X) == CONST_DOUBLE \
&& (TARGET_POWERPC64 \
|| TARGET_MINIMAL_TOC \
- || (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
+ || (SCALAR_FLOAT_MODE_P (GET_MODE (X)) \
&& ! TARGET_NO_FP_IN_TOC)))))
+#define TARGET_ASM_OUTPUT_ANCHOR rs6000_xcoff_asm_output_anchor
#define TARGET_ASM_GLOBALIZE_LABEL rs6000_xcoff_asm_globalize_label
+#define TARGET_ASM_INIT_SECTIONS rs6000_xcoff_asm_init_sections
+#define TARGET_ASM_RELOC_RW_MASK rs6000_xcoff_reloc_rw_mask
#define TARGET_ASM_NAMED_SECTION rs6000_xcoff_asm_named_section
#define TARGET_ASM_SELECT_SECTION rs6000_xcoff_select_section
#define TARGET_ASM_SELECT_RTX_SECTION rs6000_xcoff_select_rtx_section
#define TARGET_ASM_UNIQUE_SECTION rs6000_xcoff_unique_section
+#define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section
#define TARGET_STRIP_NAME_ENCODING rs6000_xcoff_strip_name_encoding
#define TARGET_SECTION_TYPE_FLAGS rs6000_xcoff_section_type_flags
@@ -212,9 +134,8 @@ toc_section (void) \
On the RS/6000, we need to place an extra '.' in the function name and
output the function descriptor.
- The csect for the function will have already been created by the
- `text_section' call previously done. We do have to go back to that
- csect, however.
+ The csect for the function will have already been created when
+ text_section was selected. We do have to go back to that csect, however.
The third and fourth parameters to the .function pseudo-op (16 and 044)
are placeholders which no longer have any use. */
@@ -243,8 +164,8 @@ toc_section (void) \
fputs (TARGET_32BIT ? "\t.long ." : "\t.llong .", FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
fputs (", TOC[tc0], 0\n", FILE); \
- in_section = no_section; \
- function_section(DECL); \
+ in_section = NULL; \
+ switch_to_section (function_section (DECL)); \
putc ('.', FILE); \
RS6000_OUTPUT_BASENAME (FILE, NAME); \
fputs (":\n", FILE); \
@@ -361,10 +282,6 @@ toc_section (void) \
Align entire section to BIGGEST_ALIGNMENT. */
#define DATA_SECTION_ASM_OP "\t.csect .data[RW],3"
-/* Define the name of the section to use for the EH language specific
- data areas (.gcc_except_table on most other systems). */
-#define TARGET_ASM_EXCEPTION_SECTION data_section
-
/* Define to prevent DWARF2 unwind info in the data section rather
than in the .eh_frame section. We do this because the AIX linker
would otherwise garbage collect these sections. */
diff --git a/contrib/gcc/config/rtems.h b/contrib/gcc/config/rtems.h
index 8063643..546c1da 100644
--- a/contrib/gcc/config/rtems.h
+++ b/contrib/gcc/config/rtems.h
@@ -15,17 +15,12 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* The system headers under RTEMS are C++-aware. */
#define NO_IMPLICIT_EXTERN_C
-/* Generate calls to memcpy, memcmp and memset. */
-#ifndef TARGET_MEM_FUNCTIONS
-#define TARGET_MEM_FUNCTIONS
-#endif
-
/*
* Dummy start/end specification to let linker work as
* needed by autoconf scripts using this compiler.
@@ -39,8 +34,7 @@ Boston, MA 02111-1307, USA. */
/*
* Some targets do not set up LIB_SPECS, override it, here.
*/
-#define STD_LIB_SPEC \
- "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
+#define STD_LIB_SPEC "%{!shared:%{g*:-lg} %{!p:%{!pg:-lc}}%{p:-lc_p}%{pg:-lc_p}}"
#undef LIB_SPEC
#define LIB_SPEC "%{!qrtems: " STD_LIB_SPEC "} " \
@@ -48,4 +42,3 @@ Boston, MA 02111-1307, USA. */
%{!qrtems_debug: -lrtemsbsp -lrtemscpu} \
%{qrtems_debug: -lrtemsbsp_g -lrtemscpu_g} \
-lc -lgcc --end-group %{!qnolinkcmds: -T linkcmds%s}}}"
-
diff --git a/contrib/gcc/config/s390/2064.md b/contrib/gcc/config/s390/2064.md
index 143cd1b..2f958a5 100644
--- a/contrib/gcc/config/s390/2064.md
+++ b/contrib/gcc/config/s390/2064.md
@@ -1,5 +1,5 @@
;; Scheduling description for z900 (cpu 2064).
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
@@ -17,8 +17,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-;; 02111-1307, USA.
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
;;
;; References:
@@ -40,62 +40,67 @@
;; |
;; wr
+;; This scheduler description is also used for the g5 and g6.
+
(define_automaton "z_ipu")
(define_cpu_unit "z_e1" "z_ipu")
(define_cpu_unit "z_wr" "z_ipu")
(define_insn_reservation "z_la" 1
- (and (eq_attr "cpu" "z900")
+ (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "la"))
"z_e1,z_wr")
(define_insn_reservation "z_larl" 1
- (and (eq_attr "cpu" "z900")
+ (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "larl"))
"z_e1,z_wr")
(define_insn_reservation "z_load" 1
- (and (eq_attr "cpu" "z900")
+ (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "load"))
"z_e1,z_wr")
(define_insn_reservation "z_store" 1
- (and (eq_attr "cpu" "z900")
+ (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "store"))
"z_e1,z_wr")
+(define_insn_reservation "z_sem" 2
+ (and (eq_attr "cpu" "z900,g5,g6")
+ (eq_attr "type" "sem"))
+ "z_e1*2,z_wr")
+
(define_insn_reservation "z_call" 5
- (and (eq_attr "cpu" "z900")
+ (and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "jsr"))
"z_e1*5,z_wr")
-(define_insn_reservation "z_o2" 2
- (and (eq_attr "cpu" "z900")
- (eq_attr "type" "o2"))
- "z_e1*2,z_wr")
+(define_insn_reservation "z_mul" 5
+ (and (eq_attr "cpu" "g5,g6,z900")
+ (eq_attr "type" "imulsi,imulhi"))
+ "z_e1*5,z_wr")
-(define_insn_reservation "z_o3" 3
- (and (eq_attr "cpu" "z900")
- (eq_attr "type" "o3"))
- "z_e1*3,z_wr")
+(define_insn_reservation "z_inf" 10
+ (and (eq_attr "cpu" "g5,g6,z900")
+ (eq_attr "type" "idiv,imuldi"))
+ "z_e1*10,z_wr")
-;
-; Insn still not mentioned are check for
-; the usage of the agen unit
-;
+;; For everything else we check the atype flag.
(define_insn_reservation "z_int" 1
- (and (eq_attr "cpu" "z900")
- (eq_attr "atype" "reg"))
+ (and (eq_attr "cpu" "z900,g5,g6")
+ (and (not (eq_attr "type" "la,larl,load,store,jsr"))
+ (eq_attr "atype" "reg")))
"z_e1,z_wr")
(define_insn_reservation "z_agen" 1
- (and (eq_attr "cpu" "z900")
- (eq_attr "atype" "agen"))
+ (and (eq_attr "cpu" "z900,g5,g6")
+ (and (not (eq_attr "type" "la,larl,load,store,jsr"))
+ (eq_attr "atype" "agen")))
"z_e1,z_wr")
-
;;
;; s390_agen_dep_p returns 1, if a register is set in the
;; first insn and used in the dependent insn to form a address.
diff --git a/contrib/gcc/config/s390/2084.md b/contrib/gcc/config/s390/2084.md
index a74ffbf..3a4479a 100644
--- a/contrib/gcc/config/s390/2084.md
+++ b/contrib/gcc/config/s390/2084.md
@@ -1,5 +1,5 @@
;; Scheduling description for z990 (cpu 2084).
-;; Copyright (C) 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
@@ -17,8 +17,8 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-;; 02111-1307, USA.
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
(define_automaton "x_ipu")
@@ -61,151 +61,199 @@
;; Simple insns
;;
+(define_insn_reservation "x_int" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (and (eq_attr "type" "integer")
+ (eq_attr "atype" "reg")))
+ "x-e1-st,x-wr-st")
+
+(define_insn_reservation "x_agen" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (and (eq_attr "type" "integer")
+ (eq_attr "atype" "agen")))
+ "x-e1-st,x-wr-st")
+
(define_insn_reservation "x_lr" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "lr"))
"x-e1-st,x-wr-st")
(define_insn_reservation "x_la" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "la"))
"x-e1-st,x-wr-st")
(define_insn_reservation "x_larl" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "larl"))
"x-e1-st,x-wr-st")
(define_insn_reservation "x_load" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "load"))
"x-e1-st+x-mem,x-wr-st")
(define_insn_reservation "x_store" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "store"))
"x-e1-st+x_store_tok,x-wr-st")
(define_insn_reservation "x_branch" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "branch"))
"x_e1_r,x_wr_r")
(define_insn_reservation "x_call" 5
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "jsr"))
- "x-e1-np*5,x-wr-np")
+ "x-e1-np*5,x-wr-np")
+
+(define_insn_reservation "x_mul_hi" 2
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "imulhi"))
+ "x-e1-np*2,x-wr-np")
+
+(define_insn_reservation "x_mul_sidi" 4
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "imulsi,imuldi"))
+ "x-e1-np*4,x-wr-np")
+
+(define_insn_reservation "x_div" 10
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "idiv"))
+ "x-e1-np*10,x-wr-np")
+
+(define_insn_reservation "x_sem" 17
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "sem"))
+ "x-e1-np+x-mem,x-e1-np*16,x-wr-st")
;;
;; Multicycle insns
;;
-(define_insn_reservation "x_ss" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "op_type" "SS"))
+(define_insn_reservation "x_cs" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "cs"))
"x-e1-np,x-wr-np")
+(define_insn_reservation "x_vs" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "vs"))
+ "x-e1-np*10,x-wr-np")
+
(define_insn_reservation "x_stm" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "stm"))
"(x-e1-np+x_store_tok)*10,x-wr-np")
(define_insn_reservation "x_lm" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "lm"))
"x-e1-np*10,x-wr-np")
-(define_insn_reservation "x_nn" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "op_type" "NN"))
+(define_insn_reservation "x_other" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "other"))
"x-e1-np,x-wr-np")
-(define_insn_reservation "x_o2" 2
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "o2"))
- "x-e1-np*2,x-wr-np")
-
-(define_insn_reservation "x_o3" 3
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "o3"))
- "x-e1-np*3,x-wr-np")
-
;;
;; Floating point insns
;;
-(define_insn_reservation "x_fsimpd" 6
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fsimpd,fmuld"))
+(define_insn_reservation "x_fsimptf" 7
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fsimptf"))
+ "x_e1_t*2,x-wr-fp")
+
+(define_insn_reservation "x_fsimpdf" 6
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fsimpdf,fmuldf"))
"x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fsimps" 6
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fsimps,fmuls"))
+(define_insn_reservation "x_fsimpsf" 6
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fsimpsf,fmulsf"))
"x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fdivd" 36
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fdivd"))
+
+(define_insn_reservation "x_fmultf" 33
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fmultf"))
+ "x_e1_t*27,x-wr-fp")
+
+
+(define_insn_reservation "x_fdivtf" 82
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fdivtf,fsqrttf"))
+ "x_e1_t*76,x-wr-fp")
+
+(define_insn_reservation "x_fdivdf" 36
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fdivdf,fsqrtdf"))
"x_e1_t*30,x-wr-fp")
-(define_insn_reservation "x_fdivs" 36
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fdivs"))
+(define_insn_reservation "x_fdivsf" 36
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fdivsf,fsqrtsf"))
"x_e1_t*30,x-wr-fp")
-(define_insn_reservation "x_floadd" 6
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "floadd"))
+
+(define_insn_reservation "x_floadtf" 6
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "floadtf"))
+ "x_e1_t,x-wr-fp")
+
+(define_insn_reservation "x_floaddf" 6
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "floaddf"))
"x_e1_t,x-wr-fp")
-(define_insn_reservation "x_floads" 6
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "floads"))
+(define_insn_reservation "x_floadsf" 6
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "floadsf"))
"x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fstored" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fstored"))
+
+(define_insn_reservation "x_fstoredf" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fstoredf"))
"x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fstores" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "type" "fstores"))
+(define_insn_reservation "x_fstoresf" 1
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "fstoresf"))
"x_e1_t,x-wr-fp")
+
+(define_insn_reservation "x_ftrunctf" 16
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "ftrunctf"))
+ "x_e1_t*10,x-wr-fp")
+
+(define_insn_reservation "x_ftruncdf" 11
+ (and (eq_attr "cpu" "z990,z9_109")
+ (eq_attr "type" "ftruncdf"))
+ "x_e1_t*5,x-wr-fp")
+
+
(define_insn_reservation "x_ftoi" 1
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "ftoi"))
"x_e1_t*3,x-wr-fp")
(define_insn_reservation "x_itof" 7
- (and (eq_attr "cpu" "z990")
+ (and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "itof"))
"x_e1_t*3,x-wr-fp")
-(define_bypass 1 "x_fsimpd" "x_fstored")
+(define_bypass 1 "x_fsimpdf" "x_fstoredf")
-(define_bypass 1 "x_fsimps" "x_fstores")
+(define_bypass 1 "x_fsimpsf" "x_fstoresf")
-(define_bypass 1 "x_floadd" "x_fsimpd,x_fstored,x_floadd")
+(define_bypass 1 "x_floaddf" "x_fsimpdf,x_fstoredf,x_floaddf")
-(define_bypass 1 "x_floads" "x_fsimps,x_fstores,x_floads")
-
-;;
-;; Insns still not mentioned are checked for
-;; the usage of the agen unit
-;;
-
-(define_insn_reservation "x_int" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "atype" "reg"))
- "x-e1-st,x-wr-st")
-
-(define_insn_reservation "x_agen" 1
- (and (eq_attr "cpu" "z990")
- (eq_attr "atype" "agen"))
- "x-e1-st+x-mem,x-wr-st")
+(define_bypass 1 "x_floadsf" "x_fsimpsf,x_fstoresf,x_floadsf")
;;
;; s390_agen_dep_p returns 1, if a register is set in the
@@ -218,12 +266,12 @@
;;
(define_bypass 5 "x_int,x_agen,x_lr"
- "x_agen,x_la,x_call,x_load,x_store,x_ss,x_stm,x_lm"
+ "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
(define_bypass 9 "x_int,x_agen,x_lr"
- "x_floadd, x_floads, x_fstored, x_fstores,\
- x_fsimpd, x_fsimps, x_fdivd, x_fdivs"
+ "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
+ x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
"s390_agen_dep_p")
;;
;; A load type instruction uses a bypass to feed the result back
@@ -231,12 +279,12 @@
;;
(define_bypass 4 "x_load"
- "x_agen,x_la,x_call,x_load,x_store,x_ss,x_stm,x_lm"
+ "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
(define_bypass 5 "x_load"
- "x_floadd, x_floads, x_fstored, x_fstores,\
- x_fsimpd, x_fsimps, x_fdivd, x_fdivs"
+ "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
+ x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
"s390_agen_dep_p")
;;
@@ -245,12 +293,12 @@
;;
(define_bypass 3 "x_larl,x_la"
- "x_agen,x_la,x_call,x_load,x_store,x_ss,x_stm,x_lm"
+ "x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
(define_bypass 5 "x_larl, x_la"
- "x_floadd, x_floads, x_fstored, x_fstores,\
- x_fsimpd, x_fsimps, x_fdivd, x_fdivs"
+ "x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
+ x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
"s390_agen_dep_p")
;;
diff --git a/contrib/gcc/config/s390/constraints.md b/contrib/gcc/config/s390/constraints.md
new file mode 100644
index 0000000..cfc8aa5
--- /dev/null
+++ b/contrib/gcc/config/s390/constraints.md
@@ -0,0 +1,438 @@
+;; Constraints definitions belonging to the gcc backend for IBM S/390.
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;; Written by Wolfgang Gellerich, using code and information found in
+;; files s390.md, s390.h, and s390.c.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify it under
+;; the terms of the GNU General Public License as published by the Free
+;; Software Foundation; either version 2, or (at your option) any later
+;; version.
+;;
+;; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+;; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+;; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+;; for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to the Free
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, USA.
+
+
+;;
+;; Special constraints for s/390 machine description:
+;;
+;; a -- Any address register from 1 to 15.
+;; c -- Condition code register 33.
+;; d -- Any register from 0 to 15.
+;; f -- Floating point registers.
+;; t -- Access registers 36 and 37.
+;; G -- Const double zero operand
+;; I -- An 8-bit constant (0..255).
+;; J -- A 12-bit constant (0..4095).
+;; K -- A 16-bit constant (-32768..32767).
+;; L -- Value appropriate as displacement.
+;; (0..4095) for short displacement
+;; (-524288..524287) for long displacement
+;; M -- Constant integer with a value of 0x7fffffff.
+;; N -- Multiple letter constraint followed by 4 parameter letters.
+;; 0..9,x: number of the part counting from most to least significant
+;; H,Q: mode of the part
+;; D,S,H: mode of the containing operand
+;; 0,F: value of the other parts (F - all bits set)
+;;
+;; The constraint matches if the specified part of a constant
+;; has a value different from its other parts. If the letter x
+;; is specified instead of a part number, the constraint matches
+;; if there is any single part with non-default value.
+;; O -- Multiple letter constraint followed by 1 parameter.
+;; s: Signed extended immediate value (-2G .. 2G-1).
+;; p: Positive extended immediate value (0 .. 4G-1).
+;; n: Negative extended immediate value (-4G .. -1).
+;; These constraints do not accept any operand if the machine does
+;; not provide the extended-immediate facility.
+;; P -- Any integer constant that can be loaded without literal pool.
+;; Q -- Memory reference without index register and with short displacement.
+;; R -- Memory reference with index register and short displacement.
+;; S -- Memory reference without index register but with long displacement.
+;; T -- Memory reference with index register and long displacement.
+;; A -- Multiple letter constraint followed by Q, R, S, or T:
+;; Offsettable memory reference of type specified by second letter.
+;; B -- Multiple letter constraint followed by Q, R, S, or T:
+;; Memory reference of the type specified by second letter that
+;; does *not* refer to a literal pool entry.
+;; U -- Pointer with short displacement.
+;; W -- Pointer with long displacement.
+;; Y -- Shift count operand.
+;;
+
+
+;;
+;; Register constraints.
+;;
+
+(define_register_constraint "a"
+ "ADDR_REGS"
+ "Any address register from 1 to 15.")
+
+
+(define_register_constraint "c"
+ "CC_REGS"
+ "Condition code register 33")
+
+
+(define_register_constraint "d"
+ "GENERAL_REGS"
+ "Any register from 0 to 15")
+
+
+(define_register_constraint "f"
+ "FP_REGS"
+ "Floating point registers")
+
+
+(define_register_constraint "t"
+ "ACCESS_REGS"
+ "@internal
+ Access registers 36 and 37")
+
+
+;;
+;; General constraints for constants.
+;;
+
+(define_constraint "G"
+ "@internal
+ Const double zero operand"
+ (and (match_code "const_double")
+ (match_test "s390_float_const_zero_p (op)")))
+
+
+(define_constraint "I"
+ "An 8-bit constant (0..255)"
+ (and (match_code "const_int")
+ (match_test "(unsigned int) ival <= 255")))
+
+
+(define_constraint "J"
+ "A 12-bit constant (0..4095)"
+ (and (match_code "const_int")
+ (match_test "(unsigned int) ival <= 4095")))
+
+
+(define_constraint "K"
+ "A 16-bit constant (-32768..32767)"
+ (and (match_code "const_int")
+ (match_test "ival >= -32768 && ival <= 32767")))
+
+
+
+(define_constraint "L"
+ "Value appropriate as displacement.
+ (0..4095) for short displacement
+ (-524288..524287) for long displacement"
+ (and (match_code "const_int")
+ (match_test "TARGET_LONG_DISPLACEMENT ?
+ (ival >= -524288 && ival <= 524287)
+ : (ival >= 0 && ival <= 4095)")))
+
+
+(define_constraint "M"
+ "Constant integer with a value of 0x7fffffff"
+ (and (match_code "const_int")
+ (match_test "ival == 2147483647")))
+
+
+(define_constraint "P"
+ "@internal
+ Any integer constant that can be loaded without literal pool"
+ (and (match_code "const_int")
+ (match_test "legitimate_reload_constant_p (GEN_INT (ival))")))
+
+
+(define_address_constraint "Y"
+ "Shift count operand"
+
+;; Simply check for the basic form of a shift count. Reload will
+;; take care of making sure we have a proper base register.
+
+ (match_test "s390_decompose_shift_count (op, NULL, NULL)" ))
+
+
+;; N -- Multiple letter constraint followed by 4 parameter letters.
+;; 0..9,x: number of the part counting from most to least significant
+;; H,Q: mode of the part
+;; D,S,H: mode of the containing operand
+;; 0,F: value of the other parts (F = all bits set)
+;;
+;; The constraint matches if the specified part of a constant
+;; has a value different from its other parts. If the letter x
+;; is specified instead of a part number, the constraint matches
+;; if there is any single part with non-default value.
+;;
+;; The following patterns define only those constraints that are actually
+;; used in s390.md. If you need an additional one, simply add it in the
+;; obvious way. Function s390_N_constraint_str is ready to handle all
+;; combinations.
+;;
+
+
+(define_constraint "NxQS0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQS0\", ival)")))
+
+
+(define_constraint "NxQD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQD0\", ival)")))
+
+
+(define_constraint "N3HD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"3HD0\", ival)")))
+
+
+(define_constraint "N2HD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"2HD0\", ival)")))
+
+
+(define_constraint "N1SD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1SD0\", ival)")))
+
+
+(define_constraint "N1HS0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1HS0\", ival)")))
+
+
+(define_constraint "N1HD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1HD0\", ival)")))
+
+
+(define_constraint "N0SD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0SD0\", ival)")))
+
+
+(define_constraint "N0HS0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0HS0\", ival)")))
+
+
+(define_constraint "N0HD0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0HD0\", ival)")))
+
+
+(define_constraint "NxQDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQDF\", ival)")))
+
+
+(define_constraint "N1SDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1SDF\", ival)")))
+
+
+(define_constraint "N0SDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0SDF\", ival)")))
+
+
+(define_constraint "N3HDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"3HDF\", ival)")))
+
+
+(define_constraint "N2HDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"2HDF\", ival)")))
+
+
+(define_constraint "N1HDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1HDF\", ival)")))
+
+
+(define_constraint "N0HDF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0HDF\", ival)")))
+
+
+(define_constraint "N0HSF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"0HSF\", ival)")))
+
+
+(define_constraint "N1HSF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"1HSF\", ival)")))
+
+
+(define_constraint "NxQSF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQSF\", ival)")))
+
+
+(define_constraint "NxQHF"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQHF\", ival)")))
+
+
+(define_constraint "NxQH0"
+ "@internal"
+ (and (match_code "const_int")
+ (match_test "s390_N_constraint_str (\"xQH0\", ival)")))
+
+
+
+
+;;
+;; Double-letter constraints starting with O follow.
+;;
+
+
+(define_constraint "Os"
+ "@internal
+ Signed extended immediate value (-2G .. 2G-1).
+ This constraint will only match if the machine provides
+ the extended-immediate facility."
+ (and (match_code "const_int")
+ (match_test "s390_O_constraint_str ('s', ival)")))
+
+
+(define_constraint "Op"
+ "@internal
+ Positive extended immediate value (0 .. 4G-1).
+ This constraint will only match if the machine provides
+ the extended-immediate facility."
+ (and (match_code "const_int")
+ (match_test "s390_O_constraint_str ('p', ival)")))
+
+
+(define_constraint "On"
+ "@internal
+ Negative extended immediate value (-4G .. -1).
+ This constraint will only match if the machine provides
+ the extended-immediate facility."
+ (and (match_code "const_int")
+ (match_test "s390_O_constraint_str ('n', ival)")))
+
+
+
+
+;;
+;; Memory constraints follow.
+;;
+
+(define_memory_constraint "Q"
+ "Memory reference without index register and with short displacement"
+ (match_test "s390_mem_constraint (\"Q\", op)"))
+
+
+
+(define_memory_constraint "R"
+ "Memory reference with index register and short displacement"
+ (match_test "s390_mem_constraint (\"R\", op)"))
+
+
+(define_memory_constraint "S"
+ "Memory reference without index register but with long displacement"
+ (match_test "s390_mem_constraint (\"S\", op)"))
+
+
+(define_memory_constraint "T"
+ "Memory reference with index register and long displacement"
+ (match_test "s390_mem_constraint (\"T\", op)"))
+
+
+
+(define_memory_constraint "AQ"
+ "@internal
+ Offsettable memory reference without index register and with short displacement"
+ (match_test "s390_mem_constraint (\"AQ\", op)"))
+
+
+(define_memory_constraint "AR"
+ "@internal
+ Offsettable memory reference with index register and short displacement"
+ (match_test "s390_mem_constraint (\"AR\", op)"))
+
+
+(define_memory_constraint "AS"
+ "@internal
+ Offsettable memory reference without index register but with long displacement"
+ (match_test "s390_mem_constraint (\"AS\", op)"))
+
+
+(define_memory_constraint "AT"
+ "@internal
+ Offsettable memory reference with index register and long displacement"
+ (match_test "s390_mem_constraint (\"AT\", op)"))
+
+
+
+(define_constraint "BQ"
+ "@internal
+ Memory reference without index register and with short
+ displacement that does *not* refer to a literal pool entry."
+ (match_test "s390_mem_constraint (\"BQ\", op)"))
+
+
+(define_constraint "BR"
+ "@internal
+ Memory reference with index register and short displacement that
+ does *not* refer to a literal pool entry. "
+ (match_test "s390_mem_constraint (\"BR\", op)"))
+
+
+(define_constraint "BS"
+ "@internal
+ Memory reference without index register but with long displacement
+ that does *not* refer to a literal pool entry. "
+ (match_test "s390_mem_constraint (\"BS\", op)"))
+
+
+(define_constraint "BT"
+ "@internal
+ Memory reference with index register and long displacement that
+ does *not* refer to a literal pool entry. "
+ (match_test "s390_mem_constraint (\"BT\", op)"))
+
+
+
+(define_address_constraint "U"
+ "Pointer with short displacement"
+ (match_test "s390_mem_constraint (\"U\", op)"))
+
+
+
+(define_address_constraint "W"
+ "Pointer with long displacement"
+ (match_test "s390_mem_constraint (\"W\", op)"))
diff --git a/contrib/gcc/config/s390/fixdfdi.h b/contrib/gcc/config/s390/fixdfdi.h
index a5b9212..88c2197 100644
--- a/contrib/gcc/config/s390/fixdfdi.h
+++ b/contrib/gcc/config/s390/fixdfdi.h
@@ -17,8 +17,158 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#ifdef L_fixunstfdi
+
+#define EXPD(fp) (((fp.l.i[0]) >> 16) & 0x7FFF)
+#define EXPONENT_BIAS 16383
+#define MANTISSA_BITS 112
+#define PRECISION (MANTISSA_BITS + 1)
+#define SIGNBIT 0x80000000
+#define SIGND(fp) ((fp.l.i[0]) & SIGNBIT)
+#define MANTD_HIGH_LL(fp) ((fp.ll[0] & HIGH_LL_FRAC_MASK) | HIGH_LL_UNIT_BIT)
+#define MANTD_LOW_LL(fp) (fp.ll[1])
+#define FRACD_ZERO_P(fp) (!fp.ll[1] && !(fp.ll[0] & HIGH_LL_FRAC_MASK))
+#define HIGH_LL_FRAC_BITS 48
+#define HIGH_LL_UNIT_BIT ((UDItype_x)1 << HIGH_LL_FRAC_BITS)
+#define HIGH_LL_FRAC_MASK (HIGH_LL_UNIT_BIT - 1)
+
+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 {
+ long double d;
+ struct {
+ SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */
+ } l;
+ UDItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */
+};
+
+UDItype_x __fixunstfdi (long double a1);
+
+/* convert double to unsigned int */
+UDItype_x
+__fixunstfdi (long double a1)
+{
+ register union double_long dl1;
+ register int exp;
+ register UDItype_x l;
+
+ dl1.d = a1;
+
+ /* +/- 0, denormalized, negative */
+ if (!EXPD (dl1) || SIGND(dl1))
+ return 0;
+
+ /* The exponent - considered the binary point at the right end of
+ the mantissa. */
+ exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
+
+ /* number < 1: If the mantissa would need to be right-shifted more bits than
+ its size (plus the implied one bit on the left) the result would be
+ zero. */
+ if (exp <= -PRECISION)
+ return 0;
+
+ /* NaN: All exponent bits set and a nonzero fraction. */
+ if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
+ return 0x0ULL;
+
+ /* If the upper ll part of the mantissa isn't
+ zeroed out after shifting the number would be to large. */
+ if (exp >= -HIGH_LL_FRAC_BITS)
+ return 0xFFFFFFFFFFFFFFFFULL;
+
+ exp += HIGH_LL_FRAC_BITS + 1;
+
+ l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
+ | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
+
+ return l >> -exp;
+}
+#define __fixunstfdi ___fixunstfdi
+#endif
+#undef L_fixunstfdi
+
+#ifdef L_fixtfdi
+#define EXPD(fp) (((fp.l.i[0]) >> 16) & 0x7FFF)
+#define EXPONENT_BIAS 16383
+#define MANTISSA_BITS 112
+#define PRECISION (MANTISSA_BITS + 1)
+#define SIGNBIT 0x80000000
+#define SIGND(fp) ((fp.l.i[0]) & SIGNBIT)
+#define MANTD_HIGH_LL(fp) ((fp.ll[0] & HIGH_LL_FRAC_MASK) | HIGH_LL_UNIT_BIT)
+#define MANTD_LOW_LL(fp) (fp.ll[1])
+#define FRACD_ZERO_P(fp) (!fp.ll[1] && !(fp.ll[0] & HIGH_LL_FRAC_MASK))
+#define HIGH_LL_FRAC_BITS 48
+#define HIGH_LL_UNIT_BIT ((UDItype_x)1 << HIGH_LL_FRAC_BITS)
+#define HIGH_LL_FRAC_MASK (HIGH_LL_UNIT_BIT - 1)
+
+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 {
+ long double d;
+ struct {
+ SItype_x i[4]; /* 32 bit parts: 0 upper ... 3 lowest */
+ } l;
+ DItype_x ll[2]; /* 64 bit parts: 0 upper, 1 lower */
+};
+
+DItype_x __fixtfdi (long double a1);
+
+/* convert double to unsigned int */
+DItype_x
+__fixtfdi (long double a1)
+{
+ register union double_long dl1;
+ register int exp;
+ register UDItype_x l;
+
+ dl1.d = a1;
+
+ /* +/- 0, denormalized */
+ if (!EXPD (dl1))
+ return 0;
+
+ /* The exponent - considered the binary point at the right end of
+ the mantissa. */
+ exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
+
+ /* number < 1: If the mantissa would need to be right-shifted more bits than
+ its size the result would be zero. */
+ if (exp <= -PRECISION)
+ return 0;
+
+ /* NaN: All exponent bits set and a nonzero fraction. */
+ if ((EXPD(dl1) == 0x7fff) && !FRACD_ZERO_P (dl1))
+ return 0x8000000000000000ULL;
+
+ /* If the upper ll part of the mantissa isn't
+ zeroed out after shifting the number would be to large. */
+ if (exp >= -HIGH_LL_FRAC_BITS)
+ {
+ l = (long long)1 << 63; /* long int min */
+ return SIGND (dl1) ? l : l - 1;
+ }
+
+ /* The extra bit is needed for the sign bit. */
+ exp += HIGH_LL_FRAC_BITS + 1;
+
+ l = MANTD_LOW_LL (dl1) >> (HIGH_LL_FRAC_BITS + 1)
+ | MANTD_HIGH_LL (dl1) << (64 - (HIGH_LL_FRAC_BITS + 1));
+
+ return SIGND (dl1) ? -(l >> -exp) : l >> -exp;
+}
+#define __fixtfdi ___fixtfdi
+#endif
+#undef L_fixtfdi
#ifdef L_fixunsdfdi
#define EXPD(fp) (((fp.l.upper) >> 20) & 0x7FF)
@@ -55,7 +205,7 @@ __fixunsdfdi (double a1)
dl1.d = a1;
- /* +/- 0, denormalized, negativ */
+ /* +/- 0, denormalized, negative */
if (!EXPD (dl1) || SIGND(dl1))
return 0;
@@ -199,7 +349,7 @@ __fixunssfdi (float a1)
fl1.f = a1;
- /* +/- 0, denormalized, negativ */
+ /* +/- 0, denormalized, negative */
if (!EXP (fl1) || SIGN(fl1))
return 0;
@@ -305,4 +455,3 @@ __fixsfdi (float a1)
#define __fixsfdi ___fixsfdi
#endif
#undef L_fixsfdi
-
diff --git a/contrib/gcc/config/s390/libgcc-glibc.ver b/contrib/gcc/config/s390/libgcc-glibc.ver
index 1d9e229..e9413d0 100644
--- a/contrib/gcc/config/s390/libgcc-glibc.ver
+++ b/contrib/gcc/config/s390/libgcc-glibc.ver
@@ -39,3 +39,36 @@ GLIBC_2.2 {
}
%endif
+# With GCC 4.1.0 long double 128 bit support was introduced. The
+# following symbols coming from libgcc are enabled when -mlong-double-128
+# is specified. These lines make the symbols to get a @@GCC_4.1.0 attached.
+
+%exclude {
+ __divtc3
+ __multc3
+ __powitf2
+ __fixtfti
+ __fixunstfti
+ __floattitf
+
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+}
+
+GCC_4.1.0 {
+ __divtc3
+ __multc3
+ __powitf2
+
+%ifdef __s390x__
+ __fixtfti
+ __fixunstfti
+ __floattitf
+
+%else
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+%endif
+}
diff --git a/contrib/gcc/config/s390/linux-unwind.h b/contrib/gcc/config/s390/linux-unwind.h
new file mode 100644
index 0000000..221a5d4
--- /dev/null
+++ b/contrib/gcc/config/s390/linux-unwind.h
@@ -0,0 +1,134 @@
+/* DWARF2 EH unwinding support for S/390 Linux.
+ Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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 with other programs, and to distribute
+those programs 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 another program.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
+
+static _Unwind_Reason_Code
+s390_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned char *pc = context->ra;
+ long new_cfa;
+ int i;
+
+ typedef struct
+ {
+ unsigned long psw_mask;
+ unsigned long psw_addr;
+ unsigned long gprs[16];
+ unsigned int acrs[16];
+ unsigned int fpc;
+ unsigned int __pad;
+ double fprs[16];
+ } __attribute__ ((__aligned__ (8))) sigregs_;
+
+ sigregs_ *regs;
+ int *signo;
+
+ /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */
+ if (pc[0] != 0x0a || (pc[1] != 119 && pc[1] != 173))
+ return _URC_END_OF_STACK;
+
+ /* Legacy frames:
+ old signal mask (8 bytes)
+ pointer to sigregs (8 bytes) - points always to next location
+ sigregs
+ retcode
+ This frame layout was used on kernels < 2.6.9 for non-RT frames,
+ and on kernels < 2.4.13 for RT frames as well. Note that we need
+ to look at RA to detect this layout -- this means that if you use
+ sa_restorer to install a different signal restorer on a legacy
+ kernel, unwinding from signal frames will not work. */
+ if (context->ra == context->cfa + 16 + sizeof (sigregs_))
+ {
+ regs = (sigregs_ *)(context->cfa + 16);
+ signo = NULL;
+ }
+
+ /* New-style RT frame:
+ retcode + alignment (8 bytes)
+ siginfo (128 bytes)
+ ucontext (contains sigregs) */
+ else if (pc[1] == 173 /* __NR_rt_sigreturn */)
+ {
+ struct ucontext_
+ {
+ unsigned long uc_flags;
+ struct ucontext_ *uc_link;
+ unsigned long uc_stack[3];
+ sigregs_ uc_mcontext;
+ } *uc = context->cfa + 8 + 128;
+
+ regs = &uc->uc_mcontext;
+ signo = context->cfa + sizeof(long);
+ }
+
+ /* New-style non-RT frame:
+ old signal mask (8 bytes)
+ pointer to sigregs (followed by signal number) */
+ else
+ {
+ regs = *(sigregs_ **)(context->cfa + 8);
+ signo = (int *)(regs + 1);
+ }
+
+ new_cfa = regs->gprs[15] + 16*sizeof(long) + 32;
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 15;
+ fs->cfa_offset =
+ new_cfa - (long) context->cfa + 16*sizeof(long) + 32;
+
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset =
+ (long)&regs->gprs[i] - new_cfa;
+ }
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[16+i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[16+i].loc.offset =
+ (long)&regs->fprs[i] - new_cfa;
+ }
+
+ /* Load return addr from PSW into dummy register 32. */
+
+ fs->regs.reg[32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[32].loc.offset = (long)&regs->psw_addr - new_cfa;
+ fs->retaddr_column = 32;
+ /* SIGILL, SIGFPE and SIGTRAP are delivered with psw_addr
+ after the faulting instruction rather than before it.
+ Don't set FS->signal_frame in that case. */
+ if (!signo || (*signo != 4 && *signo != 5 && *signo != 8))
+ fs->signal_frame = 1;
+
+ return _URC_NO_REASON;
+}
diff --git a/contrib/gcc/config/s390/linux.h b/contrib/gcc/config/s390/linux.h
index 9a6db9d..fd8ef0b 100644
--- a/contrib/gcc/config/s390/linux.h
+++ b/contrib/gcc/config/s390/linux.h
@@ -1,5 +1,6 @@
/* Definitions for Linux for S/390.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -17,8 +18,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef _LINUX_H
#define _LINUX_H
@@ -54,11 +55,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
do \
{ \
LINUX_TARGET_OS_CPP_BUILTINS(); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
@@ -77,6 +73,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#define MULTILIB_DEFAULTS { "m31" }
#endif
+#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
+#define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1"
+
#undef LINK_SPEC
#define LINK_SPEC \
"%{m31:-m elf_s390}%{m64:-m elf64_s390} \
@@ -86,88 +85,22 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
%{!static: \
%{rdynamic:-export-dynamic} \
%{!dynamic-linker: \
- %{m31:-dynamic-linker /lib/ld.so.1} \
- %{m64:-dynamic-linker /lib/ld64.so.1}}}}"
+ %{m31:-dynamic-linker " LINUX_DYNAMIC_LINKER32 "} \
+ %{m64:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}}}}"
+#define CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned char *pc_ = (CONTEXT)->ra; \
- long new_cfa_; \
- int i_; \
- \
- typedef struct \
- { \
- unsigned long psw_mask; \
- unsigned long psw_addr; \
- unsigned long gprs[16]; \
- unsigned int acrs[16]; \
- unsigned int fpc; \
- unsigned int __pad; \
- double fprs[16]; \
- } __attribute__ ((__aligned__ (8))) sigregs_; \
- \
- sigregs_ *regs_; \
- \
- /* svc $__NR_sigreturn or svc $__NR_rt_sigreturn */ \
- if (pc_[0] != 0x0a || (pc_[1] != 119 && pc_[1] != 173)) \
- break; \
- \
- /* New-style RT frame: \
- retcode + alignment (8 bytes) \
- siginfo (128 bytes) \
- ucontext (contains sigregs) */ \
- if ((CONTEXT)->ra == (CONTEXT)->cfa) \
- { \
- struct ucontext_ \
- { \
- unsigned long uc_flags; \
- struct ucontext_ *uc_link; \
- unsigned long uc_stack[3]; \
- sigregs_ uc_mcontext; \
- } *uc_ = (CONTEXT)->cfa + 8 + 128; \
- \
- regs_ = &uc_->uc_mcontext; \
- } \
- \
- /* Old-style RT frame and all non-RT frames: \
- old signal mask (8 bytes) \
- pointer to sigregs */ \
- else \
- { \
- regs_ = *(sigregs_ **)((CONTEXT)->cfa + 8); \
- } \
- \
- new_cfa_ = regs_->gprs[15] + 16*sizeof(long) + 32; \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 15; \
- (FS)->cfa_offset = \
- new_cfa_ - (long) (CONTEXT)->cfa + 16*sizeof(long) + 32; \
- \
- for (i_ = 0; i_ < 16; i_++) \
- { \
- (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_].loc.offset = \
- (long)&regs_->gprs[i_] - new_cfa_; \
- } \
- for (i_ = 0; i_ < 16; i_++) \
- { \
- (FS)->regs.reg[16+i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[16+i_].loc.offset = \
- (long)&regs_->fprs[i_] - new_cfa_; \
- } \
- \
- /* Load return addr from PSW into dummy register 32. */ \
- (FS)->regs.reg[32].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[32].loc.offset = (long)&regs_->psw_addr - new_cfa_; \
- (FS)->retaddr_column = 32; \
- \
- goto SUCCESS; \
- } while (0)
+#define MD_UNWIND_SUPPORT "config/s390/linux-unwind.h"
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* s390 glibc provides __stack_chk_guard in 0x14(tp),
+ s390x glibc provides it at 0x28(tp). */
+#define TARGET_THREAD_SSP_OFFSET (TARGET_64BIT ? 0x28 : 0x14)
+#endif
+
+/* Define if long doubles should be mangled as 'g'. */
+#define TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
#endif
diff --git a/contrib/gcc/config/s390/predicates.md b/contrib/gcc/config/s390/predicates.md
new file mode 100644
index 0000000..9f7ea36
--- /dev/null
+++ b/contrib/gcc/config/s390/predicates.md
@@ -0,0 +1,379 @@
+;; Predicate definitions for S/390 and zSeries.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
+;; Ulrich Weigand (uweigand@de.ibm.com).
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; OP is the current operation.
+;; MODE is the current operation mode.
+
+;; operands --------------------------------------------------------------
+
+;; Return true if OP a (const_int 0) operand.
+
+(define_predicate "const0_operand"
+ (and (match_code "const_int, const_double")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; Return true if OP is constant.
+
+(define_special_predicate "consttable_operand"
+ (and (match_code "symbol_ref, label_ref, const, const_int, const_double")
+ (match_test "CONSTANT_P (op)")))
+
+;; Return true if OP is a valid S-type operand.
+
+(define_predicate "s_operand"
+ (and (match_code "subreg, mem")
+ (match_operand 0 "general_operand"))
+{
+ /* Just like memory_operand, allow (subreg (mem ...))
+ after reload. */
+ if (reload_completed
+ && GET_CODE (op) == SUBREG
+ && GET_CODE (SUBREG_REG (op)) == MEM)
+ op = SUBREG_REG (op);
+
+ if (GET_CODE (op) != MEM)
+ return false;
+ if (!s390_legitimate_address_without_index_p (op))
+ return false;
+
+ return true;
+})
+
+;; Return true if OP is a valid operand for the BRAS instruction.
+;; Allow SYMBOL_REFs and @PLT stubs.
+
+(define_special_predicate "bras_sym_operand"
+ (ior (and (match_code "symbol_ref")
+ (match_test "!flag_pic || SYMBOL_REF_LOCAL_P (op)"))
+ (and (match_code "const")
+ (and (match_test "GET_CODE (XEXP (op, 0)) == UNSPEC")
+ (match_test "XINT (XEXP (op, 0), 1) == UNSPEC_PLT")))))
+
+;; Return true if OP is a PLUS that is not a legitimate
+;; operand for the LA instruction.
+
+(define_predicate "s390_plus_operand"
+ (and (match_code "plus")
+ (and (match_test "mode == Pmode")
+ (match_test "!legitimate_la_operand_p (op)"))))
+
+;; Return true if OP is a valid operand as shift count or setmem.
+
+(define_predicate "shift_count_or_setmem_operand"
+ (match_code "reg, subreg, plus, const_int")
+{
+ HOST_WIDE_INT offset;
+ rtx base;
+
+ /* Extract base register and offset. */
+ if (!s390_decompose_shift_count (op, &base, &offset))
+ return false;
+
+ /* Don't allow any non-base hard registers. Doing so without
+ confusing reload and/or regrename would be tricky, and doesn't
+ buy us much anyway. */
+ if (base && REGNO (base) < FIRST_PSEUDO_REGISTER && !ADDR_REG_P (base))
+ return false;
+
+ /* Unfortunately we have to reject constants that are invalid
+ for an address, or else reload will get confused. */
+ if (!DISP_IN_RANGE (offset))
+ return false;
+
+ return true;
+})
+
+;; Return true if OP a valid operand for the LARL instruction.
+
+(define_predicate "larl_operand"
+ (match_code "label_ref, symbol_ref, const, const_int, const_double")
+{
+ /* Allow labels and local symbols. */
+ if (GET_CODE (op) == LABEL_REF)
+ return true;
+ if (GET_CODE (op) == SYMBOL_REF)
+ return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+ && SYMBOL_REF_TLS_MODEL (op) == 0
+ && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+
+ /* Everything else must have a CONST, so strip it. */
+ if (GET_CODE (op) != CONST)
+ return false;
+ op = XEXP (op, 0);
+
+ /* Allow adding *even* in-range constants. */
+ if (GET_CODE (op) == PLUS)
+ {
+ if (GET_CODE (XEXP (op, 1)) != CONST_INT
+ || (INTVAL (XEXP (op, 1)) & 1) != 0)
+ return false;
+ if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 31
+ || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 31))
+ return false;
+ op = XEXP (op, 0);
+ }
+
+ /* Labels and local symbols allowed here as well. */
+ if (GET_CODE (op) == LABEL_REF)
+ return true;
+ if (GET_CODE (op) == SYMBOL_REF)
+ return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
+ && SYMBOL_REF_TLS_MODEL (op) == 0
+ && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+
+ /* Now we must have a @GOTENT offset or @PLT stub
+ or an @INDNTPOFF TLS offset. */
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == UNSPEC_GOTENT)
+ return true;
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == UNSPEC_PLT)
+ return true;
+ if (GET_CODE (op) == UNSPEC
+ && XINT (op, 1) == UNSPEC_INDNTPOFF)
+ return true;
+
+ return false;
+})
+
+;; operators --------------------------------------------------------------
+
+;; Return nonzero if OP is a valid comparison operator
+;; for a branch condition.
+
+(define_predicate "s390_comparison"
+ (match_code "eq, ne, lt, gt, le, ge, ltu, gtu, leu, geu,
+ uneq, unlt, ungt, unle, unge, ltgt,
+ unordered, ordered")
+{
+ if (GET_CODE (XEXP (op, 0)) != REG
+ || REGNO (XEXP (op, 0)) != CC_REGNUM
+ || XEXP (op, 1) != const0_rtx)
+ return false;
+
+ return (s390_branch_condition_mask (op) >= 0);
+})
+
+;; Return nonzero if OP is a valid comparison operator
+;; for an ALC condition.
+
+(define_predicate "s390_alc_comparison"
+ (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
+{
+ while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+ op = XEXP (op, 0);
+
+ if (!COMPARISON_P (op))
+ return false;
+
+ if (GET_CODE (XEXP (op, 0)) != REG
+ || REGNO (XEXP (op, 0)) != CC_REGNUM
+ || XEXP (op, 1) != const0_rtx)
+ return false;
+
+ switch (GET_MODE (XEXP (op, 0)))
+ {
+ case CCL1mode:
+ return GET_CODE (op) == LTU;
+
+ case CCL2mode:
+ return GET_CODE (op) == LEU;
+
+ case CCL3mode:
+ return GET_CODE (op) == GEU;
+
+ case CCUmode:
+ return GET_CODE (op) == GTU;
+
+ case CCURmode:
+ return GET_CODE (op) == LTU;
+
+ case CCSmode:
+ return GET_CODE (op) == UNGT;
+
+ case CCSRmode:
+ return GET_CODE (op) == UNLT;
+
+ default:
+ return false;
+ }
+})
+
+;; Return nonzero if OP is a valid comparison operator
+;; for an SLB condition.
+
+(define_predicate "s390_slb_comparison"
+ (match_code "zero_extend, sign_extend, ltu, gtu, leu, geu")
+{
+ while (GET_CODE (op) == ZERO_EXTEND || GET_CODE (op) == SIGN_EXTEND)
+ op = XEXP (op, 0);
+
+ if (!COMPARISON_P (op))
+ return false;
+
+ if (GET_CODE (XEXP (op, 0)) != REG
+ || REGNO (XEXP (op, 0)) != CC_REGNUM
+ || XEXP (op, 1) != const0_rtx)
+ return false;
+
+ switch (GET_MODE (XEXP (op, 0)))
+ {
+ case CCL1mode:
+ return GET_CODE (op) == GEU;
+
+ case CCL2mode:
+ return GET_CODE (op) == GTU;
+
+ case CCL3mode:
+ return GET_CODE (op) == LTU;
+
+ case CCUmode:
+ return GET_CODE (op) == LEU;
+
+ case CCURmode:
+ return GET_CODE (op) == GEU;
+
+ case CCSmode:
+ return GET_CODE (op) == LE;
+
+ case CCSRmode:
+ return GET_CODE (op) == GE;
+
+ default:
+ return false;
+ }
+})
+
+;; Return true if OP is a load multiple operation. It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_predicate "load_multiple_operation"
+ (match_code "parallel")
+{
+ enum machine_mode elt_mode;
+ int count = XVECLEN (op, 0);
+ unsigned int dest_regno;
+ rtx src_addr;
+ int i, off;
+
+ /* 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 false;
+
+ dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
+ src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
+ elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
+
+ /* Check, is base, or base + displacement. */
+
+ if (GET_CODE (src_addr) == REG)
+ off = 0;
+ else if (GET_CODE (src_addr) == PLUS
+ && GET_CODE (XEXP (src_addr, 0)) == REG
+ && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
+ {
+ off = INTVAL (XEXP (src_addr, 1));
+ src_addr = XEXP (src_addr, 0);
+ }
+ else
+ return false;
+
+ 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)) != elt_mode
+ || REGNO (SET_DEST (elt)) != dest_regno + i
+ || GET_CODE (SET_SRC (elt)) != MEM
+ || GET_MODE (SET_SRC (elt)) != elt_mode
+ || 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))
+ != off + i * GET_MODE_SIZE (elt_mode))
+ return false;
+ }
+
+ return true;
+})
+
+;; Return true if OP is a store multiple operation. It is known to be a
+;; PARALLEL and the first section will be tested.
+
+(define_special_predicate "store_multiple_operation"
+ (match_code "parallel")
+{
+ enum machine_mode elt_mode;
+ int count = XVECLEN (op, 0);
+ unsigned int src_regno;
+ rtx dest_addr;
+ int i, off;
+
+ /* 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 false;
+
+ src_regno = REGNO (SET_SRC (XVECEXP (op, 0, 0)));
+ dest_addr = XEXP (SET_DEST (XVECEXP (op, 0, 0)), 0);
+ elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
+
+ /* Check, is base, or base + displacement. */
+
+ if (GET_CODE (dest_addr) == REG)
+ off = 0;
+ else if (GET_CODE (dest_addr) == PLUS
+ && GET_CODE (XEXP (dest_addr, 0)) == REG
+ && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
+ {
+ off = INTVAL (XEXP (dest_addr, 1));
+ dest_addr = XEXP (dest_addr, 0);
+ }
+ else
+ return false;
+
+ 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)) != elt_mode
+ || REGNO (SET_SRC (elt)) != src_regno + i
+ || GET_CODE (SET_DEST (elt)) != MEM
+ || GET_MODE (SET_DEST (elt)) != elt_mode
+ || 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))
+ != off + i * GET_MODE_SIZE (elt_mode))
+ return false;
+ }
+ return true;
+})
diff --git a/contrib/gcc/config/s390/s390-modes.def b/contrib/gcc/config/s390/s390-modes.def
index 0875955..afcfb1b 100644
--- a/contrib/gcc/config/s390/s390-modes.def
+++ b/contrib/gcc/config/s390/s390-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -17,21 +17,154 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* 256-bit integer mode is needed for STACK_SAVEAREA_MODE. */
INT_MODE (OI, 32);
+/* Define TFmode to work around reload problem PR 20927. */
+FLOAT_MODE (TF, 16, ieee_quad_format);
+
/* Add any extra modes needed to represent the condition code. */
+/*
+
+Condition Codes
+
+Check for zero
+
+CCZ: EQ NE NE NE
+CCZ1: EQ NE (CS)
+
+Unsigned compares
+
+CCU: EQ LTU GTU NE (CLG/R, CL/R/Y, CLM/Y, CLI/Y)
+CCUR: EQ GTU LTU NE (CLGF/R)
+
+Signed compares
+
+CCS: EQ LT GT UNORDERED (LTGFR, LTGR, LTR, ICM/Y,
+ LTDBR, LTDR, LTEBR, LTER,
+ CG/R, C/R/Y, CGHI, CHI,
+ CDB/R, CD/R, CEB/R, CE/R,
+ ADB/R, AEB/R, SDB/R, SEB/R,
+ SRAG, SRA, SRDA)
+CCSR: EQ GT LT UNORDERED (CGF/R, CH/Y)
+
+Condition codes resulting from add with overflow
+
+CCA: EQ LT GT Overflow
+CCAP: EQ LT GT LT (AGHI, AHI)
+CCAN: EQ LT GT GT (AGHI, AHI)
+
+Condition codes of unsigned adds and subs
+
+CCL: EQ NE EQ NE (ALGF/R, ALG/R, AL/R/Y,
+ ALCG/R, ALC/R,
+ SLGF/R, SLG/R, SL/R/Y,
+ SLBG/R, SLB/R)
+CCL1: GEU GEU LTU LTU (ALG/R, AL/R/Y)
+CCL2: GTU GTU LEU LEU (SLG/R, SL/R/Y)
+CCL3: EQ LTU EQ GTU (SLG/R, SL/R/Y)
+
+Test under mask checks
+
+CCT: EQ NE NE NE (ICM/Y, TML, CG/R, CGHI,
+ C/R/Y, CHI, NG/R, N/R/Y,
+ OG/R, O/R/Y, XG/R, X/R/Y)
+CCT1: NE EQ NE NE (TMH, TML)
+CCT2: NE NE EQ NE (TMH, TML)
+CCT3: NE NE NE EQ (TMH, TML)
+
+CCA and CCT modes are request only modes. These modes are never returned by
+s390_select_cc_mode. They are only intended to match other modes.
+
+Requested mode -> Destination CC register mode
+
+CCS, CCU, CCT, CCSR, CCUR -> CCZ
+CCA -> CCAP, CCAN
+
+
+*** Comments ***
+
+CCAP, CCAN
+
+The CC obtained from add instruction usually can't be used for comparisons
+because its coupling with overflow flag. In case of an overflow the
+less than/greater than data are lost. Nevertheless a comparison can be done
+whenever immediate values are involved because they are known at compile time.
+If you know whether the used constant is positive or negative you can predict
+the sign of the result even in case of an overflow.
+
+
+CCT, CCT1, CCT2, CCT3
+
+If bits of an integer masked with an AND instruction are checked, the test under
+mask instructions turn out to be very handy for a set of special cases.
+The simple cases are checks whether all masked bits are zero or ones:
+
+ int a;
+ if ((a & (16 + 128)) == 0) -> CCT/CCZ
+ if ((a & (16 + 128)) == 16 + 128) -> CCT3
+
+Using two extra modes makes it possible to do complete checks on two bits of an
+integer (This is possible on register operands only. TM does not provide the
+information necessary for CCT1 and CCT2 modes.):
+
+ int a;
+ if ((a & (16 + 128)) == 16) -> CCT1
+ if ((a & (16 + 128)) == 128) -> CCT2
+
+
+CCSR, CCUR
+
+There are several instructions comparing 32 bit with 64 bit unsigned/signed
+values. Such instructions can be considered to have a builtin zero/sign_extend.
+The problem is that in the RTL (to be canonical) the zero/sign extended operand
+has to be the first one but the machine instructions like it the other way
+around. The following both modes can be considered as CCS and CCU modes with
+exchanged operands.
+
+
+CCL1, CCL2
+
+These modes represent the result of overflow checks.
+
+if (a + b < a) -> CCL1 state of the carry bit (CC2 | CC3)
+if (a - b > a) -> CCL2 state of the borrow bit (CC0 | CC1)
+
+They are used when multi word numbers are computed dealing one SImode part after
+another or whenever manual overflow checks like the examples above are
+compiled.
+
+
+CCL3
+
+A logical subtract instruction sets the borrow bit in case of an overflow.
+The resulting condition code of those instructions is represented by the
+CCL3 mode. Together with the CCU mode this mode is used for jumpless
+implementations of several if-constructs - see s390_expand_addcc for more
+details.
+
+CCZ1
+
+The compare and swap instructions sets the condition code to 0/1 if the
+operands were equal/unequal. The CCZ1 mode ensures the result can be
+effectively placed into a register.
+
+*/
+
+
CC_MODE (CCZ);
+CC_MODE (CCZ1);
CC_MODE (CCA);
CC_MODE (CCAP);
CC_MODE (CCAN);
CC_MODE (CCL);
CC_MODE (CCL1);
CC_MODE (CCL2);
+CC_MODE (CCL3);
CC_MODE (CCU);
CC_MODE (CCUR);
CC_MODE (CCS);
diff --git a/contrib/gcc/config/s390/s390-protos.h b/contrib/gcc/config/s390/s390-protos.h
index 90815a8..8b2db85 100644
--- a/contrib/gcc/config/s390/s390-protos.h
+++ b/contrib/gcc/config/s390/s390-protos.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390.
- Copyright (C) 2000, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com)
This file is part of GCC.
@@ -16,52 +16,64 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+
+
+/* Prototypes of functions used for constraint evaluation in
+ constraints.c. */
+
+extern int s390_mem_constraint (const char *str, rtx op);
+extern int s390_O_constraint_str (const char c, HOST_WIDE_INT value);
+extern int s390_N_constraint_str (const char *str, HOST_WIDE_INT value);
+extern int s390_float_const_zero_p (rtx value);
+
+
/* Declare functions in s390.c. */
extern void optimization_options (int, int);
extern void override_options (void);
-extern HOST_WIDE_INT s390_arg_frame_offset (void);
-extern void s390_load_got (int);
+extern bool s390_can_eliminate (int, int);
+extern HOST_WIDE_INT s390_initial_elimination_offset (int, int);
extern void s390_emit_prologue (void);
-extern void s390_emit_epilogue (void);
+extern void s390_emit_epilogue (bool);
extern void s390_function_profiler (FILE *, int);
+extern void s390_conditional_register_usage (void);
+extern void s390_set_has_landing_pad_p (bool);
+extern bool s390_hard_regno_mode_ok (unsigned int, enum machine_mode);
+extern bool s390_hard_regno_rename_ok (unsigned int, unsigned int);
+extern bool s390_class_max_nregs (enum reg_class, enum machine_mode);
#ifdef RTX_CODE
extern int s390_extra_constraint_str (rtx, int, const char *);
extern int s390_const_ok_for_constraint_p (HOST_WIDE_INT, int, const char *);
-extern int const0_operand (rtx, enum machine_mode);
-extern int consttable_operand (rtx, enum machine_mode);
-extern int larl_operand (rtx, enum machine_mode);
-extern int s_operand (rtx, enum machine_mode);
-extern int s_imm_operand (rtx, enum machine_mode);
-extern int shift_count_operand (rtx, enum machine_mode);
-extern int bras_sym_operand (rtx, enum machine_mode);
-extern int load_multiple_operation (rtx, enum machine_mode);
-extern int store_multiple_operation (rtx, enum machine_mode);
+extern int s390_const_double_ok_for_constraint_p (rtx, int, const char *);
extern int s390_single_part (rtx, enum machine_mode, enum machine_mode, int);
extern unsigned HOST_WIDE_INT s390_extract_part (rtx, enum machine_mode, int);
extern bool s390_split_ok_p (rtx, rtx, enum machine_mode, int);
+extern bool s390_overlap_p (rtx, rtx, HOST_WIDE_INT);
+extern bool s390_offset_p (rtx, rtx, rtx);
extern int tls_symbolic_operand (rtx);
-extern int s390_match_ccmode (rtx, enum machine_mode);
-extern enum machine_mode s390_tm_ccmode (rtx, rtx, int);
+extern bool s390_match_ccmode (rtx, enum machine_mode);
+extern enum machine_mode s390_tm_ccmode (rtx, rtx, bool);
extern enum machine_mode s390_select_ccmode (enum rtx_code, rtx, rtx);
-extern int s390_alc_comparison (rtx op, enum machine_mode mode);
-extern int s390_slb_comparison (rtx op, enum machine_mode mode);
-extern int symbolic_reference_mentioned_p (rtx);
-extern int tls_symbolic_reference_mentioned_p (rtx);
-extern rtx s390_tls_get_offset (void);
-extern int legitimate_la_operand_p (rtx);
-extern int preferred_la_operand_p (rtx);
+extern void s390_canonicalize_comparison (enum rtx_code *, rtx *, rtx *);
+extern rtx s390_emit_compare (enum rtx_code, rtx, rtx);
+extern void s390_emit_jump (rtx, rtx);
+extern bool symbolic_reference_mentioned_p (rtx);
+extern bool tls_symbolic_reference_mentioned_p (rtx);
+extern bool legitimate_la_operand_p (rtx);
+extern bool preferred_la_operand_p (rtx, rtx);
extern int legitimate_pic_operand_p (rtx);
extern int legitimate_constant_p (rtx);
-extern int legitimate_reload_constant_p (rtx);
-extern int legitimate_address_p (enum machine_mode, rtx, int);
+extern bool legitimate_reload_constant_p (rtx);
+extern bool legitimate_address_p (enum machine_mode, rtx, int);
extern rtx legitimize_pic_address (rtx, rtx);
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
+extern rtx legitimize_reload_address (rtx, enum machine_mode, int, int);
extern enum reg_class s390_preferred_reload_class (rtx, enum reg_class);
extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
enum machine_mode,
@@ -69,37 +81,49 @@ extern enum reg_class s390_secondary_input_reload_class (enum reg_class,
extern enum reg_class s390_secondary_output_reload_class (enum reg_class,
enum machine_mode,
rtx);
-extern int s390_plus_operand (rtx, enum machine_mode);
extern void s390_expand_plus_operand (rtx, rtx, rtx);
extern void emit_symbolic_move (rtx *);
extern void s390_load_address (rtx, rtx);
-extern void s390_expand_movstr (rtx, rtx, rtx);
-extern void s390_expand_clrstr (rtx, rtx);
+extern void s390_expand_movmem (rtx, rtx, rtx);
+extern void s390_expand_setmem (rtx, rtx, rtx);
extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
+extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
+extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
+extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
+extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
+ rtx, rtx, rtx, bool);
extern rtx s390_return_addr_rtx (int, rtx);
+extern rtx s390_back_chain_rtx (void);
+extern rtx s390_emit_call (rtx, rtx, rtx, rtx);
+extern void s390_expand_logical_operator (enum rtx_code,
+ enum machine_mode, rtx *);
+extern bool s390_logical_operator_ok_p (rtx *);
+extern void s390_narrow_logical_operator (enum rtx_code, rtx *, rtx *);
+extern void s390_split_access_reg (rtx, rtx *, rtx *);
-extern void s390_output_symbolic_const (FILE *, rtx);
+extern bool s390_output_addr_const_extra (FILE*, rtx);
extern void print_operand_address (FILE *, rtx);
extern void print_operand (FILE *, rtx, int);
-extern void s390_output_constant_pool (rtx, rtx);
-extern void s390_output_pool_entry (FILE *, rtx, enum machine_mode,
- unsigned int);
+extern void s390_output_pool_entry (rtx, enum machine_mode, unsigned int);
extern void s390_trampoline_template (FILE *);
extern void s390_initialize_trampoline (rtx, rtx, rtx);
extern rtx s390_gen_rtx_const_DI (int, int);
-extern void s390_output_dwarf_dtprel (FILE*, int, rtx);
extern int s390_agen_dep_p (rtx, rtx);
+extern rtx s390_load_got (void);
+extern rtx s390_get_thread_pointer (void);
+extern void s390_emit_tpf_eh_return (rtx);
+extern bool s390_legitimate_address_without_index_p (rtx);
+extern bool s390_decompose_shift_count (rtx, rtx *, HOST_WIDE_INT *);
+extern int s390_branch_condition_mask (rtx);
#endif /* RTX_CODE */
#ifdef TREE_CODE
-extern int s390_function_arg_pass_by_reference (enum machine_mode, tree);
extern void s390_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
tree, int);
#ifdef RTX_CODE
extern rtx s390_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
extern rtx s390_function_value (tree, enum machine_mode);
extern void s390_va_start (tree, rtx);
-extern rtx s390_va_arg (tree, tree);
#endif /* RTX_CODE */
#endif /* TREE_CODE */
diff --git a/contrib/gcc/config/s390/s390.c b/contrib/gcc/config/s390/s390.c
index ced0bf9..86b4b7e 100644
--- a/contrib/gcc/config/s390/s390.c
+++ b/contrib/gcc/config/s390/s390.c
@@ -1,5 +1,5 @@
/* Subroutines used for code generation on IBM S/390 and zSeries
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -18,8 +18,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -50,116 +50,166 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "debug.h"
#include "langhooks.h"
#include "optabs.h"
+#include "tree-gimple.h"
+
+
+/* Define the specific costs for a given cpu. */
+
+struct processor_costs
+{
+ /* multiplication */
+ const int m; /* cost of an M instruction. */
+ const int mghi; /* cost of an MGHI instruction. */
+ const int mh; /* cost of an MH instruction. */
+ const int mhi; /* cost of an MHI instruction. */
+ const int ml; /* cost of an ML instruction. */
+ const int mr; /* cost of an MR instruction. */
+ const int ms; /* cost of an MS instruction. */
+ const int msg; /* cost of an MSG instruction. */
+ const int msgf; /* cost of an MSGF instruction. */
+ const int msgfr; /* cost of an MSGFR instruction. */
+ const int msgr; /* cost of an MSGR instruction. */
+ const int msr; /* cost of an MSR instruction. */
+ const int mult_df; /* cost of multiplication in DFmode. */
+ const int mxbr;
+ /* square root */
+ const int sqxbr; /* cost of square root in TFmode. */
+ const int sqdbr; /* cost of square root in DFmode. */
+ const int sqebr; /* cost of square root in SFmode. */
+ /* multiply and add */
+ const int madbr; /* cost of multiply and add in DFmode. */
+ const int maebr; /* cost of multiply and add in SFmode. */
+ /* division */
+ const int dxbr;
+ const int dxr;
+ const int ddbr;
+ const int ddr;
+ const int debr;
+ const int der;
+ const int dlgr;
+ const int dlr;
+ const int dr;
+ const int dsgfr;
+ const int dsgr;
+};
-/* Machine-specific symbol_ref flags. */
-#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0)
-
-
-static bool s390_assemble_integer (rtx, unsigned int, int);
-static void s390_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT);
-static void s390_encode_section_info (tree, rtx, int);
-static bool s390_cannot_force_const_mem (rtx);
-static rtx s390_delegitimize_address (rtx);
-static bool s390_return_in_memory (tree, tree);
-static void s390_init_builtins (void);
-static rtx s390_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
-static void s390_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
- HOST_WIDE_INT, tree);
-static enum attr_type s390_safe_attr_type (rtx);
-
-static int s390_adjust_cost (rtx, rtx, rtx, int);
-static int s390_adjust_priority (rtx, int);
-static int s390_issue_rate (void);
-static int s390_use_dfa_pipeline_interface (void);
-static int s390_first_cycle_multipass_dfa_lookahead (void);
-static int s390_sched_reorder2 (FILE *, int, rtx *, int *, int);
-static bool s390_rtx_costs (rtx, int, int, int *);
-static int s390_address_cost (rtx);
-static void s390_reorg (void);
-static bool s390_valid_pointer_mode (enum machine_mode);
-static tree s390_build_builtin_va_list (void);
-
-#undef TARGET_ASM_ALIGNED_HI_OP
-#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
-#undef TARGET_ASM_ALIGNED_DI_OP
-#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
-#undef TARGET_ASM_INTEGER
-#define TARGET_ASM_INTEGER s390_assemble_integer
-
-#undef TARGET_ASM_OPEN_PAREN
-#define TARGET_ASM_OPEN_PAREN ""
-
-#undef TARGET_ASM_CLOSE_PAREN
-#define TARGET_ASM_CLOSE_PAREN ""
-
-#undef TARGET_ASM_SELECT_RTX_SECTION
-#define TARGET_ASM_SELECT_RTX_SECTION s390_select_rtx_section
-
-#undef TARGET_ENCODE_SECTION_INFO
-#define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
-
-#ifdef HAVE_AS_TLS
-#undef TARGET_HAVE_TLS
-#define TARGET_HAVE_TLS true
-#endif
-#undef TARGET_CANNOT_FORCE_CONST_MEM
-#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem
-
-#undef TARGET_DELEGITIMIZE_ADDRESS
-#define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
-
-#undef TARGET_RETURN_IN_MEMORY
-#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
-
-#undef TARGET_INIT_BUILTINS
-#define TARGET_INIT_BUILTINS s390_init_builtins
-#undef TARGET_EXPAND_BUILTIN
-#define TARGET_EXPAND_BUILTIN s390_expand_builtin
-
-#undef TARGET_ASM_OUTPUT_MI_THUNK
-#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
-#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
-#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
-
-#undef TARGET_SCHED_ADJUST_COST
-#define TARGET_SCHED_ADJUST_COST s390_adjust_cost
-#undef TARGET_SCHED_ADJUST_PRIORITY
-#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
-#undef TARGET_SCHED_ISSUE_RATE
-#define TARGET_SCHED_ISSUE_RATE s390_issue_rate
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE s390_use_dfa_pipeline_interface
-#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
-#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
-#undef TARGET_SCHED_REORDER2
-#define TARGET_SCHED_REORDER2 s390_sched_reorder2
-
-#undef TARGET_RTX_COSTS
-#define TARGET_RTX_COSTS s390_rtx_costs
-#undef TARGET_ADDRESS_COST
-#define TARGET_ADDRESS_COST s390_address_cost
-
-#undef TARGET_MACHINE_DEPENDENT_REORG
-#define TARGET_MACHINE_DEPENDENT_REORG s390_reorg
-
-#undef TARGET_VALID_POINTER_MODE
-#define TARGET_VALID_POINTER_MODE s390_valid_pointer_mode
+const struct processor_costs *s390_cost;
+
+static const
+struct processor_costs z900_cost =
+{
+ COSTS_N_INSNS (5), /* M */
+ COSTS_N_INSNS (10), /* MGHI */
+ COSTS_N_INSNS (5), /* MH */
+ COSTS_N_INSNS (4), /* MHI */
+ COSTS_N_INSNS (5), /* ML */
+ COSTS_N_INSNS (5), /* MR */
+ COSTS_N_INSNS (4), /* MS */
+ COSTS_N_INSNS (15), /* MSG */
+ COSTS_N_INSNS (7), /* MSGF */
+ COSTS_N_INSNS (7), /* MSGFR */
+ COSTS_N_INSNS (10), /* MSGR */
+ COSTS_N_INSNS (4), /* MSR */
+ COSTS_N_INSNS (7), /* multiplication in DFmode */
+ COSTS_N_INSNS (13), /* MXBR */
+ COSTS_N_INSNS (136), /* SQXBR */
+ COSTS_N_INSNS (44), /* SQDBR */
+ COSTS_N_INSNS (35), /* SQEBR */
+ COSTS_N_INSNS (18), /* MADBR */
+ COSTS_N_INSNS (13), /* MAEBR */
+ COSTS_N_INSNS (134), /* DXBR */
+ COSTS_N_INSNS (135), /* DXR */
+ COSTS_N_INSNS (30), /* DDBR */
+ COSTS_N_INSNS (30), /* DDR */
+ COSTS_N_INSNS (27), /* DEBR */
+ COSTS_N_INSNS (26), /* DER */
+ COSTS_N_INSNS (220), /* DLGR */
+ COSTS_N_INSNS (34), /* DLR */
+ COSTS_N_INSNS (34), /* DR */
+ COSTS_N_INSNS (32), /* DSGFR */
+ COSTS_N_INSNS (32), /* DSGR */
+};
-#undef TARGET_BUILD_BUILTIN_VA_LIST
-#define TARGET_BUILD_BUILTIN_VA_LIST s390_build_builtin_va_list
+static const
+struct processor_costs z990_cost =
+{
+ COSTS_N_INSNS (4), /* M */
+ COSTS_N_INSNS (2), /* MGHI */
+ COSTS_N_INSNS (2), /* MH */
+ COSTS_N_INSNS (2), /* MHI */
+ COSTS_N_INSNS (4), /* ML */
+ COSTS_N_INSNS (4), /* MR */
+ COSTS_N_INSNS (5), /* MS */
+ COSTS_N_INSNS (6), /* MSG */
+ COSTS_N_INSNS (4), /* MSGF */
+ COSTS_N_INSNS (4), /* MSGFR */
+ COSTS_N_INSNS (4), /* MSGR */
+ COSTS_N_INSNS (4), /* MSR */
+ COSTS_N_INSNS (1), /* multiplication in DFmode */
+ COSTS_N_INSNS (28), /* MXBR */
+ COSTS_N_INSNS (130), /* SQXBR */
+ COSTS_N_INSNS (66), /* SQDBR */
+ COSTS_N_INSNS (38), /* SQEBR */
+ COSTS_N_INSNS (1), /* MADBR */
+ COSTS_N_INSNS (1), /* MAEBR */
+ COSTS_N_INSNS (60), /* DXBR */
+ COSTS_N_INSNS (72), /* DXR */
+ COSTS_N_INSNS (40), /* DDBR */
+ COSTS_N_INSNS (44), /* DDR */
+ COSTS_N_INSNS (26), /* DDBR */
+ COSTS_N_INSNS (28), /* DER */
+ COSTS_N_INSNS (176), /* DLGR */
+ COSTS_N_INSNS (31), /* DLR */
+ COSTS_N_INSNS (31), /* DR */
+ COSTS_N_INSNS (31), /* DSGFR */
+ COSTS_N_INSNS (31), /* DSGR */
+};
-struct gcc_target targetm = TARGET_INITIALIZER;
+static const
+struct processor_costs z9_109_cost =
+{
+ COSTS_N_INSNS (4), /* M */
+ COSTS_N_INSNS (2), /* MGHI */
+ COSTS_N_INSNS (2), /* MH */
+ COSTS_N_INSNS (2), /* MHI */
+ COSTS_N_INSNS (4), /* ML */
+ COSTS_N_INSNS (4), /* MR */
+ COSTS_N_INSNS (5), /* MS */
+ COSTS_N_INSNS (6), /* MSG */
+ COSTS_N_INSNS (4), /* MSGF */
+ COSTS_N_INSNS (4), /* MSGFR */
+ COSTS_N_INSNS (4), /* MSGR */
+ COSTS_N_INSNS (4), /* MSR */
+ COSTS_N_INSNS (1), /* multiplication in DFmode */
+ COSTS_N_INSNS (28), /* MXBR */
+ COSTS_N_INSNS (130), /* SQXBR */
+ COSTS_N_INSNS (66), /* SQDBR */
+ COSTS_N_INSNS (38), /* SQEBR */
+ COSTS_N_INSNS (1), /* MADBR */
+ COSTS_N_INSNS (1), /* MAEBR */
+ COSTS_N_INSNS (60), /* DXBR */
+ COSTS_N_INSNS (72), /* DXR */
+ COSTS_N_INSNS (40), /* DDBR */
+ COSTS_N_INSNS (37), /* DDR */
+ COSTS_N_INSNS (26), /* DDBR */
+ COSTS_N_INSNS (28), /* DER */
+ COSTS_N_INSNS (30), /* DLGR */
+ COSTS_N_INSNS (23), /* DLR */
+ COSTS_N_INSNS (23), /* DR */
+ COSTS_N_INSNS (24), /* DSGFR */
+ COSTS_N_INSNS (24), /* DSGR */
+};
extern int reload_completed;
-/* The alias set for prologue/epilogue register save/restore. */
-static int s390_sr_alias_set = 0;
-
/* Save information from a "cmpxx" operation until the branch or scc is
emitted. */
rtx s390_compare_op0, s390_compare_op1;
+/* Save the result of a compare_and_swap until the branch or scc is
+ emitted. */
+rtx s390_compare_emitted = NULL_RTX;
+
/* Structure used to hold the components of a S/390 memory
address. A legitimate address on S/390 is of the general
form
@@ -174,88 +224,179 @@ struct s390_address
rtx base;
rtx indx;
rtx disp;
- int pointer;
+ bool pointer;
+ bool literal_pool;
};
/* Which cpu are we tuning for. */
-enum processor_type s390_tune;
+enum processor_type s390_tune = PROCESSOR_max;
enum processor_flags s390_tune_flags;
/* Which instruction set architecture to use. */
enum processor_type s390_arch;
enum processor_flags s390_arch_flags;
-/* Strings to hold which cpu and instruction set architecture to use. */
-const char *s390_tune_string; /* for -mtune=<xxx> */
-const char *s390_arch_string; /* for -march=<xxx> */
+HOST_WIDE_INT s390_warn_framesize = 0;
+HOST_WIDE_INT s390_stack_size = 0;
+HOST_WIDE_INT s390_stack_guard = 0;
-/* Define the structure for the machine field in struct function. */
+/* The following structure is embedded in the machine
+ specific part of struct function. */
-struct machine_function GTY(())
+struct s390_frame_layout GTY (())
{
- /* Set, if some of the fprs 8-15 need to be saved (64 bit abi). */
- int save_fprs_p;
+ /* Offset within stack frame. */
+ HOST_WIDE_INT gprs_offset;
+ HOST_WIDE_INT f0_offset;
+ HOST_WIDE_INT f4_offset;
+ HOST_WIDE_INT f8_offset;
+ HOST_WIDE_INT backchain_offset;
- /* Set if return address needs to be saved. */
- bool save_return_addr_p;
+ /* Number of first and last gpr where slots in the register
+ save area are reserved for. */
+ int first_save_gpr_slot;
+ int last_save_gpr_slot;
/* Number of first and last gpr to be saved, restored. */
int first_save_gpr;
int first_restore_gpr;
int last_save_gpr;
+ int last_restore_gpr;
+
+ /* Bits standing for floating point registers. Set, if the
+ respective register has to be saved. Starting with reg 16 (f0)
+ at the rightmost bit.
+ Bit 15 - 8 7 6 5 4 3 2 1 0
+ fpr 15 - 8 7 5 3 1 6 4 2 0
+ reg 31 - 24 23 22 21 20 19 18 17 16 */
+ unsigned int fpr_bitmap;
+
+ /* Number of floating point registers f8-f15 which must be saved. */
+ int high_fprs;
+
+ /* Set if return address needs to be saved.
+ This flag is set by s390_return_addr_rtx if it could not use
+ the initial value of r14 and therefore depends on r14 saved
+ to the stack. */
+ bool save_return_addr_p;
/* Size of stack frame. */
HOST_WIDE_INT frame_size;
+};
+
+/* Define the structure for the machine field in struct function. */
+
+struct machine_function GTY(())
+{
+ struct s390_frame_layout frame_layout;
+
+ /* Literal pool base register. */
+ rtx base_reg;
+
+ /* True if we may need to perform branch splitting. */
+ bool split_branches_pending_p;
+
+ /* True during final stage of literal pool processing. */
+ bool decomposed_literal_pool_addresses_ok_p;
/* Some local-dynamic TLS symbol name. */
const char *some_ld_name;
+
+ bool has_landing_pad_p;
};
-static int s390_match_ccmode_set (rtx, enum machine_mode);
-static int s390_branch_condition_mask (rtx);
-static const char *s390_branch_condition_mnemonic (rtx, int);
-static int check_mode (rtx, enum machine_mode *);
-static int general_s_operand (rtx, enum machine_mode, int);
-static int s390_short_displacement (rtx);
-static int s390_decompose_address (rtx, struct s390_address *);
-static rtx get_thread_pointer (void);
-static rtx legitimize_tls_address (rtx, rtx);
-static void print_shift_count_operand (FILE *, rtx);
-static const char *get_some_local_dynamic_name (void);
-static int get_some_local_dynamic_name_1 (rtx *, void *);
-static int reg_used_in_mem_p (int, rtx);
-static int addr_generation_dependency_p (rtx, rtx);
-static int s390_split_branches (void);
-static void find_constant_pool_ref (rtx, rtx *);
-static void replace_constant_pool_ref (rtx *, rtx, rtx);
-static rtx find_ltrel_base (rtx);
-static void replace_ltrel_base (rtx *, rtx);
-static void s390_optimize_prolog (bool);
-static int find_unused_clobbered_reg (void);
-static void s390_frame_info (void);
-static rtx save_fpr (rtx, int, int);
-static rtx restore_fpr (rtx, int, int);
-static rtx save_gprs (rtx, int, int, int);
-static rtx restore_gprs (rtx, int, int, int);
-static int s390_function_arg_size (enum machine_mode, tree);
-static bool s390_function_arg_float (enum machine_mode, tree);
-static struct machine_function * s390_init_machine_status (void);
-
-/* Check whether integer displacement is in range. */
-#define DISP_IN_RANGE(d) \
- (TARGET_LONG_DISPLACEMENT? ((d) >= -524288 && (d) <= 524287) \
- : ((d) >= 0 && (d) <= 4095))
+/* Few accessor macros for struct cfun->machine->s390_frame_layout. */
+
+#define cfun_frame_layout (cfun->machine->frame_layout)
+#define cfun_save_high_fprs_p (!!cfun_frame_layout.high_fprs)
+#define cfun_gprs_save_area_size ((cfun_frame_layout.last_save_gpr_slot - \
+ cfun_frame_layout.first_save_gpr_slot + 1) * UNITS_PER_WORD)
+#define cfun_set_fpr_bit(BITNUM) (cfun->machine->frame_layout.fpr_bitmap |= \
+ (1 << (BITNUM)))
+#define cfun_fpr_bit_p(BITNUM) (!!(cfun->machine->frame_layout.fpr_bitmap & \
+ (1 << (BITNUM))))
+
+/* Number of GPRs and FPRs used for argument passing. */
+#define GP_ARG_NUM_REG 5
+#define FP_ARG_NUM_REG (TARGET_64BIT? 4 : 2)
+
+/* A couple of shortcuts. */
+#define CONST_OK_FOR_J(x) \
+ CONST_OK_FOR_CONSTRAINT_P((x), 'J', "J")
+#define CONST_OK_FOR_K(x) \
+ CONST_OK_FOR_CONSTRAINT_P((x), 'K', "K")
+#define CONST_OK_FOR_Os(x) \
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Os")
+#define CONST_OK_FOR_Op(x) \
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "Op")
+#define CONST_OK_FOR_On(x) \
+ CONST_OK_FOR_CONSTRAINT_P((x), 'O', "On")
+
+#define REGNO_PAIR_OK(REGNO, MODE) \
+ (HARD_REGNO_NREGS ((REGNO), (MODE)) == 1 || !((REGNO) & 1))
+
+/* Return true if the back end supports mode MODE. */
+static bool
+s390_scalar_mode_supported_p (enum machine_mode mode)
+{
+ if (DECIMAL_FLOAT_MODE_P (mode))
+ return true;
+ else
+ return default_scalar_mode_supported_p (mode);
+}
+
+/* Set the has_landing_pad_p flag in struct machine_function to VALUE. */
+
+void
+s390_set_has_landing_pad_p (bool value)
+{
+ cfun->machine->has_landing_pad_p = value;
+}
+
+/* If two condition code modes are compatible, return a condition code
+ mode which is compatible with both. Otherwise, return
+ VOIDmode. */
+
+static enum machine_mode
+s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
+{
+ if (m1 == m2)
+ return m1;
+
+ switch (m1)
+ {
+ case CCZmode:
+ if (m2 == CCUmode || m2 == CCTmode || m2 == CCZ1mode
+ || m2 == CCSmode || m2 == CCSRmode || m2 == CCURmode)
+ return m2;
+ return VOIDmode;
+
+ case CCSmode:
+ case CCUmode:
+ case CCTmode:
+ case CCSRmode:
+ case CCURmode:
+ case CCZ1mode:
+ if (m2 == CCZmode)
+ return m1;
+
+ return VOIDmode;
+
+ default:
+ return VOIDmode;
+ }
+ return VOIDmode;
+}
/* Return true if SET either doesn't set the CC register, or else
the source and destination have matching CC modes and that
CC mode is at least as constrained as REQ_MODE. */
-static int
+static bool
s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
{
enum machine_mode set_mode;
- if (GET_CODE (set) != SET)
- abort ();
+ gcc_assert (GET_CODE (set) == SET);
if (GET_CODE (SET_DEST (set)) != REG || !CC_REGNO_P (REGNO (SET_DEST (set))))
return 1;
@@ -270,6 +411,7 @@ s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
case CCLmode:
case CCL1mode:
case CCL2mode:
+ case CCL3mode:
case CCT1mode:
case CCT2mode:
case CCT3mode:
@@ -290,7 +432,7 @@ s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
break;
default:
- abort ();
+ gcc_unreachable ();
}
return (GET_MODE (SET_SRC (set)) == set_mode);
@@ -301,14 +443,14 @@ s390_match_ccmode_set (rtx set, enum machine_mode req_mode)
CC mode is at least as constrained as REQ_MODE.
If REQ_MODE is VOIDmode, always return false. */
-int
+bool
s390_match_ccmode (rtx insn, enum machine_mode req_mode)
{
int i;
/* s390_tm_ccmode returns VOIDmode to indicate failure. */
if (req_mode == VOIDmode)
- return 0;
+ return false;
if (GET_CODE (PATTERN (insn)) == SET)
return s390_match_ccmode_set (PATTERN (insn), req_mode);
@@ -319,10 +461,10 @@ s390_match_ccmode (rtx insn, enum machine_mode req_mode)
rtx set = XVECEXP (PATTERN (insn), 0, i);
if (GET_CODE (set) == SET)
if (!s390_match_ccmode_set (set, req_mode))
- return 0;
+ return false;
}
- return 1;
+ return true;
}
/* If a test-under-mask instruction can be used to implement
@@ -333,7 +475,7 @@ s390_match_ccmode (rtx insn, enum machine_mode req_mode)
if the instruction cannot (TM). */
enum machine_mode
-s390_tm_ccmode (rtx op1, rtx op2, int mixed)
+s390_tm_ccmode (rtx op1, rtx op2, bool mixed)
{
int bit0, bit1;
@@ -341,15 +483,20 @@ s390_tm_ccmode (rtx op1, rtx op2, int mixed)
if (GET_CODE (op1) != CONST_INT || GET_CODE (op2) != CONST_INT)
return VOIDmode;
- /* Selected bits all zero: CC0. */
+ /* Selected bits all zero: CC0.
+ e.g.: int a; if ((a & (16 + 128)) == 0) */
if (INTVAL (op2) == 0)
return CCTmode;
- /* Selected bits all one: CC3. */
+ /* Selected bits all one: CC3.
+ e.g.: int a; if ((a & (16 + 128)) == 16 + 128) */
if (INTVAL (op2) == INTVAL (op1))
return CCT3mode;
- /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2. */
+ /* Exactly two bits selected, mixed zeroes and ones: CC1 or CC2. e.g.:
+ int a;
+ if ((a & (16 + 128)) == 16) -> CCT1
+ if ((a & (16 + 128)) == 128) -> CCT2 */
if (mixed)
{
bit1 = exact_log2 (INTVAL (op2));
@@ -372,8 +519,11 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
{
case EQ:
case NE:
+ if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
+ && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
+ return CCAPmode;
if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (XEXP (op0, 1)), 'K', "K"))
+ && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
return CCAPmode;
if ((GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
|| GET_CODE (op1) == NEG)
@@ -408,14 +558,28 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
case LT:
case GE:
case GT:
- if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (XEXP (op0, 1)), 'K', "K"))
- {
- if (INTVAL (XEXP((op0), 1)) < 0)
- return CCANmode;
- else
- return CCAPmode;
- }
+ /* The only overflow condition of NEG and ABS happens when
+ -INT_MAX is used as parameter, which stays negative. So
+ we have an overflow from a positive value to a negative.
+ Using CCAP mode the resulting cc can be used for comparisons. */
+ if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
+ && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
+ return CCAPmode;
+
+ /* If constants are involved in an add instruction it is possible to use
+ the resulting cc for comparisons with zero. Knowing the sign of the
+ constant the overflow behavior gets predictable. e.g.:
+ int a, b; if ((b = a + c) > 0)
+ with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP */
+ if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
+ && CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
+ {
+ if (INTVAL (XEXP((op0), 1)) < 0)
+ return CCANmode;
+ else
+ return CCAPmode;
+ }
+ /* Fall through. */
case UNORDERED:
case ORDERED:
case UNEQ:
@@ -452,98 +616,208 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
return CCUmode;
default:
- abort ();
+ gcc_unreachable ();
}
}
-/* Return nonzero if OP is a valid comparison operator
- for an ALC condition in mode MODE. */
+/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
+ that we can implement more efficiently. */
-int
-s390_alc_comparison (rtx op, enum machine_mode mode)
-{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
+void
+s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
+{
+ /* Convert ZERO_EXTRACT back to AND to enable TM patterns. */
+ if ((*code == EQ || *code == NE)
+ && *op1 == const0_rtx
+ && GET_CODE (*op0) == ZERO_EXTRACT
+ && GET_CODE (XEXP (*op0, 1)) == CONST_INT
+ && GET_CODE (XEXP (*op0, 2)) == CONST_INT
+ && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
+ {
+ rtx inner = XEXP (*op0, 0);
+ HOST_WIDE_INT modesize = GET_MODE_BITSIZE (GET_MODE (inner));
+ HOST_WIDE_INT len = INTVAL (XEXP (*op0, 1));
+ HOST_WIDE_INT pos = INTVAL (XEXP (*op0, 2));
+
+ if (len > 0 && len < modesize
+ && pos >= 0 && pos + len <= modesize
+ && modesize <= HOST_BITS_PER_WIDE_INT)
+ {
+ unsigned HOST_WIDE_INT block;
+ block = ((unsigned HOST_WIDE_INT) 1 << len) - 1;
+ block <<= modesize - pos - len;
- if (GET_RTX_CLASS (GET_CODE (op)) != '<')
- return 0;
+ *op0 = gen_rtx_AND (GET_MODE (inner), inner,
+ gen_int_mode (block, GET_MODE (inner)));
+ }
+ }
- if (GET_CODE (XEXP (op, 0)) != REG
- || REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
- return 0;
+ /* Narrow AND of memory against immediate to enable TM. */
+ if ((*code == EQ || *code == NE)
+ && *op1 == const0_rtx
+ && GET_CODE (*op0) == AND
+ && GET_CODE (XEXP (*op0, 1)) == CONST_INT
+ && SCALAR_INT_MODE_P (GET_MODE (XEXP (*op0, 0))))
+ {
+ rtx inner = XEXP (*op0, 0);
+ rtx mask = XEXP (*op0, 1);
+
+ /* Ignore paradoxical SUBREGs if all extra bits are masked out. */
+ if (GET_CODE (inner) == SUBREG
+ && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (inner)))
+ && (GET_MODE_SIZE (GET_MODE (inner))
+ >= GET_MODE_SIZE (GET_MODE (SUBREG_REG (inner))))
+ && ((INTVAL (mask)
+ & GET_MODE_MASK (GET_MODE (inner))
+ & ~GET_MODE_MASK (GET_MODE (SUBREG_REG (inner))))
+ == 0))
+ inner = SUBREG_REG (inner);
+
+ /* Do not change volatile MEMs. */
+ if (MEM_P (inner) && !MEM_VOLATILE_P (inner))
+ {
+ int part = s390_single_part (XEXP (*op0, 1),
+ GET_MODE (inner), QImode, 0);
+ if (part >= 0)
+ {
+ mask = gen_int_mode (s390_extract_part (mask, QImode, 0), QImode);
+ inner = adjust_address_nv (inner, QImode, part);
+ *op0 = gen_rtx_AND (QImode, inner, mask);
+ }
+ }
+ }
- switch (GET_MODE (XEXP (op, 0)))
+ /* Narrow comparisons against 0xffff to HImode if possible. */
+ if ((*code == EQ || *code == NE)
+ && GET_CODE (*op1) == CONST_INT
+ && INTVAL (*op1) == 0xffff
+ && SCALAR_INT_MODE_P (GET_MODE (*op0))
+ && (nonzero_bits (*op0, GET_MODE (*op0))
+ & ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
{
- case CCL1mode:
- return GET_CODE (op) == LTU;
-
- case CCL2mode:
- return GET_CODE (op) == LEU;
+ *op0 = gen_lowpart (HImode, *op0);
+ *op1 = constm1_rtx;
+ }
- case CCUmode:
- return GET_CODE (op) == GTU;
- case CCURmode:
- return GET_CODE (op) == LTU;
+ /* Remove redundant UNSPEC_CMPINT conversions if possible. */
+ if (GET_CODE (*op0) == UNSPEC
+ && XINT (*op0, 1) == UNSPEC_CMPINT
+ && XVECLEN (*op0, 0) == 1
+ && GET_MODE (XVECEXP (*op0, 0, 0)) == CCUmode
+ && GET_CODE (XVECEXP (*op0, 0, 0)) == REG
+ && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
+ && *op1 == const0_rtx)
+ {
+ enum rtx_code new_code = UNKNOWN;
+ switch (*code)
+ {
+ case EQ: new_code = EQ; break;
+ case NE: new_code = NE; break;
+ case LT: new_code = GTU; break;
+ case GT: new_code = LTU; break;
+ case LE: new_code = GEU; break;
+ case GE: new_code = LEU; break;
+ default: break;
+ }
- case CCSmode:
- return GET_CODE (op) == UNGT;
+ if (new_code != UNKNOWN)
+ {
+ *op0 = XVECEXP (*op0, 0, 0);
+ *code = new_code;
+ }
+ }
- case CCSRmode:
- return GET_CODE (op) == UNLT;
+ /* Simplify cascaded EQ, NE with const0_rtx. */
+ if ((*code == NE || *code == EQ)
+ && (GET_CODE (*op0) == EQ || GET_CODE (*op0) == NE)
+ && GET_MODE (*op0) == SImode
+ && GET_MODE (XEXP (*op0, 0)) == CCZ1mode
+ && REG_P (XEXP (*op0, 0))
+ && XEXP (*op0, 1) == const0_rtx
+ && *op1 == const0_rtx)
+ {
+ if ((*code == EQ && GET_CODE (*op0) == NE)
+ || (*code == NE && GET_CODE (*op0) == EQ))
+ *code = EQ;
+ else
+ *code = NE;
+ *op0 = XEXP (*op0, 0);
+ }
- default:
- return 0;
+ /* Prefer register over memory as first operand. */
+ if (MEM_P (*op0) && REG_P (*op1))
+ {
+ rtx tem = *op0; *op0 = *op1; *op1 = tem;
+ *code = swap_condition (*code);
}
}
-/* Return nonzero if OP is a valid comparison operator
- for an SLB condition in mode MODE. */
+/* Emit a compare instruction suitable to implement the comparison
+ OP0 CODE OP1. Return the correct condition RTL to be placed in
+ the IF_THEN_ELSE of the conditional branch testing the result. */
-int
-s390_slb_comparison (rtx op, enum machine_mode mode)
+rtx
+s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
+ enum machine_mode mode = s390_select_ccmode (code, op0, op1);
+ rtx ret = NULL_RTX;
- if (GET_RTX_CLASS (GET_CODE (op)) != '<')
- return 0;
+ /* Do not output a redundant compare instruction if a compare_and_swap
+ pattern already computed the result and the machine modes are compatible. */
+ if (s390_compare_emitted
+ && (s390_cc_modes_compatible (GET_MODE (s390_compare_emitted), mode)
+ == GET_MODE (s390_compare_emitted)))
+ ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
+ else
+ {
+ rtx cc = gen_rtx_REG (mode, CC_REGNUM);
+
+ emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
+ ret = gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
+ }
+ s390_compare_emitted = NULL_RTX;
+ return ret;
+}
- if (GET_CODE (XEXP (op, 0)) != REG
- || REGNO (XEXP (op, 0)) != CC_REGNUM
- || XEXP (op, 1) != const0_rtx)
- return 0;
+/* Emit a SImode compare and swap instruction setting MEM to NEW if OLD
+ matches CMP.
+ Return the correct condition RTL to be placed in the IF_THEN_ELSE of the
+ conditional branch testing the result. */
- switch (GET_MODE (XEXP (op, 0)))
- {
- case CCL1mode:
- return GET_CODE (op) == GEU;
+static rtx
+s390_emit_compare_and_swap (enum rtx_code code, rtx old, rtx mem, rtx cmp, rtx new)
+{
+ rtx ret;
- case CCL2mode:
- return GET_CODE (op) == GTU;
+ emit_insn (gen_sync_compare_and_swap_ccsi (old, mem, cmp, new));
+ ret = gen_rtx_fmt_ee (code, VOIDmode, s390_compare_emitted, const0_rtx);
- case CCUmode:
- return GET_CODE (op) == LEU;
+ s390_compare_emitted = NULL_RTX;
- case CCURmode:
- return GET_CODE (op) == GEU;
+ return ret;
+}
- case CCSmode:
- return GET_CODE (op) == LE;
+/* Emit a jump instruction to TARGET. If COND is NULL_RTX, emit an
+ unconditional jump, else a conditional jump under condition COND. */
- case CCSRmode:
- return GET_CODE (op) == GE;
+void
+s390_emit_jump (rtx target, rtx cond)
+{
+ rtx insn;
- default:
- return 0;
- }
+ target = gen_rtx_LABEL_REF (VOIDmode, target);
+ if (cond)
+ target = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, target, pc_rtx);
+
+ insn = gen_rtx_SET (VOIDmode, pc_rtx, target);
+ emit_jump_insn (insn);
}
/* Return branch condition mask to implement a branch
- specified by CODE. */
+ specified by CODE. Return -1 for invalid comparisons. */
-static int
+int
s390_branch_condition_mask (rtx code)
{
const int CC0 = 1 << 3;
@@ -551,20 +825,19 @@ s390_branch_condition_mask (rtx code)
const int CC2 = 1 << 1;
const int CC3 = 1 << 0;
- if (GET_CODE (XEXP (code, 0)) != REG
- || REGNO (XEXP (code, 0)) != CC_REGNUM
- || XEXP (code, 1) != const0_rtx)
- abort ();
+ gcc_assert (GET_CODE (XEXP (code, 0)) == REG);
+ gcc_assert (REGNO (XEXP (code, 0)) == CC_REGNUM);
+ gcc_assert (XEXP (code, 1) == const0_rtx);
switch (GET_MODE (XEXP (code, 0)))
{
case CCZmode:
+ case CCZ1mode:
switch (GET_CODE (code))
{
case EQ: return CC0;
case NE: return CC1 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -573,8 +846,7 @@ s390_branch_condition_mask (rtx code)
{
case EQ: return CC1;
case NE: return CC0 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -583,8 +855,7 @@ s390_branch_condition_mask (rtx code)
{
case EQ: return CC2;
case NE: return CC0 | CC1 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -593,8 +864,7 @@ s390_branch_condition_mask (rtx code)
{
case EQ: return CC3;
case NE: return CC0 | CC1 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -603,8 +873,7 @@ s390_branch_condition_mask (rtx code)
{
case EQ: return CC0 | CC2;
case NE: return CC1 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -613,8 +882,7 @@ s390_branch_condition_mask (rtx code)
{
case LTU: return CC2 | CC3; /* carry */
case GEU: return CC0 | CC1; /* no carry */
- default:
- abort ();
+ default: return -1;
}
break;
@@ -623,11 +891,22 @@ s390_branch_condition_mask (rtx code)
{
case GTU: return CC0 | CC1; /* borrow */
case LEU: return CC2 | CC3; /* no borrow */
- default:
- abort ();
+ default: return -1;
}
break;
+ case CCL3mode:
+ switch (GET_CODE (code))
+ {
+ case EQ: return CC0 | CC2;
+ case NE: return CC1 | CC3;
+ case LTU: return CC1;
+ case GTU: return CC3;
+ case LEU: return CC1 | CC2;
+ case GEU: return CC2 | CC3;
+ default: return -1;
+ }
+
case CCUmode:
switch (GET_CODE (code))
{
@@ -637,8 +916,7 @@ s390_branch_condition_mask (rtx code)
case GTU: return CC2;
case LEU: return CC0 | CC1;
case GEU: return CC0 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -651,8 +929,7 @@ s390_branch_condition_mask (rtx code)
case GTU: return CC1;
case LEU: return CC0 | CC2;
case GEU: return CC0 | CC1;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -665,8 +942,7 @@ s390_branch_condition_mask (rtx code)
case GT: return CC2;
case LE: return CC0 | CC1 | CC3;
case GE: return CC0 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -679,8 +955,7 @@ s390_branch_condition_mask (rtx code)
case GT: return CC2 | CC3;
case LE: return CC0 | CC1;
case GE: return CC0 | CC2 | CC3;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -701,8 +976,7 @@ s390_branch_condition_mask (rtx code)
case UNLE: return CC0 | CC1 | CC3;
case UNGE: return CC0 | CC2 | CC3;
case LTGT: return CC1 | CC2;
- default:
- abort ();
+ default: return -1;
}
break;
@@ -723,13 +997,12 @@ s390_branch_condition_mask (rtx code)
case UNLE: return CC0 | CC2 | CC3;
case UNGE: return CC0 | CC1 | CC3;
case LTGT: return CC2 | CC1;
- default:
- abort ();
+ default: return -1;
}
break;
default:
- abort ();
+ return -1;
}
}
@@ -749,19 +1022,19 @@ s390_branch_condition_mnemonic (rtx code, int inv)
};
int mask = s390_branch_condition_mask (code);
+ gcc_assert (mask >= 0);
if (inv)
mask ^= 15;
- if (mask < 1 || mask > 14)
- abort ();
+ gcc_assert (mask >= 1 && mask <= 14);
return mnemonic[mask];
}
/* Return the part of op which has a value different from def.
The size of the part is determined by mode.
- Use this function only if you already know that op really
+ Use this function only if you already know that op really
contains such a part. */
unsigned HOST_WIDE_INT
@@ -770,21 +1043,22 @@ s390_extract_part (rtx op, enum machine_mode mode, int def)
unsigned HOST_WIDE_INT value = 0;
int max_parts = HOST_BITS_PER_WIDE_INT / GET_MODE_BITSIZE (mode);
int part_bits = GET_MODE_BITSIZE (mode);
- unsigned HOST_WIDE_INT part_mask = (1 << part_bits) - 1;
+ unsigned HOST_WIDE_INT part_mask
+ = ((unsigned HOST_WIDE_INT)1 << part_bits) - 1;
int i;
-
+
for (i = 0; i < max_parts; i++)
{
if (i == 0)
value = (unsigned HOST_WIDE_INT) INTVAL (op);
else
value >>= part_bits;
-
+
if ((value & part_mask) != (def & part_mask))
return value & part_mask;
}
-
- abort ();
+
+ gcc_unreachable ();
}
/* If OP is an integer constant of mode MODE with exactly one
@@ -792,26 +1066,27 @@ s390_extract_part (rtx op, enum machine_mode mode, int def)
part. Otherwise, return -1. */
int
-s390_single_part (rtx op,
- enum machine_mode mode,
+s390_single_part (rtx op,
+ enum machine_mode mode,
enum machine_mode part_mode,
int def)
{
unsigned HOST_WIDE_INT value = 0;
int n_parts = GET_MODE_SIZE (mode) / GET_MODE_SIZE (part_mode);
- unsigned HOST_WIDE_INT part_mask = (1 << GET_MODE_BITSIZE (part_mode)) - 1;
+ unsigned HOST_WIDE_INT part_mask
+ = ((unsigned HOST_WIDE_INT)1 << GET_MODE_BITSIZE (part_mode)) - 1;
int i, part = -1;
if (GET_CODE (op) != CONST_INT)
return -1;
-
+
for (i = 0; i < n_parts; i++)
{
if (i == 0)
value = (unsigned HOST_WIDE_INT) INTVAL (op);
else
value >>= GET_MODE_BITSIZE (part_mode);
-
+
if ((value & part_mask) != (def & part_mask))
{
if (part != -1)
@@ -855,6 +1130,169 @@ s390_split_ok_p (rtx dst, rtx src, enum machine_mode mode, int first_subword)
return true;
}
+/* Return true if it can be proven that [MEM1, MEM1 + SIZE]
+ and [MEM2, MEM2 + SIZE] do overlap and false
+ otherwise. */
+
+bool
+s390_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
+{
+ rtx addr1, addr2, addr_delta;
+ HOST_WIDE_INT delta;
+
+ if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
+ return true;
+
+ if (size == 0)
+ return false;
+
+ addr1 = XEXP (mem1, 0);
+ addr2 = XEXP (mem2, 0);
+
+ addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
+
+ /* This overlapping check is used by peepholes merging memory block operations.
+ Overlapping operations would otherwise be recognized by the S/390 hardware
+ and would fall back to a slower implementation. Allowing overlapping
+ operations would lead to slow code but not to wrong code. Therefore we are
+ somewhat optimistic if we cannot prove that the memory blocks are
+ overlapping.
+ That's why we return false here although this may accept operations on
+ overlapping memory areas. */
+ if (!addr_delta || GET_CODE (addr_delta) != CONST_INT)
+ return false;
+
+ delta = INTVAL (addr_delta);
+
+ if (delta == 0
+ || (delta > 0 && delta < size)
+ || (delta < 0 && -delta < size))
+ return true;
+
+ return false;
+}
+
+/* Check whether the address of memory reference MEM2 equals exactly
+ the address of memory reference MEM1 plus DELTA. Return true if
+ we can prove this to be the case, false otherwise. */
+
+bool
+s390_offset_p (rtx mem1, rtx mem2, rtx delta)
+{
+ rtx addr1, addr2, addr_delta;
+
+ if (GET_CODE (mem1) != MEM || GET_CODE (mem2) != MEM)
+ return false;
+
+ addr1 = XEXP (mem1, 0);
+ addr2 = XEXP (mem2, 0);
+
+ addr_delta = simplify_binary_operation (MINUS, Pmode, addr2, addr1);
+ if (!addr_delta || !rtx_equal_p (addr_delta, delta))
+ return false;
+
+ return true;
+}
+
+/* Expand logical operator CODE in mode MODE with operands OPERANDS. */
+
+void
+s390_expand_logical_operator (enum rtx_code code, enum machine_mode mode,
+ rtx *operands)
+{
+ enum machine_mode wmode = mode;
+ rtx dst = operands[0];
+ rtx src1 = operands[1];
+ rtx src2 = operands[2];
+ rtx op, clob, tem;
+
+ /* If we cannot handle the operation directly, use a temp register. */
+ if (!s390_logical_operator_ok_p (operands))
+ dst = gen_reg_rtx (mode);
+
+ /* QImode and HImode patterns make sense only if we have a destination
+ in memory. Otherwise perform the operation in SImode. */
+ if ((mode == QImode || mode == HImode) && GET_CODE (dst) != MEM)
+ wmode = SImode;
+
+ /* Widen operands if required. */
+ if (mode != wmode)
+ {
+ if (GET_CODE (dst) == SUBREG
+ && (tem = simplify_subreg (wmode, dst, mode, 0)) != 0)
+ dst = tem;
+ else if (REG_P (dst))
+ dst = gen_rtx_SUBREG (wmode, dst, 0);
+ else
+ dst = gen_reg_rtx (wmode);
+
+ if (GET_CODE (src1) == SUBREG
+ && (tem = simplify_subreg (wmode, src1, mode, 0)) != 0)
+ src1 = tem;
+ else if (GET_MODE (src1) != VOIDmode)
+ src1 = gen_rtx_SUBREG (wmode, force_reg (mode, src1), 0);
+
+ if (GET_CODE (src2) == SUBREG
+ && (tem = simplify_subreg (wmode, src2, mode, 0)) != 0)
+ src2 = tem;
+ else if (GET_MODE (src2) != VOIDmode)
+ src2 = gen_rtx_SUBREG (wmode, force_reg (mode, src2), 0);
+ }
+
+ /* Emit the instruction. */
+ op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, wmode, src1, src2));
+ clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
+
+ /* Fix up the destination if needed. */
+ if (dst != operands[0])
+ emit_move_insn (operands[0], gen_lowpart (mode, dst));
+}
+
+/* Check whether OPERANDS are OK for a logical operation (AND, IOR, XOR). */
+
+bool
+s390_logical_operator_ok_p (rtx *operands)
+{
+ /* If the destination operand is in memory, it needs to coincide
+ with one of the source operands. After reload, it has to be
+ the first source operand. */
+ if (GET_CODE (operands[0]) == MEM)
+ return rtx_equal_p (operands[0], operands[1])
+ || (!reload_completed && rtx_equal_p (operands[0], operands[2]));
+
+ return true;
+}
+
+/* Narrow logical operation CODE of memory operand MEMOP with immediate
+ operand IMMOP to switch from SS to SI type instructions. */
+
+void
+s390_narrow_logical_operator (enum rtx_code code, rtx *memop, rtx *immop)
+{
+ int def = code == AND ? -1 : 0;
+ HOST_WIDE_INT mask;
+ int part;
+
+ gcc_assert (GET_CODE (*memop) == MEM);
+ gcc_assert (!MEM_VOLATILE_P (*memop));
+
+ mask = s390_extract_part (*immop, QImode, def);
+ part = s390_single_part (*immop, GET_MODE (*memop), QImode, def);
+ gcc_assert (part >= 0);
+
+ *memop = adjust_address (*memop, QImode, part);
+ *immop = gen_int_mode (mask, QImode);
+}
+
+
+/* How to allocate a 'struct machine_function'. */
+
+static struct machine_function *
+s390_init_machine_status (void)
+{
+ return ggc_alloc_cleared (sizeof (struct machine_function));
+}
/* Change optimizations to be performed, depending on the
optimization level.
@@ -873,12 +1311,20 @@ optimization_options (int level ATTRIBUTE_UNUSED, int size ATTRIBUTE_UNUSED)
/* By default, always emit DWARF-2 unwind info. This allows debugging
without maintaining a stack frame back-chain. */
flag_asynchronous_unwind_tables = 1;
+
+ /* Use MVCLE instructions to decrease code size if requested. */
+ if (size != 0)
+ target_flags |= MASK_MVCLE;
}
-void
-override_options (void)
+/* Return true if ARG is the name of a processor. Set *TYPE and *FLAGS
+ to the associated processor_type and processor_flags if so. */
+
+static bool
+s390_handle_arch_option (const char *arg,
+ enum processor_type *type,
+ enum processor_flags *flags)
{
- int i;
static struct pta
{
const char *const name; /* processor name or nickname. */
@@ -892,13 +1338,59 @@ override_options (void)
{"z900", PROCESSOR_2064_Z900, PF_IEEE_FLOAT | PF_ZARCH},
{"z990", PROCESSOR_2084_Z990, PF_IEEE_FLOAT | PF_ZARCH
| PF_LONG_DISPLACEMENT},
+ {"z9-109", PROCESSOR_2094_Z9_109, PF_IEEE_FLOAT | PF_ZARCH
+ | PF_LONG_DISPLACEMENT | PF_EXTIMM},
};
+ size_t i;
+
+ for (i = 0; i < ARRAY_SIZE (processor_alias_table); i++)
+ if (strcmp (arg, processor_alias_table[i].name) == 0)
+ {
+ *type = processor_alias_table[i].processor;
+ *flags = processor_alias_table[i].flags;
+ return true;
+ }
+ return false;
+}
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+s390_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_march_:
+ return s390_handle_arch_option (arg, &s390_arch, &s390_arch_flags);
+
+ case OPT_mstack_guard_:
+ if (sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_stack_guard) != 1)
+ return false;
+ if (exact_log2 (s390_stack_guard) == -1)
+ error ("stack guard value must be an exact power of 2");
+ return true;
- int const pta_size = ARRAY_SIZE (processor_alias_table);
+ case OPT_mstack_size_:
+ if (sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_stack_size) != 1)
+ return false;
+ if (exact_log2 (s390_stack_size) == -1)
+ error ("stack size must be an exact power of 2");
+ return true;
+
+ case OPT_mtune_:
+ return s390_handle_arch_option (arg, &s390_tune, &s390_tune_flags);
- /* Acquire a unique set number for our register saves and restores. */
- s390_sr_alias_set = new_alias_set ();
+ case OPT_mwarn_framesize_:
+ return sscanf (arg, HOST_WIDE_INT_PRINT_DEC, &s390_warn_framesize) == 1;
+
+ default:
+ return true;
+ }
+}
+void
+override_options (void)
+{
/* Set up function hooks. */
init_machine_status = s390_init_machine_status;
@@ -913,43 +1405,52 @@ override_options (void)
/* Determine processor architectural level. */
if (!s390_arch_string)
- s390_arch_string = TARGET_ZARCH? "z900" : "g5";
-
- for (i = 0; i < pta_size; i++)
- if (! strcmp (s390_arch_string, processor_alias_table[i].name))
- {
- s390_arch = processor_alias_table[i].processor;
- s390_arch_flags = processor_alias_table[i].flags;
- break;
- }
- if (i == pta_size)
- error ("Unknown cpu used in -march=%s.", s390_arch_string);
+ {
+ s390_arch_string = TARGET_ZARCH? "z900" : "g5";
+ s390_handle_arch_option (s390_arch_string, &s390_arch, &s390_arch_flags);
+ }
/* Determine processor to tune for. */
- if (!s390_tune_string)
+ if (s390_tune == PROCESSOR_max)
{
s390_tune = s390_arch;
s390_tune_flags = s390_arch_flags;
- s390_tune_string = s390_arch_string;
- }
- else
- {
- for (i = 0; i < pta_size; i++)
- if (! strcmp (s390_tune_string, processor_alias_table[i].name))
- {
- s390_tune = processor_alias_table[i].processor;
- s390_tune_flags = processor_alias_table[i].flags;
- break;
- }
- if (i == pta_size)
- error ("Unknown cpu used in -mtune=%s.", s390_tune_string);
}
/* Sanity checks. */
if (TARGET_ZARCH && !(s390_arch_flags & PF_ZARCH))
- error ("z/Architecture mode not supported on %s.", s390_arch_string);
+ error ("z/Architecture mode not supported on %s", s390_arch_string);
if (TARGET_64BIT && !TARGET_ZARCH)
- error ("64-bit ABI not supported in ESA/390 mode.");
+ error ("64-bit ABI not supported in ESA/390 mode");
+
+ /* Set processor cost function. */
+ if (s390_tune == PROCESSOR_2094_Z9_109)
+ s390_cost = &z9_109_cost;
+ else if (s390_tune == PROCESSOR_2084_Z990)
+ s390_cost = &z990_cost;
+ else
+ s390_cost = &z900_cost;
+
+ if (TARGET_BACKCHAIN && TARGET_PACKED_STACK && TARGET_HARD_FLOAT)
+ error ("-mbackchain -mpacked-stack -mhard-float are not supported "
+ "in combination");
+
+ if (s390_stack_size)
+ {
+ if (!s390_stack_guard)
+ error ("-mstack-size implies use of -mstack-guard");
+ else if (s390_stack_guard >= s390_stack_size)
+ error ("stack size must be greater than the stack guard value");
+ else if (s390_stack_size > 1 << 16)
+ error ("stack size must not be greater than 64k");
+ }
+ else if (s390_stack_guard)
+ error ("-mstack-guard implies use of -mstack-size");
+
+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
+ if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
+ target_flags |= MASK_LONG_DOUBLE_128;
+#endif
}
/* Map for smallest class containing reg regno. */
@@ -963,7 +1464,8 @@ const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER] =
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, ADDR_REGS
+ ADDR_REGS, CC_REGS, ADDR_REGS, ADDR_REGS,
+ ACCESS_REGS, ACCESS_REGS
};
/* Return attribute type of insn. */
@@ -977,257 +1479,424 @@ s390_safe_attr_type (rtx insn)
return TYPE_NONE;
}
-/* Return true if OP a (const_int 0) operand.
- OP is the current operation.
- MODE is the current operation mode. */
+/* Return true if DISP is a valid short displacement. */
-int
-const0_operand (register rtx op, enum machine_mode mode)
+static bool
+s390_short_displacement (rtx disp)
{
- return op == CONST0_RTX (mode);
-}
+ /* No displacement is OK. */
+ if (!disp)
+ return true;
-/* Return true if OP is constant.
- OP is the current operation.
- MODE is the current operation mode. */
+ /* Integer displacement in range. */
+ if (GET_CODE (disp) == CONST_INT)
+ return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
-int
-consttable_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return CONSTANT_P (op);
+ /* GOT offset is not OK, the GOT can be large. */
+ if (GET_CODE (disp) == CONST
+ && GET_CODE (XEXP (disp, 0)) == UNSPEC
+ && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
+ || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
+ return false;
+
+ /* All other symbolic constants are literal pool references,
+ which are OK as the literal pool must be small. */
+ if (GET_CODE (disp) == CONST)
+ return true;
+
+ return false;
}
-/* Return true if the mode of operand OP matches MODE.
- If MODE is set to VOIDmode, set it to the mode of OP. */
+/* Decompose a RTL expression ADDR for a memory address into
+ its components, returned in OUT.
+
+ Returns false if ADDR is not a valid memory address, true
+ 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
-check_mode (register rtx op, enum machine_mode *mode)
+s390_decompose_address (rtx addr, struct s390_address *out)
{
- if (*mode == VOIDmode)
- *mode = GET_MODE (op);
- else
- {
- if (GET_MODE (op) != VOIDmode && GET_MODE (op) != *mode)
- return 0;
- }
- return 1;
-}
+ HOST_WIDE_INT offset = 0;
+ rtx base = NULL_RTX;
+ rtx indx = NULL_RTX;
+ rtx disp = NULL_RTX;
+ rtx orig_disp;
+ bool pointer = false;
+ bool base_ptr = false;
+ bool indx_ptr = false;
+ bool literal_pool = false;
+
+ /* We may need to substitute the literal pool base register into the address
+ below. However, at this point we do not know which register is going to
+ be used as base, so we substitute the arg pointer register. This is going
+ to be treated as holding a pointer below -- it shouldn't be used for any
+ other purpose. */
+ rtx fake_pool_base = gen_rtx_REG (Pmode, ARG_POINTER_REGNUM);
-/* Return true if OP a valid operand for the LARL instruction.
- OP is the current operation.
- MODE is the current operation mode. */
+ /* Decompose address into base + index + displacement. */
-int
-larl_operand (register rtx op, enum machine_mode mode)
-{
- if (! check_mode (op, &mode))
- return 0;
+ if (GET_CODE (addr) == REG || GET_CODE (addr) == UNSPEC)
+ base = addr;
- /* Allow labels and local symbols. */
- if (GET_CODE (op) == LABEL_REF)
- return 1;
- if (GET_CODE (op) == SYMBOL_REF)
- return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
+ 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);
- /* Everything else must have a CONST, so strip it. */
- if (GET_CODE (op) != CONST)
- return 0;
- op = XEXP (op, 0);
+ 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;
+ }
- /* Allow adding *even* in-range constants. */
- if (GET_CODE (op) == PLUS)
+ else
+ {
+ return false;
+ }
+ }
+
+ else
+ disp = addr; /* displacement */
+
+ /* Extract integer part of displacement. */
+ orig_disp = disp;
+ if (disp)
{
- if (GET_CODE (XEXP (op, 1)) != CONST_INT
- || (INTVAL (XEXP (op, 1)) & 1) != 0)
- return 0;
-#if HOST_BITS_PER_WIDE_INT > 32
- if (INTVAL (XEXP (op, 1)) >= (HOST_WIDE_INT)1 << 32
- || INTVAL (XEXP (op, 1)) < -((HOST_WIDE_INT)1 << 32))
- return 0;
-#endif
- op = XEXP (op, 0);
+ if (GET_CODE (disp) == CONST_INT)
+ {
+ offset = INTVAL (disp);
+ disp = NULL_RTX;
+ }
+ else 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);
+ }
}
- /* Labels and local symbols allowed here as well. */
- if (GET_CODE (op) == LABEL_REF)
- return 1;
- if (GET_CODE (op) == SYMBOL_REF)
- return ((SYMBOL_REF_FLAGS (op) & SYMBOL_FLAG_ALIGN1) == 0
- && SYMBOL_REF_TLS_MODEL (op) == 0
- && (!flag_pic || SYMBOL_REF_LOCAL_P (op)));
-
- /* Now we must have a @GOTENT offset or @PLT stub
- or an @INDNTPOFF TLS offset. */
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_GOTENT)
- return 1;
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_PLT)
- return 1;
- if (GET_CODE (op) == UNSPEC
- && XINT (op, 1) == UNSPEC_INDNTPOFF)
- return 1;
+ /* Strip off CONST here to avoid special case tests later. */
+ if (disp && GET_CODE (disp) == CONST)
+ disp = XEXP (disp, 0);
- return 0;
-}
+ /* We can convert literal pool addresses to
+ displacements by basing them off the base register. */
+ if (disp && GET_CODE (disp) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (disp))
+ {
+ /* Either base or index must be free to hold the base register. */
+ if (!base)
+ base = fake_pool_base, literal_pool = true;
+ else if (!indx)
+ indx = fake_pool_base, literal_pool = true;
+ else
+ return false;
-/* Helper routine to implement s_operand and s_imm_operand.
- OP is the current operation.
- MODE is the current operation mode.
- ALLOW_IMMEDIATE specifies whether immediate operands should
- be accepted or not. */
+ /* Mark up the displacement. */
+ disp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, disp),
+ UNSPEC_LTREL_OFFSET);
+ }
-static int
-general_s_operand (register rtx op, enum machine_mode mode,
- int allow_immediate)
-{
- struct s390_address addr;
+ /* Validate base register. */
+ if (base)
+ {
+ if (GET_CODE (base) == UNSPEC)
+ switch (XINT (base, 1))
+ {
+ case UNSPEC_LTREF:
+ if (!disp)
+ disp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, XVECEXP (base, 0, 0)),
+ UNSPEC_LTREL_OFFSET);
+ else
+ return false;
+
+ base = XVECEXP (base, 0, 1);
+ break;
- /* Call general_operand first, so that we don't have to
- check for many special cases. */
- if (!general_operand (op, mode))
- return 0;
+ case UNSPEC_LTREL_BASE:
+ if (XVECLEN (base, 0) == 1)
+ base = fake_pool_base, literal_pool = true;
+ else
+ base = XVECEXP (base, 0, 1);
+ break;
- /* Just like memory_operand, allow (subreg (mem ...))
- after reload. */
- if (reload_completed
- && GET_CODE (op) == SUBREG
- && GET_CODE (SUBREG_REG (op)) == MEM)
- op = SUBREG_REG (op);
+ default:
+ return false;
+ }
- switch (GET_CODE (op))
+ if (!REG_P (base)
+ || (GET_MODE (base) != SImode
+ && GET_MODE (base) != Pmode))
+ return false;
+
+ if (REGNO (base) == STACK_POINTER_REGNUM
+ || REGNO (base) == FRAME_POINTER_REGNUM
+ || ((reload_completed || reload_in_progress)
+ && frame_pointer_needed
+ && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
+ || REGNO (base) == ARG_POINTER_REGNUM
+ || (flag_pic
+ && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
+ pointer = base_ptr = true;
+
+ if ((reload_completed || reload_in_progress)
+ && base == cfun->machine->base_reg)
+ pointer = base_ptr = literal_pool = true;
+ }
+
+ /* Validate index register. */
+ if (indx)
{
- /* Constants are OK as s-operand if ALLOW_IMMEDIATE
- is true and we are still before reload. */
- case CONST_INT:
- case CONST_DOUBLE:
- if (!allow_immediate || reload_completed)
- return 0;
- return 1;
+ if (GET_CODE (indx) == UNSPEC)
+ switch (XINT (indx, 1))
+ {
+ case UNSPEC_LTREF:
+ if (!disp)
+ disp = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, XVECEXP (indx, 0, 0)),
+ UNSPEC_LTREL_OFFSET);
+ else
+ return false;
+
+ indx = XVECEXP (indx, 0, 1);
+ break;
- /* Memory operands are OK unless they already use an
- index register. */
- case MEM:
- if (GET_CODE (XEXP (op, 0)) == ADDRESSOF)
- return 1;
- if (!s390_decompose_address (XEXP (op, 0), &addr))
- return 0;
- if (addr.indx)
- return 0;
- /* Do not allow literal pool references unless ALLOW_IMMEDIATE
- is true. This prevents compares between two literal pool
- entries from being accepted. */
- if (!allow_immediate
- && addr.base && REGNO (addr.base) == BASE_REGISTER)
- return 0;
- return 1;
+ case UNSPEC_LTREL_BASE:
+ if (XVECLEN (indx, 0) == 1)
+ indx = fake_pool_base, literal_pool = true;
+ else
+ indx = XVECEXP (indx, 0, 1);
+ break;
- default:
- break;
+ default:
+ return false;
+ }
+
+ if (!REG_P (indx)
+ || (GET_MODE (indx) != SImode
+ && GET_MODE (indx) != Pmode))
+ return false;
+
+ if (REGNO (indx) == STACK_POINTER_REGNUM
+ || REGNO (indx) == FRAME_POINTER_REGNUM
+ || ((reload_completed || reload_in_progress)
+ && frame_pointer_needed
+ && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
+ || REGNO (indx) == ARG_POINTER_REGNUM
+ || (flag_pic
+ && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
+ pointer = indx_ptr = true;
+
+ if ((reload_completed || reload_in_progress)
+ && indx == cfun->machine->base_reg)
+ pointer = indx_ptr = literal_pool = true;
}
- return 0;
-}
+ /* Prefer to use pointer as base, not index. */
+ if (base && indx && !base_ptr
+ && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx))))
+ {
+ rtx tmp = base;
+ base = indx;
+ indx = tmp;
+ }
-/* Return true if OP is a valid S-type operand.
- OP is the current operation.
- MODE is the current operation mode. */
+ /* Validate displacement. */
+ if (!disp)
+ {
+ /* If virtual registers are involved, the displacement will change later
+ anyway as the virtual registers get eliminated. This could make a
+ valid displacement invalid, but it is more likely to make an invalid
+ displacement valid, because we sometimes access the register save area
+ via negative offsets to one of those registers.
+ Thus we don't check the displacement for validity here. If after
+ elimination the displacement turns out to be invalid after all,
+ this is fixed up by reload in any case. */
+ if (base != arg_pointer_rtx
+ && indx != arg_pointer_rtx
+ && base != return_address_pointer_rtx
+ && indx != return_address_pointer_rtx
+ && base != frame_pointer_rtx
+ && indx != frame_pointer_rtx
+ && base != virtual_stack_vars_rtx
+ && indx != virtual_stack_vars_rtx)
+ if (!DISP_IN_RANGE (offset))
+ return false;
+ }
+ else
+ {
+ /* All the special cases are pointers. */
+ pointer = true;
-int
-s_operand (register rtx op, enum machine_mode mode)
-{
- return general_s_operand (op, mode, 0);
-}
+ /* In the small-PIC case, the linker converts @GOT
+ and @GOTNTPOFF offsets to possible displacements. */
+ if (GET_CODE (disp) == UNSPEC
+ && (XINT (disp, 1) == UNSPEC_GOT
+ || XINT (disp, 1) == UNSPEC_GOTNTPOFF)
+ && flag_pic == 1)
+ {
+ ;
+ }
-/* Return true if OP is a valid S-type operand or an immediate
- operand that can be addressed as S-type operand by forcing
- it into the literal pool.
- OP is the current operation.
- MODE is the current operation mode. */
+ /* Accept chunkified literal pool symbol references. */
+ else if (cfun && cfun->machine
+ && cfun->machine->decomposed_literal_pool_addresses_ok_p
+ && GET_CODE (disp) == MINUS
+ && GET_CODE (XEXP (disp, 0)) == LABEL_REF
+ && GET_CODE (XEXP (disp, 1)) == LABEL_REF)
+ {
+ ;
+ }
-int
-s_imm_operand (register rtx op, enum machine_mode mode)
-{
- return general_s_operand (op, mode, 1);
+ /* Accept literal pool references. */
+ else if (GET_CODE (disp) == UNSPEC
+ && XINT (disp, 1) == UNSPEC_LTREL_OFFSET)
+ {
+ orig_disp = gen_rtx_CONST (Pmode, disp);
+ if (offset)
+ {
+ /* If we have an offset, make sure it does not
+ exceed the size of the constant pool entry. */
+ rtx sym = XVECEXP (disp, 0, 0);
+ if (offset >= GET_MODE_SIZE (get_pool_mode (sym)))
+ return false;
+
+ orig_disp = plus_constant (orig_disp, offset);
+ }
+ }
+
+ else
+ return false;
+ }
+
+ if (!base && !indx)
+ pointer = true;
+
+ if (out)
+ {
+ out->base = base;
+ out->indx = indx;
+ out->disp = orig_disp;
+ out->pointer = pointer;
+ out->literal_pool = literal_pool;
+ }
+
+ return true;
}
-/* Return true if OP a valid shift count operand.
- OP is the current operation.
- MODE is the current operation mode. */
+/* Decompose a RTL expression OP for a shift count into its components,
+ and return the base register in BASE and the offset in OFFSET.
-int
-shift_count_operand (rtx op, enum machine_mode mode)
-{
- HOST_WIDE_INT offset = 0;
+ Return true if OP is a valid shift count, false if not. */
- if (! check_mode (op, &mode))
- return 0;
+bool
+s390_decompose_shift_count (rtx op, rtx *base, HOST_WIDE_INT *offset)
+{
+ HOST_WIDE_INT off = 0;
/* We can have an integer constant, an address register,
- or a sum of the two. Note that reload already checks
- that any register present is an address register, so
- we just check for any register here. */
+ or a sum of the two. */
if (GET_CODE (op) == CONST_INT)
{
- offset = INTVAL (op);
+ off = INTVAL (op);
op = NULL_RTX;
}
if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
{
- offset = INTVAL (XEXP (op, 1));
+ off = INTVAL (XEXP (op, 1));
op = XEXP (op, 0);
}
while (op && GET_CODE (op) == SUBREG)
op = SUBREG_REG (op);
+
if (op && GET_CODE (op) != REG)
- return 0;
+ return false;
- /* Unfortunately we have to reject constants that are invalid
- for an address, or else reload will get confused. */
- if (!DISP_IN_RANGE (offset))
- return 0;
+ if (offset)
+ *offset = off;
+ if (base)
+ *base = op;
- return 1;
+ return true;
}
-/* Return true if DISP is a valid short displacement. */
-
-static int
-s390_short_displacement (rtx disp)
-{
- /* No displacement is OK. */
- if (!disp)
- return 1;
- /* Integer displacement in range. */
- if (GET_CODE (disp) == CONST_INT)
- return INTVAL (disp) >= 0 && INTVAL (disp) < 4096;
+/* Return true if CODE is a valid address without index. */
- /* GOT offset is not OK, the GOT can be large. */
- if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == UNSPEC
- && XINT (XEXP (disp, 0), 1) == UNSPEC_GOT)
- return 0;
+bool
+s390_legitimate_address_without_index_p (rtx op)
+{
+ struct s390_address addr;
- /* All other symbolic constants are literal pool references,
- which are OK as the literal pool must be small. */
- if (GET_CODE (disp) == CONST)
- return 1;
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return false;
+ if (addr.indx)
+ return false;
- return 0;
+ return true;
}
-/* Return true if OP is a valid operand for a C constraint. */
+
+/* Evaluates constraint strings described by the regular expression
+ ([A|B](Q|R|S|T))|U|W and returns 1 if OP is a valid operand for the
+ constraint given in STR, or 0 else. */
int
-s390_extra_constraint_str (rtx op, int c, const char * str)
+s390_mem_constraint (const char *str, rtx op)
{
struct s390_address addr;
+ char c = str[0];
+
+ /* Check for offsettable variants of memory constraints. */
+ if (c == 'A')
+ {
+ /* Only accept non-volatile MEMs. */
+ if (!MEM_P (op) || MEM_VOLATILE_P (op))
+ return 0;
+
+ if ((reload_completed || reload_in_progress)
+ ? !offsettable_memref_p (op) : !offsettable_nonstrict_memref_p (op))
+ return 0;
- if (c != str[0])
- abort ();
+ c = str[1];
+ }
+
+ /* Check for non-literal-pool variants of memory constraints. */
+ else if (c == 'B')
+ {
+ if (GET_CODE (op) != MEM)
+ return 0;
+ if (!s390_decompose_address (XEXP (op, 0), &addr))
+ return 0;
+ if (addr.literal_pool)
+ return 0;
+
+ c = str[1];
+ }
switch (c)
{
@@ -1305,7 +1974,11 @@ s390_extra_constraint_str (rtx op, int c, const char * str)
break;
case 'Y':
- return shift_count_operand (op, VOIDmode);
+ /* Simply check for the basic form of a shift count. Reload will
+ take care of making sure we have a proper base register. */
+ if (!s390_decompose_shift_count (op, NULL, NULL))
+ return 0;
+ break;
default:
return 0;
@@ -1314,81 +1987,125 @@ s390_extra_constraint_str (rtx op, int c, const char * str)
return 1;
}
-/* Return true if VALUE matches the constraint STR. */
+
+
+/* Evaluates constraint strings starting with letter O. Input
+ parameter C is the second letter following the "O" in the constraint
+ string. Returns 1 if VALUE meets the respective constraint and 0
+ otherwise. */
int
-s390_const_ok_for_constraint_p (HOST_WIDE_INT value,
- int c,
- const char * str)
+s390_O_constraint_str (const char c, HOST_WIDE_INT value)
{
- enum machine_mode mode, part_mode;
- int def;
- unsigned char part;
-
- if (c != str[0])
- abort ();
+ if (!TARGET_EXTIMM)
+ return 0;
- switch (str[0])
+ switch (c)
{
- case 'I':
- return (unsigned int)value < 256;
+ case 's':
+ return trunc_int_for_mode (value, SImode) == value;
- case 'J':
- return (unsigned int)value < 4096;
+ case 'p':
+ return value == 0
+ || s390_single_part (GEN_INT (value), DImode, SImode, 0) == 1;
- case 'K':
- return value >= -32768 && value < 32768;
+ case 'n':
+ return value == -1
+ || s390_single_part (GEN_INT (value), DImode, SImode, -1) == 1;
- case 'L':
- return (TARGET_LONG_DISPLACEMENT ?
- (value >= -524288 && value <= 524287)
- : (value >= 0 && value <= 4095));
- case 'M':
- return value == 2147483647;
+ default:
+ gcc_unreachable ();
+ }
+}
- case 'N':
- part = str[1] - '0';
- switch (str[2])
- {
- case 'H': part_mode = HImode; break;
- case 'Q': part_mode = QImode; break;
- default: return 0;
- }
-
- switch (str[3])
- {
- case 'H': mode = HImode; break;
- case 'S': mode = SImode; break;
- case 'D': mode = DImode; break;
- default: return 0;
- }
+/* Evaluates constraint strings starting with letter N. Parameter STR
+ contains the letters following letter "N" in the constraint string.
+ Returns true if VALUE matches the constraint. */
- switch (str[4])
- {
- case '0': def = 0; break;
- case 'F': def = -1; break;
- default: return 0;
- }
+int
+s390_N_constraint_str (const char *str, HOST_WIDE_INT value)
+{
+ enum machine_mode mode, part_mode;
+ int def;
+ int part, part_goal;
- if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode))
- return 0;
- if (s390_single_part (GEN_INT (value), mode, part_mode, def) != part)
- return 0;
+ if (str[0] == 'x')
+ part_goal = -1;
+ else
+ part_goal = str[0] - '0';
+
+ switch (str[1])
+ {
+ case 'Q':
+ part_mode = QImode;
+ break;
+ case 'H':
+ part_mode = HImode;
+ break;
+ case 'S':
+ part_mode = SImode;
+ break;
+ default:
+ return 0;
+ }
+ switch (str[2])
+ {
+ case 'H':
+ mode = HImode;
break;
+ case 'S':
+ mode = SImode;
+ break;
+ case 'D':
+ mode = DImode;
+ break;
+ default:
+ return 0;
+ }
+ switch (str[3])
+ {
+ case '0':
+ def = 0;
+ break;
+ case 'F':
+ def = -1;
+ break;
default:
return 0;
}
+ if (GET_MODE_SIZE (mode) <= GET_MODE_SIZE (part_mode))
+ return 0;
+
+ part = s390_single_part (GEN_INT (value), mode, part_mode, def);
+ if (part < 0)
+ return 0;
+ if (part_goal != -1 && part_goal != part)
+ return 0;
+
return 1;
}
+
+/* Returns true if the input parameter VALUE is a float zero. */
+
+int
+s390_float_const_zero_p (rtx value)
+{
+ return (GET_MODE_CLASS (GET_MODE (value)) == MODE_FLOAT
+ && value == CONST0_RTX (GET_MODE (value)));
+}
+
+
/* Compute a (partial) cost for rtx X. Return true if the complete
cost has been computed, and false if subexpressions should be
- scanned. In either case, *TOTAL contains the cost result. */
+ scanned. In either case, *TOTAL contains the cost result.
+ CODE contains GET_CODE (x), OUTER_CODE contains the code
+ of the superexpression of x. */
static bool
s390_rtx_costs (rtx x, int code, int outer_code, int *total)
@@ -1396,60 +2113,195 @@ s390_rtx_costs (rtx x, int code, int outer_code, int *total)
switch (code)
{
case CONST:
- if (GET_CODE (XEXP (x, 0)) == MINUS
- && GET_CODE (XEXP (XEXP (x, 0), 1)) != CONST_INT)
- *total = 1000;
- else
- *total = 0;
- return true;
-
case CONST_INT:
- /* 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 an
- addition of greater constants a cost of 3 (reload1.c 10096). */
- /* ??? saveable_obstack no longer exists. */
- if (outer_code == PLUS
- && (INTVAL (x) > 32767 || INTVAL (x) < -32768))
- *total = COSTS_N_INSNS (3);
- else
- *total = 0;
- return true;
-
case LABEL_REF:
case SYMBOL_REF:
case CONST_DOUBLE:
+ case MEM:
*total = 0;
return true;
case ASHIFT:
case ASHIFTRT:
case LSHIFTRT:
- case PLUS:
+ case ROTATE:
+ case ROTATERT:
case AND:
case IOR:
case XOR:
- case MINUS:
case NEG:
case NOT:
*total = COSTS_N_INSNS (1);
- return true;
+ return false;
- case MULT:
- if (GET_MODE (XEXP (x, 0)) == DImode)
- *total = COSTS_N_INSNS (40);
- else
- *total = COSTS_N_INSNS (7);
- return true;
+ case PLUS:
+ case MINUS:
+ /* Check for multiply and add. */
+ if ((GET_MODE (x) == DFmode || GET_MODE (x) == SFmode)
+ && GET_CODE (XEXP (x, 0)) == MULT
+ && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD)
+ {
+ /* This is the multiply and add case. */
+ if (GET_MODE (x) == DFmode)
+ *total = s390_cost->madbr;
+ else
+ *total = s390_cost->maebr;
+ *total += rtx_cost (XEXP (XEXP (x, 0), 0), MULT)
+ + rtx_cost (XEXP (XEXP (x, 0), 1), MULT)
+ + rtx_cost (XEXP (x, 1), code);
+ return true; /* Do not do an additional recursive descent. */
+ }
+ *total = COSTS_N_INSNS (1);
+ return false;
+
+ case MULT:
+ switch (GET_MODE (x))
+ {
+ case SImode:
+ {
+ rtx left = XEXP (x, 0);
+ rtx right = XEXP (x, 1);
+ if (GET_CODE (right) == CONST_INT
+ && CONST_OK_FOR_K (INTVAL (right)))
+ *total = s390_cost->mhi;
+ else if (GET_CODE (left) == SIGN_EXTEND)
+ *total = s390_cost->mh;
+ else
+ *total = s390_cost->ms; /* msr, ms, msy */
+ break;
+ }
+ case DImode:
+ {
+ rtx left = XEXP (x, 0);
+ rtx right = XEXP (x, 1);
+ if (TARGET_64BIT)
+ {
+ if (GET_CODE (right) == CONST_INT
+ && CONST_OK_FOR_K (INTVAL (right)))
+ *total = s390_cost->mghi;
+ else if (GET_CODE (left) == SIGN_EXTEND)
+ *total = s390_cost->msgf;
+ else
+ *total = s390_cost->msg; /* msgr, msg */
+ }
+ else /* TARGET_31BIT */
+ {
+ if (GET_CODE (left) == SIGN_EXTEND
+ && GET_CODE (right) == SIGN_EXTEND)
+ /* mulsidi case: mr, m */
+ *total = s390_cost->m;
+ else if (GET_CODE (left) == ZERO_EXTEND
+ && GET_CODE (right) == ZERO_EXTEND
+ && TARGET_CPU_ZARCH)
+ /* umulsidi case: ml, mlr */
+ *total = s390_cost->ml;
+ else
+ /* Complex calculation is required. */
+ *total = COSTS_N_INSNS (40);
+ }
+ break;
+ }
+ case SFmode:
+ case DFmode:
+ *total = s390_cost->mult_df;
+ break;
+ case TFmode:
+ *total = s390_cost->mxbr;
+ break;
+ default:
+ return false;
+ }
+ return false;
- case DIV:
case UDIV:
- case MOD:
case UMOD:
- *total = COSTS_N_INSNS (33);
- return true;
+ if (GET_MODE (x) == TImode) /* 128 bit division */
+ *total = s390_cost->dlgr;
+ else if (GET_MODE (x) == DImode)
+ {
+ rtx right = XEXP (x, 1);
+ if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
+ *total = s390_cost->dlr;
+ else /* 64 by 64 bit division */
+ *total = s390_cost->dlgr;
+ }
+ else if (GET_MODE (x) == SImode) /* 32 bit division */
+ *total = s390_cost->dlr;
+ return false;
+
+ case DIV:
+ case MOD:
+ if (GET_MODE (x) == DImode)
+ {
+ rtx right = XEXP (x, 1);
+ if (GET_CODE (right) == ZERO_EXTEND) /* 64 by 32 bit division */
+ if (TARGET_64BIT)
+ *total = s390_cost->dsgfr;
+ else
+ *total = s390_cost->dr;
+ else /* 64 by 64 bit division */
+ *total = s390_cost->dsgr;
+ }
+ else if (GET_MODE (x) == SImode) /* 32 bit division */
+ *total = s390_cost->dlr;
+ else if (GET_MODE (x) == SFmode)
+ {
+ if (TARGET_IEEE_FLOAT)
+ *total = s390_cost->debr;
+ else /* TARGET_IBM_FLOAT */
+ *total = s390_cost->der;
+ }
+ else if (GET_MODE (x) == DFmode)
+ {
+ if (TARGET_IEEE_FLOAT)
+ *total = s390_cost->ddbr;
+ else /* TARGET_IBM_FLOAT */
+ *total = s390_cost->ddr;
+ }
+ else if (GET_MODE (x) == TFmode)
+ {
+ if (TARGET_IEEE_FLOAT)
+ *total = s390_cost->dxbr;
+ else /* TARGET_IBM_FLOAT */
+ *total = s390_cost->dxr;
+ }
+ return false;
+
+ case SQRT:
+ if (GET_MODE (x) == SFmode)
+ *total = s390_cost->sqebr;
+ else if (GET_MODE (x) == DFmode)
+ *total = s390_cost->sqdbr;
+ else /* TFmode */
+ *total = s390_cost->sqxbr;
+ return false;
+
+ case SIGN_EXTEND:
+ case ZERO_EXTEND:
+ if (outer_code == MULT || outer_code == DIV || outer_code == MOD
+ || outer_code == PLUS || outer_code == MINUS
+ || outer_code == COMPARE)
+ *total = 0;
+ return false;
+
+ case COMPARE:
+ *total = COSTS_N_INSNS (1);
+ if (GET_CODE (XEXP (x, 0)) == AND
+ && GET_CODE (XEXP (x, 1)) == CONST_INT
+ && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
+ {
+ rtx op0 = XEXP (XEXP (x, 0), 0);
+ rtx op1 = XEXP (XEXP (x, 0), 1);
+ rtx op2 = XEXP (x, 1);
+
+ if (memory_operand (op0, GET_MODE (op0))
+ && s390_tm_ccmode (op1, op2, 0) != VOIDmode)
+ return true;
+ if (register_operand (op0, GET_MODE (op0))
+ && s390_tm_ccmode (op1, op2, 1) != VOIDmode)
+ return true;
+ }
+ return false;
default:
return false;
@@ -1468,172 +2320,41 @@ s390_address_cost (rtx addr)
return ad.indx? COSTS_N_INSNS (1) + 1 : COSTS_N_INSNS (1);
}
-/* Return true if OP is a valid operand for the BRAS instruction.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-bras_sym_operand (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- 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) == UNSPEC_PLT)
- return 1;
- return 0;
-}
-
/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
otherwise return 0. */
int
-tls_symbolic_operand (register rtx op)
+tls_symbolic_operand (rtx op)
{
if (GET_CODE (op) != SYMBOL_REF)
return 0;
return SYMBOL_REF_TLS_MODEL (op);
}
-/* Return true if OP is a load multiple operation. It is known to be a
- PARALLEL and the first section will be tested.
- OP is the current operation.
- MODE is the current operation mode. */
+/* Split DImode access register reference REG (on 64-bit) into its constituent
+ low and high parts, and store them into LO and HI. Note that gen_lowpart/
+ gen_highpart cannot be used as they assume all registers are word-sized,
+ while our access registers have only half that size. */
-int
-load_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
+void
+s390_split_access_reg (rtx reg, rtx *lo, rtx *hi)
{
- enum machine_mode elt_mode;
- int count = XVECLEN (op, 0);
- unsigned int dest_regno;
- rtx src_addr;
- int i, off;
-
-
- /* 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;
+ gcc_assert (TARGET_64BIT);
+ gcc_assert (ACCESS_REG_P (reg));
+ gcc_assert (GET_MODE (reg) == DImode);
+ gcc_assert (!(REGNO (reg) & 1));
- dest_regno = REGNO (SET_DEST (XVECEXP (op, 0, 0)));
- src_addr = XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0);
- elt_mode = GET_MODE (SET_DEST (XVECEXP (op, 0, 0)));
-
- /* Check, is base, or base + displacement. */
-
- if (GET_CODE (src_addr) == REG)
- off = 0;
- else if (GET_CODE (src_addr) == PLUS
- && GET_CODE (XEXP (src_addr, 0)) == REG
- && GET_CODE (XEXP (src_addr, 1)) == CONST_INT)
- {
- off = INTVAL (XEXP (src_addr, 1));
- src_addr = XEXP (src_addr, 0);
- }
- else
- return 0;
-
- if (src_addr == frame_pointer_rtx || src_addr == arg_pointer_rtx)
- return 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)) != elt_mode
- || REGNO (SET_DEST (elt)) != dest_regno + i
- || GET_CODE (SET_SRC (elt)) != MEM
- || GET_MODE (SET_SRC (elt)) != elt_mode
- || 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))
- != off + i * GET_MODE_SIZE (elt_mode))
- return 0;
- }
-
- return 1;
+ *lo = gen_rtx_REG (SImode, REGNO (reg) + 1);
+ *hi = gen_rtx_REG (SImode, REGNO (reg));
}
-/* Return true if OP is a store multiple operation. It is known to be a
- PARALLEL and the first section will be tested.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-store_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum machine_mode elt_mode;
- int count = XVECLEN (op, 0);
- unsigned int src_regno;
- rtx dest_addr;
- int i, off;
-
- /* 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);
- elt_mode = GET_MODE (SET_SRC (XVECEXP (op, 0, 0)));
-
- /* Check, is base, or base + displacement. */
-
- if (GET_CODE (dest_addr) == REG)
- off = 0;
- else if (GET_CODE (dest_addr) == PLUS
- && GET_CODE (XEXP (dest_addr, 0)) == REG
- && GET_CODE (XEXP (dest_addr, 1)) == CONST_INT)
- {
- off = INTVAL (XEXP (dest_addr, 1));
- dest_addr = XEXP (dest_addr, 0);
- }
- else
- return 0;
-
- if (dest_addr == frame_pointer_rtx || dest_addr == arg_pointer_rtx)
- return 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)) != elt_mode
- || REGNO (SET_SRC (elt)) != src_regno + i
- || GET_CODE (SET_DEST (elt)) != MEM
- || GET_MODE (SET_DEST (elt)) != elt_mode
- || 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))
- != off + i * GET_MODE_SIZE (elt_mode))
- return 0;
- }
- return 1;
-}
-
-
/* Return true if OP contains a symbol reference */
-int
+bool
symbolic_reference_mentioned_p (rtx op)
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
return 1;
@@ -1643,7 +2364,7 @@ symbolic_reference_mentioned_p (rtx op)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
@@ -1659,11 +2380,11 @@ symbolic_reference_mentioned_p (rtx op)
/* Return true if OP contains a reference to a thread-local symbol. */
-int
+bool
tls_symbolic_reference_mentioned_p (rtx op)
{
- register const char *fmt;
- register int i;
+ const char *fmt;
+ int i;
if (GET_CODE (op) == SYMBOL_REF)
return tls_symbolic_operand (op);
@@ -1673,18 +2394,18 @@ tls_symbolic_reference_mentioned_p (rtx op)
{
if (fmt[i] == 'E')
{
- register int j;
+ int j;
for (j = XVECLEN (op, i) - 1; j >= 0; j--)
if (tls_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
- return 1;
+ return true;
}
else if (fmt[i] == 'e' && tls_symbolic_reference_mentioned_p (XEXP (op, i)))
- return 1;
+ return true;
}
- return 0;
+ return false;
}
@@ -1693,7 +2414,7 @@ tls_symbolic_reference_mentioned_p (rtx op)
and that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
int
-legitimate_pic_operand_p (register rtx op)
+legitimate_pic_operand_p (rtx op)
{
/* Accept all non-symbolic constants. */
if (!SYMBOLIC_CONST (op))
@@ -1708,7 +2429,7 @@ legitimate_pic_operand_p (register rtx op)
It is given that OP satisfies CONSTANT_P or is a CONST_DOUBLE. */
int
-legitimate_constant_p (register rtx op)
+legitimate_constant_p (rtx op)
{
/* Accept all non-symbolic constants. */
if (!SYMBOLIC_CONST (op))
@@ -1784,13 +2505,18 @@ s390_cannot_force_const_mem (rtx x)
case UNSPEC_INDNTPOFF:
return false;
+ /* If the literal pool shares the code section, be put
+ execute template placeholders into the pool as well. */
+ case UNSPEC_INSN:
+ return TARGET_CPU_ZARCH;
+
default:
return true;
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
@@ -1800,31 +2526,55 @@ s390_cannot_force_const_mem (rtx x)
a constant that would need to be forced to the literal pool
before it can be used as operand. */
-int
-legitimate_reload_constant_p (register rtx op)
+bool
+legitimate_reload_constant_p (rtx op)
{
/* Accept la(y) operands. */
if (GET_CODE (op) == CONST_INT
&& DISP_IN_RANGE (INTVAL (op)))
- return 1;
+ return true;
- /* Accept l(g)hi operands. */
+ /* Accept l(g)hi/l(g)fi operands. */
if (GET_CODE (op) == CONST_INT
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (op), 'K', "K"))
- return 1;
+ && (CONST_OK_FOR_K (INTVAL (op)) || CONST_OK_FOR_Os (INTVAL (op))))
+ return true;
/* Accept lliXX operands. */
if (TARGET_ZARCH
- && s390_single_part (op, DImode, HImode, 0) >= 0)
- return 1;
+ && GET_CODE (op) == CONST_INT
+ && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
+ && s390_single_part (op, word_mode, HImode, 0) >= 0)
+ return true;
+
+ if (TARGET_EXTIMM
+ && GET_CODE (op) == CONST_INT
+ && trunc_int_for_mode (INTVAL (op), word_mode) == INTVAL (op)
+ && s390_single_part (op, word_mode, SImode, 0) >= 0)
+ return true;
/* Accept larl operands. */
if (TARGET_CPU_ZARCH
&& larl_operand (op, VOIDmode))
- return 1;
+ return true;
+
+ /* Accept lzXX operands. */
+ if (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_OK_FOR_CONSTRAINT_P (op, 'G', "G"))
+ return true;
+
+ /* Accept double-word operands that can be split. */
+ if (GET_CODE (op) == CONST_INT
+ && trunc_int_for_mode (INTVAL (op), word_mode) != INTVAL (op))
+ {
+ enum machine_mode dword_mode = word_mode == SImode ? DImode : TImode;
+ rtx hi = operand_subword (op, 0, 0, dword_mode);
+ rtx lo = operand_subword (op, 1, 0, dword_mode);
+ return legitimate_reload_constant_p (hi)
+ && legitimate_reload_constant_p (lo);
+ }
/* Everything else cannot be handled without reload. */
- return 0;
+ return false;
}
/* Given an rtx OP being reloaded into a reg required to be in class CLASS,
@@ -1833,12 +2583,6 @@ legitimate_reload_constant_p (register rtx op)
enum reg_class
s390_preferred_reload_class (rtx op, enum reg_class class)
{
- /* This can happen if a floating point constant is being
- reloaded into an integer register. Leave well alone. */
- if (GET_MODE_CLASS (GET_MODE (op)) == MODE_FLOAT
- && class != FP_REGS)
- return class;
-
switch (GET_CODE (op))
{
/* Constants we cannot reload must be forced into the
@@ -1878,12 +2622,24 @@ s390_preferred_reload_class (rtx op, enum reg_class class)
is not a legitimate operand of the LOAD ADDRESS instruction. */
enum reg_class
-s390_secondary_input_reload_class (enum reg_class class ATTRIBUTE_UNUSED,
+s390_secondary_input_reload_class (enum reg_class class,
enum machine_mode mode, rtx in)
{
if (s390_plus_operand (in, mode))
return ADDR_REGS;
+ if (reg_classes_intersect_p (FP_REGS, class)
+ && mode == TFmode
+ && GET_CODE (in) == MEM
+ && GET_CODE (XEXP (in, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (in, 0), 1)) == CONST_INT
+ && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (in, 0), 1))
+ + GET_MODE_SIZE (mode) - 1))
+ return ADDR_REGS;
+
+ if (reg_classes_intersect_p (CC_REGS, class))
+ return GENERAL_REGS;
+
return NO_REGS;
}
@@ -1897,35 +2653,30 @@ enum reg_class
s390_secondary_output_reload_class (enum reg_class class,
enum machine_mode mode, rtx out)
{
- if ((TARGET_64BIT ? mode == TImode
+ if ((TARGET_64BIT ? (mode == TImode || mode == TFmode)
: (mode == DImode || mode == DFmode))
&& reg_classes_intersect_p (GENERAL_REGS, class)
&& GET_CODE (out) == MEM
- && !offsettable_memref_p (out)
- && !s_operand (out, VOIDmode))
+ && GET_CODE (XEXP (out, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (out, 0), 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (out, 0), 1)) == CONST_INT
+ && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (out, 0), 1))
+ + GET_MODE_SIZE (mode) - 1))
return ADDR_REGS;
- return NO_REGS;
-}
-
-/* Return true if OP is a PLUS that is not a legitimate
- operand for the LA instruction.
- OP is the current operation.
- MODE is the current operation mode. */
-
-int
-s390_plus_operand (register rtx op, enum machine_mode mode)
-{
- if (!check_mode (op, &mode) || mode != Pmode)
- return FALSE;
-
- if (GET_CODE (op) != PLUS)
- return FALSE;
+ if (reg_classes_intersect_p (FP_REGS, class)
+ && mode == TFmode
+ && GET_CODE (out) == MEM
+ && GET_CODE (XEXP (out, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (out, 0), 1)) == CONST_INT
+ && !DISP_IN_RANGE (INTVAL (XEXP (XEXP (out, 0), 1))
+ + GET_MODE_SIZE (mode) - 1))
+ return ADDR_REGS;
- if (legitimate_la_operand_p (op))
- return FALSE;
+ if (reg_classes_intersect_p (CC_REGS, class))
+ return GENERAL_REGS;
- return TRUE;
+ return NO_REGS;
}
/* Generate code to load SRC, which is PLUS that is not a
@@ -1933,15 +2684,15 @@ s390_plus_operand (register rtx op, enum machine_mode mode)
SCRATCH may be used as scratch register. */
void
-s390_expand_plus_operand (register rtx target, register rtx src,
- register rtx scratch)
+s390_expand_plus_operand (rtx target, rtx src,
+ rtx scratch)
{
rtx sum1, sum2;
struct s390_address ad;
/* src must be a PLUS; get its two operands. */
- if (GET_CODE (src) != PLUS || GET_MODE (src) != Pmode)
- abort ();
+ gcc_assert (GET_CODE (src) == PLUS);
+ gcc_assert (GET_MODE (src) == Pmode);
/* Check if any of the two operands is already scheduled
for replacement by reload. This can happen e.g. when
@@ -1952,8 +2703,8 @@ s390_expand_plus_operand (register rtx target, register rtx src,
/* If the address is already strictly valid, there's nothing to do. */
if (!s390_decompose_address (src, &ad)
- || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
- || (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx)))
+ || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
+ || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
{
/* Otherwise, one of the operands cannot be an address register;
we reload its value into the scratch register. */
@@ -1975,7 +2726,7 @@ s390_expand_plus_operand (register rtx target, register rtx src,
if (sum1 == scratch && sum2 == scratch)
{
debug_rtx (src);
- abort ();
+ gcc_unreachable ();
}
src = gen_rtx_PLUS (Pmode, sum1, sum2);
@@ -1988,314 +2739,83 @@ s390_expand_plus_operand (register rtx target, register rtx src,
}
-/* Decompose a RTL expression ADDR for a memory address into
- its components, returned in OUT.
-
- 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 (register rtx addr, struct s390_address *out)
-{
- rtx base = NULL_RTX;
- rtx indx = NULL_RTX;
- rtx disp = NULL_RTX;
- int pointer = FALSE;
- int base_ptr = FALSE;
- int indx_ptr = FALSE;
-
- /* 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) != UNSPEC_LTREL_BASE)
- return FALSE;
- base = gen_rtx_REG (Pmode, BASE_REGISTER);
- }
-
- if (GET_CODE (base) != REG || GET_MODE (base) != Pmode)
- return FALSE;
-
- if (REGNO (base) == BASE_REGISTER
- || REGNO (base) == STACK_POINTER_REGNUM
- || REGNO (base) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (base) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (base) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (base) == PIC_OFFSET_TABLE_REGNUM))
- pointer = base_ptr = TRUE;
- }
-
- /* Validate index register. */
- if (indx)
- {
- if (GET_CODE (indx) == UNSPEC)
- {
- if (XVECLEN (indx, 0) != 1 || XINT (indx, 1) != UNSPEC_LTREL_BASE)
- return FALSE;
- indx = gen_rtx_REG (Pmode, BASE_REGISTER);
- }
-
- if (GET_CODE (indx) != REG || GET_MODE (indx) != Pmode)
- return FALSE;
-
- if (REGNO (indx) == BASE_REGISTER
- || REGNO (indx) == STACK_POINTER_REGNUM
- || REGNO (indx) == FRAME_POINTER_REGNUM
- || ((reload_completed || reload_in_progress)
- && frame_pointer_needed
- && REGNO (indx) == HARD_FRAME_POINTER_REGNUM)
- || REGNO (indx) == ARG_POINTER_REGNUM
- || (flag_pic
- && REGNO (indx) == PIC_OFFSET_TABLE_REGNUM))
- pointer = indx_ptr = TRUE;
- }
-
- /* Prefer to use pointer as base, not index. */
- if (base && indx && !base_ptr
- && (indx_ptr || (!REG_POINTER (base) && REG_POINTER (indx))))
- {
- rtx tmp = base;
- base = indx;
- indx = tmp;
- }
-
- /* Validate displacement. */
- if (disp)
- {
- /* Allow integer constant in range. */
- if (GET_CODE (disp) == CONST_INT)
- {
- /* If the argument pointer is involved, the displacement will change
- later anyway as the argument pointer gets eliminated. This could
- make a valid displacement invalid, but it is more likely to make
- an invalid displacement valid, because we sometimes access the
- register save area via negative offsets to the arg pointer.
- Thus we don't check the displacement for validity here. If after
- elimination the displacement turns out to be invalid after all,
- this is fixed up by reload in any case. */
- if (base != arg_pointer_rtx && indx != arg_pointer_rtx)
- {
- if (!DISP_IN_RANGE (INTVAL (disp)))
- return FALSE;
- }
- }
-
- /* In the small-PIC case, the linker converts @GOT
- and @GOTNTPOFF offsets to possible displacements. */
- else if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == UNSPEC
- && (XINT (XEXP (disp, 0), 1) == UNSPEC_GOT
- || XINT (XEXP (disp, 0), 1) == UNSPEC_GOTNTPOFF))
- {
- if (flag_pic != 1)
- return FALSE;
-
- pointer = TRUE;
- }
-
- /* Accept chunkfied literal pool symbol references. */
- else if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == MINUS
- && GET_CODE (XEXP (XEXP (disp, 0), 0)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (disp, 0), 1)) == LABEL_REF)
- {
- pointer = TRUE;
- }
-
- /* Likewise if a constant offset is present. */
- else if (GET_CODE (disp) == CONST
- && GET_CODE (XEXP (disp, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (disp, 0), 1)) == CONST_INT
- && GET_CODE (XEXP (XEXP (disp, 0), 0)) == MINUS
- && GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 0)) == LABEL_REF
- && GET_CODE (XEXP (XEXP (XEXP (disp, 0), 0), 1)) == LABEL_REF)
- {
- pointer = TRUE;
- }
-
- /* 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. */
-
- unsigned 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;
-
- /* 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),
- UNSPEC_LTREL_OFFSET);
- disp = gen_rtx_CONST (Pmode, disp);
-
- if (offset)
- disp = plus_constant (disp, offset);
-
- pointer = TRUE;
- }
- }
-
- if (!base && !indx)
- pointer = TRUE;
-
- if (out)
- {
- out->base = base;
- out->indx = indx;
- out->disp = disp;
- out->pointer = pointer;
- }
-
- return TRUE;
-}
-
-/* Return nonzero if ADDR is a valid memory address.
+/* Return true if ADDR is a valid memory address.
STRICT specifies whether strict register checking applies. */
-int
+bool
legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
- register rtx addr, int strict)
+ rtx addr, int strict)
{
struct s390_address ad;
if (!s390_decompose_address (addr, &ad))
- return FALSE;
+ return false;
if (strict)
{
- if (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
- return FALSE;
- if (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx))
- return FALSE;
+ if (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
+ return false;
+
+ if (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx)))
+ return false;
}
else
{
- if (ad.base && !REG_OK_FOR_BASE_NONSTRICT_P (ad.base))
- return FALSE;
- if (ad.indx && !REG_OK_FOR_INDEX_NONSTRICT_P (ad.indx))
- return FALSE;
+ if (ad.base
+ && !(REGNO (ad.base) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (ad.base)) == ADDR_REGS))
+ return false;
+
+ if (ad.indx
+ && !(REGNO (ad.indx) >= FIRST_PSEUDO_REGISTER
+ || REGNO_REG_CLASS (REGNO (ad.indx)) == ADDR_REGS))
+ return false;
}
-
- return TRUE;
+ return true;
}
-/* Return 1 if OP is a valid operand for the LA instruction.
+/* Return true if OP is a valid operand for the LA instruction.
In 31-bit, we need to prove that the result is used as an
address, as LA performs only a 31-bit addition. */
-int
-legitimate_la_operand_p (register rtx op)
+bool
+legitimate_la_operand_p (rtx op)
{
struct s390_address addr;
if (!s390_decompose_address (op, &addr))
- return FALSE;
-
- if (TARGET_64BIT || addr.pointer)
- return TRUE;
+ return false;
- return FALSE;
+ return (TARGET_64BIT || addr.pointer);
}
-/* Return 1 if OP is a valid operand for the LA instruction,
- and we prefer to use LA over addition to compute it. */
+/* Return true if it is valid *and* preferable to use LA to
+ compute the sum of OP1 and OP2. */
-int
-preferred_la_operand_p (register rtx op)
+bool
+preferred_la_operand_p (rtx op1, rtx op2)
{
struct s390_address addr;
- if (!s390_decompose_address (op, &addr))
- return FALSE;
+
+ if (op2 != const0_rtx)
+ op1 = gen_rtx_PLUS (Pmode, op1, op2);
+
+ if (!s390_decompose_address (op1, &addr))
+ return false;
+ if (addr.base && !REGNO_OK_FOR_BASE_P (REGNO (addr.base)))
+ return false;
+ if (addr.indx && !REGNO_OK_FOR_INDEX_P (REGNO (addr.indx)))
+ return false;
if (!TARGET_64BIT && !addr.pointer)
- return FALSE;
+ return false;
if (addr.pointer)
- return TRUE;
+ return true;
if ((addr.base && REG_P (addr.base) && REG_POINTER (addr.base))
|| (addr.indx && REG_P (addr.indx) && REG_POINTER (addr.indx)))
- return TRUE;
+ return true;
- return FALSE;
+ return false;
}
/* Emit a forced load-address operation to load SRC into DST.
@@ -2336,6 +2856,8 @@ legitimize_pic_address (rtx orig, rtx reg)
rtx new = orig;
rtx base;
+ gcc_assert (!TLS_SYMBOLIC_CONST (addr));
+
if (GET_CODE (addr) == LABEL_REF
|| (GET_CODE (addr) == SYMBOL_REF && SYMBOL_REF_LOCAL_P (addr)))
{
@@ -2363,7 +2885,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
if (reg != 0)
{
- emit_move_insn (reg, new);
+ s390_load_address (reg, new);
new = reg;
}
}
@@ -2384,8 +2906,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOT);
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;
+ new = gen_const_mem (Pmode, new);
emit_move_insn (reg, new);
new = reg;
}
@@ -2400,8 +2921,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = gen_rtx_CONST (Pmode, new);
emit_move_insn (temp, new);
- new = gen_rtx_MEM (Pmode, temp);
- RTX_UNCHANGING_P (new) = 1;
+ new = gen_const_mem (Pmode, temp);
emit_move_insn (reg, new);
new = reg;
}
@@ -2421,8 +2941,7 @@ legitimize_pic_address (rtx orig, rtx reg)
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;
+ new = gen_const_mem (Pmode, new);
emit_move_insn (reg, new);
new = reg;
}
@@ -2434,8 +2953,7 @@ legitimize_pic_address (rtx orig, rtx reg)
addr = XEXP (addr, 0);
if (GET_CODE (addr) == UNSPEC)
{
- if (XVECLEN (addr, 0) != 1)
- abort ();
+ gcc_assert (XVECLEN (addr, 0) == 1);
switch (XINT (addr, 1))
{
/* If someone moved a GOT-relative UNSPEC
@@ -2475,7 +2993,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
if (reg != 0)
{
- emit_move_insn (reg, new);
+ s390_load_address (reg, new);
new = reg;
}
}
@@ -2483,22 +3001,29 @@ legitimize_pic_address (rtx orig, rtx reg)
/* Everything else cannot happen. */
default:
- abort ();
+ gcc_unreachable ();
}
}
- else if (GET_CODE (addr) != PLUS)
- abort ();
+ else
+ gcc_assert (GET_CODE (addr) == PLUS);
}
if (GET_CODE (addr) == PLUS)
{
rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
+
+ gcc_assert (!TLS_SYMBOLIC_CONST (op0));
+ gcc_assert (!TLS_SYMBOLIC_CONST (op1));
+
/* 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_LOCAL_P (op0)))
&& GET_CODE (op1) == CONST_INT)
{
- if (TARGET_CPU_ZARCH && larl_operand (op0, VOIDmode))
+ if (TARGET_CPU_ZARCH
+ && larl_operand (op0, VOIDmode)
+ && INTVAL (op1) < (HOST_WIDE_INT)1 << 31
+ && INTVAL (op1) >= -((HOST_WIDE_INT)1 << 31))
{
if (INTVAL (op1) & 1)
{
@@ -2508,10 +3033,10 @@ legitimize_pic_address (rtx orig, rtx reg)
if (!DISP_IN_RANGE (INTVAL (op1)))
{
- int even = INTVAL (op1) - 1;
+ HOST_WIDE_INT even = INTVAL (op1) - 1;
op0 = gen_rtx_PLUS (Pmode, op0, GEN_INT (even));
op0 = gen_rtx_CONST (Pmode, op0);
- op1 = GEN_INT (1);
+ op1 = const1_rtx;
}
emit_move_insn (temp, op0);
@@ -2519,7 +3044,7 @@ legitimize_pic_address (rtx orig, rtx reg)
if (reg != 0)
{
- emit_move_insn (reg, new);
+ s390_load_address (reg, new);
new = reg;
}
}
@@ -2548,7 +3073,7 @@ legitimize_pic_address (rtx orig, rtx reg)
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
if (reg != 0)
{
- emit_move_insn (reg, new);
+ s390_load_address (reg, new);
new = reg;
}
}
@@ -2561,8 +3086,7 @@ legitimize_pic_address (rtx orig, rtx reg)
&& GET_CODE (op1) == CONST_INT
&& XINT (op0, 1) == UNSPEC_GOTOFF)
{
- if (XVECLEN (op0, 0) != 1)
- abort ();
+ gcc_assert (XVECLEN (op0, 0) == 1);
new = force_const_mem (Pmode, orig);
}
@@ -2596,28 +3120,39 @@ legitimize_pic_address (rtx orig, rtx reg)
/* Load the thread pointer into a register. */
-static rtx
-get_thread_pointer (void)
+rtx
+s390_get_thread_pointer (void)
{
- rtx tp;
+ rtx tp = gen_reg_rtx (Pmode);
- tp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), UNSPEC_TP);
- tp = force_reg (Pmode, tp);
+ emit_move_insn (tp, gen_rtx_REG (Pmode, TP_REGNUM));
mark_reg_pointer (tp, BITS_PER_WORD);
return tp;
}
-/* Construct the SYMBOL_REF for the tls_get_offset function. */
+/* Emit a tls call insn. The call target is the SYMBOL_REF stored
+ in s390_tls_symbol which always refers to __tls_get_offset.
+ The returned offset is written to RESULT_REG and an USE rtx is
+ generated for TLS_CALL. */
static GTY(()) rtx s390_tls_symbol;
-rtx
-s390_tls_get_offset (void)
+
+static void
+s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
{
+ rtx insn;
+
+ gcc_assert (flag_pic);
+
if (!s390_tls_symbol)
s390_tls_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tls_get_offset");
- return s390_tls_symbol;
+ insn = s390_emit_call (s390_tls_symbol, tls_call, result_reg,
+ gen_rtx_REG (Pmode, RETURN_REGNUM));
+
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), result_reg);
+ CONST_OR_PURE_CALL_P (insn) = 1;
}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
@@ -2638,7 +3173,7 @@ legitimize_tls_address (rtx addr, rtx reg)
new = gen_rtx_CONST (Pmode, tls_call);
new = force_const_mem (Pmode, new);
emit_move_insn (r2, new);
- emit_call_insn (gen_call_value_tls (r2, tls_call));
+ s390_emit_tls_call_insn (r2, tls_call);
insn = get_insns ();
end_sequence ();
@@ -2646,7 +3181,7 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_libcall_block (insn, temp, r2, new);
- new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
if (reg != 0)
{
s390_load_address (reg, new);
@@ -2661,7 +3196,7 @@ legitimize_tls_address (rtx addr, rtx reg)
new = gen_rtx_CONST (Pmode, tls_call);
new = force_const_mem (Pmode, new);
emit_move_insn (r2, new);
- emit_call_insn (gen_call_value_tls (r2, tls_call));
+ s390_emit_tls_call_insn (r2, tls_call);
insn = get_insns ();
end_sequence ();
@@ -2669,7 +3204,7 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_libcall_block (insn, temp, r2, new);
- new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
base = gen_reg_rtx (Pmode);
s390_load_address (base, new);
@@ -2699,8 +3234,7 @@ legitimize_tls_address (rtx addr, rtx reg)
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTNTPOFF);
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;
+ new = gen_const_mem (Pmode, new);
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
}
@@ -2714,8 +3248,7 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
- new = gen_rtx_MEM (Pmode, temp);
- RTX_UNCHANGING_P (new) = 1;
+ new = gen_const_mem (Pmode, temp);
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
}
@@ -2734,8 +3267,7 @@ legitimize_tls_address (rtx addr, rtx reg)
emit_move_insn (temp, new);
new = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, temp);
- new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
+ new = gen_const_mem (Pmode, new);
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
temp = gen_reg_rtx (Pmode);
@@ -2753,15 +3285,13 @@ legitimize_tls_address (rtx addr, rtx reg)
emit_move_insn (temp, new);
new = temp;
- new = gen_rtx_MEM (Pmode, new);
- RTX_UNCHANGING_P (new) = 1;
-
+ new = gen_const_mem (Pmode, new);
new = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, new, addr), UNSPEC_TLS_LOAD);
temp = gen_reg_rtx (Pmode);
emit_insn (gen_rtx_SET (Pmode, temp, new));
}
- new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
if (reg != 0)
{
s390_load_address (reg, new);
@@ -2776,7 +3306,7 @@ legitimize_tls_address (rtx addr, rtx reg)
temp = gen_reg_rtx (Pmode);
emit_move_insn (temp, new);
- new = gen_rtx_PLUS (Pmode, get_thread_pointer (), temp);
+ new = gen_rtx_PLUS (Pmode, s390_get_thread_pointer (), temp);
if (reg != 0)
{
s390_load_address (reg, new);
@@ -2785,7 +3315,7 @@ legitimize_tls_address (rtx addr, rtx reg)
break;
default:
- abort ();
+ gcc_unreachable ();
}
else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == UNSPEC)
@@ -2793,19 +3323,29 @@ legitimize_tls_address (rtx addr, rtx reg)
switch (XINT (XEXP (addr, 0), 1))
{
case UNSPEC_INDNTPOFF:
- if (TARGET_CPU_ZARCH)
- new = addr;
- else
- abort ();
+ gcc_assert (TARGET_CPU_ZARCH);
+ new = addr;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
+ else if (GET_CODE (addr) == CONST && GET_CODE (XEXP (addr, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
+ {
+ new = XEXP (XEXP (addr, 0), 0);
+ if (GET_CODE (new) != SYMBOL_REF)
+ new = gen_rtx_CONST (Pmode, new);
+
+ new = legitimize_tls_address (new, reg);
+ new = plus_constant (new, INTVAL (XEXP (XEXP (addr, 0), 1)));
+ new = force_operand (new, 0);
+ }
+
else
- abort (); /* for now ... */
+ gcc_unreachable (); /* for now ... */
return new;
}
@@ -2837,7 +3377,7 @@ emit_symbolic_move (rtx *operands)
See comments by legitimize_pic_address for details. */
rtx
-legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
+legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED)
{
rtx constant_term = const0_rtx;
@@ -2849,6 +3389,12 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
if (legitimate_address_p (mode, x, FALSE))
return x;
}
+ else if (GET_CODE (x) == PLUS
+ && (TLS_SYMBOLIC_CONST (XEXP (x, 0))
+ || TLS_SYMBOLIC_CONST (XEXP (x, 1))))
+ {
+ return x;
+ }
else if (flag_pic)
{
if (SYMBOLIC_CONST (x)
@@ -2892,8 +3438,8 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
{
if (GET_CODE (XEXP (x, 0)) == REG)
{
- register rtx temp = gen_reg_rtx (Pmode);
- register rtx val = force_operand (XEXP (x, 1), temp);
+ rtx temp = gen_reg_rtx (Pmode);
+ rtx val = force_operand (XEXP (x, 1), temp);
if (val != temp)
emit_move_insn (temp, val);
@@ -2902,8 +3448,8 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
else if (GET_CODE (XEXP (x, 1)) == REG)
{
- register rtx temp = gen_reg_rtx (Pmode);
- register rtx val = force_operand (XEXP (x, 0), temp);
+ rtx temp = gen_reg_rtx (Pmode);
+ rtx val = force_operand (XEXP (x, 0), temp);
if (val != temp)
emit_move_insn (temp, val);
@@ -2917,37 +3463,80 @@ legitimize_address (register rtx x, register rtx oldx ATTRIBUTE_UNUSED,
return x;
}
+/* Try a machine-dependent way of reloading an illegitimate address AD
+ operand. If we find one, push the reload and and return the new address.
+
+ MODE is the mode of the enclosing MEM. OPNUM is the operand number
+ and TYPE is the reload type of the current reload. */
+
+rtx
+legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
+ int opnum, int type)
+{
+ if (!optimize || TARGET_LONG_DISPLACEMENT)
+ return NULL_RTX;
+
+ if (GET_CODE (ad) == PLUS)
+ {
+ rtx tem = simplify_binary_operation (PLUS, Pmode,
+ XEXP (ad, 0), XEXP (ad, 1));
+ if (tem)
+ ad = tem;
+ }
+
+ if (GET_CODE (ad) == PLUS
+ && GET_CODE (XEXP (ad, 0)) == REG
+ && GET_CODE (XEXP (ad, 1)) == CONST_INT
+ && !DISP_IN_RANGE (INTVAL (XEXP (ad, 1))))
+ {
+ HOST_WIDE_INT lower = INTVAL (XEXP (ad, 1)) & 0xfff;
+ HOST_WIDE_INT upper = INTVAL (XEXP (ad, 1)) ^ lower;
+ rtx cst, tem, new;
+
+ cst = GEN_INT (upper);
+ if (!legitimate_reload_constant_p (cst))
+ cst = force_const_mem (Pmode, cst);
+
+ tem = gen_rtx_PLUS (Pmode, XEXP (ad, 0), cst);
+ new = gen_rtx_PLUS (Pmode, tem, GEN_INT (lower));
+
+ push_reload (XEXP (tem, 1), 0, &XEXP (tem, 1), 0,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ opnum, (enum reload_type) type);
+ return new;
+ }
+
+ return NULL_RTX;
+}
+
/* Emit code to move LEN bytes from DST to SRC. */
void
-s390_expand_movstr (rtx dst, rtx src, rtx len)
+s390_expand_movmem (rtx dst, rtx src, rtx len)
{
if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
{
if (INTVAL (len) > 0)
- emit_insn (gen_movstr_short (dst, src, GEN_INT (INTVAL (len) - 1)));
+ emit_insn (gen_movmem_short (dst, src, GEN_INT (INTVAL (len) - 1)));
}
else if (TARGET_MVCLE)
{
- emit_insn (gen_movstr_long (dst, src, convert_to_mode (Pmode, len, 1)));
+ emit_insn (gen_movmem_long (dst, src, convert_to_mode (Pmode, len, 1)));
}
else
{
rtx dst_addr, src_addr, count, blocks, temp;
+ rtx loop_start_label = gen_label_rtx ();
+ rtx loop_end_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
enum machine_mode mode;
- tree type;
mode = GET_MODE (len);
if (mode == VOIDmode)
mode = Pmode;
- type = lang_hooks.types.type_for_mode (mode, 1);
- if (!type)
- abort ();
-
dst_addr = gen_reg_rtx (Pmode);
src_addr = gen_reg_rtx (Pmode);
count = gen_reg_rtx (mode);
@@ -2966,16 +3555,16 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
if (temp != count)
emit_move_insn (count, temp);
- temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_start_loop (1);
- expand_exit_loop_top_cond (0, build (NE_EXPR, type,
- make_tree (type, blocks),
- make_tree (type, const0_rtx)));
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
+
+ emit_label (loop_start_label);
- emit_insn (gen_movstr_short (dst, src, GEN_INT (255)));
+ emit_insn (gen_movmem_short (dst, src, GEN_INT (255)));
s390_load_address (dst_addr,
gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
s390_load_address (src_addr,
@@ -2985,45 +3574,72 @@ s390_expand_movstr (rtx dst, rtx src, rtx len)
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_end_loop ();
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
- emit_insn (gen_movstr_short (dst, src,
+ emit_jump (loop_start_label);
+ emit_label (loop_end_label);
+
+ emit_insn (gen_movmem_short (dst, src,
convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
}
}
-/* Emit code to clear LEN bytes at DST. */
+/* Emit code to set LEN bytes at DST to VAL.
+ Make use of clrmem if VAL is zero. */
void
-s390_expand_clrstr (rtx dst, rtx len)
+s390_expand_setmem (rtx dst, rtx len, rtx val)
{
- if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) == 0)
+ return;
+
+ gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
+
+ if (GET_CODE (len) == CONST_INT && INTVAL (len) > 0 && INTVAL (len) <= 257)
{
- if (INTVAL (len) > 0)
- emit_insn (gen_clrstr_short (dst, GEN_INT (INTVAL (len) - 1)));
+ if (val == const0_rtx && INTVAL (len) <= 256)
+ emit_insn (gen_clrmem_short (dst, GEN_INT (INTVAL (len) - 1)));
+ else
+ {
+ /* Initialize memory by storing the first byte. */
+ emit_move_insn (adjust_address (dst, QImode, 0), val);
+
+ if (INTVAL (len) > 1)
+ {
+ /* Initiate 1 byte overlap move.
+ The first byte of DST is propagated through DSTP1.
+ Prepare a movmem for: DST+1 = DST (length = LEN - 1).
+ DST is set to size 1 so the rest of the memory location
+ does not count as source operand. */
+ rtx dstp1 = adjust_address (dst, VOIDmode, 1);
+ set_mem_size (dst, const1_rtx);
+
+ emit_insn (gen_movmem_short (dstp1, dst,
+ GEN_INT (INTVAL (len) - 2)));
+ }
+ }
}
else if (TARGET_MVCLE)
{
- emit_insn (gen_clrstr_long (dst, convert_to_mode (Pmode, len, 1)));
+ val = force_not_mem (convert_modes (Pmode, QImode, val, 1));
+ emit_insn (gen_setmem_long (dst, convert_to_mode (Pmode, len, 1), val));
}
else
{
- rtx dst_addr, src_addr, count, blocks, temp;
+ rtx dst_addr, src_addr, count, blocks, temp, dstp1 = NULL_RTX;
+ rtx loop_start_label = gen_label_rtx ();
+ rtx loop_end_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
enum machine_mode mode;
- tree type;
mode = GET_MODE (len);
if (mode == VOIDmode)
mode = Pmode;
- type = lang_hooks.types.type_for_mode (mode, 1);
- if (!type)
- abort ();
-
dst_addr = gen_reg_rtx (Pmode);
src_addr = gen_reg_rtx (Pmode);
count = gen_reg_rtx (mode);
@@ -3036,20 +3652,38 @@ s390_expand_clrstr (rtx dst, rtx len)
emit_move_insn (dst_addr, force_operand (XEXP (dst, 0), NULL_RTX));
dst = change_address (dst, VOIDmode, dst_addr);
- temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ if (val == const0_rtx)
+ temp = expand_binop (mode, add_optab, count, constm1_rtx, count, 1, 0);
+ else
+ {
+ dstp1 = adjust_address (dst, VOIDmode, 1);
+ set_mem_size (dst, const1_rtx);
+
+ /* Initialize memory by storing the first byte. */
+ emit_move_insn (adjust_address (dst, QImode, 0), val);
+
+ /* If count is 1 we are done. */
+ emit_cmp_and_jump_insns (count, const1_rtx,
+ EQ, NULL_RTX, mode, 1, end_label);
+
+ temp = expand_binop (mode, add_optab, count, GEN_INT (-2), count, 1, 0);
+ }
if (temp != count)
emit_move_insn (count, temp);
- temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_start_loop (1);
- expand_exit_loop_top_cond (0, build (NE_EXPR, type,
- make_tree (type, blocks),
- make_tree (type, const0_rtx)));
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
+
+ emit_label (loop_start_label);
- emit_insn (gen_clrstr_short (dst, GEN_INT (255)));
+ if (val == const0_rtx)
+ emit_insn (gen_clrmem_short (dst, GEN_INT (255)));
+ else
+ emit_insn (gen_movmem_short (dstp1, dst, GEN_INT (255)));
s390_load_address (dst_addr,
gen_rtx_PLUS (Pmode, dst_addr, GEN_INT (256)));
@@ -3057,9 +3691,16 @@ s390_expand_clrstr (rtx dst, rtx len)
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_end_loop ();
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
- emit_insn (gen_clrstr_short (dst, convert_to_mode (Pmode, count, 1)));
+ emit_jump (loop_start_label);
+ emit_label (loop_end_label);
+
+ if (val == const0_rtx)
+ emit_insn (gen_clrmem_short (dst, convert_to_mode (Pmode, count, 1)));
+ else
+ emit_insn (gen_movmem_short (dstp1, dst, convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
}
}
@@ -3070,48 +3711,40 @@ s390_expand_clrstr (rtx dst, rtx len)
void
s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
{
- rtx (*gen_result) (rtx) =
- GET_MODE (target) == DImode ? gen_cmpint_di : gen_cmpint_si;
+ rtx ccreg = gen_rtx_REG (CCUmode, CC_REGNUM);
+ rtx tmp;
- op0 = protect_from_queue (op0, 0);
- op1 = protect_from_queue (op1, 0);
- len = protect_from_queue (len, 0);
+ /* As the result of CMPINT is inverted compared to what we need,
+ we have to swap the operands. */
+ tmp = op0; op0 = op1; op1 = tmp;
if (GET_CODE (len) == CONST_INT && INTVAL (len) >= 0 && INTVAL (len) <= 256)
{
if (INTVAL (len) > 0)
{
emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (INTVAL (len) - 1)));
- emit_insn (gen_result (target));
+ emit_insn (gen_cmpint (target, ccreg));
}
else
emit_move_insn (target, const0_rtx);
}
-
- else /* if (TARGET_MVCLE) */
+ else if (TARGET_MVCLE)
{
emit_insn (gen_cmpmem_long (op0, op1, convert_to_mode (Pmode, len, 1)));
- emit_insn (gen_result (target));
+ emit_insn (gen_cmpint (target, ccreg));
}
-
-#if 0
- /* Deactivate for now as profile code cannot cope with
- CC being live across basic block boundaries. */
else
{
rtx addr0, addr1, count, blocks, temp;
+ rtx loop_start_label = gen_label_rtx ();
+ rtx loop_end_label = gen_label_rtx ();
rtx end_label = gen_label_rtx ();
enum machine_mode mode;
- tree type;
mode = GET_MODE (len);
if (mode == VOIDmode)
mode = Pmode;
- type = lang_hooks.types.type_for_mode (mode, 1);
- if (!type)
- abort ();
-
addr0 = gen_reg_rtx (Pmode);
addr1 = gen_reg_rtx (Pmode);
count = gen_reg_rtx (mode);
@@ -3130,17 +3763,17 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
if (temp != count)
emit_move_insn (count, temp);
- temp = expand_binop (mode, ashr_optab, count, GEN_INT (8), blocks, 1, 0);
+ temp = expand_binop (mode, lshr_optab, count, GEN_INT (8), blocks, 1, 0);
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_start_loop (1);
- expand_exit_loop_top_cond (0, build (NE_EXPR, type,
- make_tree (type, blocks),
- make_tree (type, const0_rtx)));
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
+
+ emit_label (loop_start_label);
emit_insn (gen_cmpmem_short (op0, op1, GEN_INT (255)));
- temp = gen_rtx_NE (VOIDmode, gen_rtx_REG (CCSmode, 33), const0_rtx);
+ temp = gen_rtx_NE (VOIDmode, ccreg, const0_rtx);
temp = gen_rtx_IF_THEN_ELSE (VOIDmode, temp,
gen_rtx_LABEL_REF (VOIDmode, end_label), pc_rtx);
temp = gen_rtx_SET (VOIDmode, pc_rtx, temp);
@@ -3155,21 +3788,540 @@ s390_expand_cmpmem (rtx target, rtx op0, rtx op1, rtx len)
if (temp != blocks)
emit_move_insn (blocks, temp);
- expand_end_loop ();
+ emit_cmp_and_jump_insns (blocks, const0_rtx,
+ EQ, NULL_RTX, mode, 1, loop_end_label);
- emit_insn (gen_cmpmem_short (op0, op1,
+ emit_jump (loop_start_label);
+ emit_label (loop_end_label);
+
+ emit_insn (gen_cmpmem_short (op0, op1,
convert_to_mode (Pmode, count, 1)));
emit_label (end_label);
- emit_insn (gen_result (target));
+ emit_insn (gen_cmpint (target, ccreg));
}
-#endif
}
-/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
- We need to emit DTP-relative relocations. */
+
+/* Expand conditional increment or decrement using alc/slb instructions.
+ Should generate code setting DST to either SRC or SRC + INCREMENT,
+ depending on the result of the comparison CMP_OP0 CMP_CODE CMP_OP1.
+ Returns true if successful, false otherwise.
+
+ That makes it possible to implement some if-constructs without jumps e.g.:
+ (borrow = CC0 | CC1 and carry = CC2 | CC3)
+ unsigned int a, b, c;
+ if (a < b) c++; -> CCU b > a -> CC2; c += carry;
+ if (a < b) c--; -> CCL3 a - b -> borrow; c -= borrow;
+ if (a <= b) c++; -> CCL3 b - a -> borrow; c += carry;
+ if (a <= b) c--; -> CCU a <= b -> borrow; c -= borrow;
+
+ Checks for EQ and NE with a nonzero value need an additional xor e.g.:
+ if (a == b) c++; -> CCL3 a ^= b; 0 - a -> borrow; c += carry;
+ if (a == b) c--; -> CCU a ^= b; a <= 0 -> CC0 | CC1; c -= borrow;
+ if (a != b) c++; -> CCU a ^= b; a > 0 -> CC2; c += carry;
+ if (a != b) c--; -> CCL3 a ^= b; 0 - a -> borrow; c -= borrow; */
+
+bool
+s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
+ rtx dst, rtx src, rtx increment)
+{
+ enum machine_mode cmp_mode;
+ enum machine_mode cc_mode;
+ rtx op_res;
+ rtx insn;
+ rtvec p;
+ int ret;
+
+ if ((GET_MODE (cmp_op0) == SImode || GET_MODE (cmp_op0) == VOIDmode)
+ && (GET_MODE (cmp_op1) == SImode || GET_MODE (cmp_op1) == VOIDmode))
+ cmp_mode = SImode;
+ else if ((GET_MODE (cmp_op0) == DImode || GET_MODE (cmp_op0) == VOIDmode)
+ && (GET_MODE (cmp_op1) == DImode || GET_MODE (cmp_op1) == VOIDmode))
+ cmp_mode = DImode;
+ else
+ return false;
+
+ /* Try ADD LOGICAL WITH CARRY. */
+ if (increment == const1_rtx)
+ {
+ /* Determine CC mode to use. */
+ if (cmp_code == EQ || cmp_code == NE)
+ {
+ if (cmp_op1 != const0_rtx)
+ {
+ cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
+ NULL_RTX, 0, OPTAB_WIDEN);
+ cmp_op1 = const0_rtx;
+ }
+
+ cmp_code = cmp_code == EQ ? LEU : GTU;
+ }
+
+ if (cmp_code == LTU || cmp_code == LEU)
+ {
+ rtx tem = cmp_op0;
+ cmp_op0 = cmp_op1;
+ cmp_op1 = tem;
+ cmp_code = swap_condition (cmp_code);
+ }
+
+ switch (cmp_code)
+ {
+ case GTU:
+ cc_mode = CCUmode;
+ break;
+
+ case GEU:
+ cc_mode = CCL3mode;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* Emit comparison instruction pattern. */
+ if (!register_operand (cmp_op0, cmp_mode))
+ cmp_op0 = force_reg (cmp_mode, cmp_op0);
+
+ insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
+ gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
+ /* We use insn_invalid_p here to add clobbers if required. */
+ ret = insn_invalid_p (emit_insn (insn));
+ gcc_assert (!ret);
+
+ /* Emit ALC instruction pattern. */
+ op_res = gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
+ gen_rtx_REG (cc_mode, CC_REGNUM),
+ const0_rtx);
+
+ if (src != const0_rtx)
+ {
+ if (!register_operand (src, GET_MODE (dst)))
+ src = force_reg (GET_MODE (dst), src);
+
+ src = gen_rtx_PLUS (GET_MODE (dst), src, const0_rtx);
+ op_res = gen_rtx_PLUS (GET_MODE (dst), src, op_res);
+ }
+
+ p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0) =
+ gen_rtx_SET (VOIDmode, dst, op_res);
+ RTVEC_ELT (p, 1) =
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ return true;
+ }
+
+ /* Try SUBTRACT LOGICAL WITH BORROW. */
+ if (increment == constm1_rtx)
+ {
+ /* Determine CC mode to use. */
+ if (cmp_code == EQ || cmp_code == NE)
+ {
+ if (cmp_op1 != const0_rtx)
+ {
+ cmp_op0 = expand_simple_binop (cmp_mode, XOR, cmp_op0, cmp_op1,
+ NULL_RTX, 0, OPTAB_WIDEN);
+ cmp_op1 = const0_rtx;
+ }
+
+ cmp_code = cmp_code == EQ ? LEU : GTU;
+ }
+
+ if (cmp_code == GTU || cmp_code == GEU)
+ {
+ rtx tem = cmp_op0;
+ cmp_op0 = cmp_op1;
+ cmp_op1 = tem;
+ cmp_code = swap_condition (cmp_code);
+ }
+
+ switch (cmp_code)
+ {
+ case LEU:
+ cc_mode = CCUmode;
+ break;
+
+ case LTU:
+ cc_mode = CCL3mode;
+ break;
+
+ default:
+ return false;
+ }
+
+ /* Emit comparison instruction pattern. */
+ if (!register_operand (cmp_op0, cmp_mode))
+ cmp_op0 = force_reg (cmp_mode, cmp_op0);
+
+ insn = gen_rtx_SET (VOIDmode, gen_rtx_REG (cc_mode, CC_REGNUM),
+ gen_rtx_COMPARE (cc_mode, cmp_op0, cmp_op1));
+ /* We use insn_invalid_p here to add clobbers if required. */
+ ret = insn_invalid_p (emit_insn (insn));
+ gcc_assert (!ret);
+
+ /* Emit SLB instruction pattern. */
+ if (!register_operand (src, GET_MODE (dst)))
+ src = force_reg (GET_MODE (dst), src);
+
+ op_res = gen_rtx_MINUS (GET_MODE (dst),
+ gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx),
+ gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
+ gen_rtx_REG (cc_mode, CC_REGNUM),
+ const0_rtx));
+ p = rtvec_alloc (2);
+ RTVEC_ELT (p, 0) =
+ gen_rtx_SET (VOIDmode, dst, op_res);
+ RTVEC_ELT (p, 1) =
+ gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
+ emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
+
+ return true;
+ }
+
+ return false;
+}
+
+/* Expand code for the insv template. Return true if successful, false else. */
+
+bool
+s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
+{
+ int bitsize = INTVAL (op1);
+ int bitpos = INTVAL (op2);
+
+ /* We need byte alignment. */
+ if (bitsize % BITS_PER_UNIT)
+ return false;
+
+ if (bitpos == 0
+ && memory_operand (dest, VOIDmode)
+ && (register_operand (src, word_mode)
+ || const_int_operand (src, VOIDmode)))
+ {
+ /* Emit standard pattern if possible. */
+ enum machine_mode mode = smallest_mode_for_size (bitsize, MODE_INT);
+ if (GET_MODE_BITSIZE (mode) == bitsize)
+ emit_move_insn (adjust_address (dest, mode, 0), gen_lowpart (mode, src));
+
+ /* (set (ze (mem)) (const_int)). */
+ else if (const_int_operand (src, VOIDmode))
+ {
+ int size = bitsize / BITS_PER_UNIT;
+ rtx src_mem = adjust_address (force_const_mem (word_mode, src), BLKmode,
+ GET_MODE_SIZE (word_mode) - size);
+
+ dest = adjust_address (dest, BLKmode, 0);
+ set_mem_size (dest, GEN_INT (size));
+ s390_expand_movmem (dest, src_mem, GEN_INT (size));
+ }
+
+ /* (set (ze (mem)) (reg)). */
+ else if (register_operand (src, word_mode))
+ {
+ if (bitsize <= GET_MODE_BITSIZE (SImode))
+ emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, op1,
+ const0_rtx), src);
+ else
+ {
+ /* Emit st,stcmh sequence. */
+ int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
+ int size = stcmh_width / BITS_PER_UNIT;
+
+ emit_move_insn (adjust_address (dest, SImode, size),
+ gen_lowpart (SImode, src));
+ set_mem_size (dest, GEN_INT (size));
+ emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
+ (stcmh_width), const0_rtx),
+ gen_rtx_LSHIFTRT (word_mode, src, GEN_INT
+ (GET_MODE_BITSIZE (SImode))));
+ }
+ }
+ else
+ return false;
+
+ return true;
+ }
+
+ /* (set (ze (reg)) (const_int)). */
+ if (TARGET_ZARCH
+ && register_operand (dest, word_mode)
+ && (bitpos % 16) == 0
+ && (bitsize % 16) == 0
+ && const_int_operand (src, VOIDmode))
+ {
+ HOST_WIDE_INT val = INTVAL (src);
+ int regpos = bitpos + bitsize;
+
+ while (regpos > bitpos)
+ {
+ enum machine_mode putmode;
+ int putsize;
+
+ if (TARGET_EXTIMM && (regpos % 32 == 0) && (regpos >= bitpos + 32))
+ putmode = SImode;
+ else
+ putmode = HImode;
+
+ putsize = GET_MODE_BITSIZE (putmode);
+ regpos -= putsize;
+ emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
+ GEN_INT (putsize),
+ GEN_INT (regpos)),
+ gen_int_mode (val, putmode));
+ val >>= putsize;
+ }
+ gcc_assert (regpos == bitpos);
+ return true;
+ }
+
+ return false;
+}
+
+/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic which returns a
+ register that holds VAL of mode MODE shifted by COUNT bits. */
+
+static inline rtx
+s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
+{
+ val = expand_simple_binop (SImode, AND, val, GEN_INT (GET_MODE_MASK (mode)),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ return expand_simple_binop (SImode, ASHIFT, val, count,
+ NULL_RTX, 1, OPTAB_DIRECT);
+}
+
+/* Structure to hold the initial parameters for a compare_and_swap operation
+ in HImode and QImode. */
+
+struct alignment_context
+{
+ rtx memsi; /* SI aligned memory location. */
+ rtx shift; /* Bit offset with regard to lsb. */
+ rtx modemask; /* Mask of the HQImode shifted by SHIFT bits. */
+ rtx modemaski; /* ~modemask */
+ bool aligned; /* True if memory is aligned, false else. */
+};
+
+/* A subroutine of s390_expand_cs_hqi and s390_expand_atomic to initialize
+ structure AC for transparent simplifying, if the memory alignment is known
+ to be at least 32bit. MEM is the memory location for the actual operation
+ and MODE its mode. */
+
+static void
+init_alignment_context (struct alignment_context *ac, rtx mem,
+ enum machine_mode mode)
+{
+ ac->shift = GEN_INT (GET_MODE_SIZE (SImode) - GET_MODE_SIZE (mode));
+ ac->aligned = (MEM_ALIGN (mem) >= GET_MODE_BITSIZE (SImode));
+
+ if (ac->aligned)
+ ac->memsi = adjust_address (mem, SImode, 0); /* Memory is aligned. */
+ else
+ {
+ /* Alignment is unknown. */
+ rtx byteoffset, addr, align;
+
+ /* Force the address into a register. */
+ addr = force_reg (Pmode, XEXP (mem, 0));
+
+ /* Align it to SImode. */
+ align = expand_simple_binop (Pmode, AND, addr,
+ GEN_INT (-GET_MODE_SIZE (SImode)),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* Generate MEM. */
+ ac->memsi = gen_rtx_MEM (SImode, align);
+ MEM_VOLATILE_P (ac->memsi) = MEM_VOLATILE_P (mem);
+ set_mem_alias_set (ac->memsi, ALIAS_SET_MEMORY_BARRIER);
+ set_mem_align (ac->memsi, GET_MODE_BITSIZE (SImode));
+
+ /* Calculate shiftcount. */
+ byteoffset = expand_simple_binop (Pmode, AND, addr,
+ GEN_INT (GET_MODE_SIZE (SImode) - 1),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* As we already have some offset, evaluate the remaining distance. */
+ ac->shift = expand_simple_binop (SImode, MINUS, ac->shift, byteoffset,
+ NULL_RTX, 1, OPTAB_DIRECT);
+
+ }
+ /* Shift is the byte count, but we need the bitcount. */
+ ac->shift = expand_simple_binop (SImode, MULT, ac->shift, GEN_INT (BITS_PER_UNIT),
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* Calculate masks. */
+ ac->modemask = expand_simple_binop (SImode, ASHIFT,
+ GEN_INT (GET_MODE_MASK (mode)), ac->shift,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
+}
+
+/* Expand an atomic compare and swap operation for HImode and QImode. MEM is
+ the memory location, CMP the old value to compare MEM with and NEW the value
+ to set if CMP == MEM.
+ CMP is never in memory for compare_and_swap_cc because
+ expand_bool_compare_and_swap puts it into a register for later compare. */
+
+void
+s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx new)
+{
+ struct alignment_context ac;
+ rtx cmpv, newv, val, resv, cc;
+ rtx res = gen_reg_rtx (SImode);
+ rtx csloop = gen_label_rtx ();
+ rtx csend = gen_label_rtx ();
+
+ gcc_assert (register_operand (target, VOIDmode));
+ gcc_assert (MEM_P (mem));
+
+ init_alignment_context (&ac, mem, mode);
+
+ /* Shift the values to the correct bit positions. */
+ if (!(ac.aligned && MEM_P (cmp)))
+ cmp = s390_expand_mask_and_shift (cmp, mode, ac.shift);
+ if (!(ac.aligned && MEM_P (new)))
+ new = s390_expand_mask_and_shift (new, mode, ac.shift);
+
+ /* Load full word. Subsequent loads are performed by CS. */
+ val = expand_simple_binop (SImode, AND, ac.memsi, ac.modemaski,
+ NULL_RTX, 1, OPTAB_DIRECT);
+
+ /* Start CS loop. */
+ emit_label (csloop);
+ /* val = "<mem>00..0<mem>"
+ * cmp = "00..0<cmp>00..0"
+ * new = "00..0<new>00..0"
+ */
+
+ /* Patch cmp and new with val at correct position. */
+ if (ac.aligned && MEM_P (cmp))
+ {
+ cmpv = force_reg (SImode, val);
+ store_bit_field (cmpv, GET_MODE_BITSIZE (mode), 0, SImode, cmp);
+ }
+ else
+ cmpv = force_reg (SImode, expand_simple_binop (SImode, IOR, cmp, val,
+ NULL_RTX, 1, OPTAB_DIRECT));
+ if (ac.aligned && MEM_P (new))
+ {
+ newv = force_reg (SImode, val);
+ store_bit_field (newv, GET_MODE_BITSIZE (mode), 0, SImode, new);
+ }
+ else
+ newv = force_reg (SImode, expand_simple_binop (SImode, IOR, new, val,
+ NULL_RTX, 1, OPTAB_DIRECT));
+
+ /* Jump to end if we're done (likely?). */
+ s390_emit_jump (csend, s390_emit_compare_and_swap (EQ, res, ac.memsi,
+ cmpv, newv));
+
+ /* Check for changes outside mode. */
+ resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ cc = s390_emit_compare (NE, resv, val);
+ emit_move_insn (val, resv);
+ /* Loop internal if so. */
+ s390_emit_jump (csloop, cc);
+
+ emit_label (csend);
+
+ /* Return the correct part of the bitfield. */
+ convert_move (target, expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
+ NULL_RTX, 1, OPTAB_DIRECT), 1);
+}
+
+/* Expand an atomic operation CODE of mode MODE. MEM is the memory location
+ and VAL the value to play with. If AFTER is true then store the the value
+ MEM holds after the operation, if AFTER is false then store the value MEM
+ holds before the operation. If TARGET is zero then discard that value, else
+ store it to TARGET. */
void
+s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
+ rtx target, rtx mem, rtx val, bool after)
+{
+ struct alignment_context ac;
+ rtx cmp;
+ rtx new = gen_reg_rtx (SImode);
+ rtx orig = gen_reg_rtx (SImode);
+ rtx csloop = gen_label_rtx ();
+
+ gcc_assert (!target || register_operand (target, VOIDmode));
+ gcc_assert (MEM_P (mem));
+
+ init_alignment_context (&ac, mem, mode);
+
+ /* Shift val to the correct bit positions.
+ Preserve "icm", but prevent "ex icm". */
+ if (!(ac.aligned && code == SET && MEM_P (val)))
+ val = s390_expand_mask_and_shift (val, mode, ac.shift);
+
+ /* Further preparation insns. */
+ if (code == PLUS || code == MINUS)
+ emit_move_insn (orig, val);
+ else if (code == MULT || code == AND) /* val = "11..1<val>11..1" */
+ val = expand_simple_binop (SImode, XOR, val, ac.modemaski,
+ NULL_RTX, 1, OPTAB_DIRECT);
+
+ /* Load full word. Subsequent loads are performed by CS. */
+ cmp = force_reg (SImode, ac.memsi);
+
+ /* Start CS loop. */
+ emit_label (csloop);
+ emit_move_insn (new, cmp);
+
+ /* Patch new with val at correct position. */
+ switch (code)
+ {
+ case PLUS:
+ case MINUS:
+ val = expand_simple_binop (SImode, code, new, orig,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ val = expand_simple_binop (SImode, AND, val, ac.modemask,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ /* FALLTHRU */
+ case SET:
+ if (ac.aligned && MEM_P (val))
+ store_bit_field (new, GET_MODE_BITSIZE (mode), 0, SImode, val);
+ else
+ {
+ new = expand_simple_binop (SImode, AND, new, ac.modemaski,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ new = expand_simple_binop (SImode, IOR, new, val,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ }
+ break;
+ case AND:
+ case IOR:
+ case XOR:
+ new = expand_simple_binop (SImode, code, new, val,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ break;
+ case MULT: /* NAND */
+ new = expand_simple_binop (SImode, XOR, new, ac.modemask,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ new = expand_simple_binop (SImode, AND, new, val,
+ NULL_RTX, 1, OPTAB_DIRECT);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ s390_emit_jump (csloop, s390_emit_compare_and_swap (NE, cmp,
+ ac.memsi, cmp, new));
+
+ /* Return the correct part of the bitfield. */
+ if (target)
+ convert_move (target, expand_simple_binop (SImode, LSHIFTRT,
+ after ? new : cmp, ac.shift,
+ NULL_RTX, 1, OPTAB_DIRECT), 1);
+}
+
+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
+ We need to emit DTP-relative relocations. */
+
+static void s390_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
+
+static void
s390_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
switch (size)
@@ -3181,14 +4333,29 @@ s390_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs ("\t.quad\t", file);
break;
default:
- abort ();
+ gcc_unreachable ();
}
output_addr_const (file, x);
fputs ("@DTPOFF", file);
}
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+/* Implement TARGET_MANGLE_FUNDAMENTAL_TYPE. */
+
+static const char *
+s390_mangle_fundamental_type (tree type)
+{
+ if (TYPE_MAIN_VARIANT (type) == long_double_type_node
+ && TARGET_LONG_DOUBLE_128)
+ return "g";
+
+ /* For all other types, use normal C++ mangling. */
+ return NULL;
+}
+#endif
+
/* In the name of slightly smaller debug output, and to cater to
- general assembler losage, recognize various UNSPEC sequences
+ general assembler lossage, recognize various UNSPEC sequences
and turn them back into a direct symbol reference. */
static rtx
@@ -3224,58 +4391,35 @@ s390_delegitimize_address (rtx orig_x)
return orig_x;
}
-/* Output shift count operand OP to stdio stream FILE. */
+/* Output operand OP to stdio stream FILE.
+ OP is an address (register + offset) which is not used to address data;
+ instead the rightmost bits are interpreted as the value. */
static void
print_shift_count_operand (FILE *file, rtx op)
{
- HOST_WIDE_INT offset = 0;
+ HOST_WIDE_INT offset;
+ rtx base;
- /* We can have an integer constant, an address register,
- or a sum of the two. */
- if (GET_CODE (op) == CONST_INT)
- {
- offset = INTVAL (op);
- op = NULL_RTX;
- }
- if (op && GET_CODE (op) == PLUS && GET_CODE (XEXP (op, 1)) == CONST_INT)
- {
- offset = INTVAL (XEXP (op, 1));
- op = XEXP (op, 0);
- }
- while (op && GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
+ /* Extract base register and offset. */
+ if (!s390_decompose_shift_count (op, &base, &offset))
+ gcc_unreachable ();
/* Sanity check. */
- if (op && (GET_CODE (op) != REG
- || REGNO (op) >= FIRST_PSEUDO_REGISTER
- || REGNO_REG_CLASS (REGNO (op)) != ADDR_REGS))
- abort ();
+ if (base)
+ {
+ gcc_assert (GET_CODE (base) == REG);
+ gcc_assert (REGNO (base) < FIRST_PSEUDO_REGISTER);
+ gcc_assert (REGNO_REG_CLASS (REGNO (base)) == ADDR_REGS);
+ }
- /* Shift counts are truncated to the low six bits anyway. */
- fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & 63);
- if (op)
- fprintf (file, "(%s)", reg_names[REGNO (op)]);
+ /* Offsets are constricted to twelve bits. */
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, offset & ((1 << 12) - 1));
+ if (base)
+ fprintf (file, "(%s)", reg_names[REGNO (base)]);
}
-/* Locate some local-dynamic symbol still in use by this function
- so that we can print its name in local-dynamic base patterns. */
-
-static const char *
-get_some_local_dynamic_name (void)
-{
- rtx insn;
-
- if (cfun->machine->some_ld_name)
- return cfun->machine->some_ld_name;
-
- for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
- if (INSN_P (insn)
- && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
- return cfun->machine->some_ld_name;
-
- abort ();
-}
+/* See 'get_some_local_dynamic_name'. */
static int
get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
@@ -3298,98 +4442,82 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
return 0;
}
-/* Output symbolic constant X in assembler syntax to
- stdio stream FILE. */
+/* Locate some local-dynamic symbol still in use by this function
+ so that we can print its name in local-dynamic base patterns. */
-void
-s390_output_symbolic_const (FILE *file, rtx x)
+static const char *
+get_some_local_dynamic_name (void)
{
- switch (GET_CODE (x))
- {
- case CONST:
- case ZERO_EXTEND:
- case SIGN_EXTEND:
- s390_output_symbolic_const (file, XEXP (x, 0));
- break;
+ rtx insn;
- case PLUS:
- s390_output_symbolic_const (file, XEXP (x, 0));
- fprintf (file, "+");
- s390_output_symbolic_const (file, XEXP (x, 1));
- break;
+ if (cfun->machine->some_ld_name)
+ return cfun->machine->some_ld_name;
- case MINUS:
- s390_output_symbolic_const (file, XEXP (x, 0));
- fprintf (file, "-");
- s390_output_symbolic_const (file, XEXP (x, 1));
- break;
+ for (insn = get_insns (); insn ; insn = NEXT_INSN (insn))
+ if (INSN_P (insn)
+ && for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
+ return cfun->machine->some_ld_name;
- case CONST_INT:
- case LABEL_REF:
- case CODE_LABEL:
- case SYMBOL_REF:
- output_addr_const (file, x);
- break;
+ gcc_unreachable ();
+}
- case UNSPEC:
- if (XVECLEN (x, 0) != 1)
- output_operand_lossage ("invalid UNSPEC as operand (1)");
- switch (XINT (x, 1))
- {
- case UNSPEC_GOTENT:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTENT");
- break;
- case UNSPEC_GOT:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOT");
- break;
- case UNSPEC_GOTOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTOFF");
- break;
- case UNSPEC_PLT:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@PLT");
- break;
- case UNSPEC_PLTOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@PLTOFF");
- break;
- case UNSPEC_TLSGD:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@TLSGD");
- break;
- case UNSPEC_TLSLDM:
- assemble_name (file, get_some_local_dynamic_name ());
- fprintf (file, "@TLSLDM");
- break;
- case UNSPEC_DTPOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@DTPOFF");
- break;
- case UNSPEC_NTPOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@NTPOFF");
- break;
- case UNSPEC_GOTNTPOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@GOTNTPOFF");
- break;
- case UNSPEC_INDNTPOFF:
- s390_output_symbolic_const (file, XVECEXP (x, 0, 0));
- fprintf (file, "@INDNTPOFF");
- break;
- default:
- output_operand_lossage ("invalid UNSPEC as operand (2)");
- break;
- }
- break;
+/* Output machine-dependent UNSPECs occurring in address constant X
+ in assembler syntax to stdio stream FILE. Returns true if the
+ constant X could be recognized, false otherwise. */
- default:
- fatal_insn ("UNKNOWN in s390_output_symbolic_const !?", x);
- break;
- }
+bool
+s390_output_addr_const_extra (FILE *file, rtx x)
+{
+ if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_GOTENT:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOTENT");
+ return true;
+ case UNSPEC_GOT:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOT");
+ return true;
+ case UNSPEC_GOTOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOTOFF");
+ return true;
+ case UNSPEC_PLT:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@PLT");
+ return true;
+ case UNSPEC_PLTOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@PLTOFF");
+ return true;
+ case UNSPEC_TLSGD:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@TLSGD");
+ return true;
+ case UNSPEC_TLSLDM:
+ assemble_name (file, get_some_local_dynamic_name ());
+ fprintf (file, "@TLSLDM");
+ return true;
+ case UNSPEC_DTPOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@DTPOFF");
+ return true;
+ case UNSPEC_NTPOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@NTPOFF");
+ return true;
+ case UNSPEC_GOTNTPOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@GOTNTPOFF");
+ return true;
+ case UNSPEC_INDNTPOFF:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fprintf (file, "@INDNTPOFF");
+ return true;
+ }
+
+ return false;
}
/* Output address operand ADDR in assembler syntax to
@@ -3401,12 +4529,12 @@ print_operand_address (FILE *file, rtx addr)
struct s390_address ad;
if (!s390_decompose_address (addr, &ad)
- || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
- || (ad.indx && !REG_OK_FOR_INDEX_STRICT_P (ad.indx)))
- output_operand_lossage ("Cannot decompose address.");
+ || (ad.base && !REGNO_OK_FOR_BASE_P (REGNO (ad.base)))
+ || (ad.indx && !REGNO_OK_FOR_INDEX_P (REGNO (ad.indx))))
+ output_operand_lossage ("cannot decompose address");
if (ad.disp)
- s390_output_symbolic_const (file, ad.disp);
+ output_addr_const (file, ad.disp);
else
fprintf (file, "0");
@@ -3424,17 +4552,22 @@ print_operand_address (FILE *file, rtx addr)
'C': print opcode suffix for branch condition.
'D': print opcode suffix for inverse branch condition.
'J': print tls_load/tls_gdcall/tls_ldcall suffix
+ 'G': print the size of the operand in bytes.
'O': print only the displacement of a memory reference.
'R': print only the base register of a memory reference.
+ 'S': print S-type memory reference (base+displacement).
'N': print the second word of a DImode operand.
'M': print the second word of a TImode operand.
'Y': print shift count operand.
'b': print integer X as if it's an unsigned byte.
- 'x': print integer X as if it's an unsigned word.
- 'h': print integer X as if it's a signed word.
+ 'x': print integer X as if it's an unsigned halfword.
+ 'h': print integer X as if it's a signed halfword.
'i': print the first nonzero HImode part of X.
- 'j': print the first HImode part unequal to 0xffff of X. */
+ 'j': print the first HImode part unequal to -1 of X.
+ 'k': print the first nonzero SImode part of X.
+ 'm': print the first SImode part unequal to -1 of X.
+ 'o': print integer X as if it's an unsigned 32bit word. */
void
print_operand (FILE *file, rtx x, int code)
@@ -3466,21 +4599,26 @@ print_operand (FILE *file, rtx x, int code)
assemble_name (file, get_some_local_dynamic_name ());
}
else
- abort ();
+ gcc_unreachable ();
+ return;
+
+ case 'G':
+ fprintf (file, "%u", GET_MODE_SIZE (GET_MODE (x)));
return;
case 'O':
{
struct s390_address ad;
+ int ret;
- if (GET_CODE (x) != MEM
- || !s390_decompose_address (XEXP (x, 0), &ad)
- || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
- || ad.indx)
- abort ();
+ gcc_assert (GET_CODE (x) == MEM);
+ ret = s390_decompose_address (XEXP (x, 0), &ad);
+ gcc_assert (ret);
+ gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
+ gcc_assert (!ad.indx);
if (ad.disp)
- s390_output_symbolic_const (file, ad.disp);
+ output_addr_const (file, ad.disp);
else
fprintf (file, "0");
}
@@ -3489,12 +4627,13 @@ print_operand (FILE *file, rtx x, int code)
case 'R':
{
struct s390_address ad;
+ int ret;
- if (GET_CODE (x) != MEM
- || !s390_decompose_address (XEXP (x, 0), &ad)
- || (ad.base && !REG_OK_FOR_BASE_STRICT_P (ad.base))
- || ad.indx)
- abort ();
+ gcc_assert (GET_CODE (x) == MEM);
+ ret = s390_decompose_address (XEXP (x, 0), &ad);
+ gcc_assert (ret);
+ gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
+ gcc_assert (!ad.indx);
if (ad.base)
fprintf (file, "%s", reg_names[REGNO (ad.base)]);
@@ -3503,13 +4642,34 @@ print_operand (FILE *file, rtx x, int code)
}
return;
+ case 'S':
+ {
+ struct s390_address ad;
+ int ret;
+
+ gcc_assert (GET_CODE (x) == MEM);
+ ret = s390_decompose_address (XEXP (x, 0), &ad);
+ gcc_assert (ret);
+ gcc_assert (!ad.base || REGNO_OK_FOR_BASE_P (REGNO (ad.base)));
+ gcc_assert (!ad.indx);
+
+ if (ad.disp)
+ output_addr_const (file, ad.disp);
+ else
+ fprintf (file, "0");
+
+ if (ad.base)
+ fprintf (file, "(%s)", reg_names[REGNO (ad.base)]);
+ }
+ 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 ();
+ gcc_unreachable ();
break;
case 'M':
@@ -3518,7 +4678,7 @@ print_operand (FILE *file, rtx x, int code)
else if (GET_CODE (x) == MEM)
x = change_address (x, VOIDmode, plus_constant (XEXP (x, 0), 8));
else
- abort ();
+ gcc_unreachable ();
break;
case 'Y':
@@ -3540,7 +4700,7 @@ print_operand (FILE *file, rtx x, int code)
case CODE_LABEL:
case LABEL_REF:
case SYMBOL_REF:
- s390_output_symbolic_const (file, x);
+ output_addr_const (file, x);
break;
case CONST_INT:
@@ -3551,18 +4711,25 @@ print_operand (FILE *file, rtx x, int code)
else if (code == 'h')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((INTVAL (x) & 0xffff) ^ 0x8000) - 0x8000);
else if (code == 'i')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
s390_extract_part (x, HImode, 0));
else if (code == 'j')
- fprintf (file, HOST_WIDE_INT_PRINT_DEC,
- s390_extract_part (x, HImode, -1));
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ s390_extract_part (x, HImode, -1));
+ else if (code == 'k')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ s390_extract_part (x, SImode, 0));
+ else if (code == 'm')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC,
+ s390_extract_part (x, SImode, -1));
+ else if (code == 'o')
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 0xffffffff);
else
fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
break;
case CONST_DOUBLE:
- if (GET_MODE (x) != VOIDmode)
- abort ();
+ gcc_assert (GET_MODE (x) == VOIDmode);
if (code == 'b')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x) & 0xff);
else if (code == 'x')
@@ -3570,7 +4737,7 @@ print_operand (FILE *file, rtx x, int code)
else if (code == 'h')
fprintf (file, HOST_WIDE_INT_PRINT_DEC, ((CONST_DOUBLE_LOW (x) & 0xffff) ^ 0x8000) - 0x8000);
else
- abort ();
+ gcc_unreachable ();
break;
default:
@@ -3599,7 +4766,7 @@ s390_assemble_integer (rtx x, unsigned int size, int aligned_p)
/* Returns true if register REGNO is used for forming
a memory address in expression X. */
-static int
+static bool
reg_used_in_mem_p (int regno, rtx x)
{
enum rtx_code code = GET_CODE (x);
@@ -3610,14 +4777,14 @@ reg_used_in_mem_p (int regno, rtx x)
{
if (refers_to_regno_p (regno, regno+1,
XEXP (x, 0), 0))
- return 1;
+ return true;
}
else if (code == SET
&& GET_CODE (SET_DEST (x)) == PC)
{
if (refers_to_regno_p (regno, regno+1,
SET_SRC (x), 0))
- return 1;
+ return true;
}
fmt = GET_RTX_FORMAT (code);
@@ -3625,20 +4792,20 @@ reg_used_in_mem_p (int regno, rtx x)
{
if (fmt[i] == 'e'
&& reg_used_in_mem_p (regno, XEXP (x, i)))
- return 1;
+ return true;
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 true;
}
- return 0;
+ return false;
}
/* Returns true if expression DEP_RTX sets an address register
used by instruction INSN to address memory. */
-static int
+static bool
addr_generation_dependency_p (rtx dep_rtx, rtx insn)
{
rtx target, pat;
@@ -3663,20 +4830,17 @@ addr_generation_dependency_p (rtx dep_rtx, rtx insn)
pat = PATTERN (insn);
if (GET_CODE (pat) == PARALLEL)
{
- if (XVECLEN (pat, 0) != 2)
- abort();
+ gcc_assert (XVECLEN (pat, 0) == 2);
pat = XVECEXP (pat, 0, 0);
}
- if (GET_CODE (pat) == SET)
- return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
- else
- abort();
+ gcc_assert (GET_CODE (pat) == SET);
+ return refers_to_regno_p (regno, regno+1, SET_SRC (pat), 0);
}
else if (get_attr_atype (insn) == ATYPE_AGEN)
return reg_used_in_mem_p (regno, PATTERN (insn));
}
}
- return 0;
+ return false;
}
/* Return 1, if dep_insn sets register used in insn in the agen unit. */
@@ -3701,63 +4865,6 @@ s390_agen_dep_p (rtx dep_insn, rtx insn)
return 0;
}
-/* Return the modified cost of the dependency of instruction INSN
- on instruction DEP_INSN through the link LINK. COST is the
- default cost of that dependency.
-
- Data dependencies are all handled without delay. However, if a
- register is modified and subsequently used as base or index
- register of a memory reference, at least 4 cycles need to pass
- between setting and using the register to avoid pipeline stalls.
- An exception is the LA instruction. An address generated by LA can
- be used by introducing only a one cycle stall on the pipeline. */
-
-static int
-s390_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
-{
- rtx dep_rtx;
- 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;
-
- /* DFA based scheduling checks address dependency in md file. */
- if (s390_use_dfa_pipeline_interface ())
- {
- /* Operand forward in case of lr, load and la. */
- if (s390_tune == PROCESSOR_2084_Z990
- && cost == 1
- && (s390_safe_attr_type (dep_insn) == TYPE_LA
- || s390_safe_attr_type (dep_insn) == TYPE_LR
- || s390_safe_attr_type (dep_insn) == TYPE_LOAD))
- return 0;
- return cost;
- }
-
- dep_rtx = PATTERN (dep_insn);
-
- if (GET_CODE (dep_rtx) == SET
- && addr_generation_dependency_p (dep_rtx, insn))
- cost += (s390_safe_attr_type (dep_insn) == TYPE_LA) ? 1 : 4;
- 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))
- cost += (s390_safe_attr_type (dep_insn) == TYPE_LA) ? 1 : 4;
- }
- }
-
- return cost;
-}
/* A C statement (sans semicolon) to update the integer scheduling priority
INSN_PRIORITY (INSN). Increase the priority to execute the INSN earlier,
reduce the priority to execute INSN later. Do not define this macro if
@@ -3772,16 +4879,18 @@ s390_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
if (! INSN_P (insn))
return priority;
- if (s390_tune != PROCESSOR_2084_Z990)
+ if (s390_tune != PROCESSOR_2084_Z990
+ && s390_tune != PROCESSOR_2094_Z9_109)
return priority;
switch (s390_safe_attr_type (insn))
{
- case TYPE_FSTORED:
- case TYPE_FSTORES:
+ case TYPE_FSTOREDF:
+ case TYPE_FSTORESF:
priority = priority << 3;
break;
case TYPE_STORE:
+ case TYPE_STM:
priority = priority << 1;
break;
default:
@@ -3795,43 +4904,121 @@ s390_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
static int
s390_issue_rate (void)
{
- if (s390_tune == PROCESSOR_2084_Z990)
+ if (s390_tune == PROCESSOR_2084_Z990
+ || s390_tune == PROCESSOR_2094_Z9_109)
return 3;
return 1;
}
-/* If the following function returns TRUE, we will use the the DFA
- insn scheduler. */
-
-static int
-s390_use_dfa_pipeline_interface (void)
-{
- if (s390_tune == PROCESSOR_2064_Z900
- || s390_tune == PROCESSOR_2084_Z990)
- return 1;
-
- return 0;
-}
-
static int
s390_first_cycle_multipass_dfa_lookahead (void)
{
- return s390_use_dfa_pipeline_interface () ? 4 : 0;
+ return 4;
}
-/* Called after issuing each insn.
- Triggers default sort algorithm to better slot instructions. */
-static int
-s390_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
- int sched_verbose ATTRIBUTE_UNUSED,
- rtx *ready ATTRIBUTE_UNUSED,
- int *pn_ready ATTRIBUTE_UNUSED,
- int clock_var ATTRIBUTE_UNUSED)
+/* Annotate every literal pool reference in X by an UNSPEC_LTREF expression.
+ Fix up MEMs as required. */
+
+static void
+annotate_constant_pool_refs (rtx *x)
{
- return s390_issue_rate();
-}
+ int i, j;
+ const char *fmt;
+
+ gcc_assert (GET_CODE (*x) != SYMBOL_REF
+ || !CONSTANT_POOL_ADDRESS_P (*x));
+
+ /* Literal pool references can only occur inside a MEM ... */
+ if (GET_CODE (*x) == MEM)
+ {
+ rtx memref = XEXP (*x, 0);
+
+ if (GET_CODE (memref) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (memref))
+ {
+ rtx base = cfun->machine->base_reg;
+ rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, memref, base),
+ UNSPEC_LTREF);
+
+ *x = replace_equiv_address (*x, addr);
+ return;
+ }
+
+ if (GET_CODE (memref) == CONST
+ && GET_CODE (XEXP (memref, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (XEXP (memref, 0), 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (memref, 0), 0)))
+ {
+ HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
+ rtx sym = XEXP (XEXP (memref, 0), 0);
+ rtx base = cfun->machine->base_reg;
+ rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
+ UNSPEC_LTREF);
+
+ *x = replace_equiv_address (*x, plus_constant (addr, off));
+ return;
+ }
+ }
+ /* ... or a load-address type pattern. */
+ if (GET_CODE (*x) == SET)
+ {
+ rtx addrref = SET_SRC (*x);
+
+ if (GET_CODE (addrref) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (addrref))
+ {
+ rtx base = cfun->machine->base_reg;
+ rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, addrref, base),
+ UNSPEC_LTREF);
+
+ SET_SRC (*x) = addr;
+ return;
+ }
+
+ if (GET_CODE (addrref) == CONST
+ && GET_CODE (XEXP (addrref, 0)) == PLUS
+ && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
+ && GET_CODE (XEXP (XEXP (addrref, 0), 0)) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (XEXP (XEXP (addrref, 0), 0)))
+ {
+ HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
+ rtx sym = XEXP (XEXP (addrref, 0), 0);
+ rtx base = cfun->machine->base_reg;
+ rtx addr = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, sym, base),
+ UNSPEC_LTREF);
+
+ SET_SRC (*x) = plus_constant (addr, off);
+ return;
+ }
+ }
+
+ /* Annotate LTREL_BASE as well. */
+ if (GET_CODE (*x) == UNSPEC
+ && XINT (*x, 1) == UNSPEC_LTREL_BASE)
+ {
+ rtx base = cfun->machine->base_reg;
+ *x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XVECEXP (*x, 0, 0), base),
+ UNSPEC_LTREL_BASE);
+ return;
+ }
+
+ fmt = GET_RTX_FORMAT (GET_CODE (*x));
+ for (i = GET_RTX_LENGTH (GET_CODE (*x)) - 1; i >= 0; i--)
+ {
+ if (fmt[i] == 'e')
+ {
+ annotate_constant_pool_refs (&XEXP (*x, i));
+ }
+ else if (fmt[i] == 'E')
+ {
+ for (j = 0; j < XVECLEN (*x, i); j++)
+ annotate_constant_pool_refs (&XVECEXP (*x, i, j));
+ }
+ }
+}
/* Split all branches that exceed the maximum distance.
Returns true if this created a new literal pool entry. */
@@ -3840,7 +5027,7 @@ static int
s390_split_branches (void)
{
rtx temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
- int new_literal = 0;
+ int new_literal = 0, ret;
rtx insn, pat, tmp, target;
rtx *label;
@@ -3882,7 +5069,7 @@ s390_split_branches (void)
/* We are going to use the return register as scratch register,
make sure it will be saved/restored by the prologue/epilogue. */
- cfun->machine->save_return_addr_p = 1;
+ cfun_frame_layout.save_return_addr_p = 1;
if (!flag_pic)
{
@@ -3890,6 +5077,7 @@ s390_split_branches (void)
tmp = force_const_mem (Pmode, *label);
tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, tmp), insn);
INSN_ADDRESSES_NEW (tmp, -1);
+ annotate_constant_pool_refs (&PATTERN (tmp));
target = temp_reg;
}
@@ -3902,24 +5090,26 @@ s390_split_branches (void)
target = force_const_mem (Pmode, target);
tmp = emit_insn_before (gen_rtx_SET (Pmode, temp_reg, target), insn);
INSN_ADDRESSES_NEW (tmp, -1);
+ annotate_constant_pool_refs (&PATTERN (tmp));
- target = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (target, 0)),
+ target = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, XEXP (target, 0),
+ cfun->machine->base_reg),
UNSPEC_LTREL_BASE);
target = gen_rtx_PLUS (Pmode, temp_reg, target);
}
- if (!validate_change (insn, label, target, 0))
- abort ();
+ ret = validate_change (insn, label, target, 0);
+ gcc_assert (ret);
}
return new_literal;
}
-/* Find a literal pool symbol referenced in RTX X, and store
- it at REF. Will abort if X contains references to more than
- one such pool symbol; multiple references to the same symbol
- are allowed, however.
+/* Find an annotated literal pool symbol referenced in RTX X,
+ and store it at REF. Will abort if X contains references to
+ more than one such pool symbol; multiple references to the same
+ symbol are allowed, however.
The rtx pointed to by REF must be initialized to NULL_RTX
by the caller before calling this routine. */
@@ -3939,13 +5129,21 @@ find_constant_pool_ref (rtx x, rtx *ref)
&& XINT (x, 1) == UNSPECV_POOL_ENTRY)
return;
- if (GET_CODE (x) == SYMBOL_REF
- && CONSTANT_POOL_ADDRESS_P (x))
+ gcc_assert (GET_CODE (x) != SYMBOL_REF
+ || !CONSTANT_POOL_ADDRESS_P (x));
+
+ if (GET_CODE (x) == UNSPEC && XINT (x, 1) == UNSPEC_LTREF)
{
+ rtx sym = XVECEXP (x, 0, 0);
+ gcc_assert (GET_CODE (sym) == SYMBOL_REF
+ && CONSTANT_POOL_ADDRESS_P (sym));
+
if (*ref == NULL_RTX)
- *ref = x;
- else if (*ref != x)
- abort();
+ *ref = sym;
+ else
+ gcc_assert (*ref == sym);
+
+ return;
}
fmt = GET_RTX_FORMAT (GET_CODE (x));
@@ -3963,60 +5161,34 @@ find_constant_pool_ref (rtx x, rtx *ref)
}
}
-/* Replace every reference to the literal pool symbol REF
- in X by the address ADDR. Fix up MEMs as required. */
+/* Replace every reference to the annotated literal pool
+ symbol REF in X by its base plus OFFSET. */
static void
-replace_constant_pool_ref (rtx *x, rtx ref, rtx addr)
+replace_constant_pool_ref (rtx *x, rtx ref, rtx offset)
{
int i, j;
const char *fmt;
- if (*x == ref)
- abort ();
+ gcc_assert (*x != ref);
- /* Literal pool references can only occur inside a MEM ... */
- if (GET_CODE (*x) == MEM)
+ if (GET_CODE (*x) == UNSPEC
+ && XINT (*x, 1) == UNSPEC_LTREF
+ && XVECEXP (*x, 0, 0) == ref)
{
- rtx memref = XEXP (*x, 0);
-
- if (memref == ref)
- {
- *x = replace_equiv_address (*x, addr);
- return;
- }
-
- if (GET_CODE (memref) == CONST
- && GET_CODE (XEXP (memref, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (memref, 0), 1)) == CONST_INT
- && XEXP (XEXP (memref, 0), 0) == ref)
- {
- HOST_WIDE_INT off = INTVAL (XEXP (XEXP (memref, 0), 1));
- *x = replace_equiv_address (*x, plus_constant (addr, off));
- return;
- }
+ *x = gen_rtx_PLUS (Pmode, XVECEXP (*x, 0, 1), offset);
+ return;
}
- /* ... or a load-address type pattern. */
- if (GET_CODE (*x) == SET)
+ if (GET_CODE (*x) == PLUS
+ && GET_CODE (XEXP (*x, 1)) == CONST_INT
+ && GET_CODE (XEXP (*x, 0)) == UNSPEC
+ && XINT (XEXP (*x, 0), 1) == UNSPEC_LTREF
+ && XVECEXP (XEXP (*x, 0), 0, 0) == ref)
{
- rtx addrref = SET_SRC (*x);
-
- if (addrref == ref)
- {
- SET_SRC (*x) = addr;
- return;
- }
-
- if (GET_CODE (addrref) == CONST
- && GET_CODE (XEXP (addrref, 0)) == PLUS
- && GET_CODE (XEXP (XEXP (addrref, 0), 1)) == CONST_INT
- && XEXP (XEXP (addrref, 0), 0) == ref)
- {
- HOST_WIDE_INT off = INTVAL (XEXP (XEXP (addrref, 0), 1));
- SET_SRC (*x) = plus_constant (addr, off);
- return;
- }
+ rtx addr = gen_rtx_PLUS (Pmode, XVECEXP (XEXP (*x, 0), 0, 1), offset);
+ *x = plus_constant (addr, INTVAL (XEXP (*x, 1)));
+ return;
}
fmt = GET_RTX_FORMAT (GET_CODE (*x));
@@ -4024,12 +5196,12 @@ replace_constant_pool_ref (rtx *x, rtx ref, rtx addr)
{
if (fmt[i] == 'e')
{
- replace_constant_pool_ref (&XEXP (*x, i), ref, addr);
+ replace_constant_pool_ref (&XEXP (*x, i), ref, offset);
}
else if (fmt[i] == 'E')
{
for (j = 0; j < XVECLEN (*x, i); j++)
- replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, addr);
+ replace_constant_pool_ref (&XVECEXP (*x, i, j), ref, offset);
}
}
}
@@ -4070,10 +5242,10 @@ find_ltrel_base (rtx x)
return NULL_RTX;
}
-/* Replace any occurrence of UNSPEC_LTREL_BASE in X with BASE. */
+/* Replace any occurrence of UNSPEC_LTREL_BASE in X with its base. */
static void
-replace_ltrel_base (rtx *x, rtx base)
+replace_ltrel_base (rtx *x)
{
int i, j;
const char *fmt;
@@ -4081,7 +5253,7 @@ replace_ltrel_base (rtx *x, rtx base)
if (GET_CODE (*x) == UNSPEC
&& XINT (*x, 1) == UNSPEC_LTREL_BASE)
{
- *x = base;
+ *x = XVECEXP (*x, 0, 1);
return;
}
@@ -4090,12 +5262,12 @@ replace_ltrel_base (rtx *x, rtx base)
{
if (fmt[i] == 'e')
{
- replace_ltrel_base (&XEXP (*x, i), base);
+ replace_ltrel_base (&XEXP (*x, i));
}
else if (fmt[i] == 'E')
{
for (j = 0; j < XVECLEN (*x, i); j++)
- replace_ltrel_base (&XVECEXP (*x, i, j), base);
+ replace_ltrel_base (&XVECEXP (*x, i, j));
}
}
}
@@ -4104,12 +5276,12 @@ replace_ltrel_base (rtx *x, rtx base)
/* We keep a list of constants which we have to add to internal
constant tables in the middle of large functions. */
-#define NR_C_MODES 7
+#define NR_C_MODES 11
enum machine_mode constant_modes[NR_C_MODES] =
{
- TImode,
- DFmode, DImode,
- SFmode, SImode,
+ TFmode, TImode, TDmode,
+ DFmode, DImode, DDmode,
+ SFmode, SImode, SDmode,
HImode,
QImode
};
@@ -4129,27 +5301,33 @@ struct constant_pool
bitmap insns;
struct constant *constants[NR_C_MODES];
+ struct constant *execute;
rtx label;
int size;
};
-static struct constant_pool * s390_mainpool_start (void);
-static void s390_mainpool_finish (struct constant_pool *, rtx base_reg);
-static void s390_mainpool_cancel (struct constant_pool *);
+/* Allocate new constant_pool structure. */
-static struct constant_pool * s390_chunkify_start (rtx base_reg);
-static void s390_chunkify_finish (struct constant_pool *, rtx base_reg);
-static void s390_chunkify_cancel (struct constant_pool *);
+static struct constant_pool *
+s390_alloc_pool (void)
+{
+ struct constant_pool *pool;
+ int i;
-static struct constant_pool *s390_start_pool (struct constant_pool **, rtx);
-static void s390_end_pool (struct constant_pool *, rtx);
-static void s390_add_pool_insn (struct constant_pool *, rtx);
-static struct constant_pool *s390_find_pool (struct constant_pool *, rtx);
-static void s390_add_constant (struct constant_pool *, rtx, enum machine_mode);
-static rtx s390_find_constant (struct constant_pool *, rtx, enum machine_mode);
-static rtx s390_dump_pool (struct constant_pool *, bool);
-static struct constant_pool *s390_alloc_pool (void);
-static void s390_free_pool (struct constant_pool *);
+ pool = (struct constant_pool *) xmalloc (sizeof *pool);
+ pool->next = NULL;
+ for (i = 0; i < NR_C_MODES; i++)
+ pool->constants[i] = NULL;
+
+ pool->execute = NULL;
+ pool->label = gen_label_rtx ();
+ pool->first_insn = NULL_RTX;
+ pool->pool_insn = NULL_RTX;
+ pool->insns = BITMAP_ALLOC (NULL);
+ pool->size = 0;
+
+ return pool;
+}
/* Create new constant pool covering instructions starting at INSN
and chain it to the end of POOL_LIST. */
@@ -4217,8 +5395,7 @@ s390_add_constant (struct constant_pool *pool, rtx val, enum machine_mode mode)
for (i = 0; i < NR_C_MODES; i++)
if (constant_modes[i] == mode)
break;
- if (i == NR_C_MODES)
- abort ();
+ gcc_assert (i != NR_C_MODES);
for (c = pool->constants[i]; c != NULL; c = c->next)
if (rtx_equal_p (val, c->value))
@@ -4250,15 +5427,13 @@ s390_find_constant (struct constant_pool *pool, rtx val,
for (i = 0; i < NR_C_MODES; i++)
if (constant_modes[i] == mode)
break;
- if (i == NR_C_MODES)
- abort ();
+ gcc_assert (i != NR_C_MODES);
for (c = pool->constants[i]; c != NULL; c = c->next)
if (rtx_equal_p (val, c->value))
break;
- if (c == NULL)
- abort ();
+ gcc_assert (c);
offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
gen_rtx_LABEL_REF (Pmode, pool->label));
@@ -4266,24 +5441,126 @@ s390_find_constant (struct constant_pool *pool, rtx val,
return offset;
}
+/* Check whether INSN is an execute. Return the label_ref to its
+ execute target template if so, NULL_RTX otherwise. */
+
+static rtx
+s390_execute_label (rtx insn)
+{
+ if (GET_CODE (insn) == INSN
+ && GET_CODE (PATTERN (insn)) == PARALLEL
+ && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == UNSPEC
+ && XINT (XVECEXP (PATTERN (insn), 0, 0), 1) == UNSPEC_EXECUTE)
+ return XVECEXP (XVECEXP (PATTERN (insn), 0, 0), 0, 2);
+
+ return NULL_RTX;
+}
+
+/* Add execute target for INSN to the constant pool POOL. */
+
+static void
+s390_add_execute (struct constant_pool *pool, rtx insn)
+{
+ struct constant *c;
+
+ for (c = pool->execute; c != NULL; c = c->next)
+ if (INSN_UID (insn) == INSN_UID (c->value))
+ break;
+
+ if (c == NULL)
+ {
+ c = (struct constant *) xmalloc (sizeof *c);
+ c->value = insn;
+ c->label = gen_label_rtx ();
+ c->next = pool->execute;
+ pool->execute = c;
+ pool->size += 6;
+ }
+}
+
+/* Find execute target for INSN in the constant pool POOL.
+ Return an RTX describing the distance from the start of
+ the pool to the location of the execute target. */
+
+static rtx
+s390_find_execute (struct constant_pool *pool, rtx insn)
+{
+ struct constant *c;
+ rtx offset;
+
+ for (c = pool->execute; c != NULL; c = c->next)
+ if (INSN_UID (insn) == INSN_UID (c->value))
+ break;
+
+ gcc_assert (c);
+
+ offset = gen_rtx_MINUS (Pmode, gen_rtx_LABEL_REF (Pmode, c->label),
+ gen_rtx_LABEL_REF (Pmode, pool->label));
+ offset = gen_rtx_CONST (Pmode, offset);
+ return offset;
+}
+
+/* For an execute INSN, extract the execute target template. */
+
+static rtx
+s390_execute_target (rtx insn)
+{
+ rtx pattern = PATTERN (insn);
+ gcc_assert (s390_execute_label (insn));
+
+ if (XVECLEN (pattern, 0) == 2)
+ {
+ pattern = copy_rtx (XVECEXP (pattern, 0, 1));
+ }
+ else
+ {
+ rtvec vec = rtvec_alloc (XVECLEN (pattern, 0) - 1);
+ int i;
+
+ for (i = 0; i < XVECLEN (pattern, 0) - 1; i++)
+ RTVEC_ELT (vec, i) = copy_rtx (XVECEXP (pattern, 0, i + 1));
+
+ pattern = gen_rtx_PARALLEL (VOIDmode, vec);
+ }
+
+ return pattern;
+}
+
+/* Indicate that INSN cannot be duplicated. This is the case for
+ execute insns that carry a unique label. */
+
+static bool
+s390_cannot_copy_insn_p (rtx insn)
+{
+ rtx label = s390_execute_label (insn);
+ return label && label != const0_rtx;
+}
+
/* Dump out the constants in POOL. If REMOTE_LABEL is true,
do not emit the pool base label. */
-static rtx
+static void
s390_dump_pool (struct constant_pool *pool, bool remote_label)
{
struct constant *c;
- rtx insn;
+ rtx insn = pool->pool_insn;
int i;
- /* Pool start insn switches to proper section
- and guarantees necessary alignment. */
+ /* Switch to rodata section. */
+ if (TARGET_CPU_ZARCH)
+ {
+ insn = emit_insn_after (gen_pool_section_start (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
+ /* Ensure minimum pool alignment. */
if (TARGET_CPU_ZARCH)
- insn = emit_insn_after (gen_pool_start_64 (), pool->pool_insn);
+ insn = emit_insn_after (gen_pool_align (GEN_INT (8)), insn);
else
- insn = emit_insn_after (gen_pool_start_31 (), pool->pool_insn);
+ insn = emit_insn_after (gen_pool_align (GEN_INT (4)), insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Emit pool base label. */
if (!remote_label)
{
insn = emit_label_after (pool->label, insn);
@@ -4310,50 +5587,39 @@ s390_dump_pool (struct constant_pool *pool, bool remote_label)
insn = emit_label_after (c->label, insn);
INSN_ADDRESSES_NEW (insn, -1);
- value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i],
+ value = gen_rtx_UNSPEC_VOLATILE (constant_modes[i],
gen_rtvec (1, value),
UNSPECV_POOL_ENTRY);
insn = emit_insn_after (value, insn);
INSN_ADDRESSES_NEW (insn, -1);
}
- /* Pool end insn switches back to previous section
- and guarantees necessary alignment. */
- if (TARGET_CPU_ZARCH)
- insn = emit_insn_after (gen_pool_end_64 (), insn);
- else
- insn = emit_insn_after (gen_pool_end_31 (), insn);
+ /* Ensure minimum alignment for instructions. */
+ insn = emit_insn_after (gen_pool_align (GEN_INT (2)), insn);
INSN_ADDRESSES_NEW (insn, -1);
+ /* Output in-pool execute template insns. */
+ for (c = pool->execute; c; c = c->next)
+ {
+ insn = emit_label_after (c->label, insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+
+ insn = emit_insn_after (s390_execute_target (c->value), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
+ /* Switch back to previous section. */
+ if (TARGET_CPU_ZARCH)
+ {
+ insn = emit_insn_after (gen_pool_section_end (), insn);
+ INSN_ADDRESSES_NEW (insn, -1);
+ }
+
insn = emit_barrier_after (insn);
INSN_ADDRESSES_NEW (insn, -1);
/* Remove placeholder insn. */
remove_insn (pool->pool_insn);
-
- return insn;
-}
-
-/* Allocate new constant_pool structure. */
-
-static struct constant_pool *
-s390_alloc_pool (void)
-{
- struct constant_pool *pool;
- int i;
-
- pool = (struct constant_pool *) xmalloc (sizeof *pool);
- pool->next = NULL;
- for (i = 0; i < NR_C_MODES; i++)
- pool->constants[i] = NULL;
-
- pool->label = gen_label_rtx ();
- pool->first_insn = NULL_RTX;
- pool->pool_insn = NULL_RTX;
- pool->insns = BITMAP_XMALLOC ();
- pool->size = 0;
-
- return pool;
}
/* Free all memory used by POOL. */
@@ -4361,20 +5627,23 @@ s390_alloc_pool (void)
static void
s390_free_pool (struct constant_pool *pool)
{
+ struct constant *c, *next;
int i;
for (i = 0; i < NR_C_MODES; i++)
+ for (c = pool->constants[i]; c; c = next)
+ {
+ next = c->next;
+ free (c);
+ }
+
+ for (c = pool->execute; c; c = next)
{
- struct constant *c = pool->constants[i];
- while (c != NULL)
- {
- struct constant *next = c->next;
- free (c);
- c = next;
- }
+ next = c->next;
+ free (c);
}
- BITMAP_XFREE (pool->insns);
+ BITMAP_FREE (pool->insns);
free (pool);
}
@@ -4392,15 +5661,19 @@ s390_mainpool_start (void)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == INSN
- && GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
- && XINT (PATTERN (insn), 1) == UNSPECV_MAIN_POOL)
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_SRC (PATTERN (insn))) == UNSPEC_VOLATILE
+ && XINT (SET_SRC (PATTERN (insn)), 1) == UNSPECV_MAIN_POOL)
{
- if (pool->pool_insn)
- abort ();
+ gcc_assert (!pool->pool_insn);
pool->pool_insn = insn;
}
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
+ {
+ s390_add_execute (pool, insn);
+ }
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -4413,8 +5686,7 @@ s390_mainpool_start (void)
}
}
- if (!pool->pool_insn)
- abort ();
+ gcc_assert (pool->pool_insn || pool->size == 0);
if (pool->size >= 4096)
{
@@ -4431,18 +5703,22 @@ s390_mainpool_start (void)
/* POOL holds the main literal pool as collected by s390_mainpool_start.
Modify the current function to output the pool constants as well as
- the pool register setup instruction. BASE_REG is the register to
- be used as pool base register. */
+ the pool register setup instruction. */
static void
-s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
+s390_mainpool_finish (struct constant_pool *pool)
{
+ rtx base_reg = cfun->machine->base_reg;
rtx insn;
/* If the pool is empty, we're done. */
if (pool->size == 0)
{
- remove_insn (pool->pool_insn);
+ /* We don't actually need a base register after all. */
+ cfun->machine->base_reg = NULL_RTX;
+
+ if (pool->pool_insn)
+ remove_insn (pool->pool_insn);
s390_free_pool (pool);
return;
}
@@ -4458,8 +5734,8 @@ s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
insn = emit_insn_after (insn, pool->pool_insn);
INSN_ADDRESSES_NEW (insn, -1);
remove_insn (pool->pool_insn);
-
- insn = get_last_insn ();
+
+ insn = get_last_insn ();
pool->pool_insn = emit_insn_after (gen_pool (const0_rtx), insn);
INSN_ADDRESSES_NEW (pool->pool_insn, -1);
@@ -4516,7 +5792,7 @@ s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn), base_reg);
+ replace_ltrel_base (&PATTERN (insn));
if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
@@ -4524,9 +5800,12 @@ s390_mainpool_finish (struct constant_pool *pool, rtx base_reg)
find_constant_pool_ref (PATTERN (insn), &pool_ref);
if (pool_ref)
{
- addr = s390_find_constant (pool, get_pool_constant (pool_ref),
- get_pool_mode (pool_ref));
- addr = gen_rtx_PLUS (Pmode, base_reg, addr);
+ if (s390_execute_label (insn))
+ addr = s390_find_execute (pool, insn);
+ else
+ addr = s390_find_constant (pool, get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
INSN_CODE (insn) = -1;
}
@@ -4550,14 +5829,13 @@ s390_mainpool_cancel (struct constant_pool *pool)
}
-/* Chunkify the literal pool. BASE_REG is to be used as pool
- register. */
+/* Chunkify the literal pool. */
#define S390_POOL_CHUNK_MIN 0xc00
#define S390_POOL_CHUNK_MAX 0xe00
static struct constant_pool *
-s390_chunkify_start (rtx base_reg)
+s390_chunkify_start (void)
{
struct constant_pool *curr_pool = NULL, *pool_list = NULL;
int extra_size = 0;
@@ -4583,14 +5861,20 @@ s390_chunkify_start (rtx base_reg)
rtx ltrel_base = find_ltrel_base (PATTERN (insn));
if (ltrel_base)
{
- if (ltrel_base == pending_ltrel)
- pending_ltrel = NULL_RTX;
- else
- abort ();
+ gcc_assert (ltrel_base == pending_ltrel);
+ pending_ltrel = NULL_RTX;
}
}
- if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
+ if (!TARGET_CPU_ZARCH && s390_execute_label (insn))
+ {
+ if (!curr_pool)
+ curr_pool = s390_start_pool (&pool_list, insn);
+
+ s390_add_execute (curr_pool, insn);
+ s390_add_pool_insn (curr_pool, insn);
+ }
+ else if (GET_CODE (insn) == INSN || GET_CODE (insn) == CALL_INSN)
{
rtx pool_ref = NULL_RTX;
find_constant_pool_ref (PATTERN (insn), &pool_ref);
@@ -4611,8 +5895,7 @@ s390_chunkify_start (rtx base_reg)
&& GET_CODE (XEXP (constant, 0)) == UNSPEC
&& XINT (XEXP (constant, 0), 1) == UNSPEC_LTREL_OFFSET)
{
- if (pending_ltrel)
- abort ();
+ gcc_assert (!pending_ltrel);
pending_ltrel = pool_ref;
}
}
@@ -4623,8 +5906,7 @@ s390_chunkify_start (rtx base_reg)
if (curr_pool)
s390_add_pool_insn (curr_pool, insn);
/* An LTREL_BASE must follow within the same basic block. */
- if (pending_ltrel)
- abort ();
+ gcc_assert (!pending_ltrel);
}
if (!curr_pool
@@ -4702,14 +5984,12 @@ s390_chunkify_start (rtx base_reg)
if (curr_pool)
s390_end_pool (curr_pool, NULL_RTX);
- if (pending_ltrel)
- abort ();
-
+ gcc_assert (!pending_ltrel);
/* Find all labels that are branched into
from an insn belonging to a different chunk. */
- far_labels = BITMAP_XMALLOC ();
+ far_labels = BITMAP_ALLOC (NULL);
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
@@ -4784,7 +6064,8 @@ s390_chunkify_start (rtx base_reg)
for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
{
- rtx new_insn = gen_reload_base (base_reg, curr_pool->label);
+ rtx new_insn = gen_reload_base (cfun->machine->base_reg,
+ curr_pool->label);
rtx insn = curr_pool->first_insn;
INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
}
@@ -4798,13 +6079,14 @@ s390_chunkify_start (rtx base_reg)
struct constant_pool *pool = s390_find_pool (pool_list, insn);
if (pool)
{
- rtx new_insn = gen_reload_base (base_reg, pool->label);
+ rtx new_insn = gen_reload_base (cfun->machine->base_reg,
+ pool->label);
INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
}
}
- BITMAP_XFREE (far_labels);
+ BITMAP_FREE (far_labels);
/* Recompute insn addresses. */
@@ -4817,11 +6099,10 @@ s390_chunkify_start (rtx base_reg)
/* POOL_LIST is a chunk list as prepared by s390_chunkify_start.
After we have decided to use this list, finish implementing
- all changes to the current function as required. BASE_REG is
- to be used as pool base register. */
+ all changes to the current function as required. */
static void
-s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
+s390_chunkify_finish (struct constant_pool *pool_list)
{
struct constant_pool *curr_pool = NULL;
rtx insn;
@@ -4832,7 +6113,7 @@ s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (INSN_P (insn))
- replace_ltrel_base (&PATTERN (insn), base_reg);
+ replace_ltrel_base (&PATTERN (insn));
curr_pool = s390_find_pool (pool_list, insn);
if (!curr_pool)
@@ -4844,9 +6125,13 @@ s390_chunkify_finish (struct constant_pool *pool_list, rtx base_reg)
find_constant_pool_ref (PATTERN (insn), &pool_ref);
if (pool_ref)
{
- addr = s390_find_constant (curr_pool, get_pool_constant (pool_ref),
- get_pool_mode (pool_ref));
- addr = gen_rtx_PLUS (Pmode, base_reg, addr);
+ if (s390_execute_label (insn))
+ addr = s390_find_execute (curr_pool, insn);
+ else
+ addr = s390_find_constant (curr_pool,
+ get_pool_constant (pool_ref),
+ get_pool_mode (pool_ref));
+
replace_constant_pool_ref (&PATTERN (insn), pool_ref, addr);
INSN_CODE (insn) = -1;
}
@@ -4929,476 +6214,734 @@ s390_chunkify_cancel (struct constant_pool *pool_list)
}
-/* Output to FILE the constant pool entry EXP in mode MODE
- with alignment ALIGN. */
+/* Output the constant pool entry EXP in mode MODE with alignment ALIGN. */
void
-s390_output_pool_entry (FILE *file, rtx exp, enum machine_mode mode,
- unsigned int align)
+s390_output_pool_entry (rtx exp, enum machine_mode mode, unsigned int align)
{
REAL_VALUE_TYPE r;
switch (GET_MODE_CLASS (mode))
{
case MODE_FLOAT:
- if (GET_CODE (exp) != CONST_DOUBLE)
- abort ();
+ case MODE_DECIMAL_FLOAT:
+ gcc_assert (GET_CODE (exp) == CONST_DOUBLE);
REAL_VALUE_FROM_CONST_DOUBLE (r, exp);
assemble_real (r, mode, align);
break;
case MODE_INT:
- if (GET_CODE (exp) == CONST
- || GET_CODE (exp) == SYMBOL_REF
- || GET_CODE (exp) == LABEL_REF)
- {
- fputs (integer_asm_op (GET_MODE_SIZE (mode), TRUE), file);
- s390_output_symbolic_const (file, exp);
- fputc ('\n', file);
- }
- else
- {
- assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
- }
+ assemble_integer (exp, GET_MODE_SIZE (mode), align, 1);
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
-/* Rework the prolog/epilog to avoid saving/restoring
- registers unnecessarily. BASE_USED specifies whether
- the literal pool base register needs to be saved. */
+/* Return an RTL expression representing the value of the return address
+ for the frame COUNT steps up from the current frame. FRAME is the
+ frame pointer of that frame. */
-static void
-s390_optimize_prolog (bool base_used)
+rtx
+s390_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
{
- int save_first, save_last, restore_first, restore_last;
- int i, j;
- rtx insn, new_insn, next_insn;
-
- /* Recompute regs_ever_live data for special registers. */
- regs_ever_live[BASE_REGISTER] = base_used;
- regs_ever_live[RETURN_REGNUM] = cfun->machine->save_return_addr_p;
- regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
-
-
- /* Find first and last gpr to be saved. */
+ int offset;
+ rtx addr;
- for (i = 6; i < 16; i++)
- if (regs_ever_live[i])
- if (!global_regs[i]
- || i == STACK_POINTER_REGNUM
- || i == RETURN_REGNUM
- || i == BASE_REGISTER
- || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
- break;
+ /* Without backchain, we fail for all but the current frame. */
- for (j = 15; j > i; j--)
- if (regs_ever_live[j])
- if (!global_regs[j]
- || j == STACK_POINTER_REGNUM
- || j == RETURN_REGNUM
- || j == BASE_REGISTER
- || (flag_pic && j == (int)PIC_OFFSET_TABLE_REGNUM))
- break;
+ if (!TARGET_BACKCHAIN && count > 0)
+ return NULL_RTX;
- if (i == 16)
- {
- /* Nothing to save/restore. */
- save_first = restore_first = -1;
- save_last = restore_last = -1;
- }
- else
- {
- /* Save/restore from i to j. */
- save_first = restore_first = i;
- save_last = restore_last = j;
- }
+ /* For the current frame, we need to make sure the initial
+ value of RETURN_REGNUM is actually saved. */
- /* Varargs functions need to save gprs 2 to 6. */
- if (current_function_stdarg)
+ if (count == 0)
{
- save_first = 2;
- if (save_last < 6)
- save_last = 6;
+ /* On non-z architectures branch splitting could overwrite r14. */
+ if (TARGET_CPU_ZARCH)
+ return get_hard_reg_initial_val (Pmode, RETURN_REGNUM);
+ else
+ {
+ cfun_frame_layout.save_return_addr_p = true;
+ return gen_rtx_MEM (Pmode, return_address_pointer_rtx);
+ }
}
+ if (TARGET_PACKED_STACK)
+ offset = -2 * UNITS_PER_WORD;
+ else
+ offset = RETURN_REGNUM * UNITS_PER_WORD;
- /* If all special registers are in fact used, there's nothing we
- can do, so no point in walking the insn list. */
- if (i <= BASE_REGISTER && j >= BASE_REGISTER
- && (TARGET_CPU_ZARCH || (i <= RETURN_REGNUM && j >= RETURN_REGNUM)))
- return;
+ addr = plus_constant (frame, offset);
+ addr = memory_address (Pmode, addr);
+ return gen_rtx_MEM (Pmode, addr);
+}
+/* Return an RTL expression representing the back chain stored in
+ the current stack frame. */
- /* Search for prolog/epilog insns and replace them. */
+rtx
+s390_back_chain_rtx (void)
+{
+ rtx chain;
- for (insn = get_insns (); insn; insn = next_insn)
- {
- int first, last, off;
- rtx set, base, offset;
+ gcc_assert (TARGET_BACKCHAIN);
- next_insn = NEXT_INSN (insn);
+ if (TARGET_PACKED_STACK)
+ chain = plus_constant (stack_pointer_rtx,
+ STACK_POINTER_OFFSET - UNITS_PER_WORD);
+ else
+ chain = stack_pointer_rtx;
- if (GET_CODE (insn) != INSN)
- continue;
+ chain = gen_rtx_MEM (Pmode, chain);
+ return chain;
+}
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && store_multiple_operation (PATTERN (insn), VOIDmode))
- {
- set = XVECEXP (PATTERN (insn), 0, 0);
- first = REGNO (SET_SRC (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
- off = INTVAL (offset) - first * UNITS_PER_WORD;
+/* Find first call clobbered register unused in a function.
+ This could be used as base register in a leaf function
+ or for holding the return address before epilogue. */
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (first > BASE_REGISTER || last < BASE_REGISTER)
- continue;
+static int
+find_unused_clobbered_reg (void)
+{
+ int i;
+ for (i = 0; i < 6; i++)
+ if (!regs_ever_live[i])
+ return i;
+ return 0;
+}
- if (save_first != -1)
- {
- new_insn = save_gprs (base, off, save_first, save_last);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
- remove_insn (insn);
- continue;
- }
+/* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all
+ clobbered hard regs in SETREG. */
- if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_SRC (PATTERN (insn))) == REG
- && REGNO (SET_SRC (PATTERN (insn))) == BASE_REGISTER
- && GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
- {
- set = PATTERN (insn);
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
- off = INTVAL (offset) - BASE_REGISTER * UNITS_PER_WORD;
+static void
+s390_reg_clobbered_rtx (rtx setreg, rtx set_insn ATTRIBUTE_UNUSED, void *data)
+{
+ int *regs_ever_clobbered = (int *)data;
+ unsigned int i, regno;
+ enum machine_mode mode = GET_MODE (setreg);
- if (GET_CODE (base) != REG || off < 0)
- continue;
+ if (GET_CODE (setreg) == SUBREG)
+ {
+ rtx inner = SUBREG_REG (setreg);
+ if (!GENERAL_REG_P (inner))
+ return;
+ regno = subreg_regno (setreg);
+ }
+ else if (GENERAL_REG_P (setreg))
+ regno = REGNO (setreg);
+ else
+ return;
- if (save_first != -1)
- {
- new_insn = save_gprs (base, off, save_first, save_last);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
+ for (i = regno;
+ i < regno + HARD_REGNO_NREGS (regno, mode);
+ i++)
+ regs_ever_clobbered[i] = 1;
+}
- remove_insn (insn);
- continue;
- }
+/* Walks through all basic blocks of the current function looking
+ for clobbered hard regs using s390_reg_clobbered_rtx. The fields
+ of the passed integer array REGS_EVER_CLOBBERED are set to one for
+ each of those regs. */
- if (GET_CODE (PATTERN (insn)) == PARALLEL
- && load_multiple_operation (PATTERN (insn), VOIDmode))
+static void
+s390_regs_ever_clobbered (int *regs_ever_clobbered)
+{
+ basic_block cur_bb;
+ rtx cur_insn;
+ unsigned int i;
+
+ memset (regs_ever_clobbered, 0, 16 * sizeof (int));
+
+ /* For non-leaf functions we have to consider all call clobbered regs to be
+ clobbered. */
+ if (!current_function_is_leaf)
+ {
+ for (i = 0; i < 16; i++)
+ regs_ever_clobbered[i] = call_really_used_regs[i];
+ }
+
+ /* Make the "magic" eh_return registers live if necessary. For regs_ever_live
+ this work is done by liveness analysis (mark_regs_live_at_end).
+ Special care is needed for functions containing landing pads. Landing pads
+ may use the eh registers, but the code which sets these registers is not
+ contained in that function. Hence s390_regs_ever_clobbered is not able to
+ deal with this automatically. */
+ if (current_function_calls_eh_return || cfun->machine->has_landing_pad_p)
+ for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM ; i++)
+ if (current_function_calls_eh_return
+ || (cfun->machine->has_landing_pad_p
+ && regs_ever_live [EH_RETURN_DATA_REGNO (i)]))
+ regs_ever_clobbered[EH_RETURN_DATA_REGNO (i)] = 1;
+
+ /* For nonlocal gotos all call-saved registers have to be saved.
+ This flag is also set for the unwinding code in libgcc.
+ See expand_builtin_unwind_init. For regs_ever_live this is done by
+ reload. */
+ if (current_function_has_nonlocal_label)
+ for (i = 0; i < 16; i++)
+ if (!call_really_used_regs[i])
+ regs_ever_clobbered[i] = 1;
+
+ FOR_EACH_BB (cur_bb)
+ {
+ FOR_BB_INSNS (cur_bb, cur_insn)
{
- set = XVECEXP (PATTERN (insn), 0, 0);
- first = REGNO (SET_DEST (set));
- last = first + XVECLEN (PATTERN (insn), 0) - 1;
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
- off = INTVAL (offset) - first * UNITS_PER_WORD;
-
- if (GET_CODE (base) != REG || off < 0)
- continue;
- if (first > BASE_REGISTER || last < BASE_REGISTER)
- continue;
+ if (INSN_P (cur_insn))
+ note_stores (PATTERN (cur_insn),
+ s390_reg_clobbered_rtx,
+ regs_ever_clobbered);
+ }
+ }
+}
- if (restore_first != -1)
- {
- new_insn = restore_gprs (base, off, restore_first, restore_last);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
+/* Determine the frame area which actually has to be accessed
+ in the function epilogue. The values are stored at the
+ given pointers AREA_BOTTOM (address of the lowest used stack
+ address) and AREA_TOP (address of the first item which does
+ not belong to the stack frame). */
- remove_insn (insn);
- continue;
- }
+static void
+s390_frame_area (int *area_bottom, int *area_top)
+{
+ int b, t;
+ int i;
- if (GET_CODE (PATTERN (insn)) == SET
- && GET_CODE (SET_DEST (PATTERN (insn))) == REG
- && REGNO (SET_DEST (PATTERN (insn))) == BASE_REGISTER
- && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
- {
- set = PATTERN (insn);
- offset = const0_rtx;
- base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
- off = INTVAL (offset) - BASE_REGISTER * UNITS_PER_WORD;
+ b = INT_MAX;
+ t = INT_MIN;
- if (GET_CODE (base) != REG || off < 0)
- continue;
+ if (cfun_frame_layout.first_restore_gpr != -1)
+ {
+ b = (cfun_frame_layout.gprs_offset
+ + cfun_frame_layout.first_restore_gpr * UNITS_PER_WORD);
+ t = b + (cfun_frame_layout.last_restore_gpr
+ - cfun_frame_layout.first_restore_gpr + 1) * UNITS_PER_WORD;
+ }
- if (restore_first != -1)
- {
- new_insn = restore_gprs (base, off, restore_first, restore_last);
- new_insn = emit_insn_before (new_insn, insn);
- INSN_ADDRESSES_NEW (new_insn, -1);
- }
+ if (TARGET_64BIT && cfun_save_high_fprs_p)
+ {
+ b = MIN (b, cfun_frame_layout.f8_offset);
+ t = MAX (t, (cfun_frame_layout.f8_offset
+ + cfun_frame_layout.high_fprs * 8));
+ }
- remove_insn (insn);
- continue;
+ if (!TARGET_64BIT)
+ for (i = 2; i < 4; i++)
+ if (cfun_fpr_bit_p (i))
+ {
+ b = MIN (b, cfun_frame_layout.f4_offset + (i - 2) * 8);
+ t = MAX (t, cfun_frame_layout.f4_offset + (i - 1) * 8);
}
- }
+
+ *area_bottom = b;
+ *area_top = t;
}
-/* Perform machine-dependent processing. */
+/* Fill cfun->machine with info about register usage of current function.
+ Return in CLOBBERED_REGS which GPRs are currently considered set. */
static void
-s390_reorg (void)
+s390_register_info (int clobbered_regs[])
{
- rtx base_reg = gen_rtx_REG (Pmode, BASE_REGISTER);
- bool base_used = false;
- bool pool_overflow = false;
+ int i, j;
- /* Make sure all splits have been performed; splits after
- machine_dependent_reorg might confuse insn length counts. */
- split_all_insns_noflow ();
+ /* fprs 8 - 15 are call saved for 64 Bit ABI. */
+ cfun_frame_layout.fpr_bitmap = 0;
+ cfun_frame_layout.high_fprs = 0;
+ if (TARGET_64BIT)
+ for (i = 24; i < 32; i++)
+ if (regs_ever_live[i] && !global_regs[i])
+ {
+ cfun_set_fpr_bit (i - 16);
+ cfun_frame_layout.high_fprs++;
+ }
+ /* Find first and last gpr to be saved. We trust regs_ever_live
+ data, except that we don't save and restore global registers.
- /* In small leaf functions, try to use an unused call-clobbered
- register as base register to avoid save/restore overhead. */
- if (current_function_is_leaf && !regs_ever_live[5])
- base_reg = gen_rtx_REG (Pmode, 5);
+ Also, all registers with special meaning to the compiler need
+ to be handled extra. */
+ s390_regs_ever_clobbered (clobbered_regs);
- /* Install the main literal pool and the associated base
- register load insns.
+ for (i = 0; i < 16; i++)
+ clobbered_regs[i] = clobbered_regs[i] && !global_regs[i] && !fixed_regs[i];
- In addition, there are two problematic situations we need
- to correct:
+ if (frame_pointer_needed)
+ clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
- - the literal pool might be > 4096 bytes in size, so that
- some of its elements cannot be directly accessed
+ if (flag_pic)
+ clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
+ |= regs_ever_live[PIC_OFFSET_TABLE_REGNUM];
+
+ clobbered_regs[BASE_REGNUM]
+ |= (cfun->machine->base_reg
+ && REGNO (cfun->machine->base_reg) == BASE_REGNUM);
+
+ clobbered_regs[RETURN_REGNUM]
+ |= (!current_function_is_leaf
+ || TARGET_TPF_PROFILING
+ || cfun->machine->split_branches_pending_p
+ || cfun_frame_layout.save_return_addr_p
+ || current_function_calls_eh_return
+ || current_function_stdarg);
+
+ clobbered_regs[STACK_POINTER_REGNUM]
+ |= (!current_function_is_leaf
+ || TARGET_TPF_PROFILING
+ || cfun_save_high_fprs_p
+ || get_frame_size () > 0
+ || current_function_calls_alloca
+ || current_function_stdarg);
- - a branch target might be > 64K away from the branch, so that
- it is not possible to use a PC-relative instruction.
+ for (i = 6; i < 16; i++)
+ if (regs_ever_live[i] || clobbered_regs[i])
+ break;
+ for (j = 15; j > i; j--)
+ if (regs_ever_live[j] || clobbered_regs[j])
+ break;
- To fix those, we split the single literal pool into multiple
- pool chunks, reloading the pool base register at various
- points throughout the function to ensure it always points to
- the pool chunk the following code expects, and / or replace
- PC-relative branches by absolute branches.
+ if (i == 16)
+ {
+ /* Nothing to save/restore. */
+ cfun_frame_layout.first_save_gpr_slot = -1;
+ cfun_frame_layout.last_save_gpr_slot = -1;
+ cfun_frame_layout.first_save_gpr = -1;
+ cfun_frame_layout.first_restore_gpr = -1;
+ cfun_frame_layout.last_save_gpr = -1;
+ cfun_frame_layout.last_restore_gpr = -1;
+ }
+ else
+ {
+ /* Save slots for gprs from i to j. */
+ cfun_frame_layout.first_save_gpr_slot = i;
+ cfun_frame_layout.last_save_gpr_slot = j;
- However, the two problems are interdependent: splitting the
- literal pool can move a branch further away from its target,
- causing the 64K limit to overflow, and on the other hand,
- replacing a PC-relative branch by an absolute branch means
- we need to put the branch target address into the literal
- pool, possibly causing it to overflow.
+ for (i = cfun_frame_layout.first_save_gpr_slot;
+ i < cfun_frame_layout.last_save_gpr_slot + 1;
+ i++)
+ if (clobbered_regs[i])
+ break;
- So, we loop trying to fix up both problems until we manage
- to satisfy both conditions at the same time. Note that the
- loop is guaranteed to terminate as every pass of the loop
- strictly decreases the total number of PC-relative branches
- in the function. (This is not completely true as there
- might be branch-over-pool insns introduced by chunkify_start.
- Those never need to be split however.) */
+ for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--)
+ if (clobbered_regs[j])
+ break;
+
+ if (i == cfun_frame_layout.last_save_gpr_slot + 1)
+ {
+ /* Nothing to save/restore. */
+ cfun_frame_layout.first_save_gpr = -1;
+ cfun_frame_layout.first_restore_gpr = -1;
+ cfun_frame_layout.last_save_gpr = -1;
+ cfun_frame_layout.last_restore_gpr = -1;
+ }
+ else
+ {
+ /* Save / Restore from gpr i to j. */
+ cfun_frame_layout.first_save_gpr = i;
+ cfun_frame_layout.first_restore_gpr = i;
+ cfun_frame_layout.last_save_gpr = j;
+ cfun_frame_layout.last_restore_gpr = j;
+ }
+ }
- for (;;)
+ if (current_function_stdarg)
{
- struct constant_pool *pool = NULL;
-
- /* Collect the literal pool. */
- if (!pool_overflow)
+ /* Varargs functions need to save gprs 2 to 6. */
+ if (cfun->va_list_gpr_size
+ && current_function_args_info.gprs < GP_ARG_NUM_REG)
{
- pool = s390_mainpool_start ();
- if (!pool)
- pool_overflow = true;
+ int min_gpr = current_function_args_info.gprs;
+ int max_gpr = min_gpr + cfun->va_list_gpr_size;
+ if (max_gpr > GP_ARG_NUM_REG)
+ max_gpr = GP_ARG_NUM_REG;
+
+ if (cfun_frame_layout.first_save_gpr == -1
+ || cfun_frame_layout.first_save_gpr > 2 + min_gpr)
+ {
+ cfun_frame_layout.first_save_gpr = 2 + min_gpr;
+ cfun_frame_layout.first_save_gpr_slot = 2 + min_gpr;
+ }
+
+ if (cfun_frame_layout.last_save_gpr == -1
+ || cfun_frame_layout.last_save_gpr < 2 + max_gpr - 1)
+ {
+ cfun_frame_layout.last_save_gpr = 2 + max_gpr - 1;
+ cfun_frame_layout.last_save_gpr_slot = 2 + max_gpr - 1;
+ }
}
- /* If literal pool overflowed, start to chunkify it. */
- if (pool_overflow)
- pool = s390_chunkify_start (base_reg);
+ /* Mark f0, f2 for 31 bit and f0-f4 for 64 bit to be saved. */
+ if (TARGET_HARD_FLOAT && cfun->va_list_fpr_size
+ && current_function_args_info.fprs < FP_ARG_NUM_REG)
+ {
+ int min_fpr = current_function_args_info.fprs;
+ int max_fpr = min_fpr + cfun->va_list_fpr_size;
+ if (max_fpr > FP_ARG_NUM_REG)
+ max_fpr = FP_ARG_NUM_REG;
+
+ /* ??? This is currently required to ensure proper location
+ of the fpr save slots within the va_list save area. */
+ if (TARGET_PACKED_STACK)
+ min_fpr = 0;
+
+ for (i = min_fpr; i < max_fpr; i++)
+ cfun_set_fpr_bit (i);
+ }
+ }
- /* Split out-of-range branches. If this has created new
- literal pool entries, cancel current chunk list and
- recompute it. zSeries machines have large branch
- instructions, so we never need to split a branch. */
- if (!TARGET_CPU_ZARCH && s390_split_branches ())
- {
- if (pool_overflow)
- s390_chunkify_cancel (pool);
- else
- s390_mainpool_cancel (pool);
+ if (!TARGET_64BIT)
+ for (i = 2; i < 4; i++)
+ if (regs_ever_live[i + 16] && !global_regs[i + 16])
+ cfun_set_fpr_bit (i);
+}
- continue;
- }
+/* Fill cfun->machine with info about frame of current function. */
- /* If we made it up to here, both conditions are satisfied.
- Finish up literal pool related changes. */
- if ((pool_overflow || pool->size > 0)
- && REGNO (base_reg) == BASE_REGISTER)
- base_used = true;
+static void
+s390_frame_info (void)
+{
+ int i;
- if (pool_overflow)
- s390_chunkify_finish (pool, base_reg);
+ cfun_frame_layout.frame_size = get_frame_size ();
+ if (!TARGET_64BIT && cfun_frame_layout.frame_size > 0x7fff0000)
+ fatal_error ("total size of local variables exceeds architecture limit");
+
+ if (!TARGET_PACKED_STACK)
+ {
+ cfun_frame_layout.backchain_offset = 0;
+ cfun_frame_layout.f0_offset = 16 * UNITS_PER_WORD;
+ cfun_frame_layout.f4_offset = cfun_frame_layout.f0_offset + 2 * 8;
+ cfun_frame_layout.f8_offset = -cfun_frame_layout.high_fprs * 8;
+ cfun_frame_layout.gprs_offset = (cfun_frame_layout.first_save_gpr_slot
+ * UNITS_PER_WORD);
+ }
+ else if (TARGET_BACKCHAIN) /* kernel stack layout */
+ {
+ cfun_frame_layout.backchain_offset = (STACK_POINTER_OFFSET
+ - UNITS_PER_WORD);
+ cfun_frame_layout.gprs_offset
+ = (cfun_frame_layout.backchain_offset
+ - (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1)
+ * UNITS_PER_WORD);
+
+ if (TARGET_64BIT)
+ {
+ cfun_frame_layout.f4_offset
+ = (cfun_frame_layout.gprs_offset
+ - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
+
+ cfun_frame_layout.f0_offset
+ = (cfun_frame_layout.f4_offset
+ - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
+ }
else
- s390_mainpool_finish (pool, base_reg);
-
- break;
+ {
+ /* On 31 bit we have to care about alignment of the
+ floating point regs to provide fastest access. */
+ cfun_frame_layout.f0_offset
+ = ((cfun_frame_layout.gprs_offset
+ & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1))
+ - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
+
+ cfun_frame_layout.f4_offset
+ = (cfun_frame_layout.f0_offset
+ - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
+ }
+ }
+ else /* no backchain */
+ {
+ cfun_frame_layout.f4_offset
+ = (STACK_POINTER_OFFSET
+ - 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
+
+ cfun_frame_layout.f0_offset
+ = (cfun_frame_layout.f4_offset
+ - 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
+
+ cfun_frame_layout.gprs_offset
+ = cfun_frame_layout.f0_offset - cfun_gprs_save_area_size;
}
- s390_optimize_prolog (base_used);
-}
-
+ if (current_function_is_leaf
+ && !TARGET_TPF_PROFILING
+ && cfun_frame_layout.frame_size == 0
+ && !cfun_save_high_fprs_p
+ && !current_function_calls_alloca
+ && !current_function_stdarg)
+ return;
-/* Return an RTL expression representing the value of the return address
- for the frame COUNT steps up from the current frame. FRAME is the
- frame pointer of that frame. */
+ if (!TARGET_PACKED_STACK)
+ cfun_frame_layout.frame_size += (STACK_POINTER_OFFSET
+ + current_function_outgoing_args_size
+ + cfun_frame_layout.high_fprs * 8);
+ else
+ {
+ if (TARGET_BACKCHAIN)
+ cfun_frame_layout.frame_size += UNITS_PER_WORD;
-rtx
-s390_return_addr_rtx (int count, rtx frame)
-{
- rtx addr;
+ /* No alignment trouble here because f8-f15 are only saved under
+ 64 bit. */
+ cfun_frame_layout.f8_offset = (MIN (MIN (cfun_frame_layout.f0_offset,
+ cfun_frame_layout.f4_offset),
+ cfun_frame_layout.gprs_offset)
+ - cfun_frame_layout.high_fprs * 8);
- /* Without backchain, we fail for all but the current frame. */
+ cfun_frame_layout.frame_size += cfun_frame_layout.high_fprs * 8;
- if (!TARGET_BACKCHAIN && count > 0)
- return NULL_RTX;
+ for (i = 0; i < 8; i++)
+ if (cfun_fpr_bit_p (i))
+ cfun_frame_layout.frame_size += 8;
+
+ cfun_frame_layout.frame_size += cfun_gprs_save_area_size;
+
+ /* If under 31 bit an odd number of gprs has to be saved we have to adjust
+ the frame size to sustain 8 byte alignment of stack frames. */
+ cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
+ STACK_BOUNDARY / BITS_PER_UNIT - 1)
+ & ~(STACK_BOUNDARY / BITS_PER_UNIT - 1));
- /* For the current frame, we need to make sure the initial
- value of RETURN_REGNUM is actually saved. */
+ cfun_frame_layout.frame_size += current_function_outgoing_args_size;
+ }
+}
- if (count == 0)
- cfun->machine->save_return_addr_p = true;
+/* Generate frame layout. Fills in register and frame data for the current
+ function in cfun->machine. This routine can be called multiple times;
+ it will re-do the complete frame layout every time. */
- /* To retrieve the return address we read the stack slot where the
- corresponding RETURN_REGNUM value was saved. */
+static void
+s390_init_frame_layout (void)
+{
+ HOST_WIDE_INT frame_size;
+ int base_used;
+ int clobbered_regs[16];
+
+ /* On S/390 machines, we may need to perform branch splitting, which
+ will require both base and return address register. We have no
+ choice but to assume we're going to need them until right at the
+ end of the machine dependent reorg phase. */
+ if (!TARGET_CPU_ZARCH)
+ cfun->machine->split_branches_pending_p = true;
+
+ do
+ {
+ frame_size = cfun_frame_layout.frame_size;
+
+ /* Try to predict whether we'll need the base register. */
+ base_used = cfun->machine->split_branches_pending_p
+ || current_function_uses_const_pool
+ || (!DISP_IN_RANGE (frame_size)
+ && !CONST_OK_FOR_K (frame_size));
+
+ /* Decide which register to use as literal pool base. In small
+ leaf functions, try to use an unused call-clobbered register
+ as base register to avoid save/restore overhead. */
+ if (!base_used)
+ cfun->machine->base_reg = NULL_RTX;
+ else if (current_function_is_leaf && !regs_ever_live[5])
+ cfun->machine->base_reg = gen_rtx_REG (Pmode, 5);
+ else
+ cfun->machine->base_reg = gen_rtx_REG (Pmode, BASE_REGNUM);
- addr = plus_constant (frame, RETURN_REGNUM * UNITS_PER_WORD);
- addr = memory_address (Pmode, addr);
- return gen_rtx_MEM (Pmode, addr);
+ s390_register_info (clobbered_regs);
+ s390_frame_info ();
+ }
+ while (frame_size != cfun_frame_layout.frame_size);
}
-/* Find first call clobbered register unsused in a function.
- This could be used as base register in a leaf function
- or for holding the return address before epilogue. */
+/* Update frame layout. Recompute actual register save data based on
+ current info and update regs_ever_live for the special registers.
+ May be called multiple times, but may never cause *more* registers
+ to be saved than s390_init_frame_layout allocated room for. */
-static int
-find_unused_clobbered_reg (void)
+static void
+s390_update_frame_layout (void)
{
- int i;
- for (i = 0; i < 6; i++)
- if (!regs_ever_live[i])
- return i;
- return 0;
+ int clobbered_regs[16];
+
+ s390_register_info (clobbered_regs);
+
+ regs_ever_live[BASE_REGNUM] = clobbered_regs[BASE_REGNUM];
+ regs_ever_live[RETURN_REGNUM] = clobbered_regs[RETURN_REGNUM];
+ regs_ever_live[STACK_POINTER_REGNUM] = clobbered_regs[STACK_POINTER_REGNUM];
+
+ if (cfun->machine->base_reg)
+ regs_ever_live[REGNO (cfun->machine->base_reg)] = 1;
}
-/* Fill FRAME with info about frame of current function. */
+/* Return true if it is legal to put a value with MODE into REGNO. */
-static void
-s390_frame_info (void)
+bool
+s390_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
{
- int i, j;
- HOST_WIDE_INT fsize = get_frame_size ();
+ switch (REGNO_REG_CLASS (regno))
+ {
+ case FP_REGS:
+ if (REGNO_PAIR_OK (regno, mode))
+ {
+ if (mode == SImode || mode == DImode)
+ return true;
- if (!TARGET_64BIT && fsize > 0x7fff0000)
- fatal_error ("Total size of local variables exceeds architecture limit.");
+ if (FLOAT_MODE_P (mode) && GET_MODE_CLASS (mode) != MODE_VECTOR_FLOAT)
+ return true;
+ }
+ break;
+ case ADDR_REGS:
+ if (FRAME_REGNO_P (regno) && mode == Pmode)
+ return true;
- /* fprs 8 - 15 are caller saved for 64 Bit ABI. */
- cfun->machine->save_fprs_p = 0;
- if (TARGET_64BIT)
- for (i = 24; i < 32; i++)
- if (regs_ever_live[i] && !global_regs[i])
+ /* fallthrough */
+ case GENERAL_REGS:
+ if (REGNO_PAIR_OK (regno, mode))
{
- cfun->machine->save_fprs_p = 1;
- break;
+ if (TARGET_64BIT
+ || (mode != TFmode && mode != TCmode && mode != TDmode))
+ return true;
+ }
+ break;
+ case CC_REGS:
+ if (GET_MODE_CLASS (mode) == MODE_CC)
+ return true;
+ break;
+ case ACCESS_REGS:
+ if (REGNO_PAIR_OK (regno, mode))
+ {
+ if (mode == SImode || mode == Pmode)
+ return true;
}
+ break;
+ default:
+ return false;
+ }
+
+ return false;
+}
- cfun->machine->frame_size = fsize + cfun->machine->save_fprs_p * 64;
+/* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
- /* Does function need to setup frame and save area. */
+bool
+s390_hard_regno_rename_ok (unsigned int old_reg, unsigned int new_reg)
+{
+ /* Once we've decided upon a register to use as base register, it must
+ no longer be used for any other purpose. */
+ if (cfun->machine->base_reg)
+ if (REGNO (cfun->machine->base_reg) == old_reg
+ || REGNO (cfun->machine->base_reg) == new_reg)
+ return false;
- if (! current_function_is_leaf
- || cfun->machine->frame_size > 0
- || current_function_calls_alloca
- || current_function_stdarg)
- cfun->machine->frame_size += STARTING_FRAME_OFFSET;
+ return true;
+}
- /* If we use the return register, we'll need to make sure
- it is going to be saved/restored. */
+/* Maximum number of registers to represent a value of mode MODE
+ in a register of class CLASS. */
- if (!current_function_is_leaf
- || regs_ever_live[RETURN_REGNUM])
- cfun->machine->save_return_addr_p = 1;
+bool
+s390_class_max_nregs (enum reg_class class, enum machine_mode mode)
+{
+ switch (class)
+ {
+ case FP_REGS:
+ if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
+ return 2 * ((GET_MODE_SIZE (mode) / 2 + 8 - 1) / 8);
+ else
+ return (GET_MODE_SIZE (mode) + 8 - 1) / 8;
+ case ACCESS_REGS:
+ return (GET_MODE_SIZE (mode) + 4 - 1) / 4;
+ default:
+ break;
+ }
+ return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+}
- /* Find first and last gpr to be saved. Note that at this point,
- we assume the base register and -on S/390- the return register
- always need to be saved. This is done because the usage of these
- register might change even after the prolog was emitted.
- If it turns out later that we really don't need them, the
- prolog/epilog code is modified again. */
+/* Return true if register FROM can be eliminated via register TO. */
- regs_ever_live[BASE_REGISTER] = 1;
- if (!TARGET_CPU_ZARCH || cfun->machine->save_return_addr_p)
- regs_ever_live[RETURN_REGNUM] = 1;
- regs_ever_live[STACK_POINTER_REGNUM] = cfun->machine->frame_size > 0;
+bool
+s390_can_eliminate (int from, int to)
+{
+ /* On zSeries machines, we have not marked the base register as fixed.
+ Instead, we have an elimination rule BASE_REGNUM -> BASE_REGNUM.
+ If a function requires the base register, we say here that this
+ elimination cannot be performed. This will cause reload to free
+ up the base register (as if it were fixed). On the other hand,
+ if the current function does *not* require the base register, we
+ say here the elimination succeeds, which in turn allows reload
+ to allocate the base register for any other purpose. */
+ if (from == BASE_REGNUM && to == BASE_REGNUM)
+ {
+ if (TARGET_CPU_ZARCH)
+ {
+ s390_init_frame_layout ();
+ return cfun->machine->base_reg == NULL_RTX;
+ }
- for (i = 6; i < 16; i++)
- if (regs_ever_live[i])
- if (!global_regs[i]
- || i == STACK_POINTER_REGNUM
- || i == RETURN_REGNUM
- || i == BASE_REGISTER
- || (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
- break;
+ return false;
+ }
- for (j = 15; j > i; j--)
- if (regs_ever_live[j])
- if (!global_regs[j]
- || j == STACK_POINTER_REGNUM
- || j == RETURN_REGNUM
- || j == BASE_REGISTER
- || (flag_pic && j == (int)PIC_OFFSET_TABLE_REGNUM))
- break;
+ /* Everything else must point into the stack frame. */
+ gcc_assert (to == STACK_POINTER_REGNUM
+ || to == HARD_FRAME_POINTER_REGNUM);
- /* Save / Restore from gpr i to j. */
- cfun->machine->first_save_gpr = i;
- cfun->machine->first_restore_gpr = i;
- cfun->machine->last_save_gpr = j;
+ gcc_assert (from == FRAME_POINTER_REGNUM
+ || from == ARG_POINTER_REGNUM
+ || from == RETURN_ADDRESS_POINTER_REGNUM);
- /* Varargs functions need to save gprs 2 to 6. */
- if (current_function_stdarg)
- cfun->machine->first_save_gpr = 2;
+ /* Make sure we actually saved the return address. */
+ if (from == RETURN_ADDRESS_POINTER_REGNUM)
+ if (!current_function_calls_eh_return
+ && !current_function_stdarg
+ && !cfun_frame_layout.save_return_addr_p)
+ return false;
+
+ return true;
}
-/* Return offset between argument pointer and frame pointer
- initially after prologue. */
+/* Return offset between register FROM and TO initially after prolog. */
HOST_WIDE_INT
-s390_arg_frame_offset (void)
+s390_initial_elimination_offset (int from, int to)
{
- HOST_WIDE_INT fsize = get_frame_size ();
- int save_fprs_p, i;
+ HOST_WIDE_INT offset;
+ int index;
- /* fprs 8 - 15 are caller saved for 64 Bit ABI. */
- save_fprs_p = 0;
- if (TARGET_64BIT)
- for (i = 24; i < 32; i++)
- if (regs_ever_live[i] && !global_regs[i])
- {
- save_fprs_p = 1;
- break;
- }
+ /* ??? Why are we called for non-eliminable pairs? */
+ if (!s390_can_eliminate (from, to))
+ return 0;
- fsize = fsize + save_fprs_p * 64;
+ switch (from)
+ {
+ case FRAME_POINTER_REGNUM:
+ offset = (get_frame_size()
+ + STACK_POINTER_OFFSET
+ + current_function_outgoing_args_size);
+ break;
- /* Does function need to setup frame and save area. */
+ case ARG_POINTER_REGNUM:
+ s390_init_frame_layout ();
+ offset = cfun_frame_layout.frame_size + STACK_POINTER_OFFSET;
+ break;
+
+ case RETURN_ADDRESS_POINTER_REGNUM:
+ s390_init_frame_layout ();
+ index = RETURN_REGNUM - cfun_frame_layout.first_save_gpr_slot;
+ gcc_assert (index >= 0);
+ offset = cfun_frame_layout.frame_size + cfun_frame_layout.gprs_offset;
+ offset += index * UNITS_PER_WORD;
+ break;
- if (! current_function_is_leaf
- || fsize > 0
- || current_function_calls_alloca
- || current_function_stdarg)
- fsize += STARTING_FRAME_OFFSET;
- return fsize + STACK_POINTER_OFFSET;
+ case BASE_REGNUM:
+ offset = 0;
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return offset;
}
/* Emit insn to save fpr REGNUM at offset OFFSET relative
@@ -5409,7 +6952,11 @@ save_fpr (rtx base, int offset, int regnum)
{
rtx addr;
addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
- set_mem_alias_set (addr, s390_sr_alias_set);
+
+ if (regnum >= 16 && regnum <= (16 + FP_ARG_NUM_REG))
+ set_mem_alias_set (addr, get_varargs_alias_set ());
+ else
+ set_mem_alias_set (addr, get_frame_alias_set ());
return emit_move_insn (addr, gen_rtx_REG (DFmode, regnum));
}
@@ -5422,7 +6969,7 @@ restore_fpr (rtx base, int offset, int regnum)
{
rtx addr;
addr = gen_rtx_MEM (DFmode, plus_constant (base, offset));
- set_mem_alias_set (addr, s390_sr_alias_set);
+ set_mem_alias_set (addr, get_frame_alias_set ());
return emit_move_insn (gen_rtx_REG (DFmode, regnum), addr);
}
@@ -5437,9 +6984,10 @@ save_gprs (rtx base, int offset, int first, int last)
rtx addr, insn, note;
int i;
- addr = plus_constant (base, offset + first * UNITS_PER_WORD);
+ addr = plus_constant (base, offset);
addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
+
+ set_mem_alias_set (addr, get_frame_alias_set ());
/* Special-case single register. */
if (first == last)
@@ -5458,6 +7006,14 @@ save_gprs (rtx base, int offset, int first, int last)
gen_rtx_REG (Pmode, first),
GEN_INT (last - first + 1));
+ if (first <= 6 && current_function_stdarg)
+ for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
+ {
+ rtx mem = XEXP (XVECEXP (PATTERN (insn), 0, i), 0);
+
+ if (first + i <= 6)
+ set_mem_alias_set (mem, get_varargs_alias_set ());
+ }
/* We need to set the FRAME_RELATED flag on all SETs
inside the store-multiple pattern.
@@ -5465,7 +7021,7 @@ save_gprs (rtx base, int offset, int first, int last)
However, we must not emit DWARF records for registers 2..5
if they are stored for use by variable arguments ...
- ??? Unfortunately, it is not enough to simply not the the
+ ??? Unfortunately, it is not enough to simply not the
FRAME_RELATED flags for those SETs, because the first SET
of the PARALLEL is always treated as if it had the flag
set, even if it does not. Therefore we emit a new pattern
@@ -5483,7 +7039,7 @@ save_gprs (rtx base, int offset, int first, int last)
}
else if (last >= 6)
{
- addr = plus_constant (base, offset + 6 * UNITS_PER_WORD);
+ addr = plus_constant (base, offset + (6 - first) * UNITS_PER_WORD);
note = gen_store_multiple (gen_rtx_MEM (Pmode, addr),
gen_rtx_REG (Pmode, 6),
GEN_INT (last - 6 + 1));
@@ -5512,9 +7068,9 @@ restore_gprs (rtx base, int offset, int first, int last)
{
rtx addr, insn;
- addr = plus_constant (base, offset + first * UNITS_PER_WORD);
+ addr = plus_constant (base, offset);
addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
+ set_mem_alias_set (addr, get_frame_alias_set ());
/* Special-case single register. */
if (first == last)
@@ -5533,49 +7089,47 @@ restore_gprs (rtx base, int offset, int first, int last)
return insn;
}
-/* Emit code to load the GOT register. If MAYBE_DEAD is true,
- annotate generated insns with REG_MAYBE_DEAD notes. */
+/* Return insn sequence to load the GOT register. */
static GTY(()) rtx got_symbol;
-void
-s390_load_got (int maybe_dead)
+rtx
+s390_load_got (void)
{
+ rtx insns;
+
if (!got_symbol)
{
got_symbol = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
SYMBOL_REF_FLAGS (got_symbol) = SYMBOL_FLAG_LOCAL;
}
+ start_sequence ();
+
if (TARGET_CPU_ZARCH)
{
- rtx insn = emit_move_insn (pic_offset_table_rtx, got_symbol);
- if (maybe_dead)
- REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
- REG_NOTES (insn));
+ emit_move_insn (pic_offset_table_rtx, got_symbol);
}
else
{
- rtx offset, insn;
+ rtx offset;
offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, got_symbol),
UNSPEC_LTREL_OFFSET);
offset = gen_rtx_CONST (Pmode, offset);
offset = force_const_mem (Pmode, offset);
- insn = emit_move_insn (pic_offset_table_rtx, offset);
- if (maybe_dead)
- REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
- REG_NOTES (insn));
+ emit_move_insn (pic_offset_table_rtx, offset);
offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (offset, 0)),
UNSPEC_LTREL_BASE);
offset = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, offset);
- insn = emit_move_insn (pic_offset_table_rtx, offset);
- if (maybe_dead)
- REG_NOTES(insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
- REG_NOTES (insn));
+ emit_move_insn (pic_offset_table_rtx, offset);
}
+
+ insns = get_insns ();
+ end_sequence ();
+ return insns;
}
/* Expand the prologue into a bunch of separate insns. */
@@ -5586,90 +7140,179 @@ s390_emit_prologue (void)
rtx insn, addr;
rtx temp_reg;
int i;
+ int offset;
+ int next_fpr = 0;
+
+ /* Complete frame layout. */
+
+ s390_update_frame_layout ();
- /* Compute frame_info. */
+ /* Annotate all constant pool references to let the scheduler know
+ they implicitly use the base register. */
- s390_frame_info ();
+ push_topmost_sequence ();
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ if (INSN_P (insn))
+ annotate_constant_pool_refs (&PATTERN (insn));
+
+ pop_topmost_sequence ();
/* Choose best register to use for temp use within prologue.
See below for why TPF must use the register 1. */
- if (!current_function_is_leaf
- && !TARGET_TPF)
+ if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
+ && !current_function_is_leaf
+ && !TARGET_TPF_PROFILING)
temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
else
temp_reg = gen_rtx_REG (Pmode, 1);
/* Save call saved gprs. */
-
- insn = save_gprs (stack_pointer_rtx, 0,
- cfun->machine->first_save_gpr, cfun->machine->last_save_gpr);
- emit_insn (insn);
+ if (cfun_frame_layout.first_save_gpr != -1)
+ {
+ insn = save_gprs (stack_pointer_rtx,
+ cfun_frame_layout.gprs_offset +
+ UNITS_PER_WORD * (cfun_frame_layout.first_save_gpr
+ - cfun_frame_layout.first_save_gpr_slot),
+ cfun_frame_layout.first_save_gpr,
+ cfun_frame_layout.last_save_gpr);
+ emit_insn (insn);
+ }
/* Dummy insn to mark literal pool slot. */
- emit_insn (gen_main_pool ());
-
- /* Save fprs for variable args. */
+ if (cfun->machine->base_reg)
+ emit_insn (gen_main_pool (cfun->machine->base_reg));
- if (current_function_stdarg)
- for (i = 16; i < (TARGET_64BIT ? 20 : 18); i++)
- save_fpr (stack_pointer_rtx, 16*UNITS_PER_WORD + 8*(i-16), i);
+ offset = cfun_frame_layout.f0_offset;
- /* Save fprs 4 and 6 if used (31 bit ABI). */
+ /* Save f0 and f2. */
+ for (i = 0; i < 2; i++)
+ {
+ if (cfun_fpr_bit_p (i))
+ {
+ save_fpr (stack_pointer_rtx, offset, i + 16);
+ offset += 8;
+ }
+ else if (!TARGET_PACKED_STACK)
+ offset += 8;
+ }
- if (!TARGET_64BIT)
- for (i = 18; i < 20; i++)
- if (regs_ever_live[i] && !global_regs[i])
+ /* Save f4 and f6. */
+ offset = cfun_frame_layout.f4_offset;
+ for (i = 2; i < 4; i++)
+ {
+ if (cfun_fpr_bit_p (i))
{
- insn = save_fpr (stack_pointer_rtx, 16*UNITS_PER_WORD + 8*(i-16), i);
- RTX_FRAME_RELATED_P (insn) = 1;
+ insn = save_fpr (stack_pointer_rtx, offset, i + 16);
+ offset += 8;
+
+ /* If f4 and f6 are call clobbered they are saved due to stdargs and
+ therefore are not frame related. */
+ if (!call_really_used_regs[i + 16])
+ RTX_FRAME_RELATED_P (insn) = 1;
}
+ else if (!TARGET_PACKED_STACK)
+ offset += 8;
+ }
+
+ if (TARGET_PACKED_STACK
+ && cfun_save_high_fprs_p
+ && cfun_frame_layout.f8_offset + cfun_frame_layout.high_fprs * 8 > 0)
+ {
+ offset = (cfun_frame_layout.f8_offset
+ + (cfun_frame_layout.high_fprs - 1) * 8);
+
+ for (i = 15; i > 7 && offset >= 0; i--)
+ if (cfun_fpr_bit_p (i))
+ {
+ insn = save_fpr (stack_pointer_rtx, offset, i + 16);
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ offset -= 8;
+ }
+ if (offset >= cfun_frame_layout.f8_offset)
+ next_fpr = i + 16;
+ }
+
+ if (!TARGET_PACKED_STACK)
+ next_fpr = cfun_save_high_fprs_p ? 31 : 0;
/* Decrement stack pointer. */
- if (cfun->machine->frame_size > 0)
+ if (cfun_frame_layout.frame_size > 0)
{
- rtx frame_off = GEN_INT (-cfun->machine->frame_size);
+ rtx frame_off = GEN_INT (-cfun_frame_layout.frame_size);
- /* Save incoming stack pointer into temp reg. */
+ if (s390_stack_size)
+ {
+ HOST_WIDE_INT stack_check_mask = ((s390_stack_size - 1)
+ & ~(s390_stack_guard - 1));
+ rtx t = gen_rtx_AND (Pmode, stack_pointer_rtx,
+ GEN_INT (stack_check_mask));
- if (TARGET_BACKCHAIN || cfun->machine->save_fprs_p)
- {
- insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
- }
+ if (TARGET_64BIT)
+ gen_cmpdi (t, const0_rtx);
+ else
+ gen_cmpsi (t, const0_rtx);
+
+ emit_insn (gen_conditional_trap (gen_rtx_EQ (CCmode,
+ gen_rtx_REG (CCmode,
+ CC_REGNUM),
+ const0_rtx),
+ const0_rtx));
+ }
+
+ if (s390_warn_framesize > 0
+ && cfun_frame_layout.frame_size >= s390_warn_framesize)
+ warning (0, "frame size of %qs is " HOST_WIDE_INT_PRINT_DEC " bytes",
+ current_function_name (), cfun_frame_layout.frame_size);
+
+ if (s390_warn_dynamicstack_p && cfun->calls_alloca)
+ warning (0, "%qs uses dynamic stack allocation", current_function_name ());
+
+ /* Save incoming stack pointer into temp reg. */
+ if (TARGET_BACKCHAIN || next_fpr)
+ insn = emit_insn (gen_move_insn (temp_reg, stack_pointer_rtx));
/* Subtract frame size from stack pointer. */
if (DISP_IN_RANGE (INTVAL (frame_off)))
{
insn = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
frame_off));
insn = emit_insn (insn);
}
else
{
- if (!CONST_OK_FOR_CONSTRAINT_P (INTVAL (frame_off), 'K', "K"))
+ if (!CONST_OK_FOR_K (INTVAL (frame_off)))
frame_off = force_const_mem (Pmode, frame_off);
insn = emit_insn (gen_add2_insn (stack_pointer_rtx, frame_off));
+ annotate_constant_pool_refs (&PATTERN (insn));
}
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) =
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- GEN_INT (-cfun->machine->frame_size))),
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ GEN_INT (-cfun_frame_layout.frame_size))),
REG_NOTES (insn));
/* Set backchain. */
if (TARGET_BACKCHAIN)
{
- addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
- set_mem_alias_set (addr, s390_sr_alias_set);
+ if (cfun_frame_layout.backchain_offset)
+ addr = gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
+ cfun_frame_layout.backchain_offset));
+ else
+ addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
+ set_mem_alias_set (addr, get_frame_alias_set ());
insn = emit_insn (gen_move_insn (addr, temp_reg));
}
@@ -5686,24 +7329,30 @@ s390_emit_prologue (void)
/* Save fprs 8 - 15 (64 bit ABI). */
- if (cfun->machine->save_fprs_p)
+ if (cfun_save_high_fprs_p && next_fpr)
{
- insn = emit_insn (gen_add2_insn (temp_reg, GEN_INT(-64)));
+ insn = emit_insn (gen_add2_insn (temp_reg,
+ GEN_INT (cfun_frame_layout.f8_offset)));
- for (i = 24; i < 32; i++)
- if (regs_ever_live[i] && !global_regs[i])
+ offset = 0;
+
+ for (i = 24; i <= next_fpr; i++)
+ if (cfun_fpr_bit_p (i - 16))
{
rtx addr = plus_constant (stack_pointer_rtx,
- cfun->machine->frame_size - 64 + (i-24)*8);
-
- insn = save_fpr (temp_reg, (i-24)*8, i);
+ cfun_frame_layout.frame_size
+ + cfun_frame_layout.f8_offset
+ + offset);
+
+ insn = save_fpr (temp_reg, offset, i);
+ offset += 8;
RTX_FRAME_RELATED_P (insn) = 1;
REG_NOTES (insn) =
gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
- gen_rtx_SET (VOIDmode,
- gen_rtx_MEM (DFmode, addr),
- gen_rtx_REG (DFmode, i)),
- REG_NOTES (insn));
+ gen_rtx_SET (VOIDmode,
+ gen_rtx_MEM (DFmode, addr),
+ gen_rtx_REG (DFmode, i)),
+ REG_NOTES (insn));
}
}
@@ -5718,24 +7367,26 @@ s390_emit_prologue (void)
/* Set up got pointer, if needed. */
if (flag_pic && regs_ever_live[PIC_OFFSET_TABLE_REGNUM])
- s390_load_got(true);
-
- if (TARGET_TPF)
{
- /* Generate a BAS instruction to serve as a function
- entry intercept to facilitate the use of tracing
- algorithms located at the branch target.
+ rtx insns = s390_load_got ();
- This must use register 1. */
- rtx addr;
- rtx unkn;
- rtx link;
+ for (insn = insns; insn; insn = NEXT_INSN (insn))
+ {
+ annotate_constant_pool_refs (&PATTERN (insn));
- addr = GEN_INT (0xfe0);
- unkn = CONST0_RTX (SImode);
- link = gen_rtx_REG (Pmode, 1);
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, NULL_RTX,
+ REG_NOTES (insn));
+ }
- emit_call_insn (gen_call_exp (gen_rtx_MEM (QImode, addr), unkn, link));
+ emit_insn (insns);
+ }
+
+ if (TARGET_TPF_PROFILING)
+ {
+ /* Generate a BAS instruction to serve as a function
+ entry intercept to facilitate the use of tracing
+ algorithms located at the branch target. */
+ emit_insn (gen_prologue_tpf ());
/* Emit a blockage here so that all code
lies between the profiling mechanisms. */
@@ -5746,76 +7397,34 @@ s390_emit_prologue (void)
/* Expand the epilogue into a bunch of separate insns. */
void
-s390_emit_epilogue (void)
+s390_emit_epilogue (bool sibcall)
{
rtx frame_pointer, return_reg;
int area_bottom, area_top, offset = 0;
+ int next_offset;
rtvec p;
int i;
- if (TARGET_TPF)
+ if (TARGET_TPF_PROFILING)
{
/* Generate a BAS instruction to serve as a function
entry intercept to facilitate the use of tracing
- algorithms located at the branch target.
-
- This must use register 1. */
-
- rtx addr;
- rtx unkn;
- rtx link;
-
- addr = GEN_INT (0xfe6);
- unkn = CONST0_RTX (SImode);
- link = gen_rtx_REG (Pmode, 1);
+ algorithms located at the branch target. */
/* Emit a blockage here so that all code
lies between the profiling mechanisms. */
emit_insn (gen_blockage ());
- emit_call_insn (gen_call_exp (gen_rtx_MEM (QImode, addr), unkn, link));
+ emit_insn (gen_epilogue_tpf ());
}
/* Check whether to use frame or stack pointer for restore. */
- frame_pointer = frame_pointer_needed ?
- hard_frame_pointer_rtx : stack_pointer_rtx;
+ frame_pointer = (frame_pointer_needed
+ ? hard_frame_pointer_rtx : stack_pointer_rtx);
- /* Compute which parts of the save area we need to access. */
-
- if (cfun->machine->first_restore_gpr != -1)
- {
- area_bottom = cfun->machine->first_restore_gpr * UNITS_PER_WORD;
- area_top = (cfun->machine->last_save_gpr + 1) * UNITS_PER_WORD;
- }
- else
- {
- area_bottom = INT_MAX;
- area_top = INT_MIN;
- }
-
- if (TARGET_64BIT)
- {
- if (cfun->machine->save_fprs_p)
- {
- if (area_bottom > -64)
- area_bottom = -64;
- if (area_top < 0)
- area_top = 0;
- }
- }
- else
- {
- for (i = 18; i < 20; i++)
- if (regs_ever_live[i] && !global_regs[i])
- {
- if (area_bottom > 16*UNITS_PER_WORD + 8*(i-16))
- area_bottom = 16*UNITS_PER_WORD + 8*(i-16);
- if (area_top < 16*UNITS_PER_WORD + 8*(i-16) + 8)
- area_top = 16*UNITS_PER_WORD + 8*(i-16) + 8;
- }
- }
+ s390_frame_area (&area_bottom, &area_top);
/* Check whether we can access the register save area.
If not, increment the frame pointer as required. */
@@ -5824,18 +7433,18 @@ s390_emit_epilogue (void)
{
/* Nothing to restore. */
}
- else if (DISP_IN_RANGE (cfun->machine->frame_size + area_bottom)
- && DISP_IN_RANGE (cfun->machine->frame_size + area_top-1))
+ else if (DISP_IN_RANGE (cfun_frame_layout.frame_size + area_bottom)
+ && DISP_IN_RANGE (cfun_frame_layout.frame_size + area_top - 1))
{
/* Area is in range. */
- offset = cfun->machine->frame_size;
+ offset = cfun_frame_layout.frame_size;
}
else
{
rtx insn, frame_off;
offset = area_bottom < 0 ? -area_bottom : 0;
- frame_off = GEN_INT (cfun->machine->frame_size - offset);
+ frame_off = GEN_INT (cfun_frame_layout.frame_size - offset);
if (DISP_IN_RANGE (INTVAL (frame_off)))
{
@@ -5845,10 +7454,11 @@ s390_emit_epilogue (void)
}
else
{
- if (!CONST_OK_FOR_CONSTRAINT_P (INTVAL (frame_off), 'K', "K"))
+ if (!CONST_OK_FOR_K (INTVAL (frame_off)))
frame_off = force_const_mem (Pmode, frame_off);
insn = emit_insn (gen_add2_insn (frame_pointer, frame_off));
+ annotate_constant_pool_refs (&PATTERN (insn));
}
}
@@ -5856,18 +7466,36 @@ s390_emit_epilogue (void)
if (TARGET_64BIT)
{
- if (cfun->machine->save_fprs_p)
- for (i = 24; i < 32; i++)
- if (regs_ever_live[i] && !global_regs[i])
- restore_fpr (frame_pointer,
- offset - 64 + (i-24) * 8, i);
+ if (cfun_save_high_fprs_p)
+ {
+ next_offset = cfun_frame_layout.f8_offset;
+ for (i = 24; i < 32; i++)
+ {
+ if (cfun_fpr_bit_p (i - 16))
+ {
+ restore_fpr (frame_pointer,
+ offset + next_offset, i);
+ next_offset += 8;
+ }
+ }
+ }
+
}
else
{
+ next_offset = cfun_frame_layout.f4_offset;
for (i = 18; i < 20; i++)
- if (regs_ever_live[i] && !global_regs[i])
- restore_fpr (frame_pointer,
- offset + 16*UNITS_PER_WORD + 8*(i-16), i);
+ {
+ if (cfun_fpr_bit_p (i - 16))
+ {
+ restore_fpr (frame_pointer,
+ offset + next_offset, i);
+ next_offset += 8;
+ }
+ else if (!TARGET_PACKED_STACK)
+ next_offset += 8;
+ }
+
}
/* Return register. */
@@ -5876,7 +7504,7 @@ s390_emit_epilogue (void)
/* Restore call saved gprs. */
- if (cfun->machine->first_restore_gpr != -1)
+ if (cfun_frame_layout.first_restore_gpr != -1)
{
rtx insn, addr;
int i;
@@ -5884,66 +7512,76 @@ s390_emit_epilogue (void)
/* Check for global register and save them
to stack location from where they get restored. */
- for (i = cfun->machine->first_restore_gpr;
- i <= cfun->machine->last_save_gpr;
+ for (i = cfun_frame_layout.first_restore_gpr;
+ i <= cfun_frame_layout.last_restore_gpr;
i++)
{
/* These registers are special and need to be
restored in any case. */
if (i == STACK_POINTER_REGNUM
|| i == RETURN_REGNUM
- || i == BASE_REGISTER
+ || i == BASE_REGNUM
|| (flag_pic && i == (int)PIC_OFFSET_TABLE_REGNUM))
continue;
if (global_regs[i])
{
addr = plus_constant (frame_pointer,
- offset + i * UNITS_PER_WORD);
+ offset + cfun_frame_layout.gprs_offset
+ + (i - cfun_frame_layout.first_save_gpr_slot)
+ * UNITS_PER_WORD);
addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
+ set_mem_alias_set (addr, get_frame_alias_set ());
emit_move_insn (addr, gen_rtx_REG (Pmode, i));
}
}
- /* Fetch return address from stack before load multiple,
- this will do good for scheduling. */
-
- if (cfun->machine->save_return_addr_p
- || (cfun->machine->first_restore_gpr < BASE_REGISTER
- && cfun->machine->last_save_gpr > RETURN_REGNUM))
+ if (! sibcall)
{
- int return_regnum = find_unused_clobbered_reg();
- if (!return_regnum)
- return_regnum = 4;
- return_reg = gen_rtx_REG (Pmode, return_regnum);
-
- addr = plus_constant (frame_pointer,
- offset + RETURN_REGNUM * UNITS_PER_WORD);
- addr = gen_rtx_MEM (Pmode, addr);
- set_mem_alias_set (addr, s390_sr_alias_set);
- emit_move_insn (return_reg, addr);
- }
+ /* Fetch return address from stack before load multiple,
+ this will do good for scheduling. */
- /* ??? As references to the base register are not made
- explicit in insn RTX code, we have to add a barrier here
- to prevent incorrect scheduling. */
+ if (cfun_frame_layout.save_return_addr_p
+ || (cfun_frame_layout.first_restore_gpr < BASE_REGNUM
+ && cfun_frame_layout.last_restore_gpr > RETURN_REGNUM))
+ {
+ int return_regnum = find_unused_clobbered_reg();
+ if (!return_regnum)
+ return_regnum = 4;
+ return_reg = gen_rtx_REG (Pmode, return_regnum);
- emit_insn (gen_blockage());
+ addr = plus_constant (frame_pointer,
+ offset + cfun_frame_layout.gprs_offset
+ + (RETURN_REGNUM
+ - cfun_frame_layout.first_save_gpr_slot)
+ * UNITS_PER_WORD);
+ addr = gen_rtx_MEM (Pmode, addr);
+ set_mem_alias_set (addr, get_frame_alias_set ());
+ emit_move_insn (return_reg, addr);
+ }
+ }
- insn = restore_gprs (frame_pointer, offset,
- cfun->machine->first_restore_gpr,
- cfun->machine->last_save_gpr);
+ insn = restore_gprs (frame_pointer,
+ offset + cfun_frame_layout.gprs_offset
+ + (cfun_frame_layout.first_restore_gpr
+ - cfun_frame_layout.first_save_gpr_slot)
+ * UNITS_PER_WORD,
+ cfun_frame_layout.first_restore_gpr,
+ cfun_frame_layout.last_restore_gpr);
emit_insn (insn);
}
- /* Return to caller. */
+ if (! sibcall)
+ {
+
+ /* Return to caller. */
- p = rtvec_alloc (2);
+ p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
- RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
- emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ RTVEC_ELT (p, 0) = gen_rtx_RETURN (VOIDmode);
+ RTVEC_ELT (p, 1) = gen_rtx_USE (VOIDmode, return_reg);
+ emit_jump_insn (gen_rtx_PARALLEL (VOIDmode, p));
+ }
}
@@ -5962,7 +7600,7 @@ s390_function_arg_size (enum machine_mode mode, tree type)
return GET_MODE_SIZE (mode);
/* If we have neither type nor mode, abort */
- abort ();
+ gcc_unreachable ();
}
/* Return true if a function argument of type TYPE and mode MODE
@@ -5981,7 +7619,7 @@ s390_function_arg_float (enum machine_mode mode, tree type)
/* No type info available for some library calls ... */
if (!type)
- return mode == SFmode || mode == DFmode;
+ return mode == SFmode || mode == DFmode || mode == SDmode || mode == DDmode;
/* The ABI says that record types with a single member are treated
just like that member would be. */
@@ -6023,17 +7661,17 @@ s390_function_arg_integer (enum machine_mode mode, tree type)
/* No type info available for some library calls ... */
if (!type)
return GET_MODE_CLASS (mode) == MODE_INT
- || (TARGET_SOFT_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT);
+ || (TARGET_SOFT_FLOAT && SCALAR_FLOAT_MODE_P (mode));
/* We accept small integral (and similar) types. */
if (INTEGRAL_TYPE_P (type)
- || POINTER_TYPE_P (type)
+ || POINTER_TYPE_P (type)
|| TREE_CODE (type) == OFFSET_TYPE
|| (TARGET_SOFT_FLOAT && TREE_CODE (type) == REAL_TYPE))
return true;
/* We also accept structs of size 1, 2, 4, 8 that are not
- passed in floating-point registers. */
+ passed in floating-point registers. */
if (AGGREGATE_TYPE_P (type)
&& exact_log2 (size) >= 0
&& !s390_function_arg_float (mode, type))
@@ -6048,8 +7686,10 @@ s390_function_arg_integer (enum machine_mode mode, tree type)
all other structures (and complex numbers) are passed by
reference. */
-int
-s390_function_arg_pass_by_reference (enum machine_mode mode, tree type)
+static bool
+s390_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
{
int size = s390_function_arg_size (mode, type);
if (size > 8)
@@ -6078,11 +7718,7 @@ void
s390_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
tree type, int named ATTRIBUTE_UNUSED)
{
- if (s390_function_arg_pass_by_reference (mode, type))
- {
- cum->gprs += 1;
- }
- else if (s390_function_arg_float (mode, type))
+ if (s390_function_arg_float (mode, type))
{
cum->fprs += 1;
}
@@ -6092,7 +7728,7 @@ s390_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
cum->gprs += ((size + UNITS_PER_WORD-1) / UNITS_PER_WORD);
}
else
- abort ();
+ gcc_unreachable ();
}
/* Define where to put the arguments to a function.
@@ -6118,25 +7754,22 @@ rtx
s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
int named ATTRIBUTE_UNUSED)
{
- if (s390_function_arg_pass_by_reference (mode, type))
- return 0;
-
if (s390_function_arg_float (mode, type))
{
- if (cum->fprs + 1 > (TARGET_64BIT? 4 : 2))
+ if (cum->fprs + 1 > FP_ARG_NUM_REG)
return 0;
else
- return gen_rtx (REG, mode, cum->fprs + 16);
+ return gen_rtx_REG (mode, cum->fprs + 16);
}
else if (s390_function_arg_integer (mode, type))
{
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)
+ if (cum->gprs + n_gprs > GP_ARG_NUM_REG)
return 0;
else
- return gen_rtx (REG, mode, cum->gprs + 2);
+ return gen_rtx_REG (mode, cum->gprs + 2);
}
/* After the real arguments, expand_call calls us once again
@@ -6147,7 +7780,7 @@ s390_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
else if (type == void_type_node)
return const0_rtx;
- abort ();
+ gcc_unreachable ();
}
/* Return true if return values of type TYPE should be returned
@@ -6159,7 +7792,7 @@ s390_return_in_memory (tree type, tree fundecl ATTRIBUTE_UNUSED)
{
/* We accept small integral (and similar) types. */
if (INTEGRAL_TYPE_P (type)
- || POINTER_TYPE_P (type)
+ || POINTER_TYPE_P (type)
|| TREE_CODE (type) == OFFSET_TYPE
|| TREE_CODE (type) == REAL_TYPE)
return int_size_in_bytes (type) > 8;
@@ -6186,17 +7819,14 @@ s390_function_value (tree type, enum machine_mode mode)
{
if (type)
{
- int unsignedp = TREE_UNSIGNED (type);
+ int unsignedp = TYPE_UNSIGNED (type);
mode = promote_mode (type, TYPE_MODE (type), &unsignedp, 1);
}
- if (GET_MODE_CLASS (mode) != MODE_INT
- && GET_MODE_CLASS (mode) != MODE_FLOAT)
- abort ();
- if (GET_MODE_SIZE (mode) > 8)
- abort ();
+ gcc_assert (GET_MODE_CLASS (mode) == MODE_INT || SCALAR_FLOAT_MODE_P (mode));
+ gcc_assert (GET_MODE_SIZE (mode) <= 8);
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if (TARGET_HARD_FLOAT && SCALAR_FLOAT_MODE_P (mode))
return gen_rtx_REG (mode, 16);
else
return gen_rtx_REG (mode, 2);
@@ -6243,6 +7873,9 @@ s390_build_builtin_va_list (void)
f_sav = build_decl (FIELD_DECL, get_identifier ("__reg_save_area"),
ptr_type_node);
+ va_list_gpr_counter_field = f_gpr;
+ va_list_fpr_counter_field = f_fpr;
+
DECL_FIELD_CONTEXT (f_gpr) = record;
DECL_FIELD_CONTEXT (f_fpr) = record;
DECL_FIELD_CONTEXT (f_ovf) = record;
@@ -6287,47 +7920,64 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
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);
+ valist = build_va_arg_indirect_ref (valist);
+ gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+ fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+ ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+ sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
/* 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);
+ if (cfun->va_list_gpr_size)
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (gpr), gpr,
+ build_int_cst (NULL_TREE, n_gpr));
+ 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);
+ if (cfun->va_list_fpr_size)
+ {
+ t = build2 (MODIFY_EXPR, TREE_TYPE (fpr), fpr,
+ build_int_cst (NULL_TREE, n_fpr));
+ 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);
+ if (n_gpr + cfun->va_list_gpr_size > GP_ARG_NUM_REG
+ || n_fpr + cfun->va_list_fpr_size > FP_ARG_NUM_REG)
+ {
+ t = make_tree (TREE_TYPE (ovf), virtual_incoming_args_rtx);
- off = INTVAL (current_function_arg_offset_rtx);
- off = off < 0 ? 0 : off;
- if (TARGET_DEBUG_ARG)
- fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
- (int)n_gpr, (int)n_fpr, off);
+ off = INTVAL (current_function_arg_offset_rtx);
+ off = off < 0 ? 0 : off;
+ if (TARGET_DEBUG_ARG)
+ fprintf (stderr, "va_start: n_gpr = %d, n_fpr = %d off %d\n",
+ (int)n_gpr, (int)n_fpr, off);
- t = build (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_2 (off, 0));
+ t = build2 (PLUS_EXPR, TREE_TYPE (ovf), t, build_int_cst (NULL_TREE, off));
- t = build (MODIFY_EXPR, TREE_TYPE (ovf), ovf, t);
- TREE_SIDE_EFFECTS (t) = 1;
- expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ t = build2 (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);
+ if ((cfun->va_list_gpr_size && n_gpr < GP_ARG_NUM_REG)
+ || (cfun->va_list_fpr_size && n_fpr < FP_ARG_NUM_REG))
+ {
+ t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
+ t = build2 (PLUS_EXPR, TREE_TYPE (sav), t,
+ build_int_cst (NULL_TREE, -RETURN_REGNUM * UNITS_PER_WORD));
+
+ t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
+ TREE_SIDE_EFFECTS (t) = 1;
+ expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
+ }
}
/* Implement va_arg by updating the va_list structure
@@ -6354,28 +8004,29 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
ret = **args.overflow_arg_area++;
} */
-rtx
-s390_va_arg (tree valist, tree type)
+static tree
+s390_gimplify_va_arg (tree valist, tree type, tree *pre_p,
+ tree *post_p ATTRIBUTE_UNUSED)
{
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;
+ tree lab_false, lab_over, addr;
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);
+ valist = build_va_arg_indirect_ref (valist);
+ gpr = build3 (COMPONENT_REF, TREE_TYPE (f_gpr), valist, f_gpr, NULL_TREE);
+ fpr = build3 (COMPONENT_REF, TREE_TYPE (f_fpr), valist, f_fpr, NULL_TREE);
+ ovf = build3 (COMPONENT_REF, TREE_TYPE (f_ovf), valist, f_ovf, NULL_TREE);
+ sav = build3 (COMPONENT_REF, TREE_TYPE (f_sav), valist, f_sav, NULL_TREE);
size = int_size_in_bytes (type);
- if (s390_function_arg_pass_by_reference (TYPE_MODE (type), type))
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
if (TARGET_DEBUG_ARG)
{
@@ -6387,10 +8038,14 @@ s390_va_arg (tree valist, tree type)
indirect_p = 1;
reg = gpr;
n_reg = 1;
+
+ /* kernel stack layout on 31 bit: It is assumed here that no padding
+ will be added by s390_frame_info because for va_args always an even
+ number of gprs has to be saved r15-r2 = 14 regs. */
sav_ofs = 2 * UNITS_PER_WORD;
sav_scale = UNITS_PER_WORD;
size = UNITS_PER_WORD;
- max_reg = 4;
+ max_reg = GP_ARG_NUM_REG - n_reg;
}
else if (s390_function_arg_float (TYPE_MODE (type), type))
{
@@ -6406,8 +8061,7 @@ s390_va_arg (tree valist, tree type)
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;
+ max_reg = FP_ARG_NUM_REG - n_reg;
}
else
{
@@ -6421,93 +8075,88 @@ s390_va_arg (tree valist, tree type)
indirect_p = 0;
reg = gpr;
n_reg = (size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+ /* kernel stack layout on 31 bit: It is assumed here that no padding
+ will be added by s390_frame_info because for va_args always an even
+ number of gprs has to be saved r15-r2 = 14 regs. */
sav_ofs = 2 * UNITS_PER_WORD;
if (size < UNITS_PER_WORD)
sav_ofs += UNITS_PER_WORD - size;
sav_scale = UNITS_PER_WORD;
- if (n_reg > 1)
- max_reg = 3;
- else
- max_reg = 4;
+ max_reg = GP_ARG_NUM_REG - n_reg;
}
/* Pull the value out of the saved registers ... */
- lab_false = gen_label_rtx ();
- lab_over = gen_label_rtx ();
- addr_rtx = gen_reg_rtx (Pmode);
+ lab_false = create_artificial_label ();
+ lab_over = create_artificial_label ();
+ addr = create_tmp_var (ptr_type_node, "addr");
+ DECL_POINTER_ALIAS_SET (addr) = get_varargs_alias_set ();
- emit_cmp_and_jump_insns (expand_expr (reg, NULL_RTX, Pmode, EXPAND_NORMAL),
- GEN_INT (max_reg),
- GT, const1_rtx, Pmode, 0, lab_false);
-
- if (sav_ofs)
- t = build (PLUS_EXPR, ptr_type_node, sav, build_int_2 (sav_ofs, 0));
- else
- t = sav;
+ t = fold_convert (TREE_TYPE (reg), size_int (max_reg));
+ t = build2 (GT_EXPR, boolean_type_node, reg, t);
+ u = build1 (GOTO_EXPR, void_type_node, lab_false);
+ t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
+ gimplify_and_add (t, pre_p);
- u = build (MULT_EXPR, long_integer_type_node,
- reg, build_int_2 (sav_scale, 0));
- TREE_SIDE_EFFECTS (u) = 1;
+ t = build2 (PLUS_EXPR, ptr_type_node, sav,
+ fold_convert (ptr_type_node, size_int (sav_ofs)));
+ u = build2 (MULT_EXPR, TREE_TYPE (reg), reg,
+ fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
+ t = build2 (PLUS_EXPR, ptr_type_node, t, fold_convert (ptr_type_node, u));
- t = build (PLUS_EXPR, ptr_type_node, t, u);
- TREE_SIDE_EFFECTS (t) = 1;
+ t = build2 (MODIFY_EXPR, void_type_node, addr, t);
+ gimplify_and_add (t, pre_p);
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ t = build1 (GOTO_EXPR, void_type_node, lab_over);
+ gimplify_and_add (t, pre_p);
+ t = build1 (LABEL_EXPR, void_type_node, lab_false);
+ append_to_statement_list (t, pre_p);
- 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. */
+ t = ovf;
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 = build2 (PLUS_EXPR, ptr_type_node, t,
+ fold_convert (ptr_type_node, size_int (UNITS_PER_WORD - size)));
- t = save_expr (ovf);
- }
+ gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
+
+ u = build2 (MODIFY_EXPR, void_type_node, addr, t);
+ gimplify_and_add (u, pre_p);
- r = expand_expr (t, addr_rtx, Pmode, EXPAND_NORMAL);
- if (r != addr_rtx)
- emit_move_insn (addr_rtx, r);
+ t = build2 (PLUS_EXPR, ptr_type_node, t,
+ fold_convert (ptr_type_node, size_int (size)));
+ t = build2 (MODIFY_EXPR, ptr_type_node, ovf, t);
+ gimplify_and_add (t, pre_p);
- 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);
+ t = build1 (LABEL_EXPR, void_type_node, lab_over);
+ append_to_statement_list (t, pre_p);
- emit_label (lab_over);
- /* If less than max_regs a registers are retrieved out
- of register save area, increment. */
+ /* Increment register save count. */
- 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);
+ u = build2 (PREINCREMENT_EXPR, TREE_TYPE (reg), reg,
+ fold_convert (TREE_TYPE (reg), size_int (n_reg)));
+ gimplify_and_add (u, pre_p);
if (indirect_p)
{
- r = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (r, get_varargs_alias_set ());
- emit_move_insn (addr_rtx, r);
+ t = build_pointer_type (build_pointer_type (type));
+ addr = fold_convert (t, addr);
+ addr = build_va_arg_indirect_ref (addr);
+ }
+ else
+ {
+ t = build_pointer_type (type);
+ addr = fold_convert (t, addr);
}
-
- return addr_rtx;
+ return build_va_arg_indirect_ref (addr);
}
@@ -6537,14 +8186,14 @@ s390_init_builtins (void)
tree ftype;
ftype = build_function_type (ptr_type_node, void_list_node);
- builtin_function ("__builtin_thread_pointer", ftype,
- S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
- NULL, NULL_TREE);
+ lang_hooks.builtin_function ("__builtin_thread_pointer", ftype,
+ S390_BUILTIN_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
ftype = build_function_type_list (void_type_node, ptr_type_node, NULL_TREE);
- builtin_function ("__builtin_set_thread_pointer", ftype,
- S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
- NULL, NULL_TREE);
+ lang_hooks.builtin_function ("__builtin_set_thread_pointer", ftype,
+ S390_BUILTIN_SET_THREAD_POINTER, BUILT_IN_MD,
+ NULL, NULL_TREE);
}
/* Expand an expression EXP that calls a built-in function,
@@ -6623,7 +8272,7 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
pat = GEN_FCN (icode) (target, op[0], op[1]);
break;
default:
- abort ();
+ gcc_unreachable ();
}
if (!pat)
return NULL_RTX;
@@ -6645,23 +8294,23 @@ s390_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
void
s390_trampoline_template (FILE *file)
{
+ rtx op[2];
+ op[0] = gen_rtx_REG (Pmode, 0);
+ op[1] = gen_rtx_REG (Pmode, 1);
+
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");
+ output_asm_insn ("basr\t%1,0", op);
+ output_asm_insn ("lmg\t%0,%1,14(%1)", op);
+ output_asm_insn ("br\t%1", op);
+ ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 10));
}
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");
+ output_asm_insn ("basr\t%1,0", op);
+ output_asm_insn ("lm\t%0,%1,6(%1)", op);
+ output_asm_insn ("br\t%1", op);
+ ASM_OUTPUT_SKIP (file, (HOST_WIDE_INT)(TRAMPOLINE_SIZE - 8));
}
}
@@ -6672,14 +8321,12 @@ s390_trampoline_template (FILE *file)
void
s390_initialize_trampoline (rtx addr, rtx fnaddr, rtx cxt)
{
- emit_move_insn (gen_rtx
- (MEM, Pmode,
+ 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,
+ plus_constant (addr, (TARGET_64BIT ? 16 : 8)))), cxt);
+ emit_move_insn (gen_rtx_MEM (Pmode,
memory_address (Pmode,
- plus_constant (addr, (TARGET_64BIT ? 28 : 16) ))), fnaddr);
+ plus_constant (addr, (TARGET_64BIT ? 24 : 12)))), fnaddr);
}
/* Return rtx for 64-bit constant formed from the 32-bit subwords
@@ -6699,7 +8346,7 @@ s390_gen_rtx_const_DI (int high, int low)
#if HOST_BITS_PER_WIDE_INT >= 32
return immed_double_const ((HOST_WIDE_INT)low, (HOST_WIDE_INT)high, DImode);
#else
- abort ();
+ gcc_unreachable ();
#endif
#endif
}
@@ -6772,20 +8419,6 @@ s390_function_profiler (FILE *file, int labelno)
}
}
-/* Select section for constant in constant pool. In 32-bit mode,
- constants go in the function section; in 64-bit mode in .rodata. */
-
-static void
-s390_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
- rtx x ATTRIBUTE_UNUSED,
- unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
-{
- if (TARGET_CPU_ZARCH)
- readonly_data_section ();
- else
- function_section (current_function_decl);
-}
-
/* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
into its SYMBOL_REF_FLAGS. */
@@ -6854,9 +8487,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
{
/* Setup literal pool pointer if required. */
if ((!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
+ && !CONST_OK_FOR_K (delta)
+ && !CONST_OK_FOR_Os (delta))
|| (!DISP_IN_RANGE (vcall_offset)
- && !CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K")))
+ && !CONST_OK_FOR_K (vcall_offset)
+ && !CONST_OK_FOR_Os (vcall_offset)))
{
op[5] = gen_label_rtx ();
output_asm_insn ("larl\t%4,%5", op);
@@ -6865,12 +8500,14 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Add DELTA to this pointer. */
if (delta)
{
- if (CONST_OK_FOR_CONSTRAINT_P (delta, 'J', "J"))
+ if (CONST_OK_FOR_J (delta))
output_asm_insn ("la\t%1,%2(%1)", op);
else if (DISP_IN_RANGE (delta))
output_asm_insn ("lay\t%1,%2(%1)", op);
- else if (CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
+ else if (CONST_OK_FOR_K (delta))
output_asm_insn ("aghi\t%1,%2", op);
+ else if (CONST_OK_FOR_Os (delta))
+ output_asm_insn ("agfi\t%1,%2", op);
else
{
op[6] = gen_label_rtx ();
@@ -6886,12 +8523,18 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
output_asm_insn ("lg\t%4,0(%1)", op);
output_asm_insn ("ag\t%1,%3(%4)", op);
}
- else if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K"))
+ else if (CONST_OK_FOR_K (vcall_offset))
{
output_asm_insn ("lghi\t%4,%3", op);
output_asm_insn ("ag\t%4,0(%1)", op);
output_asm_insn ("ag\t%1,0(%4)", op);
}
+ else if (CONST_OK_FOR_Os (vcall_offset))
+ {
+ output_asm_insn ("lgfi\t%4,%3", op);
+ output_asm_insn ("ag\t%4,0(%1)", op);
+ output_asm_insn ("ag\t%1,0(%4)", op);
+ }
else
{
op[7] = gen_label_rtx ();
@@ -6929,9 +8572,11 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Setup base pointer if required. */
if (!vcall_offset
|| (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
+ && !CONST_OK_FOR_K (delta)
+ && !CONST_OK_FOR_Os (delta))
|| (!DISP_IN_RANGE (delta)
- && !CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K")))
+ && !CONST_OK_FOR_K (vcall_offset)
+ && !CONST_OK_FOR_Os (vcall_offset)))
{
op[5] = gen_label_rtx ();
output_asm_insn ("basr\t%4,0", op);
@@ -6942,12 +8587,14 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Add DELTA to this pointer. */
if (delta)
{
- if (CONST_OK_FOR_CONSTRAINT_P (delta, 'J', "J"))
+ if (CONST_OK_FOR_J (delta))
output_asm_insn ("la\t%1,%2(%1)", op);
else if (DISP_IN_RANGE (delta))
output_asm_insn ("lay\t%1,%2(%1)", op);
- else if (CONST_OK_FOR_CONSTRAINT_P (delta, 'K', "K"))
+ else if (CONST_OK_FOR_K (delta))
output_asm_insn ("ahi\t%1,%2", op);
+ else if (CONST_OK_FOR_Os (delta))
+ output_asm_insn ("afi\t%1,%2", op);
else
{
op[6] = gen_label_rtx ();
@@ -6958,22 +8605,28 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
/* Perform vcall adjustment. */
if (vcall_offset)
{
- if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'J', "J"))
+ if (CONST_OK_FOR_J (vcall_offset))
{
- output_asm_insn ("lg\t%4,0(%1)", op);
+ output_asm_insn ("l\t%4,0(%1)", op);
output_asm_insn ("a\t%1,%3(%4)", op);
}
else if (DISP_IN_RANGE (vcall_offset))
{
- output_asm_insn ("lg\t%4,0(%1)", op);
+ output_asm_insn ("l\t%4,0(%1)", op);
output_asm_insn ("ay\t%1,%3(%4)", op);
}
- else if (CONST_OK_FOR_CONSTRAINT_P (vcall_offset, 'K', "K"))
+ else if (CONST_OK_FOR_K (vcall_offset))
{
output_asm_insn ("lhi\t%4,%3", op);
output_asm_insn ("a\t%4,0(%1)", op);
output_asm_insn ("a\t%1,0(%4)", op);
}
+ else if (CONST_OK_FOR_Os (vcall_offset))
+ {
+ output_asm_insn ("iilf\t%4,%3", op);
+ output_asm_insn ("a\t%4,0(%1)", op);
+ output_asm_insn ("a\t%1,0(%4)", op);
+ }
else
{
op[7] = gen_label_rtx ();
@@ -7046,18 +8699,630 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
}
}
-bool
+static bool
s390_valid_pointer_mode (enum machine_mode mode)
{
return (mode == SImode || (TARGET_64BIT && mode == DImode));
}
-/* How to allocate a 'struct machine_function'. */
+/* Checks whether the given ARGUMENT_LIST would use a caller
+ saved register. This is used to decide whether sibling call
+ optimization could be performed on the respective function
+ call. */
-static struct machine_function *
-s390_init_machine_status (void)
+static bool
+s390_call_saved_register_used (tree argument_list)
{
- return ggc_alloc_cleared (sizeof (struct machine_function));
+ CUMULATIVE_ARGS cum;
+ tree parameter;
+ enum machine_mode mode;
+ tree type;
+ rtx parm_rtx;
+ int reg;
+
+ INIT_CUMULATIVE_ARGS (cum, NULL, NULL, 0, 0);
+
+ while (argument_list)
+ {
+ parameter = TREE_VALUE (argument_list);
+ argument_list = TREE_CHAIN (argument_list);
+
+ gcc_assert (parameter);
+
+ /* For an undeclared variable passed as parameter we will get
+ an ERROR_MARK node here. */
+ if (TREE_CODE (parameter) == ERROR_MARK)
+ return true;
+
+ type = TREE_TYPE (parameter);
+ gcc_assert (type);
+
+ mode = TYPE_MODE (type);
+ gcc_assert (mode);
+
+ if (pass_by_reference (&cum, mode, type, true))
+ {
+ mode = Pmode;
+ type = build_pointer_type (type);
+ }
+
+ parm_rtx = s390_function_arg (&cum, mode, type, 0);
+
+ s390_function_arg_advance (&cum, mode, type, 0);
+
+ if (parm_rtx && REG_P (parm_rtx))
+ {
+ for (reg = 0;
+ reg < HARD_REGNO_NREGS (REGNO (parm_rtx), GET_MODE (parm_rtx));
+ reg++)
+ if (! call_used_regs[reg + REGNO (parm_rtx)])
+ return true;
+ }
+ }
+ return false;
+}
+
+/* Return true if the given call expression can be
+ turned into a sibling call.
+ DECL holds the declaration of the function to be called whereas
+ EXP is the call expression itself. */
+
+static bool
+s390_function_ok_for_sibcall (tree decl, tree exp)
+{
+ /* The TPF epilogue uses register 1. */
+ if (TARGET_TPF_PROFILING)
+ return false;
+
+ /* The 31 bit PLT code uses register 12 (GOT pointer - caller saved)
+ which would have to be restored before the sibcall. */
+ if (!TARGET_64BIT && flag_pic && decl && !targetm.binds_local_p (decl))
+ return false;
+
+ /* Register 6 on s390 is available as an argument register but unfortunately
+ "caller saved". This makes functions needing this register for arguments
+ not suitable for sibcalls. */
+ if (TREE_OPERAND (exp, 1)
+ && s390_call_saved_register_used (TREE_OPERAND (exp, 1)))
+ return false;
+
+ return true;
+}
+
+/* Return the fixed registers used for condition codes. */
+
+static bool
+s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
+{
+ *p1 = CC_REGNUM;
+ *p2 = INVALID_REGNUM;
+
+ return true;
+}
+
+/* This function is used by the call expanders of the machine description.
+ It emits the call insn itself together with the necessary operations
+ to adjust the target address and returns the emitted insn.
+ ADDR_LOCATION is the target address rtx
+ TLS_CALL the location of the thread-local symbol
+ RESULT_REG the register where the result of the call should be stored
+ RETADDR_REG the register where the return address should be stored
+ If this parameter is NULL_RTX the call is considered
+ to be a sibling call. */
+
+rtx
+s390_emit_call (rtx addr_location, rtx tls_call, rtx result_reg,
+ rtx retaddr_reg)
+{
+ bool plt_call = false;
+ rtx insn;
+ rtx call;
+ rtx clobber;
+ rtvec vec;
+
+ /* Direct function calls need special treatment. */
+ if (GET_CODE (addr_location) == SYMBOL_REF)
+ {
+ /* When calling a global routine in PIC mode, we must
+ replace the symbol itself with the PLT stub. */
+ if (flag_pic && !SYMBOL_REF_LOCAL_P (addr_location))
+ {
+ addr_location = gen_rtx_UNSPEC (Pmode,
+ gen_rtvec (1, addr_location),
+ UNSPEC_PLT);
+ addr_location = gen_rtx_CONST (Pmode, addr_location);
+ plt_call = true;
+ }
+
+ /* Unless we can use the bras(l) insn, force the
+ routine address into a register. */
+ if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
+ {
+ if (flag_pic)
+ addr_location = legitimize_pic_address (addr_location, 0);
+ else
+ addr_location = force_reg (Pmode, addr_location);
+ }
+ }
+
+ /* If it is already an indirect call or the code above moved the
+ SYMBOL_REF to somewhere else make sure the address can be found in
+ register 1. */
+ if (retaddr_reg == NULL_RTX
+ && GET_CODE (addr_location) != SYMBOL_REF
+ && !plt_call)
+ {
+ emit_move_insn (gen_rtx_REG (Pmode, SIBCALL_REGNUM), addr_location);
+ addr_location = gen_rtx_REG (Pmode, SIBCALL_REGNUM);
+ }
+
+ addr_location = gen_rtx_MEM (QImode, addr_location);
+ call = gen_rtx_CALL (VOIDmode, addr_location, const0_rtx);
+
+ if (result_reg != NULL_RTX)
+ call = gen_rtx_SET (VOIDmode, result_reg, call);
+
+ if (retaddr_reg != NULL_RTX)
+ {
+ clobber = gen_rtx_CLOBBER (VOIDmode, retaddr_reg);
+
+ if (tls_call != NULL_RTX)
+ vec = gen_rtvec (3, call, clobber,
+ gen_rtx_USE (VOIDmode, tls_call));
+ else
+ vec = gen_rtvec (2, call, clobber);
+
+ call = gen_rtx_PARALLEL (VOIDmode, vec);
+ }
+
+ insn = emit_call_insn (call);
+
+ /* 31-bit PLT stubs and tls calls use the GOT register implicitly. */
+ if ((!TARGET_64BIT && plt_call) || tls_call != NULL_RTX)
+ {
+ /* s390_function_ok_for_sibcall should
+ have denied sibcalls in this case. */
+ gcc_assert (retaddr_reg != NULL_RTX);
+
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
+ }
+ return insn;
+}
+
+/* Implement CONDITIONAL_REGISTER_USAGE. */
+
+void
+s390_conditional_register_usage (void)
+{
+ int i;
+
+ if (flag_pic)
+ {
+ fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
+ }
+ if (TARGET_CPU_ZARCH)
+ {
+ fixed_regs[BASE_REGNUM] = 0;
+ call_used_regs[BASE_REGNUM] = 0;
+ fixed_regs[RETURN_REGNUM] = 0;
+ call_used_regs[RETURN_REGNUM] = 0;
+ }
+ if (TARGET_64BIT)
+ {
+ for (i = 24; i < 32; i++)
+ call_used_regs[i] = call_really_used_regs[i] = 0;
+ }
+ else
+ {
+ for (i = 18; i < 20; i++)
+ call_used_regs[i] = call_really_used_regs[i] = 0;
+ }
+
+ if (TARGET_SOFT_FLOAT)
+ {
+ for (i = 16; i < 32; i++)
+ call_used_regs[i] = fixed_regs[i] = 1;
+ }
+}
+
+/* Corresponding function to eh_return expander. */
+
+static GTY(()) rtx s390_tpf_eh_return_symbol;
+void
+s390_emit_tpf_eh_return (rtx target)
+{
+ rtx insn, reg;
+
+ if (!s390_tpf_eh_return_symbol)
+ s390_tpf_eh_return_symbol = gen_rtx_SYMBOL_REF (Pmode, "__tpf_eh_return");
+
+ reg = gen_rtx_REG (Pmode, 2);
+
+ emit_move_insn (reg, target);
+ insn = s390_emit_call (s390_tpf_eh_return_symbol, NULL_RTX, reg,
+ gen_rtx_REG (Pmode, RETURN_REGNUM));
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), reg);
+
+ emit_move_insn (EH_RETURN_HANDLER_RTX, reg);
+}
+
+/* Rework the prologue/epilogue to avoid saving/restoring
+ registers unnecessarily. */
+
+static void
+s390_optimize_prologue (void)
+{
+ rtx insn, new_insn, next_insn;
+
+ /* Do a final recompute of the frame-related data. */
+
+ s390_update_frame_layout ();
+
+ /* If all special registers are in fact used, there's nothing we
+ can do, so no point in walking the insn list. */
+
+ if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
+ && cfun_frame_layout.last_save_gpr >= BASE_REGNUM
+ && (TARGET_CPU_ZARCH
+ || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
+ && cfun_frame_layout.last_save_gpr >= RETURN_REGNUM)))
+ return;
+
+ /* Search for prologue/epilogue insns and replace them. */
+
+ for (insn = get_insns (); insn; insn = next_insn)
+ {
+ int first, last, off;
+ rtx set, base, offset;
+
+ next_insn = NEXT_INSN (insn);
+
+ if (GET_CODE (insn) != INSN)
+ continue;
+
+ if (GET_CODE (PATTERN (insn)) == PARALLEL
+ && store_multiple_operation (PATTERN (insn), VOIDmode))
+ {
+ set = XVECEXP (PATTERN (insn), 0, 0);
+ first = REGNO (SET_SRC (set));
+ last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
+ off = INTVAL (offset);
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (cfun_frame_layout.first_save_gpr != -1
+ && (cfun_frame_layout.first_save_gpr < first
+ || cfun_frame_layout.last_save_gpr > last))
+ continue;
+ if (REGNO (base) != STACK_POINTER_REGNUM
+ && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
+ continue;
+ if (first > BASE_REGNUM || last < BASE_REGNUM)
+ continue;
+
+ if (cfun_frame_layout.first_save_gpr != -1)
+ {
+ new_insn = save_gprs (base,
+ off + (cfun_frame_layout.first_save_gpr
+ - first) * UNITS_PER_WORD,
+ cfun_frame_layout.first_save_gpr,
+ cfun_frame_layout.last_save_gpr);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+ }
+
+ remove_insn (insn);
+ continue;
+ }
+
+ if (cfun_frame_layout.first_save_gpr == -1
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_SRC (PATTERN (insn))) == REG
+ && (REGNO (SET_SRC (PATTERN (insn))) == BASE_REGNUM
+ || (!TARGET_CPU_ZARCH
+ && REGNO (SET_SRC (PATTERN (insn))) == RETURN_REGNUM))
+ && GET_CODE (SET_DEST (PATTERN (insn))) == MEM)
+ {
+ set = PATTERN (insn);
+ first = REGNO (SET_SRC (set));
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_DEST (set), 0), &offset);
+ off = INTVAL (offset);
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (REGNO (base) != STACK_POINTER_REGNUM
+ && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
+ continue;
+
+ remove_insn (insn);
+ continue;
+ }
+
+ if (GET_CODE (PATTERN (insn)) == PARALLEL
+ && load_multiple_operation (PATTERN (insn), VOIDmode))
+ {
+ set = XVECEXP (PATTERN (insn), 0, 0);
+ first = REGNO (SET_DEST (set));
+ last = first + XVECLEN (PATTERN (insn), 0) - 1;
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
+ off = INTVAL (offset);
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (cfun_frame_layout.first_restore_gpr != -1
+ && (cfun_frame_layout.first_restore_gpr < first
+ || cfun_frame_layout.last_restore_gpr > last))
+ continue;
+ if (REGNO (base) != STACK_POINTER_REGNUM
+ && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
+ continue;
+ if (first > BASE_REGNUM || last < BASE_REGNUM)
+ continue;
+
+ if (cfun_frame_layout.first_restore_gpr != -1)
+ {
+ new_insn = restore_gprs (base,
+ off + (cfun_frame_layout.first_restore_gpr
+ - first) * UNITS_PER_WORD,
+ cfun_frame_layout.first_restore_gpr,
+ cfun_frame_layout.last_restore_gpr);
+ new_insn = emit_insn_before (new_insn, insn);
+ INSN_ADDRESSES_NEW (new_insn, -1);
+ }
+
+ remove_insn (insn);
+ continue;
+ }
+
+ if (cfun_frame_layout.first_restore_gpr == -1
+ && GET_CODE (PATTERN (insn)) == SET
+ && GET_CODE (SET_DEST (PATTERN (insn))) == REG
+ && (REGNO (SET_DEST (PATTERN (insn))) == BASE_REGNUM
+ || (!TARGET_CPU_ZARCH
+ && REGNO (SET_DEST (PATTERN (insn))) == RETURN_REGNUM))
+ && GET_CODE (SET_SRC (PATTERN (insn))) == MEM)
+ {
+ set = PATTERN (insn);
+ first = REGNO (SET_DEST (set));
+ offset = const0_rtx;
+ base = eliminate_constant_term (XEXP (SET_SRC (set), 0), &offset);
+ off = INTVAL (offset);
+
+ if (GET_CODE (base) != REG || off < 0)
+ continue;
+ if (REGNO (base) != STACK_POINTER_REGNUM
+ && REGNO (base) != HARD_FRAME_POINTER_REGNUM)
+ continue;
+
+ remove_insn (insn);
+ continue;
+ }
+ }
}
+/* Perform machine-dependent processing. */
+
+static void
+s390_reorg (void)
+{
+ bool pool_overflow = false;
+
+ /* Make sure all splits have been performed; splits after
+ machine_dependent_reorg might confuse insn length counts. */
+ split_all_insns_noflow ();
+
+ /* From here on decomposed literal pool addresses must be accepted. */
+ cfun->machine->decomposed_literal_pool_addresses_ok_p = true;
+
+ /* Install the main literal pool and the associated base
+ register load insns.
+
+ In addition, there are two problematic situations we need
+ to correct:
+
+ - the literal pool might be > 4096 bytes in size, so that
+ some of its elements cannot be directly accessed
+
+ - a branch target might be > 64K away from the branch, so that
+ it is not possible to use a PC-relative instruction.
+
+ To fix those, we split the single literal pool into multiple
+ pool chunks, reloading the pool base register at various
+ points throughout the function to ensure it always points to
+ the pool chunk the following code expects, and / or replace
+ PC-relative branches by absolute branches.
+
+ However, the two problems are interdependent: splitting the
+ literal pool can move a branch further away from its target,
+ causing the 64K limit to overflow, and on the other hand,
+ replacing a PC-relative branch by an absolute branch means
+ we need to put the branch target address into the literal
+ pool, possibly causing it to overflow.
+
+ So, we loop trying to fix up both problems until we manage
+ to satisfy both conditions at the same time. Note that the
+ loop is guaranteed to terminate as every pass of the loop
+ strictly decreases the total number of PC-relative branches
+ in the function. (This is not completely true as there
+ might be branch-over-pool insns introduced by chunkify_start.
+ Those never need to be split however.) */
+
+ for (;;)
+ {
+ struct constant_pool *pool = NULL;
+
+ /* Collect the literal pool. */
+ if (!pool_overflow)
+ {
+ pool = s390_mainpool_start ();
+ if (!pool)
+ pool_overflow = true;
+ }
+
+ /* If literal pool overflowed, start to chunkify it. */
+ if (pool_overflow)
+ pool = s390_chunkify_start ();
+
+ /* Split out-of-range branches. If this has created new
+ literal pool entries, cancel current chunk list and
+ recompute it. zSeries machines have large branch
+ instructions, so we never need to split a branch. */
+ if (!TARGET_CPU_ZARCH && s390_split_branches ())
+ {
+ if (pool_overflow)
+ s390_chunkify_cancel (pool);
+ else
+ s390_mainpool_cancel (pool);
+
+ continue;
+ }
+
+ /* If we made it up to here, both conditions are satisfied.
+ Finish up literal pool related changes. */
+ if (pool_overflow)
+ s390_chunkify_finish (pool);
+ else
+ s390_mainpool_finish (pool);
+
+ /* We're done splitting branches. */
+ cfun->machine->split_branches_pending_p = false;
+ break;
+ }
+
+ /* Generate out-of-pool execute target insns. */
+ if (TARGET_CPU_ZARCH)
+ {
+ rtx insn, label, target;
+
+ for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ {
+ label = s390_execute_label (insn);
+ if (!label)
+ continue;
+
+ gcc_assert (label != const0_rtx);
+
+ target = emit_label (XEXP (label, 0));
+ INSN_ADDRESSES_NEW (target, -1);
+
+ target = emit_insn (s390_execute_target (insn));
+ INSN_ADDRESSES_NEW (target, -1);
+ }
+ }
+
+ /* Try to optimize prologue and epilogue further. */
+ s390_optimize_prologue ();
+}
+
+
+/* Initialize GCC target structure. */
+
+#undef TARGET_ASM_ALIGNED_HI_OP
+#define TARGET_ASM_ALIGNED_HI_OP "\t.word\t"
+#undef TARGET_ASM_ALIGNED_DI_OP
+#define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
+#undef TARGET_ASM_INTEGER
+#define TARGET_ASM_INTEGER s390_assemble_integer
+
+#undef TARGET_ASM_OPEN_PAREN
+#define TARGET_ASM_OPEN_PAREN ""
+
+#undef TARGET_ASM_CLOSE_PAREN
+#define TARGET_ASM_CLOSE_PAREN ""
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS (TARGET_DEFAULT | MASK_FUSED_MADD)
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION s390_handle_option
+
+#undef TARGET_ENCODE_SECTION_INFO
+#define TARGET_ENCODE_SECTION_INFO s390_encode_section_info
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS true
+#endif
+#undef TARGET_CANNOT_FORCE_CONST_MEM
+#define TARGET_CANNOT_FORCE_CONST_MEM s390_cannot_force_const_mem
+
+#undef TARGET_DELEGITIMIZE_ADDRESS
+#define TARGET_DELEGITIMIZE_ADDRESS s390_delegitimize_address
+
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY s390_return_in_memory
+
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS s390_init_builtins
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN s390_expand_builtin
+
+#undef TARGET_ASM_OUTPUT_MI_THUNK
+#define TARGET_ASM_OUTPUT_MI_THUNK s390_output_mi_thunk
+#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
+#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
+
+#undef TARGET_SCHED_ADJUST_PRIORITY
+#define TARGET_SCHED_ADJUST_PRIORITY s390_adjust_priority
+#undef TARGET_SCHED_ISSUE_RATE
+#define TARGET_SCHED_ISSUE_RATE s390_issue_rate
+#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
+#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD s390_first_cycle_multipass_dfa_lookahead
+
+#undef TARGET_CANNOT_COPY_INSN_P
+#define TARGET_CANNOT_COPY_INSN_P s390_cannot_copy_insn_p
+#undef TARGET_RTX_COSTS
+#define TARGET_RTX_COSTS s390_rtx_costs
+#undef TARGET_ADDRESS_COST
+#define TARGET_ADDRESS_COST s390_address_cost
+
+#undef TARGET_MACHINE_DEPENDENT_REORG
+#define TARGET_MACHINE_DEPENDENT_REORG s390_reorg
+
+#undef TARGET_VALID_POINTER_MODE
+#define TARGET_VALID_POINTER_MODE s390_valid_pointer_mode
+
+#undef TARGET_BUILD_BUILTIN_VA_LIST
+#define TARGET_BUILD_BUILTIN_VA_LIST s390_build_builtin_va_list
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR s390_gimplify_va_arg
+
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE s390_pass_by_reference
+
+#undef TARGET_FUNCTION_OK_FOR_SIBCALL
+#define TARGET_FUNCTION_OK_FOR_SIBCALL s390_function_ok_for_sibcall
+
+#undef TARGET_FIXED_CONDITION_CODE_REGS
+#define TARGET_FIXED_CONDITION_CODE_REGS s390_fixed_condition_code_regs
+
+#undef TARGET_CC_MODES_COMPATIBLE
+#define TARGET_CC_MODES_COMPATIBLE s390_cc_modes_compatible
+
+#undef TARGET_INVALID_WITHIN_DOLOOP
+#define TARGET_INVALID_WITHIN_DOLOOP hook_constcharptr_rtx_null
+
+#ifdef HAVE_AS_TLS
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL s390_output_dwarf_dtprel
+#endif
+
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
+#define TARGET_MANGLE_FUNDAMENTAL_TYPE s390_mangle_fundamental_type
+#endif
+
+#undef TARGET_SCALAR_MODE_SUPPORTED_P
+#define TARGET_SCALAR_MODE_SUPPORTED_P s390_scalar_mode_supported_p
+
+struct gcc_target targetm = TARGET_INITIALIZER;
+
#include "gt-s390.h"
diff --git a/contrib/gcc/config/s390/s390.h b/contrib/gcc/config/s390/s390.h
index d2416c8..ba7a036 100644
--- a/contrib/gcc/config/s390/s390.h
+++ b/contrib/gcc/config/s390/s390.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GNU compiler, for IBM S/390
- Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Hartmut Penner (hpenner@de.ibm.com) and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -18,8 +18,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef _S390_H
#define _S390_H
@@ -40,6 +40,7 @@ enum processor_type
PROCESSOR_9672_G6,
PROCESSOR_2064_Z900,
PROCESSOR_2084_Z990,
+ PROCESSOR_2094_Z9_109,
PROCESSOR_max
};
@@ -49,16 +50,15 @@ enum processor_flags
{
PF_IEEE_FLOAT = 1,
PF_ZARCH = 2,
- PF_LONG_DISPLACEMENT = 4
+ PF_LONG_DISPLACEMENT = 4,
+ PF_EXTIMM = 8
};
extern enum processor_type s390_tune;
extern enum processor_flags s390_tune_flags;
-extern const char *s390_tune_string;
extern enum processor_type s390_arch;
extern enum processor_flags s390_arch_flags;
-extern const char *s390_arch_string;
#define TARGET_CPU_IEEE_FLOAT \
(s390_arch_flags & PF_IEEE_FLOAT)
@@ -66,13 +66,24 @@ extern const char *s390_arch_string;
(s390_arch_flags & PF_ZARCH)
#define TARGET_CPU_LONG_DISPLACEMENT \
(s390_arch_flags & PF_LONG_DISPLACEMENT)
+#define TARGET_CPU_EXTIMM \
+ (s390_arch_flags & PF_EXTIMM)
#define TARGET_LONG_DISPLACEMENT \
(TARGET_ZARCH && TARGET_CPU_LONG_DISPLACEMENT)
-
+#define TARGET_EXTIMM \
+ (TARGET_ZARCH && TARGET_CPU_EXTIMM)
/* Run-time target specification. */
+/* Defaults for option flags defined only on some subtargets. */
+#ifndef TARGET_TPF_PROFILING
+#define TARGET_TPF_PROFILING 0
+#endif
+
+/* This will be overridden by OS headers. */
+#define TARGET_TPF 0
+
/* Target CPU builtins. */
#define TARGET_CPU_CPP_BUILTINS() \
do \
@@ -82,72 +93,21 @@ extern const char *s390_arch_string;
builtin_define ("__s390__"); \
if (TARGET_64BIT) \
builtin_define ("__s390x__"); \
+ if (TARGET_LONG_DOUBLE_128) \
+ builtin_define ("__LONG_DOUBLE_128__"); \
} \
while (0)
-/* Optional target features. */
-extern int target_flags;
-
-#define MASK_HARD_FLOAT 0x01
-#define MASK_BACKCHAIN 0x02
-#define MASK_SMALL_EXEC 0x04
-#define MASK_DEBUG_ARG 0x08
-#define MASK_64BIT 0x10
-#define MASK_ZARCH 0x20
-#define MASK_MVCLE 0x40
-#define MASK_TPF 0x80
-#define MASK_NO_FUSED_MADD 0x100
-
-#define TARGET_HARD_FLOAT (target_flags & MASK_HARD_FLOAT)
-#define TARGET_SOFT_FLOAT (!(target_flags & MASK_HARD_FLOAT))
-#define TARGET_BACKCHAIN (target_flags & MASK_BACKCHAIN)
-#define TARGET_SMALL_EXEC (target_flags & MASK_SMALL_EXEC)
-#define TARGET_DEBUG_ARG (target_flags & MASK_DEBUG_ARG)
-#define TARGET_64BIT (target_flags & MASK_64BIT)
-#define TARGET_ZARCH (target_flags & MASK_ZARCH)
-#define TARGET_MVCLE (target_flags & MASK_MVCLE)
-#define TARGET_TPF (target_flags & MASK_TPF)
-#define TARGET_NO_FUSED_MADD (target_flags & MASK_NO_FUSED_MADD)
-#define TARGET_FUSED_MADD (! TARGET_NO_FUSED_MADD)
-
/* ??? Once this actually works, it could be made a runtime option. */
#define TARGET_IBM_FLOAT 0
#define TARGET_IEEE_FLOAT 1
#ifdef DEFAULT_TARGET_64BIT
-#define TARGET_DEFAULT 0x31
+#define TARGET_DEFAULT (MASK_64BIT | MASK_ZARCH | MASK_HARD_FLOAT)
#else
-#define TARGET_DEFAULT 0x1
+#define TARGET_DEFAULT MASK_HARD_FLOAT
#endif
-#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 executable < 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 ABI")}, \
- { "31", -16, N_("31 bit ABI")}, \
- { "zarch", 32, N_("z/Architecture")}, \
- { "esa", -32, N_("ESA/390 architecture")}, \
- { "mvcle", 64, N_("mvcle use")}, \
- { "no-mvcle", -64, N_("mvc&ex")}, \
- { "tpf", 128, N_("enable tpf OS code")}, \
- { "no-tpf", -128, N_("disable tpf OS code")}, \
- { "no-fused-madd", 256, N_("disable fused multiply/add instructions")},\
- { "fused-madd", -256, N_("enable fused multiply/add instructions")}, \
- { "", TARGET_DEFAULT, 0 } }
-
-#define TARGET_OPTIONS \
-{ { "tune=", &s390_tune_string, \
- N_("Schedule code for given CPU"), 0}, \
- { "arch=", &s390_arch_string, \
- N_("Generate code for given CPU"), 0}, \
-}
-
/* Support for configure-time defaults. */
#define OPTION_DEFAULT_SPECS \
{ "mode", "%{!mesa:%{!mzarch:-m%(VALUE)}}" }, \
@@ -208,11 +168,7 @@ extern int target_flags;
#define MAX_BITS_PER_WORD 64
/* Function arguments and return values are promoted to word size. */
-#define PROMOTE_FUNCTION_ARGS
-#define PROMOTE_FUNCTION_RETURN
-#define PROMOTE_FOR_CALL_ONLY
-
-#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
+#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
if (INTEGRAL_MODE_P (MODE) && \
GET_MODE_SIZE (MODE) < UNITS_PER_WORD) { \
(MODE) = Pmode; \
@@ -259,11 +215,21 @@ if (INTEGRAL_MODE_P (MODE) && \
#define SHORT_TYPE_SIZE 16
#define INT_TYPE_SIZE 32
#define LONG_TYPE_SIZE (TARGET_64BIT ? 64 : 32)
-#define MAX_LONG_TYPE_SIZE 64
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
-#define LONG_DOUBLE_TYPE_SIZE 64 /* ??? Should support extended format. */
+#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
+
+/* Define this to set long double type size to use in libgcc2.c, which can
+ not depend on target_flags. */
+#ifdef __LONG_DOUBLE_128__
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
+#else
+#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
+#endif
+
+/* Work around target_flags dependency in ada/targtyps.c. */
+#define WIDEST_HARDWARE_FP_SIZE 64
/* We use "unsigned char" as default. */
#define DEFAULT_SIGNED_CHAR 0
@@ -283,30 +249,32 @@ if (INTEGRAL_MODE_P (MODE) && \
GPR 14: Return address register
GPR 15: Stack pointer
- Registers 32-34 are 'fake' hard registers that do not
+ Registers 32-35 are 'fake' hard registers that do not
correspond to actual hardware:
Reg 32: Argument pointer
Reg 33: Condition code
- Reg 34: Frame pointer */
+ Reg 34: Frame pointer
+ Reg 35: Return address pointer
-#define FIRST_PSEUDO_REGISTER 35
+ Registers 36 and 37 are mapped to access registers
+ 0 and 1, used to implement thread-local storage. */
+
+#define FIRST_PSEUDO_REGISTER 38
/* Standard register usage. */
#define GENERAL_REGNO_P(N) ((int)(N) >= 0 && (N) < 16)
#define ADDR_REGNO_P(N) ((N) >= 1 && (N) < 16)
#define FP_REGNO_P(N) ((N) >= 16 && (N) < (TARGET_IEEE_FLOAT? 32 : 20))
#define CC_REGNO_P(N) ((N) == 33)
-#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34)
+#define FRAME_REGNO_P(N) ((N) == 32 || (N) == 34 || (N) == 35)
+#define ACCESS_REGNO_P(N) ((N) == 36 || (N) == 37)
#define GENERAL_REG_P(X) (REG_P (X) && GENERAL_REGNO_P (REGNO (X)))
#define ADDR_REG_P(X) (REG_P (X) && ADDR_REGNO_P (REGNO (X)))
#define FP_REG_P(X) (REG_P (X) && FP_REGNO_P (REGNO (X)))
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
#define FRAME_REG_P(X) (REG_P (X) && FRAME_REGNO_P (REGNO (X)))
-
-#define BASE_REGISTER 13
-#define RETURN_REGNUM 14
-#define CC_REGNUM 33
+#define ACCESS_REG_P(X) (REG_P (X) && ACCESS_REGNO_P (REGNO (X)))
/* Set up fixed registers and calling convention:
@@ -317,6 +285,7 @@ if (INTEGRAL_MODE_P (MODE) && \
GPR 14 is always fixed on S/390 machines (as return address).
GPR 15 is always fixed (as stack pointer).
The 'fake' hard registers are call-clobbered and fixed.
+ The access registers are call-saved and fixed.
On 31-bit, FPRs 18-19 are call-clobbered;
on 64-bit, FPRs 24-31 are call-clobbered.
@@ -331,7 +300,8 @@ if (INTEGRAL_MODE_P (MODE) && \
0, 0, 0, 0, \
0, 0, 0, 0, \
0, 0, 0, 0, \
- 1, 1, 1 }
+ 1, 1, 1, 1, \
+ 1, 1 }
#define CALL_USED_REGISTERS \
{ 1, 1, 1, 1, \
@@ -342,7 +312,8 @@ if (INTEGRAL_MODE_P (MODE) && \
1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, 1 }
+ 1, 1, 1, 1, \
+ 1, 1 }
#define CALL_REALLY_USED_REGISTERS \
{ 1, 1, 1, 1, \
@@ -353,41 +324,17 @@ if (INTEGRAL_MODE_P (MODE) && \
1, 1, 1, 1, \
1, 1, 1, 1, \
1, 1, 1, 1, \
- 1, 1, 1 }
-
-#define CONDITIONAL_REGISTER_USAGE \
-do \
- { \
- int i; \
- \
- if (flag_pic) \
- { \
- fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
- call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; \
- } \
- if (TARGET_CPU_ZARCH) \
- { \
- fixed_regs[RETURN_REGNUM] = 0; \
- call_used_regs[RETURN_REGNUM] = 0; \
- } \
- if (TARGET_64BIT) \
- { \
- for (i = 24; i < 32; i++) \
- call_used_regs[i] = call_really_used_regs[i] = 0; \
- } \
- else \
- { \
- for (i = 18; i < 20; i++) \
- call_used_regs[i] = call_really_used_regs[i] = 0; \
- } \
- } while (0)
+ 1, 1, 1, 1, \
+ 0, 0 }
+
+#define CONDITIONAL_REGISTER_USAGE s390_conditional_register_usage ()
/* Preferred register allocation order. */
#define REG_ALLOC_ORDER \
-{ 1, 2, 3, 4, 5, 0, 13, 12, 11, 10, 9, 8, 7, 6, 14, \
+{ 1, 2, 3, 4, 5, 0, 12, 11, 10, 9, 8, 7, 6, 14, 13, \
16, 17, 18, 19, 20, 21, 22, 23, \
24, 25, 26, 27, 28, 29, 30, 31, \
- 15, 32, 33, 34 }
+ 15, 32, 33, 34, 35, 36, 37 }
/* Fitting values into registers. */
@@ -400,31 +347,24 @@ do \
Floating point modes <= word size fit into any FPR or GPR.
Floating point modes > word size (i.e. DFmode on 32-bit) fit
into any FPR, or an even-odd GPR pair.
+ TFmode fits only into an even-odd FPR pair.
Complex floating point modes fit either into two FPRs, or into
successive GPRs (again starting with an even number).
+ TCmode fits only into two successive even-odd FPR pairs.
Condition code modes fit only into the CC register. */
+/* Because all registers in a class have the same size HARD_REGNO_NREGS
+ is equivalent to CLASS_MAX_NREGS. */
#define HARD_REGNO_NREGS(REGNO, MODE) \
- (FP_REGNO_P(REGNO)? \
- (GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT ? 2 : 1) : \
- GENERAL_REGNO_P(REGNO)? \
- ((GET_MODE_SIZE(MODE)+UNITS_PER_WORD-1) / UNITS_PER_WORD) : \
- 1)
-
-#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- (FP_REGNO_P(REGNO)? \
- ((MODE) == SImode || (MODE) == DImode || \
- GET_MODE_CLASS(MODE) == MODE_FLOAT || \
- GET_MODE_CLASS(MODE) == MODE_COMPLEX_FLOAT) : \
- GENERAL_REGNO_P(REGNO)? \
- (HARD_REGNO_NREGS(REGNO, MODE) == 1 || !((REGNO) & 1)) : \
- CC_REGNO_P(REGNO)? \
- GET_MODE_CLASS (MODE) == MODE_CC : \
- FRAME_REGNO_P(REGNO)? \
- (enum machine_mode) (MODE) == Pmode : \
- 0)
+ s390_class_max_nregs (REGNO_REG_CLASS (REGNO), (MODE))
+
+#define HARD_REGNO_MODE_OK(REGNO, MODE) \
+ s390_hard_regno_mode_ok ((REGNO), (MODE))
+
+#define HARD_REGNO_RENAME_OK(FROM, TO) \
+ s390_hard_regno_rename_ok (FROM, TO)
#define MODES_TIEABLE_P(MODE1, MODE2) \
(((MODE1) == SFmode || (MODE1) == DFmode) \
@@ -433,16 +373,18 @@ do \
/* Maximum number of registers to represent a value of 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)
+ s390_class_max_nregs ((CLASS), (MODE))
/* If a 4-byte value is loaded into a FPR, it is placed into the
*upper* half of the register, not the lower. Therefore, we
- cannot use SUBREGs to switch between modes in FP registers. */
-#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
- (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
- ? reg_classes_intersect_p (FP_REGS, CLASS) : 0)
+ cannot use SUBREGs to switch between modes in FP registers.
+ Likewise for access registers, since they have only half the
+ word size on 64-bit. */
+#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
+ (GET_MODE_SIZE (FROM) != GET_MODE_SIZE (TO) \
+ ? ((reg_classes_intersect_p (FP_REGS, CLASS) \
+ && (GET_MODE_SIZE (FROM) < 8 || GET_MODE_SIZE (TO) < 8)) \
+ || reg_classes_intersect_p (ACCESS_REGS, CLASS)) : 0)
/* Register classes. */
@@ -451,39 +393,48 @@ do \
ADDR_REGS All general purpose registers except %r0
(These registers can be used in address generation)
FP_REGS All floating point registers
+ CC_REGS The condition code register
+ ACCESS_REGS The access registers
GENERAL_FP_REGS Union of GENERAL_REGS and FP_REGS
ADDR_FP_REGS Union of ADDR_REGS and FP_REGS
+ GENERAL_CC_REGS Union of GENERAL_REGS and CC_REGS
+ ADDR_CC_REGS Union of ADDR_REGS and CC_REGS
NO_REGS No registers
ALL_REGS All registers
Note that the 'fake' frame pointer and argument pointer registers
- are included amongst the address registers here. The condition
- code register is only included in ALL_REGS. */
+ are included amongst the address registers here. */
enum reg_class
{
- NO_REGS, ADDR_REGS, GENERAL_REGS,
+ NO_REGS, CC_REGS, ADDR_REGS, GENERAL_REGS, ACCESS_REGS,
+ ADDR_CC_REGS, GENERAL_CC_REGS,
FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
ALL_REGS, LIM_REG_CLASSES
};
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-#define REG_CLASS_NAMES \
-{ "NO_REGS", "ADDR_REGS", "GENERAL_REGS", \
+#define REG_CLASS_NAMES \
+{ "NO_REGS", "CC_REGS", "ADDR_REGS", "GENERAL_REGS", "ACCESS_REGS", \
+ "ADDR_CC_REGS", "GENERAL_CC_REGS", \
"FP_REGS", "ADDR_FP_REGS", "GENERAL_FP_REGS", "ALL_REGS" }
/* Class -> register mapping. */
#define REG_CLASS_CONTENTS \
{ \
{ 0x00000000, 0x00000000 }, /* NO_REGS */ \
- { 0x0000fffe, 0x00000005 }, /* ADDR_REGS */ \
- { 0x0000ffff, 0x00000005 }, /* GENERAL_REGS */ \
+ { 0x00000000, 0x00000002 }, /* CC_REGS */ \
+ { 0x0000fffe, 0x0000000d }, /* ADDR_REGS */ \
+ { 0x0000ffff, 0x0000000d }, /* GENERAL_REGS */ \
+ { 0x00000000, 0x00000030 }, /* ACCESS_REGS */ \
+ { 0x0000fffe, 0x0000000f }, /* ADDR_CC_REGS */ \
+ { 0x0000ffff, 0x0000000f }, /* GENERAL_CC_REGS */ \
{ 0xffff0000, 0x00000000 }, /* FP_REGS */ \
- { 0xfffffffe, 0x00000005 }, /* ADDR_FP_REGS */ \
- { 0xffffffff, 0x00000005 }, /* GENERAL_FP_REGS */ \
- { 0xffffffff, 0x00000007 }, /* ALL_REGS */ \
+ { 0xfffffffe, 0x0000000d }, /* ADDR_FP_REGS */ \
+ { 0xffffffff, 0x0000000d }, /* GENERAL_FP_REGS */ \
+ { 0xffffffff, 0x0000003f }, /* ALL_REGS */ \
}
/* Register -> class mapping. */
@@ -498,8 +449,8 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
or a pseudo register currently allocated to one such. */
#define REGNO_OK_FOR_INDEX_P(REGNO) \
(((REGNO) < FIRST_PSEUDO_REGISTER \
- && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
- || (reg_renumber[REGNO] > 0 && reg_renumber[REGNO] < 16))
+ && REGNO_REG_CLASS ((REGNO)) == ADDR_REGS) \
+ || ADDR_REGNO_P (reg_renumber[REGNO]))
#define REGNO_OK_FOR_BASE_P(REGNO) REGNO_OK_FOR_INDEX_P (REGNO)
@@ -530,35 +481,13 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
: MODE)
-/* Define various machine-dependent constraint letters. */
-
-#define REG_CLASS_FROM_LETTER(C) \
- ((C) == 'a' ? ADDR_REGS : \
- (C) == 'd' ? GENERAL_REGS : \
- (C) == 'f' ? FP_REGS : NO_REGS)
-
-#define CONST_OK_FOR_CONSTRAINT_P(VALUE, C, STR) \
- s390_const_ok_for_constraint_p ((VALUE), (C), (STR))
-
-#define CONST_DOUBLE_OK_FOR_CONSTRAINT_P(VALUE, C, STR) 1
-
-#define EXTRA_CONSTRAINT_STR(OP, C, STR) \
- s390_extra_constraint_str ((OP), (C), (STR))
-#define EXTRA_MEMORY_CONSTRAINT(C, STR) \
- ((C) == 'Q' || (C) == 'R' || (C) == 'S' || (C) == 'T')
-#define EXTRA_ADDRESS_CONSTRAINT(C, STR) \
- ((C) == 'U' || (C) == 'W' || (C) == 'Y')
-
-#define CONSTRAINT_LEN(C, STR) \
- ((C) == 'N' ? 5 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
-
/* Stack layout and calling conventions. */
/* Our stack grows from higher to lower addresses. However, local variables
are accessed by positive offsets, and function arguments are stored at
increasing addresses. */
#define STACK_GROWS_DOWNWARD
-/* #undef FRAME_GROWS_DOWNWARD */
+#define FRAME_GROWS_DOWNWARD 1
/* #undef ARGS_GROW_DOWNWARD */
/* The basic stack layout looks like this: the stack pointer points
@@ -570,33 +499,39 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
#define STACK_POINTER_OFFSET (TARGET_64BIT ? 160 : 96)
/* Offset within stack frame to start allocating local variables at. */
-extern int current_function_outgoing_args_size;
-#define STARTING_FRAME_OFFSET \
- (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
+#define STARTING_FRAME_OFFSET 0
/* Offset from the stack pointer register to an item dynamically
allocated on the stack, e.g., by `alloca'. */
-#define STACK_DYNAMIC_OFFSET(FUNDECL) (STARTING_FRAME_OFFSET)
+extern int current_function_outgoing_args_size;
+#define STACK_DYNAMIC_OFFSET(FUNDECL) \
+ (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
/* Offset of first parameter from the argument pointer register value.
We have a fake argument pointer register that points directly to
the argument area. */
#define FIRST_PARM_OFFSET(FNDECL) 0
+/* Defining this macro makes __builtin_frame_address(0) and
+ __builtin_return_address(0) work with -fomit-frame-pointer. */
+#define INITIAL_FRAME_ADDRESS_RTX \
+ (TARGET_PACKED_STACK ? \
+ plus_constant (arg_pointer_rtx, -UNITS_PER_WORD) : \
+ plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
+
/* The return address of the current frame is retrieved
from the initial value of register RETURN_REGNUM.
For frames farther back, we use the stack slot where
the corresponding RETURN_REGNUM register was saved. */
+#define DYNAMIC_CHAIN_ADDRESS(FRAME) \
+ (TARGET_PACKED_STACK ? \
+ plus_constant ((FRAME), STACK_POINTER_OFFSET - UNITS_PER_WORD) : (FRAME))
-#define DYNAMIC_CHAIN_ADDRESS(FRAME) \
- ((FRAME) != hard_frame_pointer_rtx ? (FRAME) : \
- plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
-
-#define RETURN_ADDR_RTX(COUNT, FRAME) \
+#define RETURN_ADDR_RTX(COUNT, FRAME) \
s390_return_addr_rtx ((COUNT), DYNAMIC_CHAIN_ADDRESS ((FRAME)))
/* In 31-bit mode, we need to mask off the high bit of return addresses. */
-#define MASK_RETURN_ADDR (TARGET_64BIT ? GEN_INT (-1) : GEN_INT (0x7fffffff))
+#define MASK_RETURN_ADDR (TARGET_64BIT ? constm1_rtx : GEN_INT (0x7fffffff))
/* Exception handling. */
@@ -608,10 +543,8 @@ extern int current_function_outgoing_args_size;
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
-#define EH_RETURN_HANDLER_RTX \
- gen_rtx_MEM (Pmode, plus_constant (arg_pointer_rtx, \
- -STACK_POINTER_OFFSET + UNITS_PER_WORD*RETURN_REGNUM))
-
+#define EH_RETURN_HANDLER_RTX gen_rtx_MEM (Pmode, return_address_pointer_rtx)
+
/* Select a format to encode pointers in exception handling data. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
(flag_pic \
@@ -625,6 +558,7 @@ extern int current_function_outgoing_args_size;
#define FRAME_POINTER_REGNUM 34
#define HARD_FRAME_POINTER_REGNUM 11
#define ARG_POINTER_REGNUM 32
+#define RETURN_ADDRESS_POINTER_REGNUM 35
/* The static chain must be call-clobbered, but not used for
function argument passing. As register 1 is clobbered by
@@ -641,30 +575,20 @@ extern int current_function_outgoing_args_size;
#define FRAME_POINTER_REQUIRED 0
-#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = 0
-
-#define ELIMINABLE_REGS \
-{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- { ARG_POINTER_REGNUM, HARD_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) == FRAME_POINTER_REGNUM \
- && (TO) == HARD_FRAME_POINTER_REGNUM) \
- { (OFFSET) = 0; } \
- else if ((FROM) == ARG_POINTER_REGNUM \
- && (TO) == HARD_FRAME_POINTER_REGNUM) \
- { (OFFSET) = s390_arg_frame_offset (); } \
- else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \
- { (OFFSET) = s390_arg_frame_offset (); } \
- else \
- abort(); \
-}
+#define ELIMINABLE_REGS \
+{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
+ { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM }, \
+ { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM }, \
+ { BASE_REGNUM, BASE_REGNUM }}
+
+#define CAN_ELIMINATE(FROM, TO) \
+ s390_can_eliminate ((FROM), (TO))
+
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ (OFFSET) = s390_initial_elimination_offset ((FROM), (TO))
/* Stack arguments. */
@@ -694,11 +618,6 @@ CUMULATIVE_ARGS;
#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
s390_function_arg (&CUM, MODE, TYPE, NAMED)
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- s390_function_arg_pass_by_reference (MODE, TYPE)
-
-#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) 0
-
/* Arguments can be placed in general registers 2 to 6,
or in floating point registers 0 and 2. */
#define FUNCTION_ARG_REGNO_P(N) (((N) >=2 && (N) <7) || \
@@ -716,9 +635,6 @@ CUMULATIVE_ARGS;
/* Only gpr 2 and fpr 0 are ever used as return registers. */
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 2 || (N) == 16)
-/* Structure value address is passed as invisible first argument (gpr 2). */
-#define STRUCT_VALUE 0
-
/* Function entry and exit. */
@@ -739,13 +655,9 @@ CUMULATIVE_ARGS;
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
s390_va_start (valist, nextarg)
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- s390_va_arg (valist, type)
-
-
/* Trampolines for nested functions. */
-#define TRAMPOLINE_SIZE (TARGET_64BIT ? 36 : 20)
+#define TRAMPOLINE_SIZE (TARGET_64BIT ? 32 : 16)
#define INITIALIZE_TRAMPOLINE(ADDR, FNADDR, CXT) \
s390_initialize_trampoline ((ADDR), (FNADDR), (CXT))
@@ -754,12 +666,6 @@ CUMULATIVE_ARGS;
s390_trampoline_template (FILE)
-/* Library calls. */
-
-/* We should use memcpy, not bcopy. */
-#define TARGET_MEM_FUNCTIONS
-
-
/* Addressing modes, and classification of registers for them. */
/* Recognize any constant value that is a valid address. */
@@ -768,38 +674,6 @@ CUMULATIVE_ARGS;
/* Maximum number of registers that can appear in a valid memory address. */
#define MAX_REGS_PER_ADDRESS 2
-/* 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. */
-
-#define REG_OK_FOR_INDEX_NONSTRICT_P(X) \
-((GET_MODE (X) == Pmode) && \
- ((REGNO (X) >= FIRST_PSEUDO_REGISTER) \
- || REGNO_REG_CLASS (REGNO (X)) == ADDR_REGS))
-
-#define REG_OK_FOR_BASE_NONSTRICT_P(X) REG_OK_FOR_INDEX_NONSTRICT_P (X)
-
-#define REG_OK_FOR_INDEX_STRICT_P(X) \
-((GET_MODE (X) == Pmode) && (REGNO_OK_FOR_INDEX_P (REGNO (X))))
-
-#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
-
/* S/390 has no mode dependent addresses. */
#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
@@ -831,6 +705,19 @@ CUMULATIVE_ARGS;
goto WIN; \
}
+/* Try a machine-dependent way of reloading an illegitimate address
+ operand. If we find one, push the reload and jump to WIN. This
+ macro is used in only one place: `find_reloads_address' in reload.c. */
+#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \
+do { \
+ rtx new = legitimize_reload_address (AD, MODE, OPNUM, (int)(TYPE)); \
+ if (new) \
+ { \
+ (AD) = new; \
+ goto WIN; \
+ } \
+} while (0)
+
/* Nonzero if the constant value X is a legitimate general operand.
It is given that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
#define LEGITIMATE_CONSTANT_P(X) \
@@ -853,10 +740,14 @@ CUMULATIVE_ARGS;
return the mode to be used for the comparison. */
#define SELECT_CC_MODE(OP, X, Y) s390_select_ccmode ((OP), (X), (Y))
+/* Canonicalize a comparison from one we don't have to one we do have. */
+#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
+ s390_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
+
/* 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 struct rtx_def *s390_compare_op0, *s390_compare_op1, *s390_compare_emitted;
/* Relative costs of operations. */
@@ -880,9 +771,14 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
/* Nonzero if access to memory by bytes is slow and undesirable. */
#define SLOW_BYTE_ACCESS 1
+/* An integer expression for the size in bits of the largest integer machine
+ mode that should actually be used. We allow pairs of registers. */
+#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode)
+
/* The maximum number of bytes that a single instruction can move quickly
- between memory and registers or between two memory locations. */
+ between memory and registers or between two memory locations. */
#define MOVE_MAX (TARGET_64BIT ? 16 : 8)
+#define MOVE_MAX_PIECES (TARGET_64BIT ? 8 : 4)
#define MAX_MOVE_MAX 16
/* Determine whether to use move_by_pieces or block move insn. */
@@ -895,6 +791,11 @@ extern struct rtx_def *s390_compare_op0, *s390_compare_op1;
( (SIZE) == 1 || (SIZE) == 2 || (SIZE) == 4 \
|| (TARGET_64BIT && (SIZE) == 8) )
+/* This macro is used to determine whether store_by_pieces should be
+ called to "memset" storage with byte values other than zero, or
+ to "memcpy" storage when the source is a constant string. */
+#define STORE_BY_PIECES_P(SIZE, ALIGN) MOVE_BY_PIECES_P (SIZE, ALIGN)
+
/* Don't perform CSE on function addresses. */
#define NO_FUNCTION_CSE
@@ -959,23 +860,23 @@ extern int flag_pic;
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", \
+ "%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", "%fp" \
+ "%f8", "%f10", "%f12", "%f14", "%f9", "%f11", "%f13", "%f15", \
+ "%ap", "%cc", "%fp", "%rp", "%a0", "%a1" \
}
-/* Emit a dtp-relative reference to a TLS variable. */
-
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- s390_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
-
/* Print operand X (an rtx) in assembler syntax to file FILE. */
#define PRINT_OPERAND(FILE, X, CODE) print_operand (FILE, X, CODE)
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+/* Output machine-dependent UNSPECs in address constants. */
+#define OUTPUT_ADDR_CONST_EXTRA(FILE, X, FAIL) \
+do { \
+ if (!s390_output_addr_const_extra (FILE, (X))) \
+ goto FAIL; \
+} while (0);
+
/* Output an element of a case-vector that is absolute. */
#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
do { \
@@ -1002,22 +903,6 @@ do { \
/* Miscellaneous parameters. */
-/* Define the codes that are matched by predicates in aux-output.c. */
-#define PREDICATE_CODES \
- {"s_operand", { SUBREG, MEM }}, \
- {"s_imm_operand", { CONST_INT, CONST_DOUBLE, SUBREG, MEM }}, \
- {"shift_count_operand", { REG, SUBREG, PLUS, CONST_INT }}, \
- {"bras_sym_operand",{ SYMBOL_REF, CONST }}, \
- {"larl_operand", { SYMBOL_REF, CONST, CONST_INT, CONST_DOUBLE }}, \
- {"load_multiple_operation", {PARALLEL}}, \
- {"store_multiple_operation", {PARALLEL}}, \
- {"const0_operand", { CONST_INT, CONST_DOUBLE }}, \
- {"consttable_operand", { SYMBOL_REF, LABEL_REF, CONST, \
- CONST_INT, CONST_DOUBLE }}, \
- {"s390_plus_operand", { PLUS }}, \
- {"s390_alc_comparison", { LTU, GTU, LEU, GEU }}, \
- {"s390_slb_comparison", { LTU, GTU, LEU, GEU }},
-
/* Specify the machine mode that this machine uses for the index in the
tablejump instruction. */
#define CASE_VECTOR_MODE (TARGET_64BIT ? DImode : SImode)
@@ -1038,7 +923,15 @@ do { \
indexing purposes) so give the MEM rtx a byte's mode. */
#define FUNCTION_MODE QImode
-/* This macro definition sets up a default value for `main' to return. */
-#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
+/* Specify the value which is used when clz operand is zero. */
+#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 64, 1)
+
+/* Machine-specific symbol_ref flags. */
+#define SYMBOL_FLAG_ALIGN1 (SYMBOL_FLAG_MACH_DEP << 0)
+
+/* Check whether integer displacement is in range. */
+#define DISP_IN_RANGE(d) \
+ (TARGET_LONG_DISPLACEMENT? ((d) >= -524288 && (d) <= 524287) \
+ : ((d) >= 0 && (d) <= 4095))
#endif
diff --git a/contrib/gcc/config/s390/s390.md b/contrib/gcc/config/s390/s390.md
index 345a36a..2348409 100644
--- a/contrib/gcc/config/s390/s390.md
+++ b/contrib/gcc/config/s390/s390.md
@@ -1,5 +1,5 @@
;;- Machine description for GNU compiler -- S/390 / zSeries version.
-;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004
+;; Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
;; Free Software Foundation, Inc.
;; Contributed by Hartmut Penner (hpenner@de.ibm.com) and
;; Ulrich Weigand (uweigand@de.ibm.com).
@@ -18,53 +18,34 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to the Free
-;; Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-;; 02111-1307, USA.
+;; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+;; 02110-1301, 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).
-;; L -- Value appropriate as displacement.
-;; (0..4095) for short displacement
-;; (-524288..524287) for long displacement
-;; M -- Constant integer with a value of 0x7fffffff.
-;; N -- Multiple letter constraint followed by 4 parameter letters.
-;; 0..9: number of the part counting from most to least significant
-;; H,Q: mode of the part
-;; D,S,H: mode of the containing operand
-;; 0,F: value of the other parts (F - all bits set)
-;;
-;; The constraint matches if the specified part of a constant
-;; has a value different from its other parts.
-;; Q -- Memory reference without index register and with short displacement.
-;; R -- Memory reference with index register and short displacement.
-;; S -- Memory reference without index register but with long displacement.
-;; T -- Memory reference with index register and long displacement.
-;; U -- Pointer with short displacement.
-;; W -- Pointer with long displacement.
-;; Y -- Shift count operand.
+;; See constraints.md for a description of constraints specific to s390.
;;
+
;; Special formats used for outputting 390 instructions.
;;
;; %C: print opcode suffix for branch condition.
;; %D: print opcode suffix for inverse branch condition.
;; %J: print tls_load/tls_gdcall/tls_ldcall suffix
+;; %G: print the size of the operand in bytes.
;; %O: print only the displacement of a memory reference.
;; %R: print only the base register of a memory reference.
+;; %S: print S-type memory reference (base+displacement).
;; %N: print the second word of a DImode operand.
;; %M: print the second word of a TImode operand.
-
+;; %Y: print shift count operand.
+;;
;; %b: print integer X as if it's an unsigned byte.
-;; %x: print integer X as if it's an unsigned word.
-;; %h: print integer X as if it's a signed word.
-;; %i: print the first nonzero HImode part of X
-;; %j: print the first HImode part unequal to 0xffff of X
-
+;; %x: print integer X as if it's an unsigned halfword.
+;; %h: print integer X as if it's a signed halfword.
+;; %i: print the first nonzero HImode part of X.
+;; %j: print the first HImode part unequal to -1 of X.
+;; %k: print the first nonzero SImode part of X.
+;; %m: print the first SImode part unequal to -1 of X.
+;; %o: print integer X as if it's an unsigned 32bit word.
;;
;; We have a special constraint for pattern matching.
;;
@@ -78,7 +59,8 @@
(define_constants
[; Miscellaneous
(UNSPEC_ROUND 1)
- (UNSPEC_SETHIGH 10)
+ (UNSPEC_CMPINT 2)
+ (UNSPEC_ICM 10)
; GOT/PLT and lt-relative accesses
(UNSPEC_LTREL_OFFSET 100)
@@ -92,6 +74,9 @@
; Literal pool
(UNSPEC_RELOAD_BASE 210)
(UNSPEC_MAIN_BASE 211)
+ (UNSPEC_LTREF 212)
+ (UNSPEC_INSN 213)
+ (UNSPEC_EXECUTE 214)
; TLS relocation specifiers
(UNSPEC_TLSGD 500)
@@ -102,12 +87,16 @@
(UNSPEC_INDNTPOFF 505)
; TLS support
- (UNSPEC_TP 510)
(UNSPEC_TLSLDM_NTPOFF 511)
(UNSPEC_TLS_LOAD 512)
; String Functions
- (UNSPEC_SRST 600)
+ (UNSPEC_SRST 600)
+ (UNSPEC_MVST 601)
+
+ ; Stack Smashing Protector
+ (UNSPEC_SP_SET 700)
+ (UNSPEC_SP_TEST 701)
])
;;
@@ -118,233 +107,241 @@
[; Blockage
(UNSPECV_BLOCKAGE 0)
+ ; TPF Support
+ (UNSPECV_TPF_PROLOGUE 20)
+ (UNSPECV_TPF_EPILOGUE 21)
+
; Literal pool
(UNSPECV_POOL 200)
- (UNSPECV_POOL_START 201)
- (UNSPECV_POOL_END 202)
+ (UNSPECV_POOL_SECTION 201)
+ (UNSPECV_POOL_ALIGN 202)
(UNSPECV_POOL_ENTRY 203)
(UNSPECV_MAIN_POOL 300)
; TLS support
(UNSPECV_SET_TP 500)
- ])
-
-;; Processor type. This attribute must exactly match the processor_type
-;; enumeration in s390.h.
+ ; Atomic Support
+ (UNSPECV_MB 700)
+ (UNSPECV_CAS 701)
+ ])
-(define_attr "cpu" "g5,g6,z900,z990"
- (const (symbol_ref "s390_tune")))
+;;
+;; Registers
+;;
-;; Define an insn type attribute. This is used in function unit delay
-;; computations.
+(define_constants
+ [
+ ; Sibling call register.
+ (SIBCALL_REGNUM 1)
+ ; Literal pool base register.
+ (BASE_REGNUM 13)
+ ; Return address register.
+ (RETURN_REGNUM 14)
+ ; Condition code register.
+ (CC_REGNUM 33)
+ ; Thread local storage pointer register.
+ (TP_REGNUM 36)
+ ])
-(define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
- cs,vs,store,imul,idiv,
- branch,jsr,fsimpd,fsimps,
- floadd,floads,fstored, fstores,
- fmuld,fmuls,fdivd,fdivs,
- ftoi,itof,fsqrtd,fsqrts,
- other,o2,o3"
- (const_string "integer"))
-;; Operand type. Used to default length attribute values
+;; Instruction operand type as used in the Principles of Operation.
+;; Used to determine defaults for length and other attribute values.
(define_attr "op_type"
"NN,E,RR,RRE,RX,RS,RSI,RI,SI,S,SS,SSE,RXE,RSE,RIL,RIE,RXY,RSY,SIY"
- (const_string "RX"))
+ (const_string "NN"))
-;; Insn are devide in two classes:
-;; agen: Insn using agen
-;; reg: Insn not using agen
+;; Instruction type attribute used for scheduling.
+
+(define_attr "type" "none,integer,load,lr,la,larl,lm,stm,
+ cs,vs,store,sem,idiv,
+ imulhi,imulsi,imuldi,
+ branch,jsr,fsimptf,fsimpdf,fsimpsf,
+ floadtf,floaddf,floadsf,fstoredf,fstoresf,
+ fmultf,fmuldf,fmulsf,fdivtf,fdivdf,fdivsf,
+ ftoi,itof,fsqrttf,fsqrtdf,fsqrtsf,
+ ftrunctf,ftruncdf,other"
+ (cond [(eq_attr "op_type" "NN") (const_string "other")
+ (eq_attr "op_type" "SS") (const_string "cs")]
+ (const_string "integer")))
+
+;; Another attribute used for scheduling purposes:
+;; agen: Instruction uses the address generation unit
+;; reg: Instruction does not use the agen unit
(define_attr "atype" "agen,reg"
-(cond [ (eq_attr "op_type" "E") (const_string "reg")
- (eq_attr "op_type" "RR") (const_string "reg")
- (eq_attr "op_type" "RX") (const_string "agen")
- (eq_attr "op_type" "RI") (const_string "reg")
- (eq_attr "op_type" "RRE") (const_string "reg")
- (eq_attr "op_type" "RS") (const_string "agen")
- (eq_attr "op_type" "RSI") (const_string "agen")
- (eq_attr "op_type" "S") (const_string "agen")
- (eq_attr "op_type" "SI") (const_string "agen")
- (eq_attr "op_type" "SS") (const_string "agen")
- (eq_attr "op_type" "SSE") (const_string "agen")
- (eq_attr "op_type" "RXE") (const_string "agen")
- (eq_attr "op_type" "RSE") (const_string "agen")
- (eq_attr "op_type" "RIL") (const_string "agen")
- (eq_attr "op_type" "RXY") (const_string "agen")
- (eq_attr "op_type" "RSY") (const_string "agen")
- (eq_attr "op_type" "SIY") (const_string "agen")]
- (const_string "reg")))
+ (if_then_else (eq_attr "op_type" "E,RR,RI,RRE")
+ (const_string "reg")
+ (const_string "agen")))
-;; Generic pipeline function unit.
+;; Length in bytes.
-(define_function_unit "integer" 1 0
- (eq_attr "type" "none") 0 0)
+(define_attr "length" ""
+ (cond [(eq_attr "op_type" "E,RR") (const_int 2)
+ (eq_attr "op_type" "RX,RI,RRE,RS,RSI,S,SI") (const_int 4)]
+ (const_int 6)))
-(define_function_unit "integer" 1 0
- (eq_attr "type" "integer") 1 1)
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fsimpd") 1 1)
+;; Processor type. This attribute must exactly match the processor_type
+;; enumeration in s390.h. The current machine description does not
+;; distinguish between g5 and g6, but there are differences between the two
+;; CPUs could in theory be modeled.
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fsimps") 1 1)
+(define_attr "cpu" "g5,g6,z900,z990,z9_109"
+ (const (symbol_ref "s390_tune")))
-(define_function_unit "integer" 1 0
- (eq_attr "type" "load") 1 1)
+;; Pipeline description for z900. For lack of anything better,
+;; this description is also used for the g5 and g6.
+(include "2064.md")
-(define_function_unit "integer" 1 0
- (eq_attr "type" "floadd") 1 1)
+;; Pipeline description for z990.
+(include "2084.md")
-(define_function_unit "integer" 1 0
- (eq_attr "type" "floads") 1 1)
+;; Predicates
+(include "predicates.md")
-(define_function_unit "integer" 1 0
- (eq_attr "type" "la") 1 1)
+;; Constraint definitions
+(include "constraints.md")
-(define_function_unit "integer" 1 0
- (eq_attr "type" "larl") 1 1)
+;; Other includes
+(include "tpf.md")
-(define_function_unit "integer" 1 0
- (eq_attr "type" "lr") 1 1)
+;; Macros
-(define_function_unit "integer" 1 0
- (eq_attr "type" "branch") 1 1)
+;; This mode macro allows floating point patterns to be generated from the
+;; same template.
+(define_mode_macro FPR [TF DF SF])
+(define_mode_macro DSF [DF SF])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "store") 1 1)
+;; These mode macros allow 31-bit and 64-bit TDSI patterns to be generated
+;; from the same template.
+(define_mode_macro TDSI [(TI "TARGET_64BIT") DI SI])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fstored") 1 1)
+;; These mode macros allow 31-bit and 64-bit GPR patterns to be generated
+;; from the same template.
+(define_mode_macro GPR [(DI "TARGET_64BIT") SI])
+(define_mode_macro DSI [DI SI])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fstores") 1 1)
+;; This mode macro allows :P to be used for patterns that operate on
+;; pointer-sized quantities. Exactly one of the two alternatives will match.
+(define_mode_macro DP [(TI "TARGET_64BIT") (DI "!TARGET_64BIT")])
+(define_mode_macro P [(DI "TARGET_64BIT") (SI "!TARGET_64BIT")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "lm") 2 2)
+;; This mode macro allows the QI and HI patterns to be defined from
+;; the same template.
+(define_mode_macro HQI [HI QI])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "stm") 2 2)
+;; This mode macro allows the integer patterns to be defined from the
+;; same template.
+(define_mode_macro INT [(DI "TARGET_64BIT") SI HI QI])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "cs") 5 5)
+;; This macro allows to unify all 'bCOND' expander patterns.
+(define_code_macro COMPARE [eq ne gt gtu lt ltu ge geu le leu unordered
+ ordered uneq unlt ungt unle unge ltgt])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "vs") 30 30)
+;; This macro allows to unify all 'sCOND' patterns.
+(define_code_macro SCOND [ltu gtu leu geu])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "jsr") 5 5)
+;; This macro allows some 'ashift' and 'lshiftrt' pattern to be defined from
+;; the same template.
+(define_code_macro SHIFT [ashift lshiftrt])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "imul") 7 7)
+;; These macros allow to combine most atomic operations.
+(define_code_macro ATOMIC [and ior xor plus minus mult])
+(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
+ (plus "add") (minus "sub") (mult "nand")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fmuld") 6 6)
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fmuls") 6 6)
+;; In FPR templates, a string like "lt<de>br" will expand to "ltxbr" in TFmode,
+;; "ltdbr" in DFmode, and "ltebr" in SFmode.
+(define_mode_attr xde [(TF "x") (DF "d") (SF "e")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "idiv") 33 33)
+;; In FPR templates, a string like "m<dee>br" will expand to "mxbr" in TFmode,
+;; "mdbr" in DFmode, and "meebr" in SFmode.
+(define_mode_attr xdee [(TF "x") (DF "d") (SF "ee")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fdivd") 33 33)
+;; In FPR templates, "<RRe>" will expand to "RRE" in TFmode and "RR" otherwise.
+;; Likewise for "<RXe>".
+(define_mode_attr RRe [(TF "RRE") (DF "RR") (SF "RR")])
+(define_mode_attr RXe [(TF "RXE") (DF "RX") (SF "RX")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fdivs") 33 33)
+;; In FPR templates, "<Rf>" will expand to "f" in TFmode and "R" otherwise.
+;; This is used to disable the memory alternative in TFmode patterns.
+(define_mode_attr Rf [(TF "f") (DF "R") (SF "R")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fsqrtd") 30 30)
+;; In GPR and P templates, a constraint like "<d0>" will expand to "d" in DImode
+;; and "0" in SImode. This allows to combine instructions of which the 31bit
+;; version only operates on one register.
+(define_mode_attr d0 [(DI "d") (SI "0")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "fsqrts") 30 30)
+;; In combination with d0 this allows to combine instructions of which the 31bit
+;; version only operates on one register. The DImode version needs an additional
+;; register for the assembler output.
+(define_mode_attr 1 [(DI "%1,") (SI "")])
+
+;; In SHIFT templates, a string like "s<lr>dl" will expand to "sldl" in
+;; 'ashift' and "srdl" in 'lshiftrt'.
+(define_code_attr lr [(ashift "l") (lshiftrt "r")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "ftoi") 2 2)
+;; In SHIFT templates, this attribute holds the correct standard name for the
+;; pattern itself and the corresponding function calls.
+(define_code_attr shift [(ashift "ashl") (lshiftrt "lshr")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "itof") 2 2)
+;; This attribute handles differences in the instruction 'type' and will result
+;; in "RRE" for DImode and "RR" for SImode.
+(define_mode_attr E [(DI "E") (SI "")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "o2") 2 2)
+;; This attribute handles differences in the instruction 'type' and makes RX<Y>
+;; to result in "RXY" for DImode and "RX" for SImode.
+(define_mode_attr Y [(DI "Y") (SI "")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "o3") 3 3)
+;; This attribute handles differences in the instruction 'type' and will result
+;; in "RSE" for TImode and "RS" for DImode.
+(define_mode_attr TE [(TI "E") (DI "")])
-(define_function_unit "integer" 1 0
- (eq_attr "type" "other") 5 5)
+;; In GPR templates, a string like "lc<g>r" will expand to "lcgr" in DImode
+;; and "lcr" in SImode.
+(define_mode_attr g [(DI "g") (SI "")])
-;; Pipeline description for z900
+;; In GPR templates, a string like "sl<y>" will expand to "slg" in DImode
+;; and "sly" in SImode. This is useful because on 64bit the ..g instructions
+;; were enhanced with long displacements whereas 31bit instructions got a ..y
+;; variant for long displacements.
+(define_mode_attr y [(DI "g") (SI "y")])
-(include "2064.md")
-(include "2084.md")
+;; In DP templates, a string like "cds<g>" will expand to "cdsg" in TImode
+;; and "cds" in DImode.
+(define_mode_attr tg [(TI "g") (DI "")])
-;; Length in bytes.
+;; In GPR templates, a string like "c<gf>dbr" will expand to "cgdbr" in DImode
+;; and "cfdbr" in SImode.
+(define_mode_attr gf [(DI "g") (SI "f")])
-(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" "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)
- (eq_attr "op_type" "RXY") (const_int 6)
- (eq_attr "op_type" "RSY") (const_int 6)
- (eq_attr "op_type" "SIY") (const_int 6)]
- (const_int 4)))
-
-;; Define attributes for `asm' insns.
-
-(define_asm_attributes [(set_attr "type" "other")
- (set_attr "op_type" "NN")])
+;; ICM mask required to load MODE value into the lowest subreg
+;; of a SImode register.
+(define_mode_attr icm_lo [(HI "3") (QI "1")])
-;;
-;; 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)
+;; In HQI templates, a string like "llg<hc>" will expand to "llgh" in
+;; HImode and "llgc" in QImode.
+(define_mode_attr hc [(HI "h") (QI "c")])
-; CCZ -> CCL / CCZ1
-; CCZ1 -> CCA/CCU/CCS/CCT
-; CCS -> CCA
+;; In P templates, the mode <DBL> will expand to "TI" in DImode and "DI"
+;; in SImode.
+(define_mode_attr DBL [(DI "TI") (SI "DI")])
-; 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
+;; Maximum unsigned integer that fits in MODE.
+(define_mode_attr max_uint [(HI "65535") (QI "255")])
;;
;;- 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" "")))]
+(define_expand "cmp<mode>"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:GPR 0 "register_operand" "")
+ (match_operand:GPR 1 "general_operand" "")))]
""
{
s390_compare_op0 = operands[0];
@@ -352,10 +349,10 @@
DONE;
})
-(define_expand "cmpdf"
- [(set (reg:CC 33)
- (compare:CC (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "general_operand" "")))]
+(define_expand "cmp<mode>"
+ [(set (reg:CC CC_REGNUM)
+ (compare:CC (match_operand:FPR 0 "register_operand" "")
+ (match_operand:FPR 1 "general_operand" "")))]
"TARGET_HARD_FLOAT"
{
s390_compare_op0 = operands[0];
@@ -363,185 +360,28 @@
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;
-})
-
-
-; Test-under-Mask (zero_extract) instructions
-
-(define_insn "*tmdi_ext"
- [(set (reg 33)
- (compare (zero_extract:DI (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const_int_operand" "n")
- (match_operand:DI 2 "const_int_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 64
- && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
- == INTVAL (operands[2]) >> 4"
-{
- int part = INTVAL (operands[2]) >> 4;
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
- operands[2] = GEN_INT (block << shift);
-
- switch (part)
- {
- case 0: return "tmhh\t%0,%x2";
- case 1: return "tmhl\t%0,%x2";
- case 2: return "tmlh\t%0,%x2";
- case 3: return "tmll\t%0,%x2";
- default: abort ();
- }
-}
- [(set_attr "op_type" "RI")])
-
-(define_insn "*tmsi_ext"
- [(set (reg 33)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "const_int_operand" "n"))
- (const_int 0)))]
- "s390_match_ccmode(insn, CCTmode)
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32
- && (INTVAL (operands[1]) + INTVAL (operands[2]) - 1) >> 4
- == INTVAL (operands[2]) >> 4"
-{
- int part = INTVAL (operands[2]) >> 4;
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 16 - INTVAL (operands[1]) - (INTVAL (operands[2]) & 15);
-
- operands[2] = GEN_INT (block << shift);
-
- switch (part)
- {
- case 0: return "tmh\t%0,%x2";
- case 1: return "tml\t%0,%x2";
- default: abort ();
- }
-}
- [(set_attr "op_type" "RI")])
-
-(define_insn "*tmqisi_ext"
- [(set (reg 33)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "Q,S")
- (match_operand:SI 1 "const_int_operand" "n,n")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (const_int 0)))]
- "!TARGET_64BIT && s390_match_ccmode(insn, CCTmode)
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
-{
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
- operands[2] = GEN_INT (block << shift);
- return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2";
-}
- [(set_attr "op_type" "SI,SIY")])
-
-(define_insn "*tmqidi_ext"
- [(set (reg 33)
- (compare (zero_extract:DI (match_operand:QI 0 "memory_operand" "Q,S")
- (match_operand:SI 1 "const_int_operand" "n,n")
- (match_operand:SI 2 "const_int_operand" "n,n"))
- (const_int 0)))]
- "TARGET_64BIT && s390_match_ccmode(insn, CCTmode)
- && INTVAL (operands[1]) >= 1 && INTVAL (operands[2]) >= 0
- && INTVAL (operands[1]) + INTVAL (operands[2]) <= 8"
-{
- int block = (1 << INTVAL (operands[1])) - 1;
- int shift = 8 - INTVAL (operands[1]) - INTVAL (operands[2]);
-
- operands[2] = GEN_INT (block << shift);
- return which_alternative == 0 ? "tm\t%0,%b2" : "tmy\t%0,%b2";
-}
- [(set_attr "op_type" "SI,SIY")])
-
; Test-under-Mask instructions
-(define_insn "*tmdi_mem"
- [(set (reg 33)
- (compare (and:DI (match_operand:DI 0 "memory_operand" "Q,S")
- (match_operand:DI 1 "immediate_operand" "n,n"))
- (match_operand:DI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
- && s390_single_part (operands[1], DImode, QImode, 0) >= 0"
-{
- int part = s390_single_part (operands[1], DImode, QImode, 0);
- operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
- operands[0] = gen_rtx_MEM (QImode,
- plus_constant (XEXP (operands[0], 0), part));
- return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
- [(set_attr "op_type" "SI,SIY")])
-
-(define_insn "*tmsi_mem"
- [(set (reg 33)
- (compare (and:SI (match_operand:SI 0 "memory_operand" "Q,S")
- (match_operand:SI 1 "immediate_operand" "n,n"))
- (match_operand:SI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
- && s390_single_part (operands[1], SImode, QImode, 0) >= 0"
-{
- int part = s390_single_part (operands[1], SImode, QImode, 0);
- operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
- operands[0] = gen_rtx_MEM (QImode,
- plus_constant (XEXP (operands[0], 0), part));
- return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
- [(set_attr "op_type" "SI")])
-
-(define_insn "*tmhi_mem"
- [(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:HI 0 "memory_operand" "Q,S") 0)
- (match_operand:SI 1 "immediate_operand" "n,n"))
- (match_operand:SI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))
- && s390_single_part (operands[1], HImode, QImode, 0) >= 0"
-{
- int part = s390_single_part (operands[1], HImode, QImode, 0);
- operands[1] = GEN_INT (s390_extract_part (operands[1], QImode, 0));
-
- operands[0] = gen_rtx_MEM (QImode,
- plus_constant (XEXP (operands[0], 0), part));
- return which_alternative == 0 ? "tm\t%0,%b1" : "tmy\t%0,%b1";
-}
- [(set_attr "op_type" "SI")])
-
(define_insn "*tmqi_mem"
- [(set (reg 33)
- (compare (and:SI (subreg:SI (match_operand:QI 0 "memory_operand" "Q,S") 0)
- (match_operand:SI 1 "immediate_operand" "n,n"))
- (match_operand:SI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 0))"
- "@
- tm\t%0,%b1
- tmy\t%0,%b1"
+ [(set (reg CC_REGNUM)
+ (compare (and:QI (match_operand:QI 0 "memory_operand" "Q,S")
+ (match_operand:QI 1 "immediate_operand" "n,n"))
+ (match_operand:QI 2 "immediate_operand" "n,n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], false))"
+ "@
+ tm\t%S0,%b1
+ tmy\t%S0,%b1"
[(set_attr "op_type" "SI,SIY")])
(define_insn "*tmdi_reg"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (and:DI (match_operand:DI 0 "nonimmediate_operand" "d,d,d,d")
- (match_operand:DI 1 "immediate_operand"
+ (match_operand:DI 1 "immediate_operand"
"N0HD0,N1HD0,N2HD0,N3HD0"))
(match_operand:DI 2 "immediate_operand" "n,n,n,n")))]
"TARGET_64BIT
- && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
+ && s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], true))
&& s390_single_part (operands[1], DImode, HImode, 0) >= 0"
"@
tmhh\t%0,%i1
@@ -551,38 +391,34 @@
[(set_attr "op_type" "RI")])
(define_insn "*tmsi_reg"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (and:SI (match_operand:SI 0 "nonimmediate_operand" "d,d")
(match_operand:SI 1 "immediate_operand" "N0HS0,N1HS0"))
(match_operand:SI 2 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], 1))
+ "s390_match_ccmode (insn, s390_tm_ccmode (operands[1], operands[2], true))
&& s390_single_part (operands[1], SImode, HImode, 0) >= 0"
"@
tmh\t%0,%i1
tml\t%0,%i1"
[(set_attr "op_type" "RI")])
-(define_insn "*tmhi_full"
- [(set (reg 33)
- (compare (match_operand:HI 0 "register_operand" "d")
- (match_operand:HI 1 "immediate_operand" "n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
- "tml\t%0,65535"
- [(set_attr "op_type" "RX")])
-
-(define_insn "*tmqi_full"
- [(set (reg 33)
- (compare (match_operand:QI 0 "register_operand" "d")
- (match_operand:QI 1 "immediate_operand" "n")))]
- "s390_match_ccmode (insn, s390_tm_ccmode (GEN_INT (-1), operands[1], 1))"
- "tml\t%0,255"
+(define_insn "*tm<mode>_full"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HQI 0 "register_operand" "d")
+ (match_operand:HQI 1 "immediate_operand" "n")))]
+ "s390_match_ccmode (insn, s390_tm_ccmode (constm1_rtx, operands[1], true))"
+ "tml\t%0,<max_uint>"
[(set_attr "op_type" "RI")])
+;
; Load-and-Test instructions
+;
+
+; tst(di|si) instruction pattern(s).
(define_insn "*tstdi_sign"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 0 "register_operand" "d") 0)
(const_int 32)) (const_int 32))
(match_operand:DI 1 "const0_operand" "")))
@@ -592,167 +428,180 @@
"ltgfr\t%2,%0"
[(set_attr "op_type" "RRE")])
+; ltr, lt, ltgr, ltg
+(define_insn "*tst<mode>_extimm"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 0 "nonimmediate_operand" "d,m")
+ (match_operand:GPR 1 "const0_operand" "")))
+ (set (match_operand:GPR 2 "register_operand" "=d,d")
+ (match_dup 0))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_EXTIMM"
+ "@
+ lt<g>r\t%2,%0
+ lt<g>\t%2,%0"
+ [(set_attr "op_type" "RR<E>,RXY")])
+
+; ltr, lt, ltgr, ltg
+(define_insn "*tst<mode>_cconly_extimm"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 0 "nonimmediate_operand" "d,m")
+ (match_operand:GPR 1 "const0_operand" "")))
+ (clobber (match_scratch:GPR 2 "=X,d"))]
+ "s390_match_ccmode(insn, CCSmode) && TARGET_EXTIMM"
+ "@
+ lt<g>r\t%0,%0
+ lt<g>\t%2,%0"
+ [(set_attr "op_type" "RR<E>,RXY")])
+
(define_insn "*tstdi"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(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"
+ "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT && !TARGET_EXTIMM"
"ltgr\t%2,%0"
[(set_attr "op_type" "RRE")])
-(define_insn "*tstdi_cconly"
- [(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")])
-
-(define_insn "*tstdi_cconly_31"
- [(set (reg 33)
- (compare (match_operand:DI 0 "register_operand" "d")
- (match_operand:DI 1 "const0_operand" "")))]
- "s390_match_ccmode(insn, CCSmode) && !TARGET_64BIT"
- "srda\t%0,0"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-
(define_insn "*tstsi"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (match_operand:SI 0 "nonimmediate_operand" "d,Q,S")
(match_operand:SI 1 "const0_operand" "")))
(set (match_operand:SI 2 "register_operand" "=d,d,d")
(match_dup 0))]
- "s390_match_ccmode(insn, CCSmode)"
+ "s390_match_ccmode(insn, CCSmode) && !TARGET_EXTIMM"
"@
ltr\t%2,%0
- icm\t%2,15,%0
- icmy\t%2,15,%0"
+ icm\t%2,15,%S0
+ icmy\t%2,15,%S0"
[(set_attr "op_type" "RR,RS,RSY")])
(define_insn "*tstsi_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (match_operand:SI 0 "nonimmediate_operand" "d,Q,S")
(match_operand:SI 1 "const0_operand" "")))
(clobber (match_scratch:SI 2 "=X,d,d"))]
"s390_match_ccmode(insn, CCSmode)"
"@
ltr\t%0,%0
- icm\t%2,15,%0
- icmy\t%2,15,%0"
+ icm\t%2,15,%S0
+ icmy\t%2,15,%S0"
[(set_attr "op_type" "RR,RS,RSY")])
-(define_insn "*tstsi_cconly2"
- [(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const0_operand" "")))]
+(define_insn "*tstdi_cconly_31"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:DI 0 "register_operand" "d")
+ (match_operand:DI 1 "const0_operand" "")))]
+ "s390_match_ccmode(insn, CCSmode) && !TARGET_64BIT"
+ "srda\t%0,0"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "reg")])
+
+; ltr, ltgr
+(define_insn "*tst<mode>_cconly2"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 0 "register_operand" "d")
+ (match_operand:GPR 1 "const0_operand" "")))]
"s390_match_ccmode(insn, CCSmode)"
- "ltr\t%0,%0"
- [(set_attr "op_type" "RR")])
+ "lt<g>r\t%0,%0"
+ [(set_attr "op_type" "RR<E>")])
-(define_insn "*tsthiCCT"
- [(set (reg 33)
- (compare (match_operand:HI 0 "nonimmediate_operand" "?Q,?S,d")
- (match_operand:HI 1 "const0_operand" "")))
- (set (match_operand:HI 2 "register_operand" "=d,d,0")
+; tst(hi|qi) instruction pattern(s).
+
+(define_insn "*tst<mode>CCT"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HQI 0 "nonimmediate_operand" "?Q,?S,d")
+ (match_operand:HQI 1 "const0_operand" "")))
+ (set (match_operand:HQI 2 "register_operand" "=d,d,0")
(match_dup 0))]
"s390_match_ccmode(insn, CCTmode)"
"@
- icm\t%2,3,%0
- icmy\t%2,3,%0
- tml\t%0,65535"
+ icm\t%2,<icm_lo>,%S0
+ icmy\t%2,<icm_lo>,%S0
+ tml\t%0,<max_uint>"
[(set_attr "op_type" "RS,RSY,RI")])
(define_insn "*tsthiCCT_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (match_operand:HI 0 "nonimmediate_operand" "Q,S,d")
(match_operand:HI 1 "const0_operand" "")))
(clobber (match_scratch:HI 2 "=d,d,X"))]
"s390_match_ccmode(insn, CCTmode)"
"@
- icm\t%2,3,%0
- icmy\t%2,3,%0
+ icm\t%2,3,%S0
+ icmy\t%2,3,%S0
tml\t%0,65535"
[(set_attr "op_type" "RS,RSY,RI")])
-(define_insn "*tsthi"
- [(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Q,S")
- (match_operand:HI 1 "const0_operand" "")))
- (set (match_operand:HI 2 "register_operand" "=d,d")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- icm\t%2,3,%0
- icmy\t%2,3,%0"
- [(set_attr "op_type" "RS,RSY")])
-
-(define_insn "*tsthi_cconly"
- [(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Q,S")
- (match_operand:HI 1 "const0_operand" "")))
- (clobber (match_scratch:HI 2 "=d,d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "@
- icm\t%2,3,%0
- icmy\t%2,3,%0"
- [(set_attr "op_type" "RS,RSY")])
-
-(define_insn "*tstqiCCT"
- [(set (reg 33)
- (compare (match_operand:QI 0 "nonimmediate_operand" "?Q,?S,d")
- (match_operand:QI 1 "const0_operand" "")))
- (set (match_operand:QI 2 "register_operand" "=d,d,0")
- (match_dup 0))]
- "s390_match_ccmode(insn, CCTmode)"
- "@
- icm\t%2,1,%0
- icmy\t%2,1,%0
- tml\t%0,255"
- [(set_attr "op_type" "RS,RSY,RI")])
-
(define_insn "*tstqiCCT_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (match_operand:QI 0 "nonimmediate_operand" "?Q,?S,d")
(match_operand:QI 1 "const0_operand" "")))]
"s390_match_ccmode(insn, CCTmode)"
"@
- cli\t%0,0
- cliy\t%0,0
+ cli\t%S0,0
+ cliy\t%S0,0
tml\t%0,255"
[(set_attr "op_type" "SI,SIY,RI")])
-(define_insn "*tstqi"
- [(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Q,S")
- (match_operand:QI 1 "const0_operand" "")))
- (set (match_operand:QI 2 "register_operand" "=d,d")
+(define_insn "*tst<mode>"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HQI 0 "s_operand" "Q,S")
+ (match_operand:HQI 1 "const0_operand" "")))
+ (set (match_operand:HQI 2 "register_operand" "=d,d")
(match_dup 0))]
"s390_match_ccmode(insn, CCSmode)"
"@
- icm\t%2,1,%0
- icmy\t%2,1,%0"
+ icm\t%2,<icm_lo>,%S0
+ icmy\t%2,<icm_lo>,%S0"
[(set_attr "op_type" "RS,RSY")])
-(define_insn "*tstqi_cconly"
- [(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Q,S")
- (match_operand:QI 1 "const0_operand" "")))
- (clobber (match_scratch:QI 2 "=d,d"))]
+(define_insn "*tst<mode>_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HQI 0 "s_operand" "Q,S")
+ (match_operand:HQI 1 "const0_operand" "")))
+ (clobber (match_scratch:HQI 2 "=d,d"))]
"s390_match_ccmode(insn, CCSmode)"
"@
- icm\t%2,1,%0
- icmy\t%2,1,%0"
+ icm\t%2,<icm_lo>,%S0
+ icmy\t%2,<icm_lo>,%S0"
[(set_attr "op_type" "RS,RSY")])
+; Compare (equality) instructions
+
+(define_insn "*cmpdi_cct"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:DI 0 "nonimmediate_operand" "%d,d,d,d,Q")
+ (match_operand:DI 1 "general_operand" "d,K,Os,m,BQ")))]
+ "s390_match_ccmode (insn, CCTmode) && TARGET_64BIT"
+ "@
+ cgr\t%0,%1
+ cghi\t%0,%h1
+ cgfi\t%0,%1
+ cg\t%0,%1
+ #"
+ [(set_attr "op_type" "RRE,RI,RIL,RXY,SS")])
+
+(define_insn "*cmpsi_cct"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "%d,d,d,d,d,Q")
+ (match_operand:SI 1 "general_operand" "d,K,Os,R,T,BQ")))]
+ "s390_match_ccmode (insn, CCTmode)"
+ "@
+ cr\t%0,%1
+ chi\t%0,%h1
+ cfi\t%0,%1
+ c\t%0,%1
+ cy\t%0,%1
+ #"
+ [(set_attr "op_type" "RR,RI,RIL,RX,RXY,SS")])
+
+
; Compare (signed) instructions
(define_insn "*cmpdi_ccs_sign"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
(match_operand:DI 0 "register_operand" "d,d")))]
"s390_match_ccmode(insn, CCSRmode) && TARGET_64BIT"
@@ -761,19 +610,8 @@
cgf\t%0,%1"
[(set_attr "op_type" "RRE,RXY")])
-(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,RXY")])
-
(define_insn "*cmpsi_ccs_sign"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T"))
(match_operand:SI 0 "register_operand" "d,d")))]
"s390_match_ccmode(insn, CCSRmode)"
@@ -782,199 +620,168 @@
chy\t%0,%1"
[(set_attr "op_type" "RX,RXY")])
-(define_insn "*cmpsi_ccs"
- [(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d,d,d,d")
- (match_operand:SI 1 "general_operand" "d,K,R,T")))]
+; cr, chi, cfi, c, cy, cgr, cghi, cgfi, cg
+(define_insn "*cmp<mode>_ccs"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 0 "register_operand" "d,d,d,d,d")
+ (match_operand:GPR 1 "general_operand" "d,K,Os,R,T")))]
"s390_match_ccmode(insn, CCSmode)"
"@
- cr\t%0,%1
- chi\t%0,%c1
- c\t%0,%1
- cy\t%0,%1"
- [(set_attr "op_type" "RR,RI,RX,RXY")])
+ c<g>r\t%0,%1
+ c<g>hi\t%0,%h1
+ c<g>fi\t%0,%1
+ c<g>\t%0,%1
+ c<y>\t%0,%1"
+ [(set_attr "op_type" "RR<E>,RI,RIL,RX<Y>,RXY")])
; Compare (unsigned) instructions
(define_insn "*cmpdi_ccu_zero"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "d,m"))
(match_operand:DI 0 "register_operand" "d,d")))]
- "s390_match_ccmode(insn, CCURmode) && TARGET_64BIT"
+ "s390_match_ccmode (insn, CCURmode) && TARGET_64BIT"
"@
clgfr\t%0,%1
clgf\t%0,%1"
[(set_attr "op_type" "RRE,RXY")])
(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"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:DI 0 "nonimmediate_operand" "d,d,d,Q,BQ")
+ (match_operand:DI 1 "general_operand" "d,Op,m,BQ,Q")))]
+ "s390_match_ccmode (insn, CCUmode) && TARGET_64BIT"
"@
clgr\t%0,%1
- clg\t%0,%1"
- [(set_attr "op_type" "RRE,RXY")])
+ clgfi\t%0,%1
+ clg\t%0,%1
+ #
+ #"
+ [(set_attr "op_type" "RRE,RIL,RXY,SS,SS")])
(define_insn "*cmpsi_ccu"
- [(set (reg 33)
- (compare (match_operand:SI 0 "register_operand" "d,d,d")
- (match_operand:SI 1 "general_operand" "d,R,T")))]
- "s390_match_ccmode(insn, CCUmode)"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:SI 0 "nonimmediate_operand" "d,d,d,d,Q,BQ")
+ (match_operand:SI 1 "general_operand" "d,Os,R,T,BQ,Q")))]
+ "s390_match_ccmode (insn, CCUmode)"
"@
clr\t%0,%1
+ clfi\t%0,%o1
cl\t%0,%1
- cly\t%0,%1"
- [(set_attr "op_type" "RR,RX,RXY")])
+ cly\t%0,%1
+ #
+ #"
+ [(set_attr "op_type" "RR,RIL,RX,RXY,SS,SS")])
(define_insn "*cmphi_ccu"
- [(set (reg 33)
- (compare (match_operand:HI 0 "register_operand" "d,d")
- (match_operand:HI 1 "s_imm_operand" "Q,S")))]
- "s390_match_ccmode(insn, CCUmode)"
- "@
- clm\t%0,3,%1
- clmy\t%0,3,%1"
- [(set_attr "op_type" "RS,RSY")])
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:HI 0 "nonimmediate_operand" "d,d,Q,BQ")
+ (match_operand:HI 1 "general_operand" "Q,S,BQ,Q")))]
+ "s390_match_ccmode (insn, CCUmode)
+ && !register_operand (operands[1], HImode)"
+ "@
+ clm\t%0,3,%S1
+ clmy\t%0,3,%S1
+ #
+ #"
+ [(set_attr "op_type" "RS,RSY,SS,SS")])
(define_insn "*cmpqi_ccu"
- [(set (reg 33)
- (compare (match_operand:QI 0 "register_operand" "d,d")
- (match_operand:QI 1 "s_imm_operand" "Q,S")))]
- "s390_match_ccmode(insn, CCUmode)"
- "@
- clm\t%0,1,%1
- clmy\t%0,1,%1"
- [(set_attr "op_type" "RS,RSY")])
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:QI 0 "nonimmediate_operand" "d,d,Q,S,Q,BQ")
+ (match_operand:QI 1 "general_operand" "Q,S,n,n,BQ,Q")))]
+ "s390_match_ccmode (insn, CCUmode)
+ && !register_operand (operands[1], QImode)"
+ "@
+ clm\t%0,1,%S1
+ clmy\t%0,1,%S1
+ cli\t%S0,%b1
+ cliy\t%S0,%b1
+ #
+ #"
+ [(set_attr "op_type" "RS,RSY,SI,SIY,SS,SS")])
-(define_insn "*cli"
- [(set (reg 33)
- (compare (match_operand:QI 0 "memory_operand" "Q,S")
- (match_operand:QI 1 "immediate_operand" "n,n")))]
- "s390_match_ccmode (insn, CCUmode)"
- "@
- cli\t%0,%b1
- cliy\t%0,%b1"
- [(set_attr "op_type" "SI,SIY")])
-(define_insn "*cmpdi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:DI 0 "s_operand" "Q")
- (match_operand:DI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
+; Block compare (CLC) instruction patterns.
-(define_insn "*cmpsi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:SI 0 "s_operand" "Q")
- (match_operand:SI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*cmphi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:HI 0 "s_operand" "Q")
- (match_operand:HI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(2,%R0),%1"
+(define_insn "*clc"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:BLK 0 "memory_operand" "Q")
+ (match_operand:BLK 1 "memory_operand" "Q")))
+ (use (match_operand 2 "const_int_operand" "n"))]
+ "s390_match_ccmode (insn, CCUmode)
+ && INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+ "clc\t%O0(%2,%R0),%S1"
[(set_attr "op_type" "SS")])
-(define_insn "*cmpqi_ccu_mem"
- [(set (reg 33)
- (compare (match_operand:QI 0 "s_operand" "Q")
- (match_operand:QI 1 "s_imm_operand" "Q")))]
- "s390_match_ccmode(insn, CCUmode)"
- "clc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-
-; 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" "RRE")
- (set_attr "type" "fsimpd")])
-
-(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" "fsimpd")])
-
-(define_insn "*cmpdf_ccs"
- [(set (reg 33)
- (compare (match_operand:DF 0 "register_operand" "f,f")
- (match_operand:DF 1 "general_operand" "f,R")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- cdbr\t%0,%1
- cdb\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd")])
+(define_split
+ [(set (reg CC_REGNUM)
+ (compare (match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")))]
+ "reload_completed
+ && s390_match_ccmode (insn, CCUmode)
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+ [(parallel
+ [(set (match_dup 0) (match_dup 1))
+ (use (match_dup 2))])]
+{
+ operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+ operands[0] = adjust_address (operands[0], BLKmode, 0);
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
-(define_insn "*cmpdf_ccs_ibm"
- [(set (reg 33)
- (compare (match_operand:DF 0 "register_operand" "f,f")
- (match_operand:DF 1 "general_operand" "f,R")))]
- "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 "type" "fsimpd")])
+ operands[1] = gen_rtx_COMPARE (GET_MODE (SET_DEST (PATTERN (curr_insn))),
+ operands[0], operands[1]);
+ operands[0] = SET_DEST (PATTERN (curr_insn));
+})
-; SF instructions
+; (DF|SF) instructions
-(define_insn "*cmpsf_ccs_0"
- [(set (reg 33)
- (compare (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "const0_operand" "")))]
+; ltxbr, ltdbr, ltebr
+(define_insn "*cmp<mode>_ccs_0"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:FPR 0 "register_operand" "f")
+ (match_operand:FPR 1 "const0_operand" "")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "ltebr\t%0,%0"
+ "lt<xde>br\t%0,%0"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimps")])
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*cmpsf_ccs_0_ibm"
- [(set (reg 33)
- (compare (match_operand:SF 0 "register_operand" "f")
- (match_operand:SF 1 "const0_operand" "")))]
+; ltxr, ltdr, lter
+(define_insn "*cmp<mode>_ccs_0_ibm"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:FPR 0 "register_operand" "f")
+ (match_operand:FPR 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" "fsimps")])
-
-(define_insn "*cmpsf_ccs"
- [(set (reg 33)
- (compare (match_operand:SF 0 "register_operand" "f,f")
- (match_operand:SF 1 "general_operand" "f,R")))]
+ "lt<xde>r\t%0,%0"
+ [(set_attr "op_type" "<RRe>")
+ (set_attr "type" "fsimp<mode>")])
+
+; cxbr, cdbr, cebr, cxb, cdb, ceb
+(define_insn "*cmp<mode>_ccs"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:FPR 0 "register_operand" "f,f")
+ (match_operand:FPR 1 "general_operand" "f,<Rf>")))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- cebr\t%0,%1
- ceb\t%0,%1"
+ c<xde>br\t%0,%1
+ c<xde>b\t%0,%1"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps")])
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*cmpsf_ccs"
- [(set (reg 33)
- (compare (match_operand:SF 0 "register_operand" "f,f")
- (match_operand:SF 1 "general_operand" "f,R")))]
+; cxr, cdr, cer, cx, cd, ce
+(define_insn "*cmp<mode>_ccs_ibm"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:FPR 0 "register_operand" "f,f")
+ (match_operand:FPR 1 "general_operand" "f,<Rf>")))]
"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 "type" "fsimps")])
+ c<xde>r\t%0,%1
+ c<xde>\t%0,%1"
+ [(set_attr "op_type" "<RRe>,<RXe>")
+ (set_attr "type" "fsimp<mode>")])
;;
@@ -987,16 +794,16 @@
(define_insn "movti"
[(set (match_operand:TI 0 "nonimmediate_operand" "=d,QS,d,o,Q")
- (match_operand:TI 1 "general_operand" "QS,d,dKm,d,Q"))]
+ (match_operand:TI 1 "general_operand" "QS,d,dPm,d,Q"))]
"TARGET_64BIT"
"@
- lmg\t%0,%N0,%1
- stmg\t%1,%N1,%0
+ lmg\t%0,%N0,%S1
+ stmg\t%1,%N1,%S0
#
#
- mvc\t%O0(16,%R0),%1"
- [(set_attr "op_type" "RSY,RSY,NN,NN,SS")
- (set_attr "type" "lm,stm,*,*,cs")])
+ #"
+ [(set_attr "op_type" "RSY,RSY,*,*,SS")
+ (set_attr "type" "lm,stm,*,*,*")])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
@@ -1044,9 +851,8 @@
(match_operand:DI 2 "register_operand" "=&a")])]
"TARGET_64BIT"
{
- if (GET_CODE (operands[0]) != MEM)
- abort ();
- s390_load_address (operands[2], XEXP (operands[0], 0));
+ gcc_assert (MEM_P (operands[0]));
+ s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -1062,16 +868,12 @@
""
{
/* Handle symbolic constants. */
- if (TARGET_64BIT && SYMBOLIC_CONST (operands[1]))
+ if (TARGET_64BIT
+ && (SYMBOLIC_CONST (operands[1])
+ || (GET_CODE (operands[1]) == PLUS
+ && XEXP (operands[1], 0) == pic_offset_table_rtx
+ && SYMBOLIC_CONST (XEXP (operands[1], 1)))))
emit_symbolic_move (operands);
-
- /* During and after reload, we need to force constants
- to the literal pool ourselves, if necessary. */
- if ((reload_in_progress || reload_completed)
- && CONSTANT_P (operands[1])
- && (!legitimate_reload_constant_p (operands[1])
- || FP_REG_P (operands[0])))
- operands[1] = force_const_mem (DImode, operands[1]);
})
(define_insn "*movdi_larl"
@@ -1083,12 +885,46 @@
[(set_attr "op_type" "RIL")
(set_attr "type" "larl")])
+(define_insn "*movdi_64extimm"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=d,d,d,d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+ (match_operand:DI 1 "general_operand"
+ "K,N0HD0,N1HD0,N2HD0,N3HD0,Os,N0SD0,N1SD0,L,d,m,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+ "TARGET_64BIT && TARGET_EXTIMM"
+ "@
+ lghi\t%0,%h1
+ llihh\t%0,%i1
+ llihl\t%0,%i1
+ llilh\t%0,%i1
+ llill\t%0,%i1
+ lgfi\t%0,%1
+ llihf\t%0,%k1
+ llilf\t%0,%k1
+ lay\t%0,%a1
+ lgr\t%0,%1
+ lg\t%0,%1
+ stg\t%1,%0
+ ldr\t%0,%1
+ ld\t%0,%1
+ ldy\t%0,%1
+ std\t%1,%0
+ stdy\t%1,%0
+ #
+ #
+ stam\t%1,%N1,%S0
+ lam\t%0,%N0,%S1
+ #"
+ [(set_attr "op_type" "RI,RI,RI,RI,RI,RIL,RIL,RIL,RXY,RRE,RXY,RXY,
+ RR,RX,RXY,RX,RXY,*,*,RS,RS,SS")
+ (set_attr "type" "*,*,*,*,*,*,*,*,la,lr,load,store,
+ floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*,*,*,*")])
+
(define_insn "*movdi_64"
- [(set (match_operand:DI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,?Q")
- (match_operand:DI 1 "general_operand"
- "K,N0HD0,N1HD0,N2HD0,N3HD0,L,d,m,d,*f,R,T,*f,*f,?Q"))]
- "TARGET_64BIT"
+ [(set (match_operand:DI 0 "nonimmediate_operand"
+ "=d,d,d,d,d,d,d,d,m,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+ (match_operand:DI 1 "general_operand"
+ "K,N0HD0,N1HD0,N2HD0,N3HD0,L,d,m,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
+ "TARGET_64BIT && !TARGET_EXTIMM"
"@
lghi\t%0,%h1
llihh\t%0,%i1
@@ -1104,18 +940,58 @@
ldy\t%0,%1
std\t%1,%0
stdy\t%1,%0
- mvc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,RR,RX,RXY,RX,RXY,SS")
- (set_attr "type" "*,*,*,*,*,la,lr,load,store,floadd,floadd,floadd,
- fstored,fstored,cs")])
+ #
+ #
+ stam\t%1,%N1,%S0
+ lam\t%0,%N0,%S1
+ #"
+ [(set_attr "op_type" "RI,RI,RI,RI,RI,RXY,RRE,RXY,RXY,
+ RR,RX,RXY,RX,RXY,*,*,RS,RS,SS")
+ (set_attr "type" "*,*,*,*,*,la,lr,load,store,
+ floaddf,floaddf,floaddf,fstoredf,fstoredf,*,*,*,*,*")])
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_64BIT && ACCESS_REG_P (operands[1])"
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (ashift:DI (match_dup 0) (const_int 32)))
+ (set (strict_low_part (match_dup 2)) (match_dup 4))]
+ "operands[2] = gen_lowpart (SImode, operands[0]);
+ s390_split_access_reg (operands[1], &operands[4], &operands[3]);")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_64BIT && ACCESS_REG_P (operands[0])
+ && dead_or_set_p (insn, operands[1])"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 1) (lshiftrt:DI (match_dup 1) (const_int 32)))
+ (set (match_dup 4) (match_dup 2))]
+ "operands[2] = gen_lowpart (SImode, operands[1]);
+ s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "")
+ (match_operand:DI 1 "register_operand" ""))]
+ "TARGET_64BIT && ACCESS_REG_P (operands[0])
+ && !dead_or_set_p (insn, operands[1])"
+ [(set (match_dup 3) (match_dup 2))
+ (set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))
+ (set (match_dup 4) (match_dup 2))
+ (set (match_dup 1) (rotate:DI (match_dup 1) (const_int 32)))]
+ "operands[2] = gen_lowpart (SImode, operands[1]);
+ s390_split_access_reg (operands[0], &operands[3], &operands[4]);")
(define_insn "*movdi_31"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=d,Q,d,o,!*f,!*f,!*f,!R,!T,Q")
- (match_operand:DI 1 "general_operand" "Q,d,dKm,d,*f,R,T,*f,*f,Q"))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,Q,S,d,o,!*f,!*f,!*f,!R,!T,Q")
+ (match_operand:DI 1 "general_operand" "Q,S,d,d,dPm,d,*f,R,T,*f,*f,Q"))]
"!TARGET_64BIT"
"@
- lm\t%0,%N0,%1
- stm\t%1,%N1,%0
+ lm\t%0,%N0,%S1
+ lmy\t%0,%N0,%S1
+ stm\t%1,%N1,%S0
+ stmy\t%1,%N1,%S0
#
#
ldr\t%0,%1
@@ -1123,9 +999,9 @@
ldy\t%0,%1
std\t%1,%0
stdy\t%1,%0
- mvc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RS,RS,NN,NN,RR,RX,RXY,RX,RXY,SS")
- (set_attr "type" "lm,stm,*,*,floadd,floadd,floadd,fstored,fstored,cs")])
+ #"
+ [(set_attr "op_type" "RS,RSY,RS,RSY,*,*,RR,RX,RXY,RX,RXY,SS")
+ (set_attr "type" "lm,lm,stm,stm,*,*,floaddf,floaddf,floaddf,fstoredf,fstoredf,*")])
(define_split
[(set (match_operand:DI 0 "nonimmediate_operand" "")
@@ -1174,9 +1050,8 @@
(match_operand:SI 2 "register_operand" "=&a")])]
"!TARGET_64BIT"
{
- if (GET_CODE (operands[0]) != MEM)
- abort ();
- s390_load_address (operands[2], XEXP (operands[0], 0));
+ gcc_assert (MEM_P (operands[0]));
+ s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -1208,10 +1083,9 @@
[(parallel
[(set (match_operand:DI 0 "register_operand" "")
(match_operand:QI 1 "address_operand" ""))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
"TARGET_64BIT
- && strict_memory_address_p (VOIDmode, operands[1])
- && preferred_la_operand_p (operands[1])"
+ && preferred_la_operand_p (operands[1], const0_rtx)"
[(set (match_dup 0) (match_dup 1))]
"")
@@ -1222,11 +1096,10 @@
[(set (match_dup 0)
(plus:DI (match_dup 0)
(match_operand:DI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
"TARGET_64BIT
&& !reg_overlap_mentioned_p (operands[0], operands[2])
- && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (DImode, operands[1], operands[2]))
- && preferred_la_operand_p (gen_rtx_PLUS (DImode, operands[1], operands[2]))"
+ && preferred_la_operand_p (operands[1], operands[2])"
[(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2)))]
"")
@@ -1250,29 +1123,12 @@
""
{
/* Handle symbolic constants. */
- if (!TARGET_64BIT && SYMBOLIC_CONST (operands[1]))
+ if (!TARGET_64BIT
+ && (SYMBOLIC_CONST (operands[1])
+ || (GET_CODE (operands[1]) == PLUS
+ && XEXP (operands[1], 0) == pic_offset_table_rtx
+ && SYMBOLIC_CONST (XEXP(operands[1], 1)))))
emit_symbolic_move (operands);
-
- /* expr.c tries to load an effective address using
- force_reg. This fails because we don't have a
- generic load_address pattern. Convert the move
- to a proper arithmetic operation instead, unless
- it is guaranteed to be OK. */
- if (GET_CODE (operands[1]) == PLUS
- && !legitimate_la_operand_p (operands[1]))
- {
- operands[1] = force_operand (operands[1], operands[0]);
- if (operands[1] == operands[0])
- DONE;
- }
-
- /* During and after reload, we need to force constants
- to the literal pool ourselves, if necessary. */
- if ((reload_in_progress || reload_completed)
- && CONSTANT_P (operands[1])
- && (!legitimate_reload_constant_p (operands[1])
- || FP_REG_P (operands[0])))
- operands[1] = force_const_mem (SImode, operands[1]);
})
(define_insn "*movsi_larl"
@@ -1285,15 +1141,16 @@
(set_attr "type" "larl")])
(define_insn "*movsi_zarch"
- [(set (match_operand:SI 0 "nonimmediate_operand"
- "=d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,?Q")
- (match_operand:SI 1 "general_operand"
- "K,N0HS0,N1HS0,L,d,R,T,d,d,*f,R,T,*f,*f,?Q"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand"
+ "=d,d,d,d,d,d,d,d,R,T,!*f,!*f,!*f,!R,!T,d,t,Q,t,?Q")
+ (match_operand:SI 1 "general_operand"
+ "K,N0HS0,N1HS0,Os,L,d,R,T,d,d,*f,R,T,*f,*f,t,d,t,Q,?Q"))]
"TARGET_ZARCH"
"@
lhi\t%0,%h1
llilh\t%0,%i1
llill\t%0,%i1
+ iilf\t%0,%o1
lay\t%0,%a1
lr\t%0,%1
l\t%0,%1
@@ -1305,13 +1162,19 @@
ley\t%0,%1
ste\t%1,%0
stey\t%1,%0
- mvc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RI,RI,RI,RXY,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
- (set_attr "type" "*,*,*,la,lr,load,load,store,store,floads,floads,floads,fstores,fstores,cs")])
+ ear\t%0,%1
+ sar\t%0,%1
+ stam\t%1,%1,%S0
+ lam\t%0,%0,%S1
+ #"
+ [(set_attr "op_type" "RI,RI,RI,RIL,RXY,RR,RX,RXY,RX,RXY,
+ RR,RX,RXY,RX,RXY,RRE,RRE,RS,RS,SS")
+ (set_attr "type" "*,*,*,*,la,lr,load,load,store,store,
+ floadsf,floadsf,floadsf,fstoresf,fstoresf,*,*,*,*,*")])
(define_insn "*movsi_esa"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,?Q")
- (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,?Q"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,R,!*f,!*f,!R,d,t,Q,t,?Q")
+ (match_operand:SI 1 "general_operand" "K,d,R,d,*f,R,*f,t,d,t,Q,?Q"))]
"!TARGET_ZARCH"
"@
lhi\t%0,%h1
@@ -1321,9 +1184,13 @@
ler\t%0,%1
le\t%0,%1
ste\t%1,%0
- mvc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,SS")
- (set_attr "type" "*,lr,load,store,floads,floads,fstores,cs")])
+ ear\t%0,%1
+ sar\t%0,%1
+ stam\t%1,%1,%S0
+ lam\t%0,%0,%S1
+ #"
+ [(set_attr "op_type" "RI,RR,RX,RX,RR,RX,RX,RRE,RRE,RS,RS,SS")
+ (set_attr "type" "*,lr,load,store,floadsf,floadsf,fstoresf,*,*,*,*,*")])
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
@@ -1350,10 +1217,9 @@
[(parallel
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:QI 1 "address_operand" ""))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
"!TARGET_64BIT
- && strict_memory_address_p (VOIDmode, operands[1])
- && preferred_la_operand_p (operands[1])"
+ && preferred_la_operand_p (operands[1], const0_rtx)"
[(set (match_dup 0) (match_dup 1))]
"")
@@ -1364,11 +1230,10 @@
[(set (match_dup 0)
(plus:SI (match_dup 0)
(match_operand:SI 2 "nonmemory_operand" "")))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
"!TARGET_64BIT
&& !reg_overlap_mentioned_p (operands[0], operands[2])
- && strict_memory_address_p (VOIDmode, gen_rtx_PLUS (SImode, operands[1], operands[2]))
- && preferred_la_operand_p (gen_rtx_PLUS (SImode, operands[1], operands[2]))"
+ && preferred_la_operand_p (operands[1], operands[2])"
[(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))]
"")
@@ -1387,7 +1252,7 @@
[(set (match_operand:SI 0 "register_operand" "=d")
(and:SI (match_operand:QI 1 "address_operand" "p")
(const_int 2147483647)))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT"
"#"
"&& reload_completed"
@@ -1427,12 +1292,11 @@
(match_operand:HI 1 "general_operand" ""))]
""
{
- /* Make it explicit that loading a register from memory
+ /* Make it explicit that loading a register from memory
always sign-extends (at least) to SImode. */
if (optimize && !no_new_pseudos
&& register_operand (operands[0], VOIDmode)
- && GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) != ADDRESSOF)
+ && GET_CODE (operands[1]) == MEM)
{
rtx tmp = gen_reg_rtx (SImode);
rtx ext = gen_rtx_SIGN_EXTEND (SImode, operands[1]);
@@ -1452,9 +1316,9 @@
lhy\t%0,%1
sth\t%1,%0
sthy\t%1,%0
- mvc\t%O0(2,%R0),%1"
+ #"
[(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SS")
- (set_attr "type" "lr,*,*,*,store,store,cs")])
+ (set_attr "type" "lr,*,*,*,store,store,*")])
(define_peephole2
[(set (match_operand:HI 0 "register_operand" "")
@@ -1479,8 +1343,7 @@
is just as fast as a QImode load. */
if (TARGET_ZARCH && optimize && !no_new_pseudos
&& register_operand (operands[0], VOIDmode)
- && GET_CODE (operands[1]) == MEM
- && GET_CODE (XEXP (operands[1], 0)) != ADDRESSOF)
+ && GET_CODE (operands[1]) == MEM)
{
rtx tmp = gen_reg_rtx (word_mode);
rtx ext = gen_rtx_ZERO_EXTEND (word_mode, operands[1]);
@@ -1500,11 +1363,11 @@
icy\t%0,%1
stc\t%1,%0
stcy\t%1,%0
- mvi\t%0,%b1
- mviy\t%0,%b1
- mvc\t%O0(1,%R0),%1"
+ mvi\t%S0,%b1
+ mviy\t%S0,%b1
+ #"
[(set_attr "op_type" "RR,RI,RX,RXY,RX,RXY,SI,SIY,SS")
- (set_attr "type" "lr,*,*,*,store,store,store,store,cs")])
+ (set_attr "type" "lr,*,*,*,store,store,store,store,*")])
(define_peephole2
[(set (match_operand:QI 0 "nonimmediate_operand" "")
@@ -1535,12 +1398,12 @@
(define_insn "*movstricthi"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d,d"))
- (match_operand:HI 1 "s_imm_operand" "Q,S"))
- (clobber (reg:CC 33))]
+ (match_operand:HI 1 "memory_operand" "Q,S"))
+ (clobber (reg:CC CC_REGNUM))]
""
"@
- icm\t%0,3,%1
- icmy\t%0,3,%1"
+ icm\t%0,3,%S1
+ icmy\t%0,3,%S1"
[(set_attr "op_type" "RS,RSY")])
;
@@ -1548,15 +1411,159 @@
;
(define_insn "movstrictsi"
- [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d"))
- (match_operand:SI 1 "general_operand" "d,R,T"))]
+ [(set (strict_low_part (match_operand:SI 0 "register_operand" "+d,d,d,d"))
+ (match_operand:SI 1 "general_operand" "d,R,T,t"))]
"TARGET_64BIT"
"@
lr\t%0,%1
l\t%0,%1
- ly\t%0,%1"
- [(set_attr "op_type" "RR,RX,RXY")
- (set_attr "type" "lr,load,load")])
+ ly\t%0,%1
+ ear\t%0,%1"
+ [(set_attr "op_type" "RR,RX,RXY,RRE")
+ (set_attr "type" "lr,load,load,*")])
+
+;
+; movtf instruction pattern(s).
+;
+
+(define_expand "movtf"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ ""
+ "")
+
+(define_insn "*movtf_64"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,f,o,d,QS,d,o,Q")
+ (match_operand:TF 1 "general_operand" "G,f,o,f,QS,d,dm,d,Q"))]
+ "TARGET_64BIT"
+ "@
+ lzxr\t%0
+ lxr\t%0,%1
+ #
+ #
+ lmg\t%0,%N0,%S1
+ stmg\t%1,%N1,%S0
+ #
+ #
+ #"
+ [(set_attr "op_type" "RRE,RRE,*,*,RSY,RSY,*,*,*")
+ (set_attr "type" "fsimptf,fsimptf,*,*,lm,stm,*,*,*")])
+
+(define_insn "*movtf_31"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=f,f,f,o,Q")
+ (match_operand:TF 1 "general_operand" "G,f,o,f,Q"))]
+ "!TARGET_64BIT"
+ "@
+ lzxr\t%0
+ lxr\t%0,%1
+ #
+ #
+ #"
+ [(set_attr "op_type" "RRE,RRE,*,*,*")
+ (set_attr "type" "fsimptf,fsimptf,*,*,*")])
+
+; TFmode in GPRs splitters
+
+(define_split
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && s390_split_ok_p (operands[0], operands[1], TFmode, 0)"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = operand_subword (operands[0], 0, 0, TFmode);
+ operands[3] = operand_subword (operands[0], 1, 0, TFmode);
+ operands[4] = operand_subword (operands[1], 0, 0, TFmode);
+ operands[5] = operand_subword (operands[1], 1, 0, TFmode);
+})
+
+(define_split
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
+ (match_operand:TF 1 "general_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && s390_split_ok_p (operands[0], operands[1], TFmode, 1)"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = operand_subword (operands[0], 1, 0, TFmode);
+ operands[3] = operand_subword (operands[0], 0, 0, TFmode);
+ operands[4] = operand_subword (operands[1], 1, 0, TFmode);
+ operands[5] = operand_subword (operands[1], 0, 0, TFmode);
+})
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "memory_operand" ""))]
+ "TARGET_64BIT && reload_completed
+ && !FP_REG_P (operands[0])
+ && !s_operand (operands[1], VOIDmode)"
+ [(set (match_dup 0) (match_dup 1))]
+{
+ rtx addr = operand_subword (operands[0], 1, 0, DFmode);
+ s390_load_address (addr, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+})
+
+; TFmode in FPRs splitters
+
+(define_split
+ [(set (match_operand:TF 0 "register_operand" "")
+ (match_operand:TF 1 "memory_operand" ""))]
+ "reload_completed && offsettable_memref_p (operands[1])
+ && FP_REG_P (operands[0])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = simplify_gen_subreg (DFmode, operands[0], TFmode, 0);
+ operands[3] = simplify_gen_subreg (DFmode, operands[0], TFmode, 8);
+ operands[4] = adjust_address_nv (operands[1], DFmode, 0);
+ operands[5] = adjust_address_nv (operands[1], DFmode, 8);
+})
+
+(define_split
+ [(set (match_operand:TF 0 "memory_operand" "")
+ (match_operand:TF 1 "register_operand" ""))]
+ "reload_completed && offsettable_memref_p (operands[0])
+ && FP_REG_P (operands[1])"
+ [(set (match_dup 2) (match_dup 4))
+ (set (match_dup 3) (match_dup 5))]
+{
+ operands[2] = adjust_address_nv (operands[0], DFmode, 0);
+ operands[3] = adjust_address_nv (operands[0], DFmode, 8);
+ operands[4] = simplify_gen_subreg (DFmode, operands[1], TFmode, 0);
+ operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, 8);
+})
+
+(define_expand "reload_outtf"
+ [(parallel [(match_operand:TF 0 "" "")
+ (match_operand:TF 1 "register_operand" "f")
+ (match_operand:SI 2 "register_operand" "=&a")])]
+ ""
+{
+ rtx addr = gen_lowpart (Pmode, operands[2]);
+
+ gcc_assert (MEM_P (operands[0]));
+ s390_load_address (addr, find_replacement (&XEXP (operands[0], 0)));
+ operands[0] = replace_equiv_address (operands[0], addr);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
+
+(define_expand "reload_intf"
+ [(parallel [(match_operand:TF 0 "register_operand" "=f")
+ (match_operand:TF 1 "" "")
+ (match_operand:SI 2 "register_operand" "=&a")])]
+ ""
+{
+ rtx addr = gen_lowpart (Pmode, operands[2]);
+
+ gcc_assert (MEM_P (operands[1]));
+ s390_load_address (addr, find_replacement (&XEXP (operands[1], 0)));
+ operands[1] = replace_equiv_address (operands[1], addr);
+ emit_move_insn (operands[0], operands[1]);
+ DONE;
+})
;
; movdf instruction pattern(s).
@@ -1566,19 +1573,14 @@
[(set (match_operand:DF 0 "nonimmediate_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
-{
- /* During and after reload, we need to force constants
- to the literal pool ourselves, if necessary. */
- if ((reload_in_progress || reload_completed)
- && CONSTANT_P (operands[1]))
- operands[1] = force_const_mem (DFmode, operands[1]);
-})
+ "")
(define_insn "*movdf_64"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,T,d,d,m,?Q")
- (match_operand:DF 1 "general_operand" "f,R,T,f,f,d,m,d,?Q"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d,d,m,?Q")
+ (match_operand:DF 1 "general_operand" "G,f,R,T,f,f,d,m,d,?Q"))]
"TARGET_64BIT"
"@
+ lzdr\t%0
ldr\t%0,%1
ld\t%0,%1
ldy\t%0,%1
@@ -1587,27 +1589,31 @@
lgr\t%0,%1
lg\t%0,%1
stg\t%1,%0
- mvc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RRE,RXY,RXY,SS")
- (set_attr "type" "floadd,floadd,floadd,fstored,fstored,lr,load,store,cs")])
+ #"
+ [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RRE,RXY,RXY,SS")
+ (set_attr "type" "fsimpdf,floaddf,floaddf,floaddf,fstoredf,fstoredf,lr,load,store,*")])
(define_insn "*movdf_31"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,T,d,Q,d,o,Q")
- (match_operand:DF 1 "general_operand" "f,R,T,f,f,Q,d,dKm,d,Q"))]
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d,d,Q,S,d,o,Q")
+ (match_operand:DF 1 "general_operand" "G,f,R,T,f,f,Q,S,d,d,dPm,d,Q"))]
"!TARGET_64BIT"
"@
+ lzdr\t%0
ldr\t%0,%1
ld\t%0,%1
ldy\t%0,%1
std\t%1,%0
stdy\t%1,%0
- lm\t%0,%N0,%1
- stm\t%1,%N1,%0
+ lm\t%0,%N0,%S1
+ lmy\t%0,%N0,%S1
+ stm\t%1,%N1,%S0
+ stmy\t%1,%N1,%S0
#
#
- mvc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RS,RS,NN,NN,SS")
- (set_attr "type" "floadd,floadd,floadd,fstored,fstored,lm,stm,*,*,cs")])
+ #"
+ [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RS,RSY,RS,RSY,*,*,SS")
+ (set_attr "type" "fsimpdf,floaddf,floaddf,floaddf,fstoredf,fstoredf,\
+ lm,lm,stm,stm,*,*,*")])
(define_split
[(set (match_operand:DF 0 "nonimmediate_operand" "")
@@ -1656,9 +1662,8 @@
(match_operand:SI 2 "register_operand" "=&a")])]
"!TARGET_64BIT"
{
- if (GET_CODE (operands[0]) != MEM)
- abort ();
- s390_load_address (operands[2], XEXP (operands[0], 0));
+ gcc_assert (MEM_P (operands[0]));
+ s390_load_address (operands[2], find_replacement (&XEXP (operands[0], 0)));
operands[0] = replace_equiv_address (operands[0], operands[2]);
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -1668,23 +1673,12 @@
; movsf instruction pattern(s).
;
-(define_expand "movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
-{
- /* During and after reload, we need to force constants
- to the literal pool ourselves, if necessary. */
- if ((reload_in_progress || reload_completed)
- && CONSTANT_P (operands[1]))
- operands[1] = force_const_mem (SFmode, operands[1]);
-})
-
-(define_insn "*movsf"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,R,T,d,d,d,R,T,?Q")
- (match_operand:SF 1 "general_operand" "f,R,T,f,f,d,R,T,d,d,?Q"))]
+(define_insn "movsf"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,T,d,d,d,R,T,?Q")
+ (match_operand:SF 1 "general_operand" "G,f,R,T,f,f,d,R,T,d,d,?Q"))]
""
"@
+ lzer\t%0
ler\t%0,%1
le\t%0,%1
ley\t%0,%1
@@ -1695,9 +1689,78 @@
ly\t%0,%1
st\t%1,%0
sty\t%1,%0
- mvc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
- (set_attr "type" "floads,floads,floads,fstores,fstores,lr,load,load,store,store,cs")])
+ #"
+ [(set_attr "op_type" "RRE,RR,RX,RXY,RX,RXY,RR,RX,RXY,RX,RXY,SS")
+ (set_attr "type" "fsimpsf,floadsf,floadsf,floadsf,fstoresf,fstoresf,
+ lr,load,load,store,store,*")])
+
+;
+; movcc instruction pattern
+;
+
+(define_insn "movcc"
+ [(set (match_operand:CC 0 "nonimmediate_operand" "=d,c,d,d,d,R,T")
+ (match_operand:CC 1 "nonimmediate_operand" "d,d,c,R,T,d,d"))]
+ ""
+ "@
+ lr\t%0,%1
+ tmh\t%1,12288
+ ipm\t%0
+ st\t%0,%1
+ sty\t%0,%1
+ l\t%1,%0
+ ly\t%1,%0"
+ [(set_attr "op_type" "RR,RI,RRE,RX,RXY,RX,RXY")
+ (set_attr "type" "lr,*,*,store,store,load,load")])
+
+;
+; Block move (MVC) patterns.
+;
+
+(define_insn "*mvc"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (match_operand:BLK 1 "memory_operand" "Q"))
+ (use (match_operand 2 "const_int_operand" "n"))]
+ "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+ "mvc\t%O0(%2,%R0),%S1"
+ [(set_attr "op_type" "SS")])
+
+(define_split
+ [(set (match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" ""))]
+ "reload_completed
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+ [(parallel
+ [(set (match_dup 0) (match_dup 1))
+ (use (match_dup 2))])]
+{
+ operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+ operands[0] = adjust_address (operands[0], BLKmode, 0);
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "const_int_operand" ""))])
+ (parallel
+ [(set (match_operand:BLK 3 "memory_operand" "")
+ (match_operand:BLK 4 "memory_operand" ""))
+ (use (match_operand 5 "const_int_operand" ""))])]
+ "s390_offset_p (operands[0], operands[3], operands[2])
+ && s390_offset_p (operands[1], operands[4], operands[2])
+ && !s390_overlap_p (operands[0], operands[1],
+ INTVAL (operands[2]) + INTVAL (operands[5]))
+ && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+ [(parallel
+ [(set (match_dup 6) (match_dup 7))
+ (use (match_dup 8))])]
+ "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+ operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+ operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
;
; load_multiple pattern(s).
@@ -1751,9 +1814,6 @@
}
else
FAIL;
-
- if (from == frame_pointer_rtx || from == arg_pointer_rtx)
- FAIL;
}
else
{
@@ -1776,7 +1836,7 @@
{
int words = XVECLEN (operands[0], 0);
operands[0] = gen_rtx_REG (DImode, REGNO (operands[1]) + words - 1);
- return "lmg\t%1,%0,%2";
+ return "lmg\t%1,%0,%S2";
}
[(set_attr "op_type" "RSY")
(set_attr "type" "lm")])
@@ -1789,7 +1849,7 @@
{
int words = XVECLEN (operands[0], 0);
operands[0] = gen_rtx_REG (SImode, REGNO (operands[1]) + words - 1);
- return which_alternative == 0 ? "lm\t%1,%0,%2" : "lmy\t%1,%0,%2";
+ return which_alternative == 0 ? "lm\t%1,%0,%S2" : "lmy\t%1,%0,%S2";
}
[(set_attr "op_type" "RS,RSY")
(set_attr "type" "lm")])
@@ -1844,9 +1904,6 @@
}
else
FAIL;
-
- if (to == frame_pointer_rtx || to == arg_pointer_rtx)
- FAIL;
}
else
{
@@ -1870,7 +1927,7 @@
{
int words = XVECLEN (operands[0], 0);
operands[0] = gen_rtx_REG (DImode, REGNO (operands[2]) + words - 1);
- return "stmg\t%2,%0,%1";
+ return "stmg\t%2,%0,%S1";
}
[(set_attr "op_type" "RSY")
(set_attr "type" "stm")])
@@ -1884,7 +1941,7 @@
{
int words = XVECLEN (operands[0], 0);
operands[0] = gen_rtx_REG (SImode, REGNO (operands[2]) + words - 1);
- return which_alternative == 0 ? "stm\t%2,%0,%1" : "stmy\t%2,%0,%1";
+ return which_alternative == 0 ? "stm\t%2,%0,%S1" : "stmy\t%2,%0,%S1";
}
[(set_attr "op_type" "RS,RSY")
(set_attr "type" "stm")])
@@ -1893,144 +1950,225 @@
;; String instructions.
;;
+(define_insn "*execute"
+ [(match_parallel 0 ""
+ [(unspec [(match_operand 1 "register_operand" "a")
+ (match_operand:BLK 2 "memory_operand" "R")
+ (match_operand 3 "" "")] UNSPEC_EXECUTE)])]
+ "GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT
+ && GET_MODE_SIZE (GET_MODE (operands[1])) <= UNITS_PER_WORD"
+ "ex\t%1,%2"
+ [(set_attr "op_type" "RX")
+ (set_attr "type" "cs")])
+
+
;
; strlenM instruction pattern(s).
;
-(define_expand "strlendi"
- [(set (reg:QI 0) (match_operand:QI 2 "immediate_operand" ""))
- (parallel
+(define_expand "strlen<mode>"
+ [(set (reg:SI 0) (match_operand:SI 2 "immediate_operand" ""))
+ (parallel
[(set (match_dup 4)
- (unspec:DI [(const_int 0)
+ (unspec:P [(const_int 0)
(match_operand:BLK 1 "memory_operand" "")
- (reg:QI 0)
+ (reg:SI 0)
(match_operand 3 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (scratch:DI))
- (clobber (reg:CC 33))])
+ (clobber (scratch:P))
+ (clobber (reg:CC CC_REGNUM))])
(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 33))])]
- "TARGET_64BIT"
+ [(set (match_operand:P 0 "register_operand" "")
+ (minus:P (match_dup 4) (match_dup 5)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
{
- operands[4] = gen_reg_rtx (DImode);
- operands[5] = gen_reg_rtx (DImode);
+ operands[4] = gen_reg_rtx (Pmode);
+ operands[5] = gen_reg_rtx (Pmode);
emit_move_insn (operands[5], force_operand (XEXP (operands[1], 0), NULL_RTX));
operands[1] = replace_equiv_address (operands[1], operands[5]);
})
-(define_insn "*strlendi"
- [(set (match_operand:DI 0 "register_operand" "=a")
- (unspec:DI [(match_operand:DI 2 "general_operand" "0")
- (mem:BLK (match_operand:DI 3 "register_operand" "1"))
- (reg:QI 0)
+(define_insn "*strlen<mode>"
+ [(set (match_operand:P 0 "register_operand" "=a")
+ (unspec:P [(match_operand:P 2 "general_operand" "0")
+ (mem:BLK (match_operand:P 3 "register_operand" "1"))
+ (reg:SI 0)
(match_operand 4 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (match_scratch:DI 1 "=a"))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
+ (clobber (match_scratch:P 1 "=a"))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
"srst\t%0,%1\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
-(define_expand "strlensi"
- [(set (reg:QI 0) (match_operand:QI 2 "immediate_operand" ""))
- (parallel
- [(set (match_dup 4)
- (unspec:SI [(const_int 0)
- (match_operand:BLK 1 "memory_operand" "")
- (reg:QI 0)
- (match_operand 3 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (scratch:SI))
- (clobber (reg:CC 33))])
+;
+; cmpstrM instruction pattern(s).
+;
+
+(define_expand "cmpstrsi"
+ [(set (reg:SI 0) (const_int 0))
(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (minus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 33))])]
- "!TARGET_64BIT"
+ [(clobber (match_operand 3 "" ""))
+ (clobber (match_dup 4))
+ (set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:BLK 2 "memory_operand" "")))
+ (use (reg:SI 0))])
+ (parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(reg:CCU CC_REGNUM)] UNSPEC_CMPINT))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
{
- operands[4] = gen_reg_rtx (SImode);
- operands[5] = gen_reg_rtx (SImode);
- emit_move_insn (operands[5], force_operand (XEXP (operands[1], 0), NULL_RTX));
- operands[1] = replace_equiv_address (operands[1], operands[5]);
+ /* As the result of CMPINT is inverted compared to what we need,
+ we have to swap the operands. */
+ rtx op1 = operands[2];
+ rtx op2 = operands[1];
+ rtx addr1 = gen_reg_rtx (Pmode);
+ rtx addr2 = gen_reg_rtx (Pmode);
+
+ emit_move_insn (addr1, force_operand (XEXP (op1, 0), NULL_RTX));
+ emit_move_insn (addr2, force_operand (XEXP (op2, 0), NULL_RTX));
+ operands[1] = replace_equiv_address_nv (op1, addr1);
+ operands[2] = replace_equiv_address_nv (op2, addr2);
+ operands[3] = addr1;
+ operands[4] = addr2;
})
-(define_insn "*strlensi"
- [(set (match_operand:SI 0 "register_operand" "=a")
- (unspec:SI [(match_operand:SI 2 "general_operand" "0")
- (mem:BLK (match_operand:SI 3 "register_operand" "1"))
- (reg:QI 0)
- (match_operand 4 "immediate_operand" "")] UNSPEC_SRST))
- (clobber (match_scratch:SI 1 "=a"))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT"
- "srst\t%0,%1\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
+(define_insn "*cmpstr<mode>"
+ [(clobber (match_operand:P 0 "register_operand" "=d"))
+ (clobber (match_operand:P 1 "register_operand" "=d"))
+ (set (reg:CCU CC_REGNUM)
+ (compare:CCU (mem:BLK (match_operand:P 2 "register_operand" "0"))
+ (mem:BLK (match_operand:P 3 "register_operand" "1"))))
+ (use (reg:SI 0))]
+ ""
+ "clst\t%0,%1\;jo\t.-4"
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
+
;
-; movstrM instruction pattern(s).
+; movstr instruction pattern.
;
-(define_expand "movstrdi"
- [(set (match_operand:BLK 0 "memory_operand" "")
- (match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:DI 2 "general_operand" ""))
- (match_operand 3 "" "")]
- "TARGET_64BIT"
- "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
+(define_expand "movstr"
+ [(set (reg:SI 0) (const_int 0))
+ (parallel
+ [(clobber (match_dup 3))
+ (set (match_operand:BLK 1 "memory_operand" "")
+ (match_operand:BLK 2 "memory_operand" ""))
+ (set (match_operand 0 "register_operand" "")
+ (unspec [(match_dup 1)
+ (match_dup 2)
+ (reg:SI 0)] UNSPEC_MVST))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+{
+ rtx addr1 = gen_reg_rtx (Pmode);
+ rtx addr2 = gen_reg_rtx (Pmode);
+
+ emit_move_insn (addr1, force_operand (XEXP (operands[1], 0), NULL_RTX));
+ emit_move_insn (addr2, force_operand (XEXP (operands[2], 0), NULL_RTX));
+ operands[1] = replace_equiv_address_nv (operands[1], addr1);
+ operands[2] = replace_equiv_address_nv (operands[2], addr2);
+ operands[3] = addr2;
+})
-(define_expand "movstrsi"
+(define_insn "*movstr"
+ [(clobber (match_operand:P 2 "register_operand" "=d"))
+ (set (mem:BLK (match_operand:P 1 "register_operand" "0"))
+ (mem:BLK (match_operand:P 3 "register_operand" "2")))
+ (set (match_operand:P 0 "register_operand" "=d")
+ (unspec [(mem:BLK (match_dup 1))
+ (mem:BLK (match_dup 3))
+ (reg:SI 0)] UNSPEC_MVST))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "mvst\t%1,%2\;jo\t.-4"
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
+
+
+;
+; movmemM instruction pattern(s).
+;
+
+(define_expand "movmem<mode>"
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
- (use (match_operand:SI 2 "general_operand" ""))
+ (use (match_operand:GPR 2 "general_operand" ""))
(match_operand 3 "" "")]
""
- "s390_expand_movstr (operands[0], operands[1], operands[2]); DONE;")
+ "s390_expand_movmem (operands[0], operands[1], operands[2]); DONE;")
; Move a block that is up to 256 bytes in length.
; The block length is taken as (operands[2] % 256) + 1.
-(define_expand "movstr_short"
+(define_expand "movmem_short"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_SCRATCH (Pmode);")
-(define_insn "*movstr_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q"))
- (use (match_operand 2 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 3 "=X,&a"))]
+(define_insn "*movmem_short"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q"))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 4 "=X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[3]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "mvc\t%O0(%b2+1,%R0),%1";
+ && GET_MODE (operands[4]) == Pmode"
+ "#"
+ [(set_attr "type" "cs")])
- case 1:
- output_asm_insn ("bras\t%3,.+10", operands);
- output_asm_insn ("mvc\t%O0(1,%R0),%1", operands);
- return "ex\t%2,0(%3)";
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "immediate_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (match_dup 1))
+ (use (match_dup 2))])]
+ "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "register_operand" ""))
+ (use (match_operand 3 "memory_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (match_dup 3)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (match_dup 0) (match_dup 1))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" ""))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 3 "register_operand" ""))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 3) (label_ref (match_dup 4)))
+ (parallel
+ [(unspec [(match_dup 2) (mem:BLK (match_dup 3))
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (match_dup 1))
+ (use (const_int 1))])]
+ "operands[4] = gen_label_rtx ();")
; Move a block of arbitrary length.
-(define_expand "movstr_long"
+(define_expand "movmem_long"
[(parallel
[(clobber (match_dup 2))
(clobber (match_dup 3))
@@ -2038,7 +2176,7 @@
(match_operand:BLK 1 "memory_operand" ""))
(use (match_operand 2 "general_operand" ""))
(use (match_dup 3))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
""
{
enum machine_mode dword_mode = word_mode == DImode ? TImode : DImode;
@@ -2063,105 +2201,114 @@
operands[3] = reg1;
})
-(define_insn "*movstr_long_64"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (clobber (match_operand:TI 1 "register_operand" "=d"))
- (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0)))
- (use (match_dup 2))
- (use (match_dup 3))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
-(define_insn "*movstr_long_31"
- [(clobber (match_operand:DI 0 "register_operand" "=d"))
- (clobber (match_operand:DI 1 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0)))
+(define_insn "*movmem_long"
+ [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
+ (clobber (match_operand:<DBL> 1 "register_operand" "=d"))
+ (set (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "1") 0)))
(use (match_dup 2))
(use (match_dup 3))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT"
+ (clobber (reg:CC CC_REGNUM))]
+ ""
"mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
;
-; clrstrM instruction pattern(s).
+; setmemM instruction pattern(s).
;
-(define_expand "clrstrdi"
+(define_expand "setmem<mode>"
[(set (match_operand:BLK 0 "memory_operand" "")
- (const_int 0))
- (use (match_operand:DI 1 "general_operand" ""))
- (match_operand 2 "" "")]
- "TARGET_64BIT"
- "s390_expand_clrstr (operands[0], operands[1]); DONE;")
-
-(define_expand "clrstrsi"
- [(set (match_operand:BLK 0 "memory_operand" "")
- (const_int 0))
- (use (match_operand:SI 1 "general_operand" ""))
- (match_operand 2 "" "")]
+ (match_operand:QI 2 "general_operand" ""))
+ (use (match_operand:GPR 1 "general_operand" ""))
+ (match_operand 3 "" "")]
""
- "s390_expand_clrstr (operands[0], operands[1]); DONE;")
+ "s390_expand_setmem (operands[0], operands[1], operands[2]); DONE;")
; Clear a block that is up to 256 bytes in length.
; The block length is taken as (operands[1] % 256) + 1.
-(define_expand "clrstr_short"
+(define_expand "clrmem_short"
[(parallel
[(set (match_operand:BLK 0 "memory_operand" "")
(const_int 0))
(use (match_operand 1 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 2))
- (clobber (reg:CC 33))])]
+ (clobber (reg:CC CC_REGNUM))])]
""
"operands[2] = gen_rtx_SCRATCH (Pmode);")
-(define_insn "*clrstr_short"
- [(set (match_operand:BLK 0 "memory_operand" "=Q,Q")
+(define_insn "*clrmem_short"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q,Q,Q")
(const_int 0))
- (use (match_operand 1 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 2 "=X,&a"))
- (clobber (reg:CC 33))]
+ (use (match_operand 1 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 2 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 3 "=X,X,&a"))
+ (clobber (reg:CC CC_REGNUM))]
"(GET_MODE (operands[1]) == Pmode || GET_MODE (operands[1]) == VOIDmode)
- && GET_MODE (operands[2]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "xc\t%O0(%b1+1,%R0),%0";
+ && GET_MODE (operands[3]) == Pmode"
+ "#"
+ [(set_attr "type" "cs")])
+
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "const_int_operand" ""))
+ (use (match_operand 2 "immediate_operand" ""))
+ (clobber (scratch))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (const_int 0))
+ (use (match_dup 1))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[1] = GEN_INT ((INTVAL (operands[1]) & 0xff) + 1);")
- case 1:
- output_asm_insn ("bras\t%2,.+10", operands);
- output_asm_insn ("xc\t%O0(1,%R0),%0", operands);
- return "ex\t%1,0(%2)";
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "register_operand" ""))
+ (use (match_operand 2 "memory_operand" ""))
+ (clobber (scratch))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 1) (match_dup 2)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (match_dup 0) (const_int 0))
+ (use (const_int 1))
+ (clobber (reg:CC CC_REGNUM))])]
+ "")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 2 "register_operand" ""))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 2) (label_ref (match_dup 3)))
+ (parallel
+ [(unspec [(match_dup 1) (mem:BLK (match_dup 2))
+ (label_ref (match_dup 3))] UNSPEC_EXECUTE)
+ (set (match_dup 0) (const_int 0))
+ (use (const_int 1))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[3] = gen_label_rtx ();")
-; Clear a block of arbitrary length.
+; Initialize a block of arbitrary length with (operands[2] % 256).
-(define_expand "clrstr_long"
+(define_expand "setmem_long"
[(parallel
[(clobber (match_dup 1))
(set (match_operand:BLK 0 "memory_operand" "")
- (const_int 0))
+ (match_operand 2 "shift_count_or_setmem_operand" ""))
(use (match_operand 1 "general_operand" ""))
- (use (match_dup 2))
- (clobber (reg:CC 33))])]
+ (use (match_dup 3))
+ (clobber (reg:CC CC_REGNUM))])]
""
{
enum machine_mode dword_mode = word_mode == DImode ? TImode : DImode;
@@ -2178,49 +2325,37 @@
operands[0] = replace_equiv_address_nv (operands[0], addr0);
operands[1] = reg0;
- operands[2] = reg1;
+ operands[3] = reg1;
})
-(define_insn "*clrstr_long_64"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
- (const_int 0))
- (use (match_dup 2))
- (use (match_operand:TI 1 "register_operand" "d"))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
-(define_insn "*clrstr_long_31"
- [(clobber (match_operand:DI 0 "register_operand" "=d"))
- (set (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
- (const_int 0))
- (use (match_dup 2))
- (use (match_operand:DI 1 "register_operand" "d"))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT"
- "mvcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
+(define_insn "*setmem_long"
+ [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
+ (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
+ (match_operand 2 "shift_count_or_setmem_operand" "Y"))
+ (use (match_dup 3))
+ (use (match_operand:<DBL> 1 "register_operand" "d"))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "mvcle\t%0,%1,%Y2\;jo\t.-4"
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
+
+(define_insn "*setmem_long_and"
+ [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
+ (set (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "0") 0))
+ (and (match_operand 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand 4 "const_int_operand" "n")))
+ (use (match_dup 3))
+ (use (match_operand:<DBL> 1 "register_operand" "d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "(INTVAL (operands[4]) & 255) == 255"
+ "mvcle\t%0,%1,%Y2\;jo\t.-4"
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
;
; cmpmemM instruction pattern(s).
;
-(define_expand "cmpmemdi"
- [(set (match_operand:DI 0 "register_operand" "")
- (compare:DI (match_operand:BLK 1 "memory_operand" "")
- (match_operand:BLK 2 "memory_operand" "") ) )
- (use (match_operand:DI 3 "general_operand" ""))
- (use (match_operand:DI 4 "" ""))]
- "TARGET_64BIT"
- "s390_expand_cmpmem (operands[0], operands[1],
- operands[2], operands[3]); DONE;")
-
(define_expand "cmpmemsi"
[(set (match_operand:SI 0 "register_operand" "")
(compare:SI (match_operand:BLK 1 "memory_operand" "")
@@ -2236,41 +2371,70 @@
(define_expand "cmpmem_short"
[(parallel
- [(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "nonmemory_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
(clobber (match_dup 3))])]
""
"operands[3] = gen_rtx_SCRATCH (Pmode);")
(define_insn "*cmpmem_short"
- [(set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "=Q,Q")
- (match_operand:BLK 1 "memory_operand" "Q,Q")))
- (use (match_operand 2 "nonmemory_operand" "n,a"))
- (clobber (match_scratch 3 "=X,&a"))]
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "Q,Q,Q")
+ (match_operand:BLK 1 "memory_operand" "Q,Q,Q")))
+ (use (match_operand 2 "nonmemory_operand" "n,a,a"))
+ (use (match_operand 3 "immediate_operand" "X,R,X"))
+ (clobber (match_scratch 4 "=X,X,&a"))]
"(GET_MODE (operands[2]) == Pmode || GET_MODE (operands[2]) == VOIDmode)
- && GET_MODE (operands[3]) == Pmode"
-{
- switch (which_alternative)
- {
- case 0:
- return "clc\t%O0(%b2+1,%R0),%1";
+ && GET_MODE (operands[4]) == Pmode"
+ "#"
+ [(set_attr "type" "cs")])
- case 1:
- output_asm_insn ("bras\t%3,.+10", operands);
- output_asm_insn ("clc\t%O0(1,%R0),%1", operands);
- return "ex\t%2,0(%3)";
+(define_split
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "const_int_operand" ""))
+ (use (match_operand 3 "immediate_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (match_dup 2))])]
+ "operands[2] = GEN_INT ((INTVAL (operands[2]) & 0xff) + 1);")
- default:
- abort ();
- }
-}
- [(set_attr "op_type" "SS,NN")
- (set_attr "type" "cs,cs")
- (set_attr "atype" "*,agen")
- (set_attr "length" "*,14")])
+(define_split
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "register_operand" ""))
+ (use (match_operand 3 "memory_operand" ""))
+ (clobber (scratch))]
+ "reload_completed"
+ [(parallel
+ [(unspec [(match_dup 2) (match_dup 3)
+ (const_int 0)] UNSPEC_EXECUTE)
+ (set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (const_int 1))])]
+ "")
+
+(define_split
+ [(set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "register_operand" ""))
+ (use (const:BLK (unspec:BLK [(const_int 0)] UNSPEC_INSN)))
+ (clobber (match_operand 3 "register_operand" ""))]
+ "reload_completed && TARGET_CPU_ZARCH"
+ [(set (match_dup 3) (label_ref (match_dup 4)))
+ (parallel
+ [(unspec [(match_dup 2) (mem:BLK (match_dup 3))
+ (label_ref (match_dup 4))] UNSPEC_EXECUTE)
+ (set (reg:CCU CC_REGNUM) (compare:CCU (match_dup 0) (match_dup 1)))
+ (use (const_int 1))])]
+ "operands[4] = gen_label_rtx ();")
; Compare a block of arbitrary length.
@@ -2278,8 +2442,8 @@
[(parallel
[(clobber (match_dup 2))
(clobber (match_dup 3))
- (set (reg:CCS 33)
- (compare:CCS (match_operand:BLK 0 "memory_operand" "")
+ (set (reg:CCU CC_REGNUM)
+ (compare:CCU (match_operand:BLK 0 "memory_operand" "")
(match_operand:BLK 1 "memory_operand" "")))
(use (match_operand 2 "general_operand" ""))
(use (match_dup 3))])]
@@ -2307,148 +2471,268 @@
operands[3] = reg1;
})
-(define_insn "*cmpmem_long_64"
- [(clobber (match_operand:TI 0 "register_operand" "=d"))
- (clobber (match_operand:TI 1 "register_operand" "=d"))
- (set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:DI (match_operand:TI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:DI (match_operand:TI 3 "register_operand" "1") 0))))
- (use (match_dup 2))
- (use (match_dup 3))]
- "TARGET_64BIT"
- "clcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
-
-(define_insn "*cmpmem_long_31"
- [(clobber (match_operand:DI 0 "register_operand" "=d"))
- (clobber (match_operand:DI 1 "register_operand" "=d"))
- (set (reg:CCS 33)
- (compare:CCS (mem:BLK (subreg:SI (match_operand:DI 2 "register_operand" "0") 0))
- (mem:BLK (subreg:SI (match_operand:DI 3 "register_operand" "1") 0))))
+(define_insn "*cmpmem_long"
+ [(clobber (match_operand:<DBL> 0 "register_operand" "=d"))
+ (clobber (match_operand:<DBL> 1 "register_operand" "=d"))
+ (set (reg:CCU CC_REGNUM)
+ (compare:CCU (mem:BLK (subreg:P (match_operand:<DBL> 2 "register_operand" "0") 0))
+ (mem:BLK (subreg:P (match_operand:<DBL> 3 "register_operand" "1") 0))))
(use (match_dup 2))
(use (match_dup 3))]
- "!TARGET_64BIT"
+ ""
"clcle\t%0,%1,0\;jo\t.-4"
- [(set_attr "op_type" "NN")
- (set_attr "type" "vs")
- (set_attr "length" "8")])
+ [(set_attr "length" "8")
+ (set_attr "type" "vs")])
-; Convert condition code to integer in range (-1, 0, 1)
+; Convert CCUmode condition code to integer.
+; Result is zero if EQ, positive if LTU, negative if GTU.
-(define_insn "cmpint_si"
+(define_insn_and_split "cmpint"
[(set (match_operand:SI 0 "register_operand" "=d")
- (compare:SI (reg:CCS 33) (const_int 0)))]
+ (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
+ UNSPEC_CMPINT))
+ (clobber (reg:CC CC_REGNUM))]
""
+ "#"
+ "reload_completed"
+ [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 2)))
+ (parallel
+ [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 30)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn_and_split "*cmpint_cc"
+ [(set (reg CC_REGNUM)
+ (compare (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
+ UNSPEC_CMPINT)
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=d")
+ (unspec:SI [(match_dup 1)] UNSPEC_CMPINT))]
+ "s390_match_ccmode (insn, CCSmode)"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashift:SI (match_dup 0) (const_int 2)))
+ (parallel
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 30)))])]
{
- 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 "type" "other")])
+ rtx result = gen_rtx_ASHIFTRT (SImode, operands[0], GEN_INT (30));
+ operands[2] = SET_DEST (XVECEXP (PATTERN (curr_insn), 0, 0));
+ operands[3] = gen_rtx_COMPARE (GET_MODE (operands[2]), result, const0_rtx);
+})
-(define_insn "cmpint_di"
+(define_insn_and_split "*cmpint_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
- (compare:DI (reg:CCS 33) (const_int 0)))]
+ (sign_extend:DI (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
+ UNSPEC_CMPINT)))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 34)))
+ (parallel
+ [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 62)))
+ (clobber (reg:CC CC_REGNUM))])])
+
+(define_insn_and_split "*cmpint_sign_cc"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:DI (ashift:DI (subreg:DI
+ (unspec:SI [(match_operand:CCU 1 "register_operand" "0")]
+ UNSPEC_CMPINT) 0)
+ (const_int 32)) (const_int 32))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI (unspec:SI [(match_dup 1)] UNSPEC_CMPINT)))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashift:DI (match_dup 0) (const_int 34)))
+ (parallel
+ [(set (match_dup 2) (match_dup 3))
+ (set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 62)))])]
{
- output_asm_insn ("lghi\t%0,1", operands);
- output_asm_insn ("jh\t.+16", operands);
- output_asm_insn ("jl\t.+8", operands);
- output_asm_insn ("sgr\t%0,%0", operands);
- return "lcgr\t%0,%0";
-}
- [(set_attr "op_type" "NN")
- (set_attr "length" "20")
- (set_attr "type" "other")])
+ rtx result = gen_rtx_ASHIFTRT (DImode, operands[0], GEN_INT (62));
+ operands[2] = SET_DEST (XVECEXP (PATTERN (curr_insn), 0, 0));
+ operands[3] = gen_rtx_COMPARE (GET_MODE (operands[2]), result, const0_rtx);
+})
;;
;;- Conversion instructions.
;;
-(define_insn "*sethighqisi"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (unspec:SI [(match_operand:QI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))]
- ""
- "@
- icm\t%0,8,%1
- icmy\t%0,8,%1"
- [(set_attr "op_type" "RS,RSY")])
-
-(define_insn "*sethighhisi"
+(define_insn "*sethighpartsi"
[(set (match_operand:SI 0 "register_operand" "=d,d")
- (unspec:SI [(match_operand:HI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))]
+ (unspec:SI [(match_operand:BLK 1 "s_operand" "Q,S")
+ (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))]
""
"@
- icm\t%0,12,%1
- icmy\t%0,12,%1"
+ icm\t%0,%2,%S1
+ icmy\t%0,%2,%S1"
[(set_attr "op_type" "RS,RSY")])
-(define_insn "*sethighqidi_64"
+(define_insn "*sethighpartdi_64"
[(set (match_operand:DI 0 "register_operand" "=d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "QS")] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))]
+ (unspec:DI [(match_operand:BLK 1 "s_operand" "QS")
+ (match_operand 2 "const_int_operand" "n")] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
- "icmh\t%0,8,%1"
+ "icmh\t%0,%2,%S1"
[(set_attr "op_type" "RSY")])
-(define_insn "*sethighqidi_31"
+(define_insn "*sethighpartdi_31"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (unspec:DI [(match_operand:QI 1 "s_operand" "Q,S")] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))]
+ (unspec:DI [(match_operand:BLK 1 "s_operand" "Q,S")
+ (match_operand 2 "const_int_operand" "n,n")] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT"
"@
- icm\t%0,8,%1
- icmy\t%0,8,%1"
+ icm\t%0,%2,%S1
+ icmy\t%0,%2,%S1"
[(set_attr "op_type" "RS,RSY")])
-(define_insn_and_split "*extractqi"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
- (match_operand 2 "const_int_operand" "n")
- (const_int 0)))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT
- && INTVAL (operands[2]) > 0 && INTVAL (operands[2]) < 8"
+(define_insn_and_split "*extzv<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extract:GPR (match_operand:QI 1 "s_operand" "QS")
+ (match_operand 2 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
"#"
"&& reload_completed"
[(parallel
- [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))])
- (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+ [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))])
+ (set (match_dup 0) (lshiftrt:GPR (match_dup 0) (match_dup 2)))]
{
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));
- operands[1] = change_address (operands[1], QImode, 0);
-}
- [(set_attr "atype" "agen")])
+ int bitsize = INTVAL (operands[2]);
+ int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
+ int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
+
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+ set_mem_size (operands[1], GEN_INT (size));
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
+ operands[3] = GEN_INT (mask);
+})
-(define_insn_and_split "*extracthi"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extract:SI (match_operand:QI 1 "s_operand" "Q")
- (match_operand 2 "const_int_operand" "n")
- (const_int 0)))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT
- && INTVAL (operands[2]) >= 8 && INTVAL (operands[2]) < 16"
+(define_insn_and_split "*extv<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (sign_extract:GPR (match_operand:QI 1 "s_operand" "QS")
+ (match_operand 2 "const_int_operand" "n")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[2]) > 0
+ && INTVAL (operands[2]) <= GET_MODE_BITSIZE (SImode)"
"#"
"&& reload_completed"
[(parallel
- [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))])
- (set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 2)))]
+ [(set (match_dup 0) (unspec:GPR [(match_dup 1) (match_dup 3)] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])]
{
- operands[2] = GEN_INT (32 - INTVAL (operands[2]));
- operands[1] = change_address (operands[1], HImode, 0);
+ int bitsize = INTVAL (operands[2]);
+ int size = (bitsize - 1) / BITS_PER_UNIT + 1; /* round up */
+ int mask = ((1ul << size) - 1) << (GET_MODE_SIZE (SImode) - size);
+
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+ set_mem_size (operands[1], GEN_INT (size));
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode) - bitsize);
+ operands[3] = GEN_INT (mask);
+})
+
+;
+; insv instruction patterns
+;
+
+(define_expand "insv"
+ [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
+ (match_operand 1 "const_int_operand" "")
+ (match_operand 2 "const_int_operand" ""))
+ (match_operand 3 "general_operand" ""))]
+ ""
+{
+ if (s390_expand_insv (operands[0], operands[1], operands[2], operands[3]))
+ DONE;
+ FAIL;
+})
+
+(define_insn "*insv<mode>_mem_reg"
+ [(set (zero_extract:P (match_operand:QI 0 "memory_operand" "+Q,S")
+ (match_operand 1 "const_int_operand" "n,n")
+ (const_int 0))
+ (match_operand:P 2 "register_operand" "d,d"))]
+ "INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+ && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+{
+ int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+
+ operands[1] = GEN_INT ((1ul << size) - 1);
+ return (which_alternative == 0) ? "stcm\t%2,%1,%S0"
+ : "stcmy\t%2,%1,%S0";
}
- [(set_attr "atype" "agen")])
+ [(set_attr "op_type" "RS,RSY")])
+
+(define_insn "*insvdi_mem_reghigh"
+ [(set (zero_extract:DI (match_operand:QI 0 "memory_operand" "+QS")
+ (match_operand 1 "const_int_operand" "n")
+ (const_int 0))
+ (lshiftrt:DI (match_operand:DI 2 "register_operand" "d")
+ (const_int 32)))]
+ "TARGET_64BIT
+ && INTVAL (operands[1]) > 0
+ && INTVAL (operands[1]) <= GET_MODE_BITSIZE (SImode)
+ && INTVAL (operands[1]) % BITS_PER_UNIT == 0"
+{
+ int size = INTVAL (operands[1]) / BITS_PER_UNIT;
+
+ operands[1] = GEN_INT ((1ul << size) - 1);
+ return "stcmh\t%2,%1,%S0";
+}
+[(set_attr "op_type" "RSY")])
+
+(define_insn "*insv<mode>_reg_imm"
+ [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+ (const_int 16)
+ (match_operand 1 "const_int_operand" "n"))
+ (match_operand:P 2 "const_int_operand" "n"))]
+ "TARGET_ZARCH
+ && INTVAL (operands[1]) >= 0
+ && INTVAL (operands[1]) < BITS_PER_WORD
+ && INTVAL (operands[1]) % 16 == 0"
+{
+ switch (BITS_PER_WORD - INTVAL (operands[1]))
+ {
+ case 64: return "iihh\t%0,%x2"; break;
+ case 48: return "iihl\t%0,%x2"; break;
+ case 32: return "iilh\t%0,%x2"; break;
+ case 16: return "iill\t%0,%x2"; break;
+ default: gcc_unreachable();
+ }
+}
+ [(set_attr "op_type" "RI")])
+
+(define_insn "*insv<mode>_reg_extimm"
+ [(set (zero_extract:P (match_operand:P 0 "register_operand" "+d")
+ (const_int 32)
+ (match_operand 1 "const_int_operand" "n"))
+ (match_operand:P 2 "const_int_operand" "n"))]
+ "TARGET_EXTIMM
+ && INTVAL (operands[1]) >= 0
+ && INTVAL (operands[1]) < BITS_PER_WORD
+ && INTVAL (operands[1]) % 32 == 0"
+{
+ switch (BITS_PER_WORD - INTVAL (operands[1]))
+ {
+ case 64: return "iihf\t%0,%o2"; break;
+ case 32: return "iilf\t%0,%o2"; break;
+ default: gcc_unreachable();
+ }
+}
+ [(set_attr "op_type" "RIL")])
;
; extendsidi2 instruction pattern(s).
@@ -2458,7 +2742,6 @@
[(set (match_operand:DI 0 "register_operand" "")
(sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
""
- "
{
if (!TARGET_64BIT)
{
@@ -2468,8 +2751,7 @@
emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (32)));
DONE;
}
-}
-")
+})
(define_insn "*extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d")
@@ -2481,31 +2763,45 @@
[(set_attr "op_type" "RRE,RXY")])
;
-; extendhidi2 instruction pattern(s).
+; extend(hi|qi)(si|di)2 instruction pattern(s).
;
-(define_expand "extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (sign_extend:DI (match_operand:HI 1 "register_operand" "")))]
+(define_expand "extend<HQI:mode><DSI:mode>2"
+ [(set (match_operand:DSI 0 "register_operand" "")
+ (sign_extend:DSI (match_operand:HQI 1 "nonimmediate_operand" "")))]
""
- "
{
- if (!TARGET_64BIT)
+ if (<DSI:MODE>mode == DImode && !TARGET_64BIT)
{
rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_extendhisi2 (tmp, operands[1]));
+ emit_insn (gen_extend<HQI:mode>si2 (tmp, operands[1]));
emit_insn (gen_extendsidi2 (operands[0], tmp));
DONE;
}
- else
+ else if (!TARGET_EXTIMM)
{
- operands[1] = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
- emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (48)));
+ rtx bitcount = GEN_INT (GET_MODE_BITSIZE (<DSI:MODE>mode) -
+ GET_MODE_BITSIZE (<HQI:MODE>mode));
+
+ operands[1] = gen_lowpart (<DSI:MODE>mode, operands[1]);
+ emit_insn (gen_ashl<DSI:mode>3 (operands[0], operands[1], bitcount));
+ emit_insn (gen_ashr<DSI:mode>3 (operands[0], operands[0], bitcount));
DONE;
}
-}
-")
+})
+
+;
+; extendhidi2 instruction pattern(s).
+;
+
+(define_insn "*extendhidi2_extimm"
+ [(set (match_operand:DI 0 "register_operand" "=d,d")
+ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_64BIT && TARGET_EXTIMM"
+ "@
+ lghr\t%0,%1
+ lgh\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY")])
(define_insn "*extendhidi2"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -2515,123 +2811,69 @@
[(set_attr "op_type" "RXY")])
;
-; extendqidi2 instruction pattern(s).
-;
-
-(define_expand "extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (sign_extend:DI (match_operand:QI 1 "register_operand" "")))]
- ""
- "
-{
- if (!TARGET_64BIT)
- {
- rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_extendqisi2 (tmp, operands[1]));
- emit_insn (gen_extendsidi2 (operands[0], tmp));
- DONE;
- }
- else
- {
- operands[1] = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
- emit_insn (gen_ashrdi3 (operands[0], operands[0], GEN_INT (56)));
- DONE;
- }
-}
-")
-
-(define_insn "*extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_64BIT && TARGET_LONG_DISPLACEMENT"
- "lgb\t%0,%1"
- [(set_attr "op_type" "RXY")])
-
-(define_insn_and_split "*extendqidi2_short_displ"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI (match_operand:QI 1 "s_operand" "Q")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT && !TARGET_LONG_DISPLACEMENT"
- "#"
- "&& reload_completed"
- [(parallel
- [(set (match_dup 0) (unspec:DI [(match_dup 1)] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))])
- (parallel
- [(set (match_dup 0) (ashiftrt:DI (match_dup 0) (const_int 56)))
- (clobber (reg:CC 33))])]
- "")
-
-;
; extendhisi2 instruction pattern(s).
;
-(define_expand "extendhisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
- ""
- "
-{
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (16)));
- emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (16)));
- DONE;
-}
-")
+(define_insn "*extendhisi2_extimm"
+ [(set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "d,R,T")))]
+ "TARGET_EXTIMM"
+ "@
+ lhr\t%0,%1
+ lh\t%0,%1
+ lhy\t%0,%1"
+ [(set_attr "op_type" "RRE,RX,RXY")])
(define_insn "*extendhisi2"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(sign_extend:SI (match_operand:HI 1 "memory_operand" "R,T")))]
- ""
+ "!TARGET_EXTIMM"
"@
lh\t%0,%1
lhy\t%0,%1"
[(set_attr "op_type" "RX,RXY")])
;
-; extendqisi2 instruction pattern(s).
+; extendqi(si|di)2 instruction pattern(s).
;
-(define_expand "extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
- ""
- "
-{
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_ashlsi3 (operands[0], operands[1], GEN_INT (24)));
- emit_insn (gen_ashrsi3 (operands[0], operands[0], GEN_INT (24)));
- DONE;
-}
-")
+; lbr, lgbr, lb, lgb
+(define_insn "*extendqi<mode>2_extimm"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (sign_extend:GPR (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_EXTIMM"
+ "@
+ l<g>br\t%0,%1
+ l<g>b\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY")])
-(define_insn "*extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_LONG_DISPLACEMENT"
- "lb\t%0,%1"
+; lb, lgb
+(define_insn "*extendqi<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (sign_extend:GPR (match_operand:QI 1 "memory_operand" "m")))]
+ "!TARGET_EXTIMM && TARGET_LONG_DISPLACEMENT"
+ "l<g>b\t%0,%1"
[(set_attr "op_type" "RXY")])
-(define_insn_and_split "*extendsiqi2_short_displ"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI (match_operand:QI 1 "s_operand" "Q")))
- (clobber (reg:CC 33))]
- "!TARGET_LONG_DISPLACEMENT"
+(define_insn_and_split "*extendqi<mode>2_short_displ"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (sign_extend:GPR (match_operand:QI 1 "s_operand" "Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_EXTIMM && !TARGET_LONG_DISPLACEMENT"
"#"
"&& reload_completed"
[(parallel
- [(set (match_dup 0) (unspec:SI [(match_dup 1)] UNSPEC_SETHIGH))
- (clobber (reg:CC 33))])
+ [(set (match_dup 0) (unspec:GPR [(match_dup 1) (const_int 8)] UNSPEC_ICM))
+ (clobber (reg:CC CC_REGNUM))])
(parallel
- [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 24)))
- (clobber (reg:CC 33))])]
- "")
-
-;
-; extendqihi2 instruction pattern(s).
-;
-
+ [(set (match_dup 0) (ashiftrt:GPR (match_dup 0) (match_dup 2)))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+ set_mem_size (operands[1], GEN_INT (GET_MODE_SIZE (QImode)));
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<MODE>mode)
+ - GET_MODE_BITSIZE (QImode));
+})
;
; zero_extendsidi2 instruction pattern(s).
@@ -2641,7 +2883,6 @@
[(set (match_operand:DI 0 "register_operand" "")
(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "")))]
""
- "
{
if (!TARGET_64BIT)
{
@@ -2650,8 +2891,7 @@
emit_move_insn (gen_highpart (SImode, operands[0]), const0_rtx);
DONE;
}
-}
-")
+})
(define_insn "*zero_extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=d,d")
@@ -2663,64 +2903,40 @@
[(set_attr "op_type" "RRE,RXY")])
;
-; zero_extendhidi2 instruction pattern(s).
+; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
;
-(define_expand "zero_extendhidi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (match_operand:HI 1 "register_operand" "")))]
- ""
- "
-{
- if (!TARGET_64BIT)
- {
- rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_zero_extendhisi2 (tmp, operands[1]));
- emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
- DONE;
- }
- else
- {
- operands[1] = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (48)));
- emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (48)));
- DONE;
- }
-}
-")
-
-(define_insn "*zero_extendhidi2"
+(define_insn "*llgt_sidi"
[(set (match_operand:DI 0 "register_operand" "=d")
- (zero_extend:DI (match_operand:HI 1 "memory_operand" "m")))]
+ (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "m") 0)
+ (const_int 2147483647)))]
"TARGET_64BIT"
- "llgh\t%0,%1"
- [(set_attr "op_type" "RXY")])
+ "llgt\t%0,%1"
+ [(set_attr "op_type" "RXE")])
-;
-; LLGT-type instructions (zero-extend from 31 bit to 64 bit).
-;
+(define_insn_and_split "*llgt_sidi_split"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "m") 0)
+ (const_int 2147483647)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0)
+ (and:DI (subreg:DI (match_dup 1) 0)
+ (const_int 2147483647)))]
+ "")
(define_insn "*llgt_sisi"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(and:SI (match_operand:SI 1 "nonimmediate_operand" "d,m")
(const_int 2147483647)))]
- "TARGET_64BIT"
+ "TARGET_ZARCH"
"@
llgtr\t%0,%1
llgt\t%0,%1"
[(set_attr "op_type" "RRE,RXE")])
-(define_split
- [(set (match_operand:SI 0 "register_operand" "")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (const_int 2147483647)))
- (clobber (reg:CC 33))]
- "TARGET_64BIT && reload_completed"
- [(set (match_dup 0)
- (and:SI (match_dup 1)
- (const_int 2147483647)))]
- "")
-
(define_insn "*llgt_didi"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o")
@@ -2732,130 +2948,87 @@
[(set_attr "op_type" "RRE,RXE")])
(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (const_int 2147483647)))
- (clobber (reg:CC 33))]
- "TARGET_64BIT && reload_completed"
+ [(set (match_operand:GPR 0 "register_operand" "")
+ (and:GPR (match_operand:GPR 1 "nonimmediate_operand" "")
+ (const_int 2147483647)))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && reload_completed"
[(set (match_dup 0)
- (and:DI (match_dup 1)
- (const_int 2147483647)))]
- "")
-
-(define_insn "*llgt_sidi"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "m") 0)
- (const_int 2147483647)))]
- "TARGET_64BIT"
- "llgt\t%0,%1"
- [(set_attr "op_type" "RXE")])
-
-(define_insn_and_split "*llgt_sidi_split"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (and:DI (subreg:DI (match_operand:SI 1 "memory_operand" "m") 0)
- (const_int 2147483647)))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "#"
- "&& reload_completed"
- [(set (match_dup 0)
- (and:DI (subreg:DI (match_dup 1) 0)
- (const_int 2147483647)))]
+ (and:GPR (match_dup 1)
+ (const_int 2147483647)))]
"")
;
-; zero_extendqidi2 instruction pattern(s)
+; zero_extend(hi|qi)(si|di)2 instruction pattern(s).
;
-(define_expand "zero_extendqidi2"
+(define_expand "zero_extend<mode>di2"
[(set (match_operand:DI 0 "register_operand" "")
- (zero_extend:DI (match_operand:QI 1 "register_operand" "")))]
+ (zero_extend:DI (match_operand:HQI 1 "nonimmediate_operand" "")))]
""
- "
{
if (!TARGET_64BIT)
{
rtx tmp = gen_reg_rtx (SImode);
- emit_insn (gen_zero_extendqisi2 (tmp, operands[1]));
+ emit_insn (gen_zero_extend<mode>si2 (tmp, operands[1]));
emit_insn (gen_zero_extendsidi2 (operands[0], tmp));
DONE;
}
- else
+ else if (!TARGET_EXTIMM)
{
+ rtx bitcount = GEN_INT (GET_MODE_BITSIZE(DImode) -
+ GET_MODE_BITSIZE(<MODE>mode));
operands[1] = gen_lowpart (DImode, operands[1]);
- emit_insn (gen_ashldi3 (operands[0], operands[1], GEN_INT (56)));
- emit_insn (gen_lshrdi3 (operands[0], operands[0], GEN_INT (56)));
+ emit_insn (gen_ashldi3 (operands[0], operands[1], bitcount));
+ emit_insn (gen_lshrdi3 (operands[0], operands[0], bitcount));
DONE;
}
-}
-")
-
-(define_insn "*zero_extendqidi2"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (zero_extend:DI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_64BIT"
- "llgc\t%0,%1"
- [(set_attr "op_type" "RXY")])
-
-;
-; zero_extendhisi2 instruction pattern(s).
-;
+})
-(define_expand "zero_extendhisi2"
+(define_expand "zero_extend<mode>si2"
[(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:HI 1 "register_operand" "")))]
+ (zero_extend:SI (match_operand:HQI 1 "nonimmediate_operand" "")))]
""
- "
{
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xffff)));
- DONE;
-}
-")
+ if (!TARGET_EXTIMM)
+ {
+ operands[1] = gen_lowpart (SImode, operands[1]);
+ emit_insn (gen_andsi3 (operands[0], operands[1],
+ GEN_INT ((1 << GET_MODE_BITSIZE(<MODE>mode)) - 1)));
+ DONE;
+ }
+})
-(define_insn "*zero_extendhisi2_64"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- "TARGET_64BIT"
- "llgh\t%0,%1"
+; llhr, llcr, llghr, llgcr, llh, llc, llgh, llgc
+(define_insn "*zero_extend<HQI:mode><GPR:mode>2_extimm"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (zero_extend:GPR (match_operand:HQI 1 "nonimmediate_operand" "d,m")))]
+ "TARGET_EXTIMM"
+ "@
+ ll<g><hc>r\t%0,%1
+ ll<g><hc>\t%0,%1"
+ [(set_attr "op_type" "RRE,RXY")])
+
+; llgh, llgc
+(define_insn "*zero_extend<HQI:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extend:GPR (match_operand:HQI 1 "memory_operand" "m")))]
+ "TARGET_ZARCH && !TARGET_EXTIMM"
+ "llg<hc>\t%0,%1"
[(set_attr "op_type" "RXY")])
(define_insn_and_split "*zero_extendhisi2_31"
[(set (match_operand:SI 0 "register_operand" "=&d")
(zero_extend:SI (match_operand:HI 1 "s_operand" "QS")))
- (clobber (reg:CC 33))]
- "!TARGET_64BIT"
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH"
"#"
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
(parallel
[(set (strict_low_part (match_dup 2)) (match_dup 1))
- (clobber (reg:CC 33))])]
- "operands[2] = gen_lowpart (HImode, operands[0]);"
- [(set_attr "atype" "agen")])
-
-;
-; zero_extendqisi2 instruction pattern(s).
-;
-
-(define_expand "zero_extendqisi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
- ""
- "
-{
- operands[1] = gen_lowpart (SImode, operands[1]);
- emit_insn (gen_andsi3 (operands[0], operands[1], GEN_INT (0xff)));
- DONE;
-}
-")
-
-(define_insn "*zero_extendqisi2_64"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ZARCH"
- "llgc\t%0,%1"
- [(set_attr "op_type" "RXY")])
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[2] = gen_lowpart (HImode, operands[0]);")
(define_insn_and_split "*zero_extendqisi2_31"
[(set (match_operand:SI 0 "register_operand" "=&d")
@@ -2865,8 +3038,7 @@
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
(set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);"
- [(set_attr "atype" "agen")])
+ "operands[2] = gen_lowpart (QImode, operands[0]);")
;
; zero_extendqihi2 instruction pattern(s).
@@ -2875,19 +3047,17 @@
(define_expand "zero_extendqihi2"
[(set (match_operand:HI 0 "register_operand" "")
(zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
- "TARGET_ZARCH"
- "
+ "TARGET_ZARCH && !TARGET_EXTIMM"
{
operands[1] = gen_lowpart (HImode, operands[1]);
emit_insn (gen_andhi3 (operands[0], operands[1], GEN_INT (0xff)));
DONE;
-}
-")
+})
(define_insn "*zero_extendqihi2_64"
[(set (match_operand:HI 0 "register_operand" "=d")
(zero_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
- "TARGET_ZARCH"
+ "TARGET_ZARCH && !TARGET_EXTIMM"
"llgc\t%0,%1"
[(set_attr "op_type" "RXY")])
@@ -2899,89 +3069,80 @@
"&& reload_completed"
[(set (match_dup 0) (const_int 0))
(set (strict_low_part (match_dup 2)) (match_dup 1))]
- "operands[2] = gen_lowpart (QImode, operands[0]);"
- [(set_attr "atype" "agen")])
+ "operands[2] = gen_lowpart (QImode, operands[0]);")
;
-; fixuns_truncdfdi2 and fix_truncdfsi2 instruction pattern(s).
+; fixuns_trunc(sf|df)(si|di)2 and fix_trunc(sf|df)(si|di)2 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"
+(define_expand "fixuns_trunc<FPR:mode><GPR:mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "")
+ (unsigned_fix:GPR (match_operand:FPR 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],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("9223372036854775808.0", DFmode), DFmode)));
+ rtx temp = gen_reg_rtx (<FPR:MODE>mode);
+ REAL_VALUE_TYPE cmp, sub;
+
+ operands[1] = force_reg (<FPR:MODE>mode, operands[1]);
+ real_2expN (&cmp, GET_MODE_BITSIZE(<GPR:MODE>mode) - 1);
+ real_2expN (&sub, GET_MODE_BITSIZE(<GPR:MODE>mode));
+
+ emit_insn (gen_cmp<FPR:mode> (operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (cmp, <FPR:MODE>mode)));
emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subdf3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("18446744073709551616.0", DFmode), DFmode)));
- emit_insn (gen_fix_truncdfdi2_ieee (operands[0], temp, GEN_INT(7)));
+ emit_insn (gen_sub<FPR:mode>3 (temp, operands[1],
+ CONST_DOUBLE_FROM_REAL_VALUE (sub, <FPR:MODE>mode)));
+ emit_insn (gen_fix_trunc<FPR:mode><GPR:mode>2_ieee (operands[0], temp,
+ GEN_INT(7)));
emit_jump (label2);
emit_label (label1);
- emit_insn (gen_fix_truncdfdi2_ieee (operands[0], operands[1], GEN_INT(5)));
+ emit_insn (gen_fix_trunc<FPR:mode><GPR:mode>2_ieee (operands[0],
+ operands[1], GEN_INT(5)));
emit_label (label2);
DONE;
})
-(define_expand "fix_truncdfdi2"
+(define_expand "fix_trunc<mode>di2"
[(set (match_operand:DI 0 "register_operand" "")
- (fix:DI (match_operand:DF 1 "nonimmediate_operand" "")))]
+ (fix:DI (match_operand:DSF 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)));
+ operands[1] = force_reg (<MODE>mode, operands[1]);
+ emit_insn (gen_fix_trunc<mode>di2_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")] UNSPEC_ROUND)
- (clobber (reg:CC 33))]
- "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cgdbr\t%0,%h2,%1"
+; cgxbr, cgdbr, cgebr, cfxbr, cfdbr, cfebr
+(define_insn "fix_trunc<FPR:mode><GPR:mode>2_ieee"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (fix:GPR (match_operand:FPR 1 "register_operand" "f")))
+ (unspec:GPR [(match_operand:GPR 2 "immediate_operand" "K")] UNSPEC_ROUND)
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "c<GPR:gf><FPR:xde>br\t%0,%h2,%1"
[(set_attr "op_type" "RRE")
(set_attr "type" "ftoi")])
;
-; fixuns_truncdfsi2 and fix_truncdfsi2 instruction pattern(s).
+; fix_trunctf(si|di)2 instruction pattern(s).
;
-(define_expand "fixuns_truncdfsi2"
- [(set (match_operand:SI 0 "register_operand" "")
- (unsigned_fix:SI (match_operand:DF 1 "register_operand" "")))]
+(define_expand "fix_trunctf<mode>2"
+ [(parallel [(set (match_operand:GPR 0 "register_operand" "")
+ (fix:GPR (match_operand:TF 1 "register_operand" "")))
+ (unspec:GPR [(const_int 5)] UNSPEC_ROUND)
+ (clobber (reg:CC CC_REGNUM))])]
"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],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("2147483648.0", DFmode), DFmode)));
- emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subdf3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("4294967296.0", DFmode), DFmode)));
- emit_insn (gen_fix_truncdfsi2_ieee (operands[0], temp, GEN_INT (7)));
- emit_jump (label2);
+ "")
- emit_label (label1);
- emit_insn (gen_fix_truncdfsi2_ieee (operands[0], operands[1], GEN_INT (5)));
- emit_label (label2);
- DONE;
-})
+;
+; fix_truncdfsi2 instruction pattern(s).
+;
(define_expand "fix_truncdfsi2"
[(set (match_operand:SI 0 "register_operand" "")
@@ -3009,23 +3170,13 @@
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")] UNSPEC_ROUND)
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cfdbr\t%0,%h2,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "other" )])
-
(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:DI 2 "immediate_operand" "m"))
(use (match_operand:DI 3 "immediate_operand" "m"))
(use (match_operand:BLK 4 "memory_operand" "m"))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
{
output_asm_insn ("sd\t%1,%2", operands);
@@ -3034,92 +3185,12 @@
output_asm_insn ("xi\t%N4,128", operands);
return "l\t%0,%N4";
}
- [(set_attr "op_type" "NN")
- (set_attr "type" "ftoi")
- (set_attr "atype" "agen")
- (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],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("9223372036854775808.0", SFmode), SFmode)));
- emit_jump_insn (gen_blt (label1));
-
- emit_insn (gen_subsf3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("18446744073709551616.0", SFmode), SFmode)));
- emit_insn (gen_fix_truncsfdi2_ieee (operands[0], temp, GEN_INT(7)));
- emit_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")] UNSPEC_ROUND)
- (clobber (reg:CC 33))]
- "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cgebr\t%0,%h2,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "ftoi")])
+ [(set_attr "length" "20")])
;
-; fixuns_truncsfsi2 and fix_truncsfsi2 instruction pattern(s).
+; 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],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("2147483648.0", SFmode), SFmode)));
- emit_jump_insn (gen_blt (label1));
- emit_insn (gen_subsf3 (temp, operands[1],
- CONST_DOUBLE_FROM_REAL_VALUE (
- REAL_VALUE_ATOF ("4294967296.0", SFmode), SFmode)));
- emit_insn (gen_fix_truncsfsi2_ieee (operands[0], temp, GEN_INT (7)));
- emit_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" "")))]
@@ -3141,51 +3212,42 @@
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")] UNSPEC_ROUND)
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cfebr\t%0,%h2,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "ftoi")])
-
;
-; floatdidf2 instruction pattern(s).
+; float(si|di)(tf|df|sf)2 instruction pattern(s).
;
-(define_insn "floatdidf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
+; cxgbr, cdgbr, cegbr
+(define_insn "floatdi<mode>2"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (float:FPR (match_operand:DI 1 "register_operand" "d")))]
"TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cdgbr\t%0,%1"
+ "c<xde>gbr\t%0,%1"
[(set_attr "op_type" "RRE")
(set_attr "type" "itof" )])
-;
-; floatdisf2 instruction pattern(s).
-;
-
-(define_insn "floatdisf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cegbr\t%0,%1"
+; cxfbr, cdfbr, cefbr
+(define_insn "floatsi<mode>2_ieee"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (float:FPR (match_operand:SI 1 "register_operand" "d")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "c<xde>fbr\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "itof" )])
+ (set_attr "type" "itof" )])
+
;
-; floatsidf2 instruction pattern(s).
+; floatsi(tf|df)2 instruction pattern(s).
;
+(define_expand "floatsitf2"
+ [(set (match_operand:TF 0 "register_operand" "")
+ (float:TF (match_operand:SI 1 "register_operand" "")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "")
+
(define_expand "floatsidf2"
- [(parallel
- [(set (match_operand:DF 0 "register_operand" "")
- (float:DF (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float:DF (match_operand:SI 1 "register_operand" "")))]
"TARGET_HARD_FLOAT"
{
if (TARGET_IBM_FLOAT)
@@ -3200,21 +3262,12 @@
}
})
-(define_insn "floatsidf2_ieee"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (float:DF (match_operand:SI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cdfbr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof" )])
-
(define_insn "floatsidf2_ibm"
[(set (match_operand:DF 0 "register_operand" "=f")
(float:DF (match_operand:SI 1 "register_operand" "d")))
(use (match_operand:DI 2 "immediate_operand" "m"))
(use (match_operand:BLK 3 "memory_operand" "m"))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
{
output_asm_insn ("st\t%1,%N3", operands);
@@ -3223,20 +3276,15 @@
output_asm_insn ("ld\t%0,%3", operands);
return "sd\t%0,%2";
}
- [(set_attr "op_type" "NN")
- (set_attr "type" "other" )
- (set_attr "atype" "agen")
- (set_attr "length" "20")])
+ [(set_attr "length" "20")])
;
; floatsisf2 instruction pattern(s).
;
(define_expand "floatsisf2"
- [(parallel
- [(set (match_operand:SF 0 "register_operand" "")
- (float:SF (match_operand:SI 1 "register_operand" "")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:SF 0 "register_operand" "")
+ (float:SF (match_operand:SI 1 "register_operand" "")))]
"TARGET_HARD_FLOAT"
{
if (TARGET_IBM_FLOAT)
@@ -3249,41 +3297,93 @@
}
})
-(define_insn "floatsisf2_ieee"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (float:SF (match_operand:SI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "cefbr\t%0,%1"
- [(set_attr "op_type" "RRE")
- (set_attr "type" "itof" )])
-
;
; truncdfsf2 instruction pattern(s).
;
(define_expand "truncdfsf2"
[(set (match_operand:SF 0 "register_operand" "")
- (float_truncate:SF (match_operand:DF 1 "general_operand" "")))]
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "")))]
"TARGET_HARD_FLOAT"
"")
(define_insn "truncdfsf2_ieee"
[(set (match_operand:SF 0 "register_operand" "=f")
- (float_truncate:SF (match_operand:DF 1 "general_operand" "f")))]
+ (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"ledbr\t%0,%1"
- [(set_attr "op_type" "RRE")])
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "ftruncdf")])
(define_insn "truncdfsf2_ibm"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (float_truncate:SF (match_operand:DF 1 "general_operand" "f,R")))]
+ (float_truncate:SF (match_operand:DF 1 "nonimmediate_operand" "f,R")))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
- lrer\t%0,%1
+ ler\t%0,%1
le\t%0,%1"
[(set_attr "op_type" "RR,RX")
- (set_attr "type" "floads,floads")])
+ (set_attr "type" "floadsf")])
+
+;
+; trunctfdf2 instruction pattern(s).
+;
+
+(define_expand "trunctfdf2"
+ [(parallel
+ [(set (match_operand:DF 0 "register_operand" "")
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "")))
+ (clobber (match_scratch:TF 2 "=f"))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*trunctfdf2_ieee"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "f")))
+ (clobber (match_scratch:TF 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ldxbr\t%2,%1\;ldr\t%0,%2"
+ [(set_attr "length" "6")
+ (set_attr "type" "ftrunctf")])
+
+(define_insn "*trunctfdf2_ibm"
+ [(set (match_operand:DF 0 "register_operand" "=f")
+ (float_truncate:DF (match_operand:TF 1 "register_operand" "f")))
+ (clobber (match_scratch:TF 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "ldxr\t%2,%1\;ldr\t%0,%2"
+ [(set_attr "length" "4")
+ (set_attr "type" "ftrunctf")])
+
+;
+; trunctfsf2 instruction pattern(s).
+;
+
+(define_expand "trunctfsf2"
+ [(parallel
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:TF 1 "register_operand" "f")))
+ (clobber (match_scratch:TF 2 "=f"))])]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*trunctfsf2_ieee"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:TF 1 "register_operand" "f")))
+ (clobber (match_scratch:TF 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lexbr\t%2,%1\;ler\t%0,%2"
+ [(set_attr "length" "6")
+ (set_attr "type" "ftrunctf")])
+
+(define_insn "*trunctfsf2_ibm"
+ [(set (match_operand:SF 0 "register_operand" "=f")
+ (float_truncate:SF (match_operand:TF 1 "register_operand" "f")))
+ (clobber (match_scratch:TF 2 "=f"))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "lexr\t%2,%1\;ler\t%0,%2"
+ [(set_attr "length" "6")
+ (set_attr "type" "ftrunctf")])
;
; extendsfdf2 instruction pattern(s).
@@ -3309,20 +3409,78 @@
ldebr\t%0,%1
ldeb\t%0,%1"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "floads,floads")])
+ (set_attr "type" "fsimpsf, floadsf")])
(define_insn "extendsfdf2_ibm"
[(set (match_operand:DF 0 "register_operand" "=f,f")
(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "f,R")))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"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" "NN,NN")
- (set_attr "atype" "reg,agen")
- (set_attr "length" "4,6")
- (set_attr "type" "o2,o2")])
+ [(set_attr "length" "4,6")
+ (set_attr "type" "floadsf")])
+
+;
+; extenddftf2 instruction pattern(s).
+;
+
+(define_expand "extenddftf2"
+ [(set (match_operand:TF 0 "register_operand" "")
+ (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*extenddftf2_ieee"
+ [(set (match_operand:TF 0 "register_operand" "=f,f")
+ (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "f,R")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ lxdbr\t%0,%1
+ lxdb\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "fsimptf, floadtf")])
+
+(define_insn "*extenddftf2_ibm"
+ [(set (match_operand:TF 0 "register_operand" "=f,f")
+ (float_extend:TF (match_operand:DF 1 "nonimmediate_operand" "f,R")))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ lxdr\t%0,%1
+ lxd\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "fsimptf, floadtf")])
+
+;
+; extendsftf2 instruction pattern(s).
+;
+
+(define_expand "extendsftf2"
+ [(set (match_operand:TF 0 "register_operand" "")
+ (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "")))]
+ "TARGET_HARD_FLOAT"
+ "")
+
+(define_insn "*extendsftf2_ieee"
+ [(set (match_operand:TF 0 "register_operand" "=f,f")
+ (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "f,R")))]
+ "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "@
+ lxebr\t%0,%1
+ lxeb\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "fsimptf, floadtf")])
+
+(define_insn "*extendsftf2_ibm"
+ [(set (match_operand:TF 0 "register_operand" "=f,f")
+ (float_extend:TF (match_operand:SF 1 "nonimmediate_operand" "f,R")))]
+ "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ "@
+ lxer\t%0,%1
+ lxe\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "fsimptf, floadtf")])
;;
@@ -3337,14 +3495,51 @@
;;
;
+; addti3 instruction pattern(s).
+;
+
+(define_insn_and_split "addti3"
+ [(set (match_operand:TI 0 "register_operand" "=&d")
+ (plus:TI (match_operand:TI 1 "nonimmediate_operand" "%0")
+ (match_operand:TI 2 "general_operand" "do") ) )
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (reg:CCL1 CC_REGNUM)
+ (compare:CCL1 (plus:DI (match_dup 7) (match_dup 8))
+ (match_dup 7)))
+ (set (match_dup 6) (plus:DI (match_dup 7) (match_dup 8)))])
+ (parallel
+ [(set (match_dup 3) (plus:DI (plus:DI (match_dup 4) (match_dup 5))
+ (ltu:DI (reg:CCL1 CC_REGNUM) (const_int 0))))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[3] = operand_subword (operands[0], 0, 0, TImode);
+ operands[4] = operand_subword (operands[1], 0, 0, TImode);
+ operands[5] = operand_subword (operands[2], 0, 0, TImode);
+ operands[6] = operand_subword (operands[0], 1, 0, TImode);
+ operands[7] = operand_subword (operands[1], 1, 0, TImode);
+ operands[8] = operand_subword (operands[2], 1, 0, TImode);")
+
+;
; adddi3 instruction pattern(s).
;
+(define_expand "adddi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ "")
+
(define_insn "*adddi3_sign"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(plus:DI (sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
(match_operand:DI 1 "register_operand" "0,0")))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
"@
agfr\t%0,%2
@@ -3352,7 +3547,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*adddi3_zero_cc"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
(match_operand:DI 1 "register_operand" "0,0"))
(const_int 0)))
@@ -3365,7 +3560,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*adddi3_zero_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
(match_operand:DI 1 "register_operand" "0,0"))
(const_int 0)))
@@ -3380,172 +3575,60 @@
[(set (match_operand:DI 0 "register_operand" "=d,d")
(plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))
(match_operand:DI 1 "register_operand" "0,0")))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
"@
algfr\t%0,%2
algf\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "*adddi3_imm_cc"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "0")
- (match_operand:DI 2 "const_int_operand" "K"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT
- && s390_match_ccmode (insn, CCAmode)
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")"
- "aghi\t%0,%h2"
- [(set_attr "op_type" "RI")])
-
-(define_insn "*adddi3_carry1_cc"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 1)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_carry1_cconly"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 1)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_carry2_cc"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 2)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_carry2_cconly"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 2)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL1mode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_cc"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_cconly"
- [(set (reg 33)
- (compare (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_cconly2"
- [(set (reg 33)
- (compare (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (neg:SI (match_operand:DI 2 "general_operand" "d,m"))))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode(insn, CCLmode) && TARGET_64BIT"
- "@
- algr\t%0,%2
- alg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*adddi3_64"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d")
- (plus:DI (match_operand:DI 1 "nonimmediate_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,RXY")])
-
(define_insn_and_split "*adddi3_31z"
[(set (match_operand:DI 0 "register_operand" "=&d")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT && TARGET_CPU_ZARCH"
"#"
"&& reload_completed"
[(parallel
- [(set (reg:CCL1 33)
+ [(set (reg:CCL1 CC_REGNUM)
(compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
(match_dup 7)))
(set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
(parallel
[(set (match_dup 3) (plus:SI (plus:SI (match_dup 4) (match_dup 5))
- (ltu:SI (reg:CCL1 33) (const_int 0))))
- (clobber (reg:CC 33))])]
+ (ltu:SI (reg:CCL1 CC_REGNUM) (const_int 0))))
+ (clobber (reg:CC CC_REGNUM))])]
"operands[3] = operand_subword (operands[0], 0, 0, DImode);
operands[4] = operand_subword (operands[1], 0, 0, DImode);
operands[5] = operand_subword (operands[2], 0, 0, DImode);
operands[6] = operand_subword (operands[0], 1, 0, DImode);
operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);"
- [(set_attr "op_type" "NN")])
+ operands[8] = operand_subword (operands[2], 1, 0, DImode);")
(define_insn_and_split "*adddi3_31"
[(set (match_operand:DI 0 "register_operand" "=&d")
(plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0")
(match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_CPU_ZARCH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 3) (plus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 33))])
+ (clobber (reg:CC CC_REGNUM))])
(parallel
- [(set (reg:CCL1 33)
+ [(set (reg:CCL1 CC_REGNUM)
(compare:CCL1 (plus:SI (match_dup 7) (match_dup 8))
(match_dup 7)))
(set (match_dup 6) (plus:SI (match_dup 7) (match_dup 8)))])
(set (pc)
- (if_then_else (ltu (reg:CCL1 33) (const_int 0))
+ (if_then_else (ltu (reg:CCL1 CC_REGNUM) (const_int 0))
(pc)
(label_ref (match_dup 9))))
(parallel
[(set (match_dup 3) (plus:SI (match_dup 3) (const_int 1)))
- (clobber (reg:CC 33))])
+ (clobber (reg:CC CC_REGNUM))])
(match_dup 9)]
"operands[3] = operand_subword (operands[0], 0, 0, DImode);
operands[4] = operand_subword (operands[1], 0, 0, DImode);
@@ -3553,278 +3636,242 @@
operands[6] = operand_subword (operands[0], 1, 0, DImode);
operands[7] = operand_subword (operands[1], 1, 0, DImode);
operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();"
- [(set_attr "op_type" "NN")])
+ operands[9] = gen_label_rtx ();")
-(define_expand "adddi3"
+;
+; addsi3 instruction pattern(s).
+;
+
+(define_expand "addsi3"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- (match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:SI 0 "register_operand" "")
+ (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
""
"")
+(define_insn "*addsi3_sign"
+ [(set (match_operand:SI 0 "register_operand" "=d,d")
+ (plus:SI (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))
+ (match_operand:SI 1 "register_operand" "0,0")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "@
+ ah\t%0,%2
+ ahy\t%0,%2"
+ [(set_attr "op_type" "RX,RXY")])
+
;
-; addsi3 instruction pattern(s).
+; add(di|si)3 instruction pattern(s).
;
-(define_insn "*addsi3_imm_cc"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "0")
- (match_operand:SI 2 "const_int_operand" "K"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d")
- (plus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCAmode)
- && CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")"
- "ahi\t%0,%h2"
- [(set_attr "op_type" "RI")])
-
-(define_insn "*addsi3_carry1_cc"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+; ar, ahi, alfi, slfi, a, ay, agr, aghi, algfi, slgfi, ag
+(define_insn "*add<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d,d")
+ (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,K,Op,On,R,T") ) )
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "@
+ a<g>r\t%0,%2
+ a<g>hi\t%0,%h2
+ al<g>fi\t%0,%2
+ sl<g>fi\t%0,%n2
+ a<g>\t%0,%2
+ a<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RI,RIL,RIL,RX<Y>,RXY")])
+
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+(define_insn "*add<mode>3_carry1_cc"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
(match_dup 1)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCL1mode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*addsi3_carry1_cconly"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ al<g>r\t%0,%2
+ al<g>fi\t%0,%2
+ sl<g>fi\t%0,%n2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+
+; alr, al, aly, algr, alg
+(define_insn "*add<mode>3_carry1_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
(match_dup 1)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
"s390_match_ccmode (insn, CCL1mode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ al<g>r\t%0,%2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-(define_insn "*addsi3_carry2_cc"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+(define_insn "*add<mode>3_carry2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
(match_dup 2)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCL1mode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*addsi3_carry2_cconly"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ al<g>r\t%0,%2
+ al<g>fi\t%0,%2
+ sl<g>fi\t%0,%n2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+
+; alr, al, aly, algr, alg
+(define_insn "*add<mode>3_carry2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
(match_dup 2)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
"s390_match_ccmode (insn, CCL1mode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ al<g>r\t%0,%2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-(define_insn "*addsi3_cc"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+; alr, alfi, slfi, al, aly, algr, algfi, slgfi, alg
+(define_insn "*add<mode>3_cc"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,Op,On,R,T"))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
- (plus:SI (match_dup 1) (match_dup 2)))]
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d,d,d")
+ (plus:GPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCLmode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*addsi3_cconly"
- [(set (reg 33)
- (compare (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ al<g>r\t%0,%2
+ al<g>fi\t%0,%2
+ sl<g>fi\t%0,%n2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RIL,RIL,RX<Y>,RXY")])
+
+; alr, al, aly, algr, alg
+(define_insn "*add<mode>3_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*addsi3_cconly2"
- [(set (reg 33)
- (compare (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (neg:SI (match_operand:SI 2 "general_operand" "d,R,T"))))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
"s390_match_ccmode (insn, CCLmode)"
"@
- alr\t%0,%2
- al\t%0,%2
- aly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*addsi3_sign"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (plus:SI (match_operand:SI 1 "register_operand" "0,0")
- (sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))))
- (clobber (reg:CC 33))]
- ""
- "@
- ah\t%0,%2
- ahy\t%0,%2"
- [(set_attr "op_type" "RX,RXY")])
-
-(define_insn "addsi3"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
- (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
- (match_operand:SI 2 "general_operand" "d,K,R,T")))
- (clobber (reg:CC 33))]
- ""
- "@
- ar\t%0,%2
- ahi\t%0,%h2
- a\t%0,%2
- ay\t%0,%2"
- [(set_attr "op_type" "RR,RI,RX,RXY")])
-
-;
-; adddf3 instruction pattern(s).
-;
-
-(define_expand "adddf3"
- [(parallel
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))
- (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 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- adbr\t%0,%2
- adb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
-
-(define_insn "*adddf3_cc"
- [(set (reg 33)
- (compare (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R"))
- (match_operand:DF 3 "const0_operand" "")))
- (set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- adbr\t%0,%2
- adb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
-
-(define_insn "*adddf3_cconly"
- [(set (reg 33)
- (compare (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R"))
- (match_operand:DF 3 "const0_operand" "")))
- (clobber (match_scratch:DF 0 "=f,f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- adbr\t%0,%2
- adb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
-
-(define_insn "*adddf3_ibm"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+ al<g>r\t%0,%2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; alr, al, aly, algr, alg
+(define_insn "*add<mode>3_cconly2"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 1 "nonimmediate_operand" "%0,0,0")
+ (neg:GPR (match_operand:GPR 2 "general_operand" "d,R,T"))))
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
+ "s390_match_ccmode(insn, CCLmode)"
+ "@
+ al<g>r\t%0,%2
+ al<g>\t%0,%2
+ al<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; ahi, afi, aghi, agfi
+(define_insn "*add<mode>3_imm_cc"
+ [(set (reg CC_REGNUM)
+ (compare (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
+ (match_operand:GPR 2 "const_int_operand" "K,Os"))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d,d")
+ (plus:GPR (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCAmode)
+ && (CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'K', \"K\")
+ || CONST_OK_FOR_CONSTRAINT_P (INTVAL (operands[2]), 'O', \"Os\"))
+ && INTVAL (operands[2]) != -((HOST_WIDE_INT)1 << (GET_MODE_BITSIZE(<MODE>mode) - 1))"
"@
- adr\t%0,%2
- ad\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fsimpd,fsimpd")])
+ a<g>hi\t%0,%h2
+ a<g>fi\t%0,%2"
+ [(set_attr "op_type" "RI,RIL")])
;
-; addsf3 instruction pattern(s).
+; add(df|sf)3 instruction pattern(s).
;
-(define_expand "addsf3"
+(define_expand "add<mode>3"
[(parallel
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (plus:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))
+ (clobber (reg:CC CC_REGNUM))])]
"TARGET_HARD_FLOAT"
"")
-(define_insn "*addsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
+; axbr, adbr, aebr, axb, adb, aeb
+(define_insn "*add<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (plus:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- aebr\t%0,%2
- aeb\t%0,%2"
+ a<xde>br\t%0,%2
+ a<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(define_insn "*addsf3_cc"
- [(set (reg 33)
- (compare (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R"))
- (match_operand:SF 3 "const0_operand" "")))
- (set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_dup 1) (match_dup 2)))]
+ (set_attr "type" "fsimp<mode>")])
+
+; axbr, adbr, aebr, axb, adb, aeb
+(define_insn "*add<mode>3_cc"
+ [(set (reg CC_REGNUM)
+ (compare (plus:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>"))
+ (match_operand:FPR 3 "const0_operand" "")))
+ (set (match_operand:FPR 0 "register_operand" "=f,f")
+ (plus:FPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- aebr\t%0,%2
- aeb\t%0,%2"
+ a<xde>br\t%0,%2
+ a<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(define_insn "*addsf3_cconly"
- [(set (reg 33)
- (compare (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R"))
- (match_operand:SF 3 "const0_operand" "")))
- (clobber (match_scratch:SF 0 "=f,f"))]
+ (set_attr "type" "fsimp<mode>")])
+
+; axbr, adbr, aebr, axb, adb, aeb
+(define_insn "*add<mode>3_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (plus:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>"))
+ (match_operand:FPR 3 "const0_operand" "")))
+ (clobber (match_scratch:FPR 0 "=f,f"))]
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- aebr\t%0,%2
- aeb\t%0,%2"
+ a<xde>br\t%0,%2
+ a<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(define_insn "*addsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
+ (set_attr "type" "fsimp<mode>")])
+
+; axr, adr, aer, ax, ad, ae
+(define_insn "*add<mode>3_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (plus:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
- aer\t%0,%2
- ae\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fsimps,fsimps")])
+ a<xde>r\t%0,%2
+ a<xde>\t%0,%2"
+ [(set_attr "op_type" "<RRe>,<RXe>")
+ (set_attr "type" "fsimp<mode>")])
;;
@@ -3832,14 +3879,51 @@
;;
;
+; subti3 instruction pattern(s).
+;
+
+(define_insn_and_split "subti3"
+ [(set (match_operand:TI 0 "register_operand" "=&d")
+ (minus:TI (match_operand:TI 1 "register_operand" "0")
+ (match_operand:TI 2 "general_operand" "do") ) )
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT"
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (reg:CCL2 CC_REGNUM)
+ (compare:CCL2 (minus:DI (match_dup 7) (match_dup 8))
+ (match_dup 7)))
+ (set (match_dup 6) (minus:DI (match_dup 7) (match_dup 8)))])
+ (parallel
+ [(set (match_dup 3) (minus:DI (minus:DI (match_dup 4) (match_dup 5))
+ (gtu:DI (reg:CCL2 CC_REGNUM) (const_int 0))))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[3] = operand_subword (operands[0], 0, 0, TImode);
+ operands[4] = operand_subword (operands[1], 0, 0, TImode);
+ operands[5] = operand_subword (operands[2], 0, 0, TImode);
+ operands[6] = operand_subword (operands[0], 1, 0, TImode);
+ operands[7] = operand_subword (operands[1], 1, 0, TImode);
+ operands[8] = operand_subword (operands[2], 1, 0, TImode);")
+
+;
; subdi3 instruction pattern(s).
;
+(define_expand "subdi3"
+ [(parallel
+ [(set (match_operand:DI 0 "register_operand" "")
+ (minus:DI (match_operand:DI 1 "register_operand" "")
+ (match_operand:DI 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ "")
+
(define_insn "*subdi3_sign"
[(set (match_operand:DI 0 "register_operand" "=d,d")
(minus:DI (match_operand:DI 1 "register_operand" "0,0")
(sign_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
"@
sgfr\t%0,%2
@@ -3847,7 +3931,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*subdi3_zero_cc"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
(zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
(const_int 0)))
@@ -3860,7 +3944,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*subdi3_zero_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
(zero_extend:DI (match_operand:SI 2 "general_operand" "d,m")))
(const_int 0)))
@@ -3875,122 +3959,60 @@
[(set (match_operand:DI 0 "register_operand" "=d,d")
(minus:DI (match_operand:DI 1 "register_operand" "0,0")
(zero_extend:DI (match_operand:SI 2 "general_operand" "d,m"))))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
"@
slgfr\t%0,%2
slgf\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "*subdi3_borrow_cc"
- [(set (reg 33)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 1)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL2mode) && TARGET_64BIT"
- "@
- slgr\t%0,%2
- slg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*subdi3_borrow_cconly"
- [(set (reg 33)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_dup 1)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCL2mode) && TARGET_64BIT"
- "@
- slgr\t%0,%2
- slg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*subdi3_cc"
- [(set (reg 33)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
- "@
- slgr\t%0,%2
- slg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(define_insn "*subdi3_cconly"
- [(set (reg 33)
- (compare (minus:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (const_int 0)))
- (clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
- "@
- slgr\t%0,%2
- slg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-
-(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")])
-
(define_insn_and_split "*subdi3_31z"
[(set (match_operand:DI 0 "register_operand" "=&d")
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT && TARGET_CPU_ZARCH"
"#"
"&& reload_completed"
[(parallel
- [(set (reg:CCL2 33)
+ [(set (reg:CCL2 CC_REGNUM)
(compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
(match_dup 7)))
(set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
(parallel
[(set (match_dup 3) (minus:SI (minus:SI (match_dup 4) (match_dup 5))
- (gtu:SI (reg:CCL2 33) (const_int 0))))
- (clobber (reg:CC 33))])]
+ (gtu:SI (reg:CCL2 CC_REGNUM) (const_int 0))))
+ (clobber (reg:CC CC_REGNUM))])]
"operands[3] = operand_subword (operands[0], 0, 0, DImode);
operands[4] = operand_subword (operands[1], 0, 0, DImode);
operands[5] = operand_subword (operands[2], 0, 0, DImode);
operands[6] = operand_subword (operands[0], 1, 0, DImode);
operands[7] = operand_subword (operands[1], 1, 0, DImode);
- operands[8] = operand_subword (operands[2], 1, 0, DImode);"
- [(set_attr "op_type" "NN")])
+ operands[8] = operand_subword (operands[2], 1, 0, DImode);")
(define_insn_and_split "*subdi3_31"
[(set (match_operand:DI 0 "register_operand" "=&d")
(minus:DI (match_operand:DI 1 "register_operand" "0")
(match_operand:DI 2 "general_operand" "do") ) )
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_CPU_ZARCH"
"#"
"&& reload_completed"
[(parallel
[(set (match_dup 3) (minus:SI (match_dup 4) (match_dup 5)))
- (clobber (reg:CC 33))])
+ (clobber (reg:CC CC_REGNUM))])
(parallel
- [(set (reg:CCL2 33)
+ [(set (reg:CCL2 CC_REGNUM)
(compare:CCL2 (minus:SI (match_dup 7) (match_dup 8))
(match_dup 7)))
(set (match_dup 6) (minus:SI (match_dup 7) (match_dup 8)))])
(set (pc)
- (if_then_else (gtu (reg:CCL2 33) (const_int 0))
+ (if_then_else (gtu (reg:CCL2 CC_REGNUM) (const_int 0))
(pc)
(label_ref (match_dup 9))))
(parallel
[(set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))
- (clobber (reg:CC 33))])
+ (clobber (reg:CC CC_REGNUM))])
(match_dup 9)]
"operands[3] = operand_subword (operands[0], 0, 0, DImode);
operands[4] = operand_subword (operands[1], 0, 0, DImode);
@@ -3998,227 +4020,201 @@
operands[6] = operand_subword (operands[0], 1, 0, DImode);
operands[7] = operand_subword (operands[1], 1, 0, DImode);
operands[8] = operand_subword (operands[2], 1, 0, DImode);
- operands[9] = gen_label_rtx ();"
- [(set_attr "op_type" "NN")])
-
-(define_expand "subdi3"
- [(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "general_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "")
+ operands[9] = gen_label_rtx ();")
;
; subsi3 instruction pattern(s).
;
-(define_insn "*subsi3_borrow_cc"
- [(set (reg 33)
- (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
- (match_dup 1)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCL2mode)"
- "@
- slr\t%0,%2
- sl\t%0,%2
- sly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*subsi3_borrow_cconly"
- [(set (reg 33)
- (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
- (match_dup 1)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode (insn, CCL2mode)"
- "@
- slr\t%0,%2
- sl\t%0,%2
- sly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*subsi3_cc"
- [(set (reg 33)
- (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
- (minus:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- slr\t%0,%2
- sl\t%0,%2
- sly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_insn "*subsi3_cconly"
- [(set (reg 33)
- (compare (minus:SI (match_operand:SI 1 "register_operand" "0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode (insn, CCLmode)"
- "@
- slr\t%0,%2
- sl\t%0,%2
- sly\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+(define_expand "subsi3"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (minus:SI (match_operand:SI 1 "register_operand" "")
+ (match_operand:SI 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+ "")
(define_insn "*subsi3_sign"
[(set (match_operand:SI 0 "register_operand" "=d,d")
(minus:SI (match_operand:SI 1 "register_operand" "0,0")
(sign_extend:SI (match_operand:HI 2 "memory_operand" "R,T"))))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
""
"@
sh\t%0,%2
shy\t%0,%2"
[(set_attr "op_type" "RX,RXY")])
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (minus:SI (match_operand:SI 1 "register_operand" "0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T")))
- (clobber (reg:CC 33))]
- ""
- "@
- sr\t%0,%2
- s\t%0,%2
- sy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-
;
-; subdf3 instruction pattern(s).
+; sub(di|si)3 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 "general_operand" "f,R")))
- (clobber (reg:CC 33))])]
- "TARGET_HARD_FLOAT"
- "")
+; sr, s, sy, sgr, sg
+(define_insn "*sub<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (minus:GPR (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T") ) )
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "@
+ s<g>r\t%0,%2
+ s<g>\t%0,%2
+ s<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-(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 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_borrow_cc"
+ [(set (reg CC_REGNUM)
+ (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
+ (match_dup 1)))
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (minus:GPR (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCL2mode)"
"@
- sdbr\t%0,%2
- sdb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
-
-(define_insn "*subdf3_cc"
- [(set (reg 33)
- (compare (minus:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")
- (match_operand:DF 2 "general_operand" "f,R"))
- (match_operand:DF 3 "const0_operand" "")))
- (set (match_operand:DF 0 "register_operand" "=f,f")
- (minus:DF (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_borrow_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
+ (match_dup 1)))
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
+ "s390_match_ccmode (insn, CCL2mode)"
"@
- sdbr\t%0,%2
- sdb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
-
-(define_insn "*subdf3_cconly"
- [(set (reg 33)
- (compare (minus:DF (match_operand:DF 1 "nonimmediate_operand" "0,0")
- (match_operand:DF 2 "general_operand" "f,R"))
- (match_operand:DF 3 "const0_operand" "")))
- (clobber (match_scratch:DF 0 "=f,f"))]
- "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_cc"
+ [(set (reg CC_REGNUM)
+ (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (minus:GPR (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCLmode)"
"@
- sdbr\t%0,%2
- sdb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimpd,fsimpd")])
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_cc2"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T")))
+ (set (match_operand:GPR 0 "register_operand" "=d,d,d")
+ (minus:GPR (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode (insn, CCL3mode)"
+ "@
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
+
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (minus:GPR (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T"))
+ (const_int 0)))
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
+ "s390_match_ccmode (insn, CCLmode)"
+ "@
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
-(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 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
+; slr, sl, sly, slgr, slg
+(define_insn "*sub<mode>3_cconly2"
+ [(set (reg CC_REGNUM)
+ (compare (match_operand:GPR 1 "register_operand" "0,0,0")
+ (match_operand:GPR 2 "general_operand" "d,R,T")))
+ (clobber (match_scratch:GPR 0 "=d,d,d"))]
+ "s390_match_ccmode (insn, CCL3mode)"
"@
- sdr\t%0,%2
- sd\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fsimpd,fsimpd")])
+ sl<g>r\t%0,%2
+ sl<g>\t%0,%2
+ sl<y>\t%0,%2"
+ [(set_attr "op_type" "RR<E>,RX<Y>,RXY")])
;
-; subsf3 instruction pattern(s).
+; sub(df|sf)3 instruction pattern(s).
;
-(define_expand "subsf3"
+(define_expand "sub<mode>3"
[(parallel
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (minus:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (minus:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,R")))
+ (clobber (reg:CC CC_REGNUM))])]
"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 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
+; sxbr, sdbr, sebr, sxb, sdb, seb
+(define_insn "*sub<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (minus:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- sebr\t%0,%2
- seb\t%0,%2"
+ s<xde>br\t%0,%2
+ s<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(define_insn "*subsf3_cc"
- [(set (reg 33)
- (compare (minus:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R"))
- (match_operand:SF 3 "const0_operand" "")))
- (set (match_operand:SF 0 "register_operand" "=f,f")
- (minus:SF (match_dup 1) (match_dup 2)))]
+ (set_attr "type" "fsimp<mode>")])
+
+; sxbr, sdbr, sebr, sxb, sdb, seb
+(define_insn "*sub<mode>3_cc"
+ [(set (reg CC_REGNUM)
+ (compare (minus:FPR (match_operand:FPR 1 "nonimmediate_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>"))
+ (match_operand:FPR 3 "const0_operand" "")))
+ (set (match_operand:FPR 0 "register_operand" "=f,f")
+ (minus:FPR (match_dup 1) (match_dup 2)))]
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- sebr\t%0,%2
- seb\t%0,%2"
+ s<xde>br\t%0,%2
+ s<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(define_insn "*subsf3_cconly"
- [(set (reg 33)
- (compare (minus:SF (match_operand:SF 1 "nonimmediate_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R"))
- (match_operand:SF 3 "const0_operand" "")))
- (clobber (match_scratch:SF 0 "=f,f"))]
+ (set_attr "type" "fsimp<mode>")])
+
+; sxbr, sdbr, sebr, sxb, sdb, seb
+(define_insn "*sub<mode>3_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (minus:FPR (match_operand:FPR 1 "nonimmediate_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>"))
+ (match_operand:FPR 3 "const0_operand" "")))
+ (clobber (match_scratch:FPR 0 "=f,f"))]
"s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- sebr\t%0,%2
- seb\t%0,%2"
+ s<xde>br\t%0,%2
+ s<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fsimps,fsimps")])
-
-(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 "general_operand" "f,R")))
- (clobber (reg:CC 33))]
+ (set_attr "type" "fsimp<mode>")])
+
+; sxr, sdr, ser, sx, sd, se
+(define_insn "*sub<mode>3_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (minus:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
- ser\t%0,%2
- se\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fsimps,fsimps")])
+ s<xde>r\t%0,%2
+ s<xde>\t%0,%2"
+ [(set_attr "op_type" "<RRe>,<RXe>")
+ (set_attr "type" "fsimp<mode>")])
;;
@@ -4226,120 +4222,149 @@
;;
;
-; adddicc instruction pattern(s).
+; add(di|si)cc instruction pattern(s).
;
-(define_insn "*adddi3_alc_cc"
- [(set (reg 33)
+; alcr, alc, alcgr, alcg
+(define_insn "*add<mode>3_alc_cc"
+ [(set (reg CC_REGNUM)
(compare
- (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_operand:DI 3 "s390_alc_comparison" ""))
+ (plus:GPR (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:GPR 2 "general_operand" "d,m"))
+ (match_operand:GPR 3 "s390_alc_comparison" ""))
(const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (plus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ (set (match_operand:GPR 0 "register_operand" "=d,d")
+ (plus:GPR (plus:GPR (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
"@
- alcgr\\t%0,%2
- alcg\\t%0,%2"
+ alc<g>r\t%0,%2
+ alc<g>\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "*adddi3_alc"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (plus:DI (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_operand:DI 3 "s390_alc_comparison" "")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "@
- alcgr\\t%0,%2
- alcg\\t%0,%2"
+; alcr, alc, alcgr, alcg
+(define_insn "*add<mode>3_alc"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (plus:GPR (plus:GPR (match_operand:GPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:GPR 2 "general_operand" "d,m"))
+ (match_operand:GPR 3 "s390_alc_comparison" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_CPU_ZARCH"
+ "@
+ alc<g>r\t%0,%2
+ alc<g>\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "*subdi3_slb_cc"
- [(set (reg 33)
+; slbr, slb, slbgr, slbg
+(define_insn "*sub<mode>3_slb_cc"
+ [(set (reg CC_REGNUM)
(compare
- (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_operand:DI 3 "s390_slb_comparison" ""))
+ (minus:GPR (minus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
+ (match_operand:GPR 2 "general_operand" "d,m"))
+ (match_operand:GPR 3 "s390_slb_comparison" ""))
(const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (minus:DI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_64BIT"
+ (set (match_operand:GPR 0 "register_operand" "=d,d")
+ (minus:GPR (minus:GPR (match_dup 1) (match_dup 2)) (match_dup 3)))]
+ "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
"@
- slbgr\\t%0,%2
- slbg\\t%0,%2"
+ slb<g>r\t%0,%2
+ slb<g>\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "*subdi3_slb"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (minus:DI (minus:DI (match_operand:DI 1 "nonimmediate_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m"))
- (match_operand:DI 3 "s390_slb_comparison" "")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "@
- slbgr\\t%0,%2
- slbg\\t%0,%2"
+; slbr, slb, slbgr, slbg
+(define_insn "*sub<mode>3_slb"
+ [(set (match_operand:GPR 0 "register_operand" "=d,d")
+ (minus:GPR (minus:GPR (match_operand:GPR 1 "nonimmediate_operand" "0,0")
+ (match_operand:GPR 2 "general_operand" "d,m"))
+ (match_operand:GPR 3 "s390_slb_comparison" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_CPU_ZARCH"
+ "@
+ slb<g>r\t%0,%2
+ slb<g>\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
+(define_expand "add<mode>cc"
+ [(match_operand:GPR 0 "register_operand" "")
+ (match_operand 1 "comparison_operator" "")
+ (match_operand:GPR 2 "register_operand" "")
+ (match_operand:GPR 3 "const_int_operand" "")]
+ "TARGET_CPU_ZARCH"
+ "if (!s390_expand_addcc (GET_CODE (operands[1]),
+ s390_compare_op0, s390_compare_op1,
+ operands[0], operands[2],
+ operands[3])) FAIL; DONE;")
+
;
-; addsicc instruction pattern(s).
+; scond instruction pattern(s).
;
-(define_insn "*addsi3_alc_cc"
- [(set (reg 33)
- (compare
- (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "d,m"))
- (match_operand:SI 3 "s390_alc_comparison" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d")
- (plus:SI (plus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
- "@
- alcr\\t%0,%2
- alc\\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
+(define_insn_and_split "*scond<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=&d")
+ (match_operand:GPR 1 "s390_alc_comparison" ""))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_CPU_ZARCH"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (const_int 0))
+ (parallel
+ [(set (match_dup 0) (plus:GPR (plus:GPR (match_dup 0) (match_dup 0))
+ (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "")
-(define_insn "*addsi3_alc"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (plus:SI (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "d,m"))
- (match_operand:SI 3 "s390_alc_comparison" "")))
- (clobber (reg:CC 33))]
- "TARGET_CPU_ZARCH"
- "@
- alcr\\t%0,%2
- alc\\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
+(define_insn_and_split "*scond<mode>_neg"
+ [(set (match_operand:GPR 0 "register_operand" "=&d")
+ (match_operand:GPR 1 "s390_slb_comparison" ""))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_CPU_ZARCH"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 0) (const_int 0))
+ (parallel
+ [(set (match_dup 0) (minus:GPR (minus:GPR (match_dup 0) (match_dup 0))
+ (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_dup 0) (neg:GPR (match_dup 0)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "")
-(define_insn "*subsi3_slb_cc"
- [(set (reg 33)
- (compare
- (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
- (match_operand:SI 2 "general_operand" "d,m"))
- (match_operand:SI 3 "s390_slb_comparison" ""))
- (const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d")
- (minus:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 3)))]
- "s390_match_ccmode (insn, CCLmode) && TARGET_CPU_ZARCH"
- "@
- slbr\\t%0,%2
- slb\\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
-(define_insn "*subsi3_slb"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (minus:SI (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
- (match_operand:SI 2 "general_operand" "d,m"))
- (match_operand:SI 3 "s390_slb_comparison" "")))
- (clobber (reg:CC 33))]
- "TARGET_CPU_ZARCH"
- "@
- slbr\\t%0,%2
- slb\\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
+(define_expand "s<code>"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (SCOND (match_dup 0)
+ (match_dup 0)))]
+ "TARGET_CPU_ZARCH"
+ "if (!s390_expand_addcc (<CODE>, s390_compare_op0, s390_compare_op1,
+ operands[0], const0_rtx, const1_rtx)) FAIL; DONE;")
+
+(define_expand "seq"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (match_dup 1))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_dup 0) (xor:SI (match_dup 0) (const_int 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+{
+ if (!s390_compare_emitted || GET_MODE (s390_compare_emitted) != CCZ1mode)
+ FAIL;
+ operands[1] = s390_emit_compare (NE, s390_compare_op0, s390_compare_op1);
+ PUT_MODE (operands[1], SImode);
+})
+
+(define_insn_and_split "*sne"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (ne:SI (match_operand:CCZ1 1 "register_operand" "0")
+ (const_int 0)))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "#"
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (ashiftrt:SI (match_dup 0) (const_int 28)))
+ (clobber (reg:CC CC_REGNUM))])])
;;
@@ -4359,7 +4384,7 @@
msgfr\t%0,%2
msgf\t%0,%2"
[(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imul")])
+ (set_attr "type" "imuldi")])
(define_insn "muldi3"
[(set (match_operand:DI 0 "register_operand" "=d,d,d")
@@ -4371,7 +4396,7 @@
mghi\t%0,%h2
msg\t%0,%2"
[(set_attr "op_type" "RRE,RI,RXY")
- (set_attr "type" "imul")])
+ (set_attr "type" "imuldi")])
;
; mulsi3 instruction pattern(s).
@@ -4384,7 +4409,7 @@
""
"mh\t%0,%2"
[(set_attr "op_type" "RX")
- (set_attr "type" "imul")])
+ (set_attr "type" "imulhi")])
(define_insn "mulsi3"
[(set (match_operand:SI 0 "register_operand" "=d,d,d,d")
@@ -4397,7 +4422,7 @@
ms\t%0,%2
msy\t%0,%2"
[(set_attr "op_type" "RRE,RI,RX,RXY")
- (set_attr "type" "imul")])
+ (set_attr "type" "imulsi,imulhi,imulsi,imulsi")])
;
; mulsidi3 instruction pattern(s).
@@ -4414,7 +4439,7 @@
mr\t%0,%2
m\t%0,%2"
[(set_attr "op_type" "RR,RX")
- (set_attr "type" "imul")])
+ (set_attr "type" "imulsi")])
;
; umulsidi3 instruction pattern(s).
@@ -4431,121 +4456,68 @@
mlr\t%0,%2
ml\t%0,%2"
[(set_attr "op_type" "RRE,RXY")
- (set_attr "type" "imul")])
+ (set_attr "type" "imulsi")])
;
-; muldf3 instruction pattern(s).
+; mul(df|sf)3 instruction pattern(s).
;
-(define_expand "muldf3"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
+(define_expand "mul<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (mult:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT"
"")
-(define_insn "*muldf3"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- mdbr\t%0,%2
- mdb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuld")])
-
-(define_insn "*muldf3_ibm"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (mult:DF (match_operand:DF 1 "nonimmediate_operand" "%0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
- "@
- mdr\t%0,%2
- md\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fmuld")])
-
-(define_insn "*fmadddf"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (plus:DF (mult:DF (match_operand:DF 1 "register_operand" "%f,f")
- (match_operand:DF 2 "nonimmediate_operand" "f,R"))
- (match_operand:DF 3 "register_operand" "0,0")))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD"
- "@
- madbr\t%0,%1,%2
- madb\t%0,%1,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuld")])
-
-(define_insn "*fmsubdf"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (minus:DF (mult:DF (match_operand:DF 1 "register_operand" "f,f")
- (match_operand:DF 2 "nonimmediate_operand" "f,R"))
- (match_operand:DF 3 "register_operand" "0,0")))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD"
- "@
- msdbr\t%0,%1,%2
- msdb\t%0,%1,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuld")])
-
-;
-; mulsf3 instruction pattern(s).
-;
-
-(define_expand "mulsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT"
- "")
-
-(define_insn "*mulsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
+; mxbr mdbr, meebr, mxb, mxb, meeb
+(define_insn "*mul<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (mult:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- meebr\t%0,%2
- meeb\t%0,%2"
+ m<xdee>br\t%0,%2
+ m<xdee>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuls")])
+ (set_attr "type" "fmul<mode>")])
-(define_insn "*mulsf3_ibm"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (mult:SF (match_operand:SF 1 "nonimmediate_operand" "%0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
+; mxr, mdr, mer, mx, md, me
+(define_insn "*mul<mode>3_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (mult:FPR (match_operand:FPR 1 "nonimmediate_operand" "%0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
- mer\t%0,%2
- me\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fmuls")])
-
-(define_insn "*fmaddsf"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (plus:SF (mult:SF (match_operand:SF 1 "register_operand" "%f,f")
- (match_operand:SF 2 "nonimmediate_operand" "f,R"))
- (match_operand:SF 3 "register_operand" "0,0")))]
+ m<xde>r\t%0,%2
+ m<xde>\t%0,%2"
+ [(set_attr "op_type" "<RRe>,<RXe>")
+ (set_attr "type" "fmul<mode>")])
+
+; maxbr, madbr, maebr, maxb, madb, maeb
+(define_insn "*fmadd<mode>"
+ [(set (match_operand:DSF 0 "register_operand" "=f,f")
+ (plus:DSF (mult:DSF (match_operand:DSF 1 "register_operand" "%f,f")
+ (match_operand:DSF 2 "nonimmediate_operand" "f,R"))
+ (match_operand:DSF 3 "register_operand" "0,0")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD"
"@
- maebr\t%0,%1,%2
- maeb\t%0,%1,%2"
+ ma<xde>br\t%0,%1,%2
+ ma<xde>b\t%0,%1,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuls")])
-
-(define_insn "*fmsubsf"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (minus:SF (mult:SF (match_operand:SF 1 "register_operand" "f,f")
- (match_operand:SF 2 "nonimmediate_operand" "f,R"))
- (match_operand:SF 3 "register_operand" "0,0")))]
+ (set_attr "type" "fmul<mode>")])
+
+; msxbr, msdbr, msebr, msxb, msdb, mseb
+(define_insn "*fmsub<mode>"
+ [(set (match_operand:DSF 0 "register_operand" "=f,f")
+ (minus:DSF (mult:DSF (match_operand:DSF 1 "register_operand" "f,f")
+ (match_operand:DSF 2 "nonimmediate_operand" "f,R"))
+ (match_operand:DSF 3 "register_operand" "0,0")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT && TARGET_FUSED_MADD"
"@
- msebr\t%0,%1,%2
- mseb\t%0,%1,%2"
+ ms<xde>br\t%0,%1,%2
+ ms<xde>b\t%0,%1,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fmuls")])
+ (set_attr "type" "fmul<mode>")])
;;
;;- Divide and modulo instructions.
@@ -4586,14 +4558,12 @@
(define_insn "divmodtidi3"
[(set (match_operand:TI 0 "register_operand" "=d,d")
(ior:TI
- (zero_extend:TI
- (div:DI (match_operand:DI 1 "register_operand" "0,0")
- (match_operand:DI 2 "general_operand" "d,m")))
(ashift:TI
(zero_extend:TI
- (mod:DI (match_dup 1)
- (match_dup 2)))
- (const_int 64))))]
+ (mod:DI (match_operand:DI 1 "register_operand" "0,0")
+ (match_operand:DI 2 "general_operand" "d,m")))
+ (const_int 64))
+ (zero_extend:TI (div:DI (match_dup 1) (match_dup 2)))))]
"TARGET_64BIT"
"@
dsgr\t%0,%2
@@ -4604,14 +4574,14 @@
(define_insn "divmodtisi3"
[(set (match_operand:TI 0 "register_operand" "=d,d")
(ior:TI
- (zero_extend:TI
- (div:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
(ashift:TI
(zero_extend:TI
- (mod:DI (match_dup 1)
- (sign_extend:DI (match_dup 2))))
- (const_int 64))))]
+ (mod:DI (match_operand:DI 1 "register_operand" "0,0")
+ (sign_extend:DI
+ (match_operand:SI 2 "nonimmediate_operand" "d,m"))))
+ (const_int 64))
+ (zero_extend:TI
+ (div:DI (match_dup 1) (sign_extend:DI (match_dup 2))))))]
"TARGET_64BIT"
"@
dsgfr\t%0,%2
@@ -4637,10 +4607,10 @@
div_equal = gen_rtx_UDIV (DImode, operands[1], operands[2]);
mod_equal = gen_rtx_UMOD (DImode, operands[1], operands[2]);
equal = gen_rtx_IOR (TImode,
- gen_rtx_ZERO_EXTEND (TImode, div_equal),
gen_rtx_ASHIFT (TImode,
gen_rtx_ZERO_EXTEND (TImode, mod_equal),
- GEN_INT (64)));
+ GEN_INT (64)),
+ gen_rtx_ZERO_EXTEND (TImode, div_equal));
operands[4] = gen_reg_rtx(TImode);
emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
@@ -4663,16 +4633,17 @@
(define_insn "udivmodtidi3"
[(set (match_operand:TI 0 "register_operand" "=d,d")
- (ior:TI (zero_extend:TI
- (truncate:DI
- (udiv:TI (match_operand:TI 1 "register_operand" "0,0")
- (zero_extend:TI
- (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
- (ashift:TI
- (zero_extend:TI
- (truncate:DI
- (umod:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))
- (const_int 64))))]
+ (ior:TI
+ (ashift:TI
+ (zero_extend:TI
+ (truncate:DI
+ (umod:TI (match_operand:TI 1 "register_operand" "0,0")
+ (zero_extend:TI
+ (match_operand:DI 2 "nonimmediate_operand" "d,m")))))
+ (const_int 64))
+ (zero_extend:TI
+ (truncate:DI
+ (udiv:TI (match_dup 1) (zero_extend:TI (match_dup 2)))))))]
"TARGET_64BIT"
"@
dlgr\t%0,%2
@@ -4698,10 +4669,10 @@
div_equal = gen_rtx_DIV (SImode, operands[1], operands[2]);
mod_equal = gen_rtx_MOD (SImode, operands[1], operands[2]);
equal = gen_rtx_IOR (DImode,
- gen_rtx_ZERO_EXTEND (DImode, div_equal),
gen_rtx_ASHIFT (DImode,
gen_rtx_ZERO_EXTEND (DImode, mod_equal),
- GEN_INT (32)));
+ GEN_INT (32)),
+ gen_rtx_ZERO_EXTEND (DImode, div_equal));
operands[4] = gen_reg_rtx(DImode);
emit_insn (gen_extendsidi2 (operands[4], operands[1]));
@@ -4722,16 +4693,17 @@
(define_insn "divmoddisi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (ior:DI (zero_extend:DI
- (truncate:SI
- (div:DI (match_operand:DI 1 "register_operand" "0,0")
- (sign_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,R")))))
- (ashift:DI
- (zero_extend:DI
- (truncate:SI
- (mod:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))
- (const_int 32))))]
+ (ior:DI
+ (ashift:DI
+ (zero_extend:DI
+ (truncate:SI
+ (mod:DI (match_operand:DI 1 "register_operand" "0,0")
+ (sign_extend:DI
+ (match_operand:SI 2 "nonimmediate_operand" "d,R")))))
+ (const_int 32))
+ (zero_extend:DI
+ (truncate:SI
+ (div:DI (match_dup 1) (sign_extend:DI (match_dup 2)))))))]
"!TARGET_64BIT"
"@
dr\t%0,%2
@@ -4757,10 +4729,10 @@
div_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
mod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
equal = gen_rtx_IOR (DImode,
- gen_rtx_ZERO_EXTEND (DImode, div_equal),
gen_rtx_ASHIFT (DImode,
gen_rtx_ZERO_EXTEND (DImode, mod_equal),
- GEN_INT (32)));
+ GEN_INT (32)),
+ gen_rtx_ZERO_EXTEND (DImode, div_equal));
operands[4] = gen_reg_rtx(DImode);
emit_insn (gen_rtx_CLOBBER (VOIDmode, operands[4]));
@@ -4783,16 +4755,17 @@
(define_insn "udivmoddisi3"
[(set (match_operand:DI 0 "register_operand" "=d,d")
- (ior:DI (zero_extend:DI
- (truncate:SI
- (udiv:DI (match_operand:DI 1 "register_operand" "0,0")
- (zero_extend:DI
- (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
- (ashift:DI
- (zero_extend:DI
- (truncate:SI
- (umod:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))
- (const_int 32))))]
+ (ior:DI
+ (ashift:DI
+ (zero_extend:DI
+ (truncate:SI
+ (umod:DI (match_operand:DI 1 "register_operand" "0,0")
+ (zero_extend:DI
+ (match_operand:SI 2 "nonimmediate_operand" "d,m")))))
+ (const_int 32))
+ (zero_extend:DI
+ (truncate:SI
+ (udiv:DI (match_dup 1) (zero_extend:DI (match_dup 2)))))))]
"!TARGET_64BIT && TARGET_CPU_ZARCH"
"@
dlr\t%0,%2
@@ -4812,10 +4785,10 @@
udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
equal = gen_rtx_IOR (DImode,
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
gen_rtx_ASHIFT (DImode,
gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)));
+ GEN_INT (32)),
+ gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
operands[3] = gen_reg_rtx (DImode);
@@ -4864,7 +4837,7 @@
emit_move_insn (operands[0], 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_insn (gen_cmpsi (operands[2], const0_rtx));
emit_jump_insn (gen_blt (label2));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_beq (label1));
@@ -4903,10 +4876,10 @@
udiv_equal = gen_rtx_UDIV (SImode, operands[1], operands[2]);
umod_equal = gen_rtx_UMOD (SImode, operands[1], operands[2]);
equal = gen_rtx_IOR (DImode,
- gen_rtx_ZERO_EXTEND (DImode, udiv_equal),
gen_rtx_ASHIFT (DImode,
gen_rtx_ZERO_EXTEND (DImode, umod_equal),
- GEN_INT (32)));
+ GEN_INT (32)),
+ gen_rtx_ZERO_EXTEND (DImode, udiv_equal));
operands[3] = gen_reg_rtx (DImode);
@@ -4956,7 +4929,7 @@
emit_move_insn(operands[0], operands[1]);
emit_insn (gen_cmpsi (operands[2], operands[1]));
emit_jump_insn (gen_bgtu (label3));
- emit_insn (gen_cmpsi (operands[2], const1_rtx));
+ emit_insn (gen_cmpsi (operands[2], const0_rtx));
emit_jump_insn (gen_blt (label2));
emit_insn (gen_cmpsi (operands[2], const1_rtx));
emit_jump_insn (gen_beq (label1));
@@ -4983,82 +4956,59 @@
})
;
-; divdf3 instruction pattern(s).
+; div(df|sf)3 instruction pattern(s).
;
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
+(define_expand "div<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (div:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT"
"")
-(define_insn "*divdf3"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
+; dxbr, ddbr, debr, dxb, ddb, deb
+(define_insn "*div<mode>3"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (div:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- ddbr\t%0,%2
- ddb\t%0,%2"
+ d<xde>br\t%0,%2
+ d<xde>b\t%0,%2"
[(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fdivd")])
+ (set_attr "type" "fdiv<mode>")])
-(define_insn "*divdf3_ibm"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (div:DF (match_operand:DF 1 "register_operand" "0,0")
- (match_operand:DF 2 "general_operand" "f,R")))]
+; dxr, ddr, der, dx, dd, de
+(define_insn "*div<mode>3_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (div:FPR (match_operand:FPR 1 "register_operand" "0,0")
+ (match_operand:FPR 2 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
"@
- ddr\t%0,%2
- dd\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fdivd")])
-
-;
-; divsf3 instruction pattern(s).
-;
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT"
- "")
-
-(define_insn "*divsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- debr\t%0,%2
- deb\t%0,%2"
- [(set_attr "op_type" "RRE,RXE")
- (set_attr "type" "fdivs")])
-
-(define_insn "*divsf3"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (div:SF (match_operand:SF 1 "register_operand" "0,0")
- (match_operand:SF 2 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
- "@
- der\t%0,%2
- de\t%0,%2"
- [(set_attr "op_type" "RR,RX")
- (set_attr "type" "fdivs")])
+ d<xde>r\t%0,%2
+ d<xde>\t%0,%2"
+ [(set_attr "op_type" "<RRe>,<RXe>")
+ (set_attr "type" "fdiv<mode>")])
;;
;;- And instructions.
;;
+(define_expand "and<mode>3"
+ [(set (match_operand:INT 0 "nonimmediate_operand" "")
+ (and:INT (match_operand:INT 1 "nonimmediate_operand" "")
+ (match_operand:INT 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "s390_expand_logical_operator (AND, <MODE>mode, operands); DONE;")
+
;
; anddi3 instruction pattern(s).
;
(define_insn "*anddi3_cc"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
@@ -5071,239 +5021,299 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*anddi3_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (and:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d,d"))]
- "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT"
+ "s390_match_ccmode(insn, CCTmode) && TARGET_64BIT
+ /* Do not steal TM patterns. */
+ && s390_single_part (operands[2], DImode, HImode, 0) < 0"
"@
ngr\t%0,%2
ng\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "anddi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d,d,d,d,d,d")
- (and:DI (match_operand:DI 1 "nonimmediate_operand" "d,o,0,0,0,0,0,0")
- (match_operand:DI 2 "general_operand"
- "M,M,N0HDF,N1HDF,N2HDF,N3HDF,d,m")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "@
- #
- #
- nihh\t%0,%j2
- nihl\t%0,%j2
- nilh\t%0,%j2
- nill\t%0,%j2
- ngr\t%0,%2
- ng\t%0,%2"
- [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY")])
-
-(define_insn "*anddi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (and:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*anddi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (and:DI (match_operand:DI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*anddi3_extimm"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,d,d,AQ,Q")
+ (and:DI (match_operand:DI 1 "nonimmediate_operand"
+ "%d,o,0,0,0,0,0,0,0,0,0,0")
+ (match_operand:DI 2 "general_operand"
+ "M,M,N0HDF,N1HDF,N2HDF,N3HDF,N0SDF,N1SDF,d,m,NxQDF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
+ "@
+ #
+ #
+ nihh\t%0,%j2
+ nihl\t%0,%j2
+ nilh\t%0,%j2
+ nill\t%0,%j2
+ nihf\t%0,%m2
+ nilf\t%0,%m2
+ ngr\t%0,%2
+ ng\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RIL,RIL,RRE,RXY,SI,SS")])
+
+(define_insn "*anddi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,AQ,Q")
+ (and:DI (match_operand:DI 1 "nonimmediate_operand"
+ "%d,o,0,0,0,0,0,0,0,0")
+ (match_operand:DI 2 "general_operand"
+ "M,M,N0HDF,N1HDF,N2HDF,N3HDF,d,m,NxQDF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && !TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
+ "@
+ #
+ #
+ nihh\t%0,%j2
+ nihl\t%0,%j2
+ nilh\t%0,%j2
+ nill\t%0,%j2
+ ngr\t%0,%2
+ ng\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RRE,RXE,RI,RI,RI,RI,RRE,RXY,SI,SS")])
+
+(define_split
+ [(set (match_operand:DI 0 "s_operand" "")
+ (and:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
+
;
; andsi3 instruction pattern(s).
;
(define_insn "*andsi3_cc"
- [(set (reg 33)
- (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
(and:SI (match_dup 1) (match_dup 2)))]
"s390_match_ccmode(insn, CCTmode)"
"@
+ nilf\t%0,%o2
nr\t%0,%2
n\t%0,%2
ny\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
(define_insn "*andsi3_cconly"
- [(set (reg 33)
- (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
- "s390_match_ccmode(insn, CCTmode)"
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
+ "s390_match_ccmode(insn, CCTmode)
+ /* Do not steal TM patterns. */
+ && s390_single_part (operands[2], SImode, HImode, 0) < 0"
"@
+ nilf\t%0,%o2
nr\t%0,%2
n\t%0,%2
ny\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
-
-(define_expand "andsi3"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "")
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
(define_insn "*andsi3_zarch"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d,d,d")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "d,o,0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "M,M,N0HSF,N1HSF,d,R,T")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,AQ,Q")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand"
+ "%d,o,0,0,0,0,0,0,0,0")
+ (match_operand:SI 2 "general_operand"
+ "M,M,N0HSF,N1HSF,Os,d,R,T,NxQSF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
#
#
nilh\t%0,%j2
- nill\t%0,%j2
+ nill\t%0,%j2
+ nilf\t%0,%o2
nr\t%0,%2
n\t%0,%2
- ny\t%0,%2"
- [(set_attr "op_type" "RRE,RXE,RI,RI,RR,RX,RXY")])
+ ny\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RRE,RXE,RI,RI,RIL,RR,RX,RXY,SI,SS")])
(define_insn "*andsi3_esa"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
- (match_operand:SI 2 "general_operand" "d,R")))
- (clobber (reg:CC 33))]
- "!TARGET_ZARCH"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "d,R,NxQSF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
nr\t%0,%2
- n\t%0,%2"
- [(set_attr "op_type" "RR,RX")])
-
-(define_insn "*andsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (and:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*andsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (and:SI (match_operand:SI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
+ n\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RR,RX,SI,SS")])
+
+(define_split
+ [(set (match_operand:SI 0 "s_operand" "")
+ (and:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
;
; andhi3 instruction pattern(s).
;
-(define_insn "*andhi3_ni"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (and:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "nonmemory_operand" "d,n")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+(define_insn "*andhi3_zarch"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:HI 2 "general_operand" "d,n,NxQHF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
nr\t%0,%2
- nill\t%0,%x2"
- [(set_attr "op_type" "RR,RI")])
+ nill\t%0,%x2
+ #
+ #"
+ [(set_attr "op_type" "RR,RI,SI,SS")])
-(define_insn "andhi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (and:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "nr\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*andhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (and:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*andhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (and:HI (match_operand:HI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "nc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*andhi3_esa"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q")
+ (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:HI 2 "general_operand" "d,NxQHF,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
+ "@
+ nr\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RR,SI,SS")])
+
+(define_split
+ [(set (match_operand:HI 0 "s_operand" "")
+ (and:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (and:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (AND, &operands[0], &operands[1]);")
;
; andqi3 instruction pattern(s).
;
-(define_insn "*andqi3_ni"
- [(set (match_operand:QI 0 "register_operand" "=d,d")
- (and:QI (match_operand:QI 1 "register_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "d,n")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+(define_insn "*andqi3_zarch"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,Q,S,Q")
+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "d,n,n,n,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
nr\t%0,%2
- nill\t%0,%b2"
- [(set_attr "op_type" "RR,RI")])
-
-(define_insn "andqi3"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (and:QI (match_operand:QI 1 "register_operand" "%0")
- (match_operand:QI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "nr\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*andqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (and:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,n,Q")))
- (clobber (reg:CC 33))]
- ""
+ nill\t%0,%b2
+ ni\t%S0,%b2
+ niy\t%S0,%b2
+ #"
+ [(set_attr "op_type" "RR,RI,SI,SIY,SS")])
+
+(define_insn "*andqi3_esa"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,Q,Q")
+ (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "d,n,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
- ni\t%0,%b1
- niy\t%0,%b1
- nc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+ nr\t%0,%2
+ ni\t%S0,%b2
+ #"
+ [(set_attr "op_type" "RR,SI,SS")])
-(define_insn "*andqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (and:QI (match_operand:QI 1 "s_imm_operand" "n,n,Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "@
- ni\t%0,%b1
- niy\t%0,%b1
- nc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+;
+; Block and (NC) patterns.
+;
+
+(define_insn "*nc"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (and:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "Q")))
+ (use (match_operand 2 "const_int_operand" "n"))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+ "nc\t%O0(%2,%R0),%S1"
+ [(set_attr "op_type" "SS")])
+
+(define_split
+ [(set (match_operand 0 "memory_operand" "")
+ (and (match_dup 0)
+ (match_operand 1 "memory_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+ [(parallel
+ [(set (match_dup 0) (and:BLK (match_dup 0) (match_dup 1)))
+ (use (match_dup 2))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+ operands[0] = adjust_address (operands[0], BLKmode, 0);
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (and:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_operand:BLK 3 "memory_operand" "")
+ (and:BLK (match_dup 3)
+ (match_operand:BLK 4 "memory_operand" "")))
+ (use (match_operand 5 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_offset_p (operands[0], operands[3], operands[2])
+ && s390_offset_p (operands[1], operands[4], operands[2])
+ && !s390_overlap_p (operands[0], operands[1],
+ INTVAL (operands[2]) + INTVAL (operands[5]))
+ && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+ [(parallel
+ [(set (match_dup 6) (and:BLK (match_dup 6) (match_dup 7)))
+ (use (match_dup 8))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+ operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+ operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
;;
;;- Bit set (inclusive or) instructions.
;;
+(define_expand "ior<mode>3"
+ [(set (match_operand:INT 0 "nonimmediate_operand" "")
+ (ior:INT (match_operand:INT 1 "nonimmediate_operand" "")
+ (match_operand:INT 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "s390_expand_logical_operator (IOR, <MODE>mode, operands); DONE;")
+
;
; iordi3 instruction pattern(s).
;
(define_insn "*iordi3_cc"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
@@ -5316,7 +5326,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*iordi3_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
@@ -5327,223 +5337,273 @@
og\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "iordi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d,d,d,d,d")
- (ior:DI (match_operand:DI 1 "nonimmediate_operand" "0,0,0,0,0,0")
- (match_operand:DI 2 "general_operand" "N0HD0,N1HD0,N2HD0,N3HD0,d,m")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
+(define_insn "*iordi3_extimm"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,d,d,AQ,Q")
+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0,0,0,0,0,0,0")
+ (match_operand:DI 2 "general_operand"
+ "N0HD0,N1HD0,N2HD0,N3HD0,N0SD0,N1SD0,d,m,NxQD0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
"@
oihh\t%0,%i2
oihl\t%0,%i2
oilh\t%0,%i2
oill\t%0,%i2
+ oihf\t%0,%k2
+ oilf\t%0,%k2
ogr\t%0,%2
- og\t%0,%2"
- [(set_attr "op_type" "RI,RI,RI,RI,RRE,RXY")])
+ og\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RI,RI,RI,RI,RIL,RIL,RRE,RXY,SI,SS")])
-(define_insn "*iordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (ior:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*iordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (ior:DI (match_operand:DI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*iordi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,d,d,AQ,Q")
+ (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0,0,0,0,0")
+ (match_operand:DI 2 "general_operand"
+ "N0HD0,N1HD0,N2HD0,N3HD0,d,m,NxQD0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && !TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
+ "@
+ oihh\t%0,%i2
+ oihl\t%0,%i2
+ oilh\t%0,%i2
+ oill\t%0,%i2
+ ogr\t%0,%2
+ og\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RI,RI,RI,RI,RRE,RXY,SI,SS")])
+
+(define_split
+ [(set (match_operand:DI 0 "s_operand" "")
+ (ior:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
;
; iorsi3 instruction pattern(s).
;
(define_insn "*iorsi3_cc"
- [(set (reg 33)
- (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
(ior:SI (match_dup 1) (match_dup 2)))]
"s390_match_ccmode(insn, CCTmode)"
"@
+ oilf\t%0,%o2
or\t%0,%2
o\t%0,%2
oy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
(define_insn "*iorsi3_cconly"
- [(set (reg 33)
- (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
"s390_match_ccmode(insn, CCTmode)"
"@
+ oilf\t%0,%o2
or\t%0,%2
o\t%0,%2
oy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
-(define_expand "iorsi3"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (clobber (reg:CC 33))])]
- ""
- "")
-
-(define_insn "iorsi3_zarch"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d,d,d")
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0,0,0,0")
- (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,d,R,T")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+(define_insn "*iorsi3_zarch"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,AQ,Q")
+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0,0,0")
+ (match_operand:SI 2 "general_operand" "N0HS0,N1HS0,Os,d,R,T,NxQS0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
oilh\t%0,%i2
oill\t%0,%i2
+ oilf\t%0,%o2
or\t%0,%2
o\t%0,%2
- oy\t%0,%2"
- [(set_attr "op_type" "RI,RI,RR,RX,RXY")])
+ oy\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RI,RI,RIL,RR,RX,RXY,SI,SS")])
-(define_insn "iorsi3_esa"
- [(set (match_operand:SI 0 "register_operand" "=d,d")
- (ior:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
- (match_operand:SI 2 "general_operand" "d,R")))
- (clobber (reg:CC 33))]
- "!TARGET_ZARCH"
+(define_insn "*iorsi3_esa"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "d,R,NxQS0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
or\t%0,%2
- o\t%0,%2"
- [(set_attr "op_type" "RR,RX")])
-
-(define_insn "*iorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (ior:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*iorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (ior:SI (match_operand:SI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
+ o\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RR,RX,SI,SS")])
+
+(define_split
+ [(set (match_operand:SI 0 "s_operand" "")
+ (ior:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
;
; iorhi3 instruction pattern(s).
;
-(define_insn "*iorhi3_oi"
- [(set (match_operand:HI 0 "register_operand" "=d,d")
- (ior:HI (match_operand:HI 1 "register_operand" "%0,0")
- (match_operand:HI 2 "nonmemory_operand" "d,n")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+(define_insn "*iorhi3_zarch"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:HI 2 "general_operand" "d,n,NxQH0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
or\t%0,%2
- oill\t%0,%x2"
- [(set_attr "op_type" "RR,RI")])
+ oill\t%0,%x2
+ #
+ #"
+ [(set_attr "op_type" "RR,RI,SI,SS")])
-(define_insn "iorhi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (ior:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "or\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*iorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (ior:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*iorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (ior:HI (match_operand:HI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "oc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*iorhi3_esa"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,AQ,Q")
+ (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:HI 2 "general_operand" "d,NxQH0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
+ "@
+ or\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RR,SI,SS")])
+
+(define_split
+ [(set (match_operand:HI 0 "s_operand" "")
+ (ior:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (ior:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (IOR, &operands[0], &operands[1]);")
;
; iorqi3 instruction pattern(s).
;
-(define_insn "*iorqi3_oi"
- [(set (match_operand:QI 0 "register_operand" "=d,d")
- (ior:QI (match_operand:QI 1 "register_operand" "%0,0")
- (match_operand:QI 2 "nonmemory_operand" "d,n")))
- (clobber (reg:CC 33))]
- "TARGET_ZARCH"
+(define_insn "*iorqi3_zarch"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,Q,S,Q")
+ (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "d,n,n,n,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
or\t%0,%2
- oill\t%0,%b2"
- [(set_attr "op_type" "RR,RI")])
-
-(define_insn "iorqi3"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ior:QI (match_operand:QI 1 "register_operand" "%0")
- (match_operand:QI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "or\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*iorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (ior:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,n,Q")))
- (clobber (reg:CC 33))]
- ""
+ oill\t%0,%b2
+ oi\t%S0,%b2
+ oiy\t%S0,%b2
+ #"
+ [(set_attr "op_type" "RR,RI,SI,SIY,SS")])
+
+(define_insn "*iorqi3_esa"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,Q,Q")
+ (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0")
+ (match_operand:QI 2 "general_operand" "d,n,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_ZARCH && s390_logical_operator_ok_p (operands)"
"@
- oi\t%0,%b1
- oiy\t%0,%b1
- oc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+ or\t%0,%2
+ oi\t%S0,%b2
+ #"
+ [(set_attr "op_type" "RR,SI,SS")])
-(define_insn "*iorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (ior:QI (match_operand:QI 1 "s_imm_operand" "n,n,Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "@
- oi\t%0,%b1
- oiy\t%0,%b1
- oc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+;
+; Block inclusive or (OC) patterns.
+;
+
+(define_insn "*oc"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (ior:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "Q")))
+ (use (match_operand 2 "const_int_operand" "n"))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+ "oc\t%O0(%2,%R0),%S1"
+ [(set_attr "op_type" "SS")])
+
+(define_split
+ [(set (match_operand 0 "memory_operand" "")
+ (ior (match_dup 0)
+ (match_operand 1 "memory_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+ [(parallel
+ [(set (match_dup 0) (ior:BLK (match_dup 0) (match_dup 1)))
+ (use (match_dup 2))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+ operands[0] = adjust_address (operands[0], BLKmode, 0);
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (ior:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_operand:BLK 3 "memory_operand" "")
+ (ior:BLK (match_dup 3)
+ (match_operand:BLK 4 "memory_operand" "")))
+ (use (match_operand 5 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_offset_p (operands[0], operands[3], operands[2])
+ && s390_offset_p (operands[1], operands[4], operands[2])
+ && !s390_overlap_p (operands[0], operands[1],
+ INTVAL (operands[2]) + INTVAL (operands[5]))
+ && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+ [(parallel
+ [(set (match_dup 6) (ior:BLK (match_dup 6) (match_dup 7)))
+ (use (match_dup 8))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+ operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+ operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
;;
;;- Xor instructions.
;;
+(define_expand "xor<mode>3"
+ [(set (match_operand:INT 0 "nonimmediate_operand" "")
+ (xor:INT (match_operand:INT 1 "nonimmediate_operand" "")
+ (match_operand:INT 2 "general_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "s390_expand_logical_operator (XOR, <MODE>mode, operands); DONE;")
+
;
; xordi3 instruction pattern(s).
;
(define_insn "*xordi3_cc"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
@@ -5556,7 +5616,7 @@
[(set_attr "op_type" "RRE,RXY")])
(define_insn "*xordi3_cconly"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
(match_operand:DI 2 "general_operand" "d,m"))
(const_int 0)))
@@ -5567,163 +5627,237 @@
xr\t%0,%2"
[(set_attr "op_type" "RRE,RXY")])
-(define_insn "xordi3"
- [(set (match_operand:DI 0 "register_operand" "=d,d")
- (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0")
- (match_operand:DI 2 "general_operand" "d,m")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
+(define_insn "*xordi3_extimm"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,AQ,Q")
+ (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:DI 2 "general_operand" "N0SD0,N1SD0,d,m,NxQD0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
"@
+ xihf\t%0,%k2
+ xilf\t%0,%k2
xgr\t%0,%2
- xg\t%0,%2"
- [(set_attr "op_type" "RRE,RXY")])
+ xg\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RIL,RIL,RRE,RXY,SI,SS")])
-(define_insn "*xordi3_ss"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (xor:DI (match_dup 0)
- (match_operand:DI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*xordi3_ss_inv"
- [(set (match_operand:DI 0 "s_operand" "=Q")
- (xor:DI (match_operand:DI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(8,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*xordi3"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:DI 2 "general_operand" "d,m,NxQD0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_64BIT && !TARGET_EXTIMM && s390_logical_operator_ok_p (operands)"
+ "@
+ xgr\t%0,%2
+ xg\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RRE,RXY,SI,SS")])
+
+(define_split
+ [(set (match_operand:DI 0 "s_operand" "")
+ (xor:DI (match_dup 0) (match_operand:DI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
;
; xorsi3 instruction pattern(s).
;
(define_insn "*xorsi3_cc"
- [(set (reg 33)
- (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d,d,d")
+ (set (match_operand:SI 0 "register_operand" "=d,d,d,d")
(xor:SI (match_dup 1) (match_dup 2)))]
"s390_match_ccmode(insn, CCTmode)"
"@
+ xilf\t%0,%o2
xr\t%0,%2
x\t%0,%2
xy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
(define_insn "*xorsi3_cconly"
- [(set (reg 33)
- (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T"))
+ [(set (reg CC_REGNUM)
+ (compare (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T"))
(const_int 0)))
- (clobber (match_scratch:SI 0 "=d,d,d"))]
+ (clobber (match_scratch:SI 0 "=d,d,d,d"))]
"s390_match_ccmode(insn, CCTmode)"
"@
+ xilf\t%0,%o2
xr\t%0,%2
x\t%0,%2
xy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ [(set_attr "op_type" "RIL,RR,RX,RXY")])
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=d,d,d")
- (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
- (match_operand:SI 2 "general_operand" "d,R,T")))
- (clobber (reg:CC 33))]
- ""
+(define_insn "*xorsi3"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,AQ,Q")
+ (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0,0,0,0")
+ (match_operand:SI 2 "general_operand" "Os,d,R,T,NxQS0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "s390_logical_operator_ok_p (operands)"
"@
+ xilf\t%0,%o2
xr\t%0,%2
x\t%0,%2
- xy\t%0,%2"
- [(set_attr "op_type" "RR,RX,RXY")])
+ xy\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RIL,RR,RX,RXY,SI,SS")])
-(define_insn "*xorsi3_ss"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (xor:SI (match_dup 0)
- (match_operand:SI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*xorsi3_ss_inv"
- [(set (match_operand:SI 0 "s_operand" "=Q")
- (xor:SI (match_operand:SI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(4,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_split
+ [(set (match_operand:SI 0 "s_operand" "")
+ (xor:SI (match_dup 0) (match_operand:SI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
;
; xorhi3 instruction pattern(s).
;
-(define_insn "xorhi3"
- [(set (match_operand:HI 0 "register_operand" "=d")
- (xor:HI (match_operand:HI 1 "register_operand" "%0")
- (match_operand:HI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "xr\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*xorhi3_ss"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (xor:HI (match_dup 0)
- (match_operand:HI 1 "s_imm_operand" "Q")))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
-
-(define_insn "*xorhi3_ss_inv"
- [(set (match_operand:HI 0 "s_operand" "=Q")
- (xor:HI (match_operand:HI 1 "s_imm_operand" "Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "xc\t%O0(2,%R0),%1"
- [(set_attr "op_type" "SS")])
+(define_insn "*xorhi3"
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,AQ,Q")
+ (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0,0")
+ (match_operand:HI 2 "general_operand" "Os,d,NxQH0,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "s390_logical_operator_ok_p (operands)"
+ "@
+ xilf\t%0,%x2
+ xr\t%0,%2
+ #
+ #"
+ [(set_attr "op_type" "RIL,RR,SI,SS")])
+
+(define_split
+ [(set (match_operand:HI 0 "s_operand" "")
+ (xor:HI (match_dup 0) (match_operand:HI 1 "immediate_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed"
+ [(parallel
+ [(set (match_dup 0) (xor:QI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_narrow_logical_operator (XOR, &operands[0], &operands[1]);")
;
; xorqi3 instruction pattern(s).
;
-(define_insn "xorqi3"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (xor:QI (match_operand:QI 1 "register_operand" "%0")
- (match_operand:QI 2 "nonmemory_operand" "d")))
- (clobber (reg:CC 33))]
- ""
- "xr\t%0,%2"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*xorqi3_ss"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (xor:QI (match_dup 0)
- (match_operand:QI 1 "s_imm_operand" "n,n,Q")))
- (clobber (reg:CC 33))]
- ""
+(define_insn "*xorqi3"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,Q,S,Q")
+ (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,0,0,0")
+ (match_operand:QI 2 "general_operand" "Os,d,n,n,Q")))
+ (clobber (reg:CC CC_REGNUM))]
+ "s390_logical_operator_ok_p (operands)"
"@
- xi\t%0,%b1
- xiy\t%0,%b1
- xc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+ xilf\t%0,%b2
+ xr\t%0,%2
+ xi\t%S0,%b2
+ xiy\t%S0,%b2
+ #"
+ [(set_attr "op_type" "RIL,RR,SI,SIY,SS")])
-(define_insn "*xorqi3_ss_inv"
- [(set (match_operand:QI 0 "s_operand" "=Q,S,Q")
- (xor:QI (match_operand:QI 1 "s_imm_operand" "n,n,Q")
- (match_dup 0)))
- (clobber (reg:CC 33))]
- ""
- "@
- xi\t%0,%b1
- xiy\t%0,%b1
- xc\t%O0(1,%R0),%1"
- [(set_attr "op_type" "SI,SIY,SS")])
+;
+; Block exclusive or (XC) patterns.
+;
+
+(define_insn "*xc"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (xor:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "Q")))
+ (use (match_operand 2 "const_int_operand" "n"))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 256"
+ "xc\t%O0(%2,%R0),%S1"
+ [(set_attr "op_type" "SS")])
+
+(define_split
+ [(set (match_operand 0 "memory_operand" "")
+ (xor (match_dup 0)
+ (match_operand 1 "memory_operand" "")))
+ (clobber (reg:CC CC_REGNUM))]
+ "reload_completed
+ && GET_MODE (operands[0]) == GET_MODE (operands[1])
+ && GET_MODE_SIZE (GET_MODE (operands[0])) > 0"
+ [(parallel
+ [(set (match_dup 0) (xor:BLK (match_dup 0) (match_dup 1)))
+ (use (match_dup 2))
+ (clobber (reg:CC CC_REGNUM))])]
+{
+ operands[2] = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[0])));
+ operands[0] = adjust_address (operands[0], BLKmode, 0);
+ operands[1] = adjust_address (operands[1], BLKmode, 0);
+})
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (xor:BLK (match_dup 0)
+ (match_operand:BLK 1 "memory_operand" "")))
+ (use (match_operand 2 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_operand:BLK 3 "memory_operand" "")
+ (xor:BLK (match_dup 3)
+ (match_operand:BLK 4 "memory_operand" "")))
+ (use (match_operand 5 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_offset_p (operands[0], operands[3], operands[2])
+ && s390_offset_p (operands[1], operands[4], operands[2])
+ && !s390_overlap_p (operands[0], operands[1],
+ INTVAL (operands[2]) + INTVAL (operands[5]))
+ && INTVAL (operands[2]) + INTVAL (operands[5]) <= 256"
+ [(parallel
+ [(set (match_dup 6) (xor:BLK (match_dup 6) (match_dup 7)))
+ (use (match_dup 8))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[6] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+ operands[7] = gen_rtx_MEM (BLKmode, XEXP (operands[1], 0));
+ operands[8] = GEN_INT (INTVAL (operands[2]) + INTVAL (operands[5]));")
+
+;
+; Block xor (XC) patterns with src == dest.
+;
+
+(define_insn "*xc_zero"
+ [(set (match_operand:BLK 0 "memory_operand" "=Q")
+ (const_int 0))
+ (use (match_operand 1 "const_int_operand" "n"))
+ (clobber (reg:CC CC_REGNUM))]
+ "INTVAL (operands[1]) >= 1 && INTVAL (operands[1]) <= 256"
+ "xc\t%O0(%1,%R0),%S0"
+ [(set_attr "op_type" "SS")])
+
+(define_peephole2
+ [(parallel
+ [(set (match_operand:BLK 0 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 1 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (match_operand:BLK 2 "memory_operand" "")
+ (const_int 0))
+ (use (match_operand 3 "const_int_operand" ""))
+ (clobber (reg:CC CC_REGNUM))])]
+ "s390_offset_p (operands[0], operands[2], operands[1])
+ && INTVAL (operands[1]) + INTVAL (operands[3]) <= 256"
+ [(parallel
+ [(set (match_dup 4) (const_int 0))
+ (use (match_dup 5))
+ (clobber (reg:CC CC_REGNUM))])]
+ "operands[4] = gen_rtx_MEM (BLKmode, XEXP (operands[0], 0));
+ operands[5] = GEN_INT (INTVAL (operands[1]) + INTVAL (operands[3]));")
;;
@@ -5731,116 +5865,149 @@
;;
;
-; negdi2 instruction pattern(s).
+; neg(di|si)2 instruction pattern(s).
;
-(define_expand "negdi2"
+(define_expand "neg<mode>2"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:DSI 0 "register_operand" "=d")
+ (neg:DSI (match_operand:DSI 1 "register_operand" "d")))
+ (clobber (reg:CC CC_REGNUM))])]
""
"")
-(define_insn "*negdi2_64"
+(define_insn "*negdi2_sign_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:DI (ashiftrt:DI (ashift:DI (subreg:DI
+ (match_operand:SI 1 "register_operand" "d") 0)
+ (const_int 32)) (const_int 32)))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (sign_extend:DI (match_dup 1))))]
+ "TARGET_64BIT && s390_match_ccmode (insn, CCAmode)"
+ "lcgfr\t%0,%1"
+ [(set_attr "op_type" "RRE")])
+
+(define_insn "*negdi2_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
+ (neg:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
- "lcgr\t%0,%1"
- [(set_attr "op_type" "RR")])
+ "lcgfr\t%0,%1"
+ [(set_attr "op_type" "RRE")])
-(define_insn "*negdi2_31"
+; lcr, lcgr
+(define_insn "*neg<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:GPR (match_operand:GPR 1 "register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d")
+ (neg:GPR (match_dup 1)))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "lc<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+; lcr, lcgr
+(define_insn "*neg<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (neg:GPR (match_operand:GPR 1 "register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:GPR 0 "=d"))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "lc<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+; lcr, lcgr
+(define_insn "*neg<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (neg:GPR (match_operand:GPR 1 "register_operand" "d")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "lc<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+(define_insn_and_split "*negdi2_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(neg:DI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
+ (clobber (reg:CC CC_REGNUM))]
"!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);
- targetm.asm_out.internal_label (asm_out_file, "L",
- CODE_LABEL_NUMBER (xop[0]));
- return "";
-}
- [(set_attr "op_type" "NN")
- (set_attr "type" "other")
- (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")])
+ "#"
+ "&& reload_completed"
+ [(parallel
+ [(set (match_dup 2) (neg:SI (match_dup 3)))
+ (clobber (reg:CC CC_REGNUM))])
+ (parallel
+ [(set (reg:CCAP CC_REGNUM)
+ (compare:CCAP (neg:SI (match_dup 5)) (const_int 0)))
+ (set (match_dup 4) (neg:SI (match_dup 5)))])
+ (set (pc)
+ (if_then_else (ne (reg:CCAP CC_REGNUM) (const_int 0))
+ (pc)
+ (label_ref (match_dup 6))))
+ (parallel
+ [(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
+ (clobber (reg:CC CC_REGNUM))])
+ (match_dup 6)]
+ "operands[2] = operand_subword (operands[0], 0, 0, DImode);
+ operands[3] = operand_subword (operands[1], 0, 0, DImode);
+ operands[4] = operand_subword (operands[0], 1, 0, DImode);
+ operands[5] = operand_subword (operands[1], 1, 0, DImode);
+ operands[6] = gen_label_rtx ();")
;
-; negdf2 instruction pattern(s).
+; neg(df|sf)2 instruction pattern(s).
;
-(define_expand "negdf2"
+(define_expand "neg<mode>2"
[(parallel
- [(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (match_operand:DF 1 "register_operand" "f")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))])]
"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"
+; lcxbr, lcdbr, lcebr
+(define_insn "*neg<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:FPR (match_operand:FPR 1 "register_operand" "f"))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (match_dup 1)))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lc<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimpd")])
-
-(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")
- (set_attr "type" "fsimpd")])
-
-;
-; 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"
- "")
+ (set_attr "type" "fsimp<mode>")])
+
+; lcxbr, lcdbr, lcebr
+(define_insn "*neg<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (neg:FPR (match_operand:FPR 1 "register_operand" "f"))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (clobber (match_scratch:FPR 0 "=f"))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lc<xde>br\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*negsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (match_operand:SF 1 "register_operand" "f")))
- (clobber (reg:CC 33))]
+; lcxbr, lcdbr, lcebr
+(define_insn "*neg<mode>2"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "lcebr\t%0,%1"
+ "lc<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimps")])
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*negsf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (match_operand:SF 1 "register_operand" "f")))
- (clobber (reg:CC 33))]
+; lcxr, lcdr, lcer
+(define_insn "*neg<mode>2_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
- "lcer\t%0,%1"
- [(set_attr "op_type" "RR")
- (set_attr "type" "fsimps")])
+ "lc<xde>r\t%0,%1"
+ [(set_attr "op_type" "<RRe>")
+ (set_attr "type" "fsimp<mode>")])
;;
@@ -5848,88 +6015,113 @@
;;
;
-; absdi2 instruction pattern(s).
+; abs(di|si)2 instruction pattern(s).
;
-(define_insn "absdi2"
+(define_insn "*absdi2_sign_cc"
+ [(set (reg CC_REGNUM)
+ (compare (abs:DI (ashiftrt:DI (ashift:DI (subreg:DI
+ (match_operand:SI 1 "register_operand" "d") 0)
+ (const_int 32)) (const_int 32)))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (abs:DI (sign_extend:DI (match_dup 1))))]
+ "TARGET_64BIT && s390_match_ccmode (insn, CCAmode)"
+ "lpgfr\t%0,%1"
+ [(set_attr "op_type" "RRE")])
+
+(define_insn "*absdi2_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
- (abs:DI (match_operand:DI 1 "register_operand" "d")))
- (clobber (reg:CC 33))]
+ (abs:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "d"))))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
- "lpgr\t%0,%1"
+ "lpgfr\t%0,%1"
[(set_attr "op_type" "RRE")])
-;
-; abssi2 instruction pattern(s).
-;
+; lpr, lpgr
+(define_insn "*abs<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (abs:GPR (match_operand:DI 1 "register_operand" "d"))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d")
+ (abs:GPR (match_dup 1)))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "lp<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+; lpr, lpgr
+(define_insn "*abs<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (abs:GPR (match_operand:GPR 1 "register_operand" "d"))
+ (const_int 0)))
+ (clobber (match_scratch:GPR 0 "=d"))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "lp<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
-(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, lpgr
+(define_insn "abs<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
+ (clobber (reg:CC CC_REGNUM))]
""
- "lpr\t%0,%1"
- [(set_attr "op_type" "RR")])
+ "lp<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
;
-; absdf2 instruction pattern(s).
+; abs(df|sf)2 instruction pattern(s).
;
-(define_expand "absdf2"
+(define_expand "abs<mode>2"
[(parallel
- [(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "register_operand" "f")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (abs:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))])]
"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"
+; lpxbr, lpdbr, lpebr
+(define_insn "*abs<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (abs:FPR (match_operand:FPR 1 "register_operand" "f"))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (set (match_operand:FPR 0 "register_operand" "=f")
+ (abs:FPR (match_dup 1)))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lp<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimpd")])
-
-(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")
- (set_attr "type" "fsimpd")])
-
-;
-; 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"
- "")
+ (set_attr "type" "fsimp<mode>")])
+
+; lpxbr, lpdbr, lpebr
+(define_insn "*abs<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (abs:FPR (match_operand:FPR 1 "register_operand" "f"))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (clobber (match_scratch:FPR 0 "=f"))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "lp<xde>br\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*abssf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "register_operand" "f")))
- (clobber (reg:CC 33))]
+; lpxbr, lpdbr, lpebr
+(define_insn "*abs<mode>2"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (abs:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "lpebr\t%0,%1"
+ "lp<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimps")])
+ (set_attr "type" "fsimp<mode>")])
-(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))]
+; lpxr, lpdr, lper
+(define_insn "*abs<mode>2_ibm"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (abs:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IBM_FLOAT"
- "lper\t%0,%1"
- [(set_attr "op_type" "RR")
- (set_attr "type" "fsimps")])
+ "lp<xde>r\t%0,%1"
+ [(set_attr "op_type" "<RRe>")
+ (set_attr "type" "fsimp<mode>")])
;;
;;- Negated absolute value instructions
@@ -5939,129 +6131,173 @@
; Integer
;
-(define_insn "*negabssi2"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (neg:SI (abs:SI (match_operand:SI 1 "register_operand" "d"))))
- (clobber (reg:CC 33))]
- ""
- "lnr\t%0,%1"
- [(set_attr "op_type" "RR")])
-
-(define_insn "*negabsdi2"
+(define_insn "*negabsdi2_sign_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:DI (abs:DI (ashiftrt:DI (ashift:DI (subreg:DI
+ (match_operand:SI 1 "register_operand" "d") 0)
+ (const_int 32)) (const_int 32))))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (neg:DI (abs:DI (sign_extend:DI (match_dup 1)))))]
+ "TARGET_64BIT && s390_match_ccmode (insn, CCAmode)"
+ "lngfr\t%0,%1"
+ [(set_attr "op_type" "RRE")])
+
+(define_insn "*negabsdi2_sign"
[(set (match_operand:DI 0 "register_operand" "=d")
- (neg:DI (abs:DI (match_operand:DI 1 "register_operand" "d"))))
- (clobber (reg:CC 33))]
+ (neg:DI (abs:DI (sign_extend:DI
+ (match_operand:SI 1 "register_operand" "d")))))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
- "lngr\t%0,%1"
+ "lngfr\t%0,%1"
[(set_attr "op_type" "RRE")])
+; lnr, lngr
+(define_insn "*negabs<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d")
+ (neg:GPR (abs:GPR (match_dup 1))))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "ln<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+; lnr, lngr
+(define_insn "*negabs<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d")))
+ (const_int 0)))
+ (clobber (match_scratch:GPR 0 "=d"))]
+ "s390_match_ccmode (insn, CCAmode)"
+ "ln<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
+; lnr, lngr
+(define_insn "*negabs<mode>2"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (neg:GPR (abs:GPR (match_operand:GPR 1 "register_operand" "d"))))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "ln<g>r\t%0,%1"
+ [(set_attr "op_type" "RR<E>")])
+
;
; Floating point
;
-(define_insn "*negabssf2"
- [(set (match_operand:SF 0 "register_operand" "=f")
- (neg:SF (abs:SF (match_operand:SF 1 "register_operand" "f"))))
- (clobber (reg:CC 33))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "lnebr\t%0,%1"
+; lnxbr, lndbr, lnebr
+(define_insn "*negabs<mode>2_cc"
+ [(set (reg CC_REGNUM)
+ (compare (neg:FPR (abs:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (abs:FPR (match_dup 1))))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ln<xde>br\t%0,%1"
+ [(set_attr "op_type" "RRE")
+ (set_attr "type" "fsimp<mode>")])
+
+; lnxbr, lndbr, lnebr
+(define_insn "*negabs<mode>2_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (neg:FPR (abs:FPR (match_operand:FPR 1 "register_operand" "f")))
+ (match_operand:FPR 2 "const0_operand" "")))
+ (clobber (match_scratch:FPR 0 "=f"))]
+ "s390_match_ccmode (insn, CCSmode) && TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
+ "ln<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimps")])
+ (set_attr "type" "fsimp<mode>")])
-(define_insn "*negabsdf2"
- [(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (abs:DF (match_operand:DF 1 "register_operand" "f"))))
- (clobber (reg:CC 33))]
+; lnxbr, lndbr, lnebr
+(define_insn "*negabs<mode>2"
+ [(set (match_operand:FPR 0 "register_operand" "=f")
+ (neg:FPR (abs:FPR (match_operand:FPR 1 "register_operand" "f"))))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "lndbr\t%0,%1"
+ "ln<xde>br\t%0,%1"
[(set_attr "op_type" "RRE")
- (set_attr "type" "fsimpd")])
+ (set_attr "type" "fsimp<mode>")])
;;
;;- Square root instructions.
;;
;
-; sqrtdf2 instruction pattern(s).
+; sqrt(df|sf)2 instruction pattern(s).
;
-(define_insn "sqrtdf2"
- [(set (match_operand:DF 0 "register_operand" "=f,f")
- (sqrt:DF (match_operand:DF 1 "general_operand" "f,R")))]
+; sqxbr, sqdbr, sqebr, sqxb, sqdb, sqeb
+(define_insn "sqrt<mode>2"
+ [(set (match_operand:FPR 0 "register_operand" "=f,f")
+ (sqrt:FPR (match_operand:FPR 1 "general_operand" "f,<Rf>")))]
"TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
"@
- sqdbr\t%0,%1
- sqdb\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")])
-
-;
-; sqrtsf2 instruction pattern(s).
-;
+ sq<xde>br\t%0,%1
+ sq<xde>b\t%0,%1"
+ [(set_attr "op_type" "RRE,RXE")
+ (set_attr "type" "fsqrt<mode>")])
-(define_insn "sqrtsf2"
- [(set (match_operand:SF 0 "register_operand" "=f,f")
- (sqrt:SF (match_operand:SF 1 "general_operand" "f,R")))]
- "TARGET_HARD_FLOAT && TARGET_IEEE_FLOAT"
- "@
- sqebr\t%0,%1
- sqeb\t%0,%1"
- [(set_attr "op_type" "RRE,RXE")])
;;
;;- One complement instructions.
;;
;
-; one_cmpldi2 instruction pattern(s).
+; one_cmpl(di|si|hi|qi)2 instruction pattern(s).
;
-(define_expand "one_cmpldi2"
+(define_expand "one_cmpl<mode>2"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (xor:DI (match_operand:DI 1 "register_operand" "")
- (const_int -1)))
- (clobber (reg:CC 33))])]
- "TARGET_64BIT"
+ [(set (match_operand:INT 0 "register_operand" "")
+ (xor:INT (match_operand:INT 1 "register_operand" "")
+ (const_int -1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
"")
-;
-; one_cmplsi2 instruction pattern(s).
-;
-(define_expand "one_cmplsi2"
- [(parallel
- [(set (match_operand:SI 0 "register_operand" "")
- (xor:SI (match_operand:SI 1 "register_operand" "")
- (const_int -1)))
- (clobber (reg:CC 33))])]
- ""
- "")
+;;
+;; Find leftmost bit instructions.
+;;
-;
-; one_cmplhi2 instruction pattern(s).
-;
+(define_expand "clzdi2"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (clz:DI (match_operand:DI 1 "register_operand" "d")))]
+ "TARGET_EXTIMM && TARGET_64BIT"
+{
+ rtx insn, clz_equal;
+ rtx wide_reg = gen_reg_rtx (TImode);
+ rtx msb = gen_rtx_CONST_INT (DImode, (unsigned HOST_WIDE_INT) 1 << 63);
-(define_expand "one_cmplhi2"
- [(parallel
- [(set (match_operand:HI 0 "register_operand" "")
- (xor:HI (match_operand:HI 1 "register_operand" "")
- (const_int -1)))
- (clobber (reg:CC 33))])]
- ""
- "")
+ clz_equal = gen_rtx_CLZ (DImode, operands[1]);
-;
-; one_cmplqi2 instruction pattern(s).
-;
+ emit_insn (gen_clztidi2 (wide_reg, operands[1], msb));
-(define_expand "one_cmplqi2"
- [(parallel
- [(set (match_operand:QI 0 "register_operand" "")
- (xor:QI (match_operand:QI 1 "register_operand" "")
- (const_int -1)))
- (clobber (reg:CC 33))])]
- ""
- "")
+ insn = emit_move_insn (operands[0], gen_highpart (DImode, wide_reg));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_EQUAL, clz_equal, REG_NOTES (insn));
+
+ DONE;
+})
+
+(define_insn "clztidi2"
+ [(set (match_operand:TI 0 "register_operand" "=d")
+ (ior:TI
+ (ashift:TI
+ (zero_extend:TI
+ (xor:DI (match_operand:DI 1 "register_operand" "d")
+ (lshiftrt (match_operand:DI 2 "const_int_operand" "")
+ (subreg:SI (clz:DI (match_dup 1)) 4))))
+
+ (const_int 64))
+ (zero_extend:TI (clz:DI (match_dup 1)))))
+ (clobber (reg:CC CC_REGNUM))]
+ "(unsigned HOST_WIDE_INT) INTVAL (operands[2])
+ == (unsigned HOST_WIDE_INT) 1 << 63
+ && TARGET_EXTIMM && TARGET_64BIT"
+ "flogr\t%0,%1"
+ [(set_attr "op_type" "RRE")])
;;
@@ -6069,82 +6305,105 @@
;;
;
-; rotldi3 instruction pattern(s).
+; rotl(di|si)3 instruction pattern(s).
;
-(define_insn "rotldi3"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (rotate:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- "TARGET_64BIT"
- "rllg\t%0,%1,%Y2"
+; rll, rllg
+(define_insn "rotl<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ "TARGET_CPU_ZARCH"
+ "rll<g>\t%0,%1,%Y2"
[(set_attr "op_type" "RSE")
(set_attr "atype" "reg")])
-;
-; rotlsi3 instruction pattern(s).
-;
-
-(define_insn "rotlsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (rotate:SI (match_operand:SI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- "TARGET_CPU_ZARCH"
- "rll\t%0,%1,%Y2"
+; rll, rllg
+(define_insn "*rotl<mode>3_and"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (rotate:GPR (match_operand:GPR 1 "register_operand" "d")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n"))))]
+ "TARGET_CPU_ZARCH && (INTVAL (operands[3]) & 63) == 63"
+ "rll<g>\t%0,%1,%Y2"
[(set_attr "op_type" "RSE")
(set_attr "atype" "reg")])
;;
-;;- Arithmetic shift instructions.
+;;- Shift instructions.
;;
;
-; ashldi3 instruction pattern(s).
+; (ashl|lshr)(di|si)3 instruction pattern(s).
;
-(define_expand "ashldi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (ashift:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_operand" "")))]
+(define_expand "<shift><mode>3"
+ [(set (match_operand:DSI 0 "register_operand" "")
+ (SHIFT:DSI (match_operand:DSI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")))]
""
"")
-(define_insn "*ashldi3_31"
+; sldl, srdl
+(define_insn "*<shift>di3_31"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
+ (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
"!TARGET_64BIT"
- "sldl\t%0,%Y2"
+ "s<lr>dl\t%0,%Y2"
[(set_attr "op_type" "RS")
(set_attr "atype" "reg")])
-(define_insn "*ashldi3_64"
+; sll, srl, sllg, srlg
+(define_insn "*<shift><mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))]
+ ""
+ "s<lr>l<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
+ (set_attr "atype" "reg")])
+
+; sldl, srdl
+(define_insn "*<shift>di3_31_and"
[(set (match_operand:DI 0 "register_operand" "=d")
- (ashift:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- "TARGET_64BIT"
- "sllg\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
+ (SHIFT:DI (match_operand:DI 1 "register_operand" "0")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n"))))]
+ "!TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+ "s<lr>dl\t%0,%Y2"
+ [(set_attr "op_type" "RS")
+ (set_attr "atype" "reg")])
+
+; sll, srl, sllg, srlg
+(define_insn "*<shift><mode>3_and"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (SHIFT:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n"))))]
+ "(INTVAL (operands[3]) & 63) == 63"
+ "s<lr>l<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
;
-; ashrdi3 instruction pattern(s).
+; ashr(di|si)3 instruction pattern(s).
;
-(define_expand "ashrdi3"
+(define_expand "ashr<mode>3"
[(parallel
- [(set (match_operand:DI 0 "register_operand" "")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_operand" "")))
- (clobber (reg:CC 33))])]
+ [(set (match_operand:DSI 0 "register_operand" "")
+ (ashiftrt:DSI (match_operand:DSI 1 "register_operand" "")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "")))
+ (clobber (reg:CC CC_REGNUM))])]
""
"")
(define_insn "*ashrdi3_cc_31"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y"))
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=d")
(ashiftrt:DI (match_dup 1) (match_dup 2)))]
@@ -6154,9 +6413,9 @@
(set_attr "atype" "reg")])
(define_insn "*ashrdi3_cconly_31"
- [(set (reg 33)
+ [(set (reg CC_REGNUM)
(compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y"))
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
(const_int 0)))
(clobber (match_scratch:DI 0 "=d"))]
"!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)"
@@ -6167,143 +6426,127 @@
(define_insn "*ashrdi3_31"
[(set (match_operand:DI 0 "register_operand" "=d")
(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))
- (clobber (reg:CC 33))]
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
+ (clobber (reg:CC CC_REGNUM))]
"!TARGET_64BIT"
"srda\t%0,%Y2"
[(set_attr "op_type" "RS")
(set_attr "atype" "reg")])
-(define_insn "*ashrdi3_cc_64"
- [(set (reg 33)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y"))
+; sra, srag
+(define_insn "*ashr<mode>3_cc"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
(const_int 0)))
- (set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "srag\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
+ (set (match_operand:GPR 0 "register_operand" "=d")
+ (ashiftrt:GPR (match_dup 1) (match_dup 2)))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
-(define_insn "*ashrdi3_cconly_64"
- [(set (reg 33)
- (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y"))
+; sra, srag
+(define_insn "*ashr<mode>3_cconly"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y"))
(const_int 0)))
- (clobber (match_scratch:DI 0 "=d"))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_64BIT"
- "srag\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
+ (clobber (match_scratch:GPR 0 "=d"))]
+ "s390_match_ccmode(insn, CCSmode)"
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
-(define_insn "*ashrdi3_64"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (ashiftrt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y")))
- (clobber (reg:CC 33))]
- "TARGET_64BIT"
- "srag\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
+; sra, srag
+(define_insn "*ashr<mode>3"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")))
+ (clobber (reg:CC CC_REGNUM))]
+ ""
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
-;
-; ashlsi3 instruction pattern(s).
-;
+; shift pattern with implicit ANDs
-(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ashift:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- ""
- "sll\t%0,%Y2"
+(define_insn "*ashrdi3_cc_31_and"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (const_int 0)))
+ (set (match_operand:DI 0 "register_operand" "=d")
+ (ashiftrt:DI (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+ "!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+ && (INTVAL (operands[3]) & 63) == 63"
+ "srda\t%0,%Y2"
[(set_attr "op_type" "RS")
(set_attr "atype" "reg")])
-;
-; ashrsi3 instruction pattern(s).
-;
-
-(define_insn "*ashrsi3_cc"
- [(set (reg 33)
- (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y"))
+(define_insn "*ashrdi3_cconly_31_and"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n")))
(const_int 0)))
- (set (match_operand:SI 0 "register_operand" "=d")
- (ashiftrt:SI (match_dup 1) (match_dup 2)))]
- "s390_match_ccmode(insn, CCSmode)"
- "sra\t%0,%Y2"
+ (clobber (match_scratch:DI 0 "=d"))]
+ "!TARGET_64BIT && s390_match_ccmode(insn, CCSmode)
+ && (INTVAL (operands[3]) & 63) == 63"
+ "srda\t%0,%Y2"
[(set_attr "op_type" "RS")
(set_attr "atype" "reg")])
-
-(define_insn "*ashrsi3_cconly"
- [(set (reg 33)
- (compare (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y"))
- (const_int 0)))
- (clobber (match_scratch:SI 0 "=d"))]
- "s390_match_ccmode(insn, CCSmode)"
- "sra\t%0,%Y2"
+(define_insn "*ashrdi3_31_and"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_64BIT && (INTVAL (operands[3]) & 63) == 63"
+ "srda\t%0,%Y2"
[(set_attr "op_type" "RS")
(set_attr "atype" "reg")])
-(define_insn "ashrsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))
- (clobber (reg:CC 33))]
- ""
- "sra\t%0,%Y2"
- [(set_attr "op_type" "RS")
+; sra, srag
+(define_insn "*ashr<mode>3_cc_and"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (const_int 0)))
+ (set (match_operand:GPR 0 "register_operand" "=d")
+ (ashiftrt:GPR (match_dup 1) (and:SI (match_dup 2) (match_dup 3))))]
+ "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
-
-;;
-;;- logical shift instructions.
-;;
-
-;
-; lshrdi3 instruction pattern(s).
-;
-
-(define_expand "lshrdi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:SI 2 "shift_count_operand" "")))]
- ""
- "")
-
-(define_insn "*lshrdi3_31"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- "!TARGET_64BIT"
- "srdl\t%0,%Y2"
- [(set_attr "op_type" "RS")
- (set_attr "atype" "reg")])
-
-(define_insn "*lshrdi3_64"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "d")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- "TARGET_64BIT"
- "srlg\t%0,%1,%Y2"
- [(set_attr "op_type" "RSE")
+; sra, srag
+(define_insn "*ashr<mode>3_cconly_and"
+ [(set (reg CC_REGNUM)
+ (compare (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n")))
+ (const_int 0)))
+ (clobber (match_scratch:GPR 0 "=d"))]
+ "s390_match_ccmode(insn, CCSmode) && (INTVAL (operands[3]) & 63) == 63"
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
-;
-; lshrsi3 instruction pattern(s).
-;
-
-(define_insn "lshrsi3"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "shift_count_operand" "Y")))]
- ""
- "srl\t%0,%Y2"
- [(set_attr "op_type" "RS")
+; sra, srag
+(define_insn "*ashr<mode>3_and"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (ashiftrt:GPR (match_operand:GPR 1 "register_operand" "<d0>")
+ (and:SI (match_operand:SI 2 "shift_count_or_setmem_operand" "Y")
+ (match_operand:SI 3 "const_int_operand" "n"))))
+ (clobber (reg:CC CC_REGNUM))]
+ "(INTVAL (operands[3]) & 63) == 63"
+ "sra<g>\t%0,<1>%Y2"
+ [(set_attr "op_type" "RS<E>")
(set_attr "atype" "reg")])
@@ -6311,204 +6554,66 @@
;; 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;")
-
-(define_expand "bunordered"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (unordered (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bordered"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (ordered (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "buneq"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (uneq (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bungt"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (ungt (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bunlt"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (unlt (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bunge"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (unge (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bunle"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (unle (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
-
-(define_expand "bltgt"
- [(set (reg:CCS 33) (compare:CCS (match_dup 1) (match_dup 2)))
- (set (pc)
- (if_then_else (ltgt (reg:CCS 33) (const_int 0))
- (label_ref (match_operand 0 "" ""))
+(define_expand "b<code>"
+ [(set (pc)
+ (if_then_else (COMPARE (match_operand 0 "" "")
+ (const_int 0))
+ (match_dup 0)
(pc)))]
""
- "operands[1] = s390_compare_op0; operands[2] = s390_compare_op1;")
+ "s390_emit_jump (operands[0],
+ s390_emit_compare (<CODE>, s390_compare_op0, s390_compare_op1)); DONE;")
;;
;;- 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)))]
- ""
+(define_insn "*cjump_64"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "TARGET_CPU_ZARCH"
{
if (get_attr_length (insn) == 4)
return "j%C1\t%l0";
- else if (TARGET_CPU_ZARCH)
- return "jg%C1\t%l0";
else
- abort ();
+ return "jg%C1\t%l0";
+}
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")
+ (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_31"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ "!TARGET_CPU_ZARCH"
+{
+ gcc_assert (get_attr_length (insn) == 4);
+ return "j%C1\t%l0";
}
[(set_attr "op_type" "RI")
(set_attr "type" "branch")
(set (attr "length")
- (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4)
- (ne (symbol_ref "TARGET_CPU_ZARCH") (const_int 0))
- (const_int 6)
- (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 6)] (const_int 8)))])
+ (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 8))))])
(define_insn "*cjump_long"
- [(set (pc)
- (if_then_else
- (match_operator 1 "comparison_operator" [(reg 33) (const_int 0)])
- (match_operand 0 "address_operand" "U")
- (pc)))]
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (match_operand 0 "address_operand" "U")
+ (pc)))]
""
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
@@ -6519,7 +6624,7 @@
[(set (attr "op_type")
(if_then_else (match_operand 0 "register_operand" "")
(const_string "RR") (const_string "RX")))
- (set_attr "type" "branch")
+ (set_attr "type" "branch")
(set_attr "atype" "agen")])
@@ -6527,37 +6632,51 @@
;;- 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 "" ""))))]
- ""
+(define_insn "*icjump_64"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "TARGET_CPU_ZARCH"
{
if (get_attr_length (insn) == 4)
return "j%D1\t%l0";
- else if (TARGET_CPU_ZARCH)
- return "jg%D1\t%l0";
else
- abort ();
+ return "jg%D1\t%l0";
+}
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")
+ (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_31"
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (pc)
+ (label_ref (match_operand 0 "" ""))))]
+ "!TARGET_CPU_ZARCH"
+{
+ gcc_assert (get_attr_length (insn) == 4);
+ return "j%D1\t%l0";
}
[(set_attr "op_type" "RI")
(set_attr "type" "branch")
(set (attr "length")
- (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4)
- (ne (symbol_ref "TARGET_CPU_ZARCH") (const_int 0))
- (const_int 6)
- (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 6)] (const_int 8)))])
+ (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 8))))])
(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" "U")))]
+ [(set (pc)
+ (if_then_else
+ (match_operator 1 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
+ (pc)
+ (match_operand 0 "address_operand" "U")))]
""
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
@@ -6579,28 +6698,21 @@
[(trap_if (const_int 1) (const_int 0))]
""
"j\t.+2"
- [(set_attr "op_type" "RX")
+ [(set_attr "op_type" "RI")
(set_attr "type" "branch")])
(define_expand "conditional_trap"
- [(set (match_dup 2) (match_dup 3))
- (trap_if (match_operator 0 "comparison_operator"
- [(match_dup 2) (const_int 0)])
- (match_operand:SI 1 "general_operand" ""))]
+ [(trap_if (match_operand 0 "comparison_operator" "")
+ (match_operand 1 "general_operand" ""))]
""
{
- enum machine_mode ccmode;
-
- if (operands[1] != const0_rtx) FAIL;
-
- ccmode = s390_select_ccmode (GET_CODE (operands[0]),
- s390_compare_op0, s390_compare_op1);
- operands[2] = gen_rtx_REG (ccmode, 33);
- operands[3] = gen_rtx_COMPARE (ccmode, s390_compare_op0, s390_compare_op1);
+ if (operands[1] != const0_rtx) FAIL;
+ operands[0] = s390_emit_compare (GET_CODE (operands[0]),
+ s390_compare_op0, s390_compare_op1);
})
(define_insn "*trap"
- [(trap_if (match_operator 0 "comparison_operator" [(reg 33) (const_int 0)])
+ [(trap_if (match_operator 0 "s390_comparison" [(reg CC_REGNUM) (const_int 0)])
(const_int 0))]
""
"j%C0\t.+2";
@@ -6621,8 +6733,10 @@
(use (match_operand 4 "" ""))] ; label
""
{
- if (GET_MODE (operands[0]) == SImode)
- emit_jump_insn (gen_doloop_si (operands[4], operands[0], operands[0]));
+ if (GET_MODE (operands[0]) == SImode && !TARGET_CPU_ZARCH)
+ emit_jump_insn (gen_doloop_si31 (operands[4], operands[0], operands[0]));
+ else if (GET_MODE (operands[0]) == SImode && TARGET_CPU_ZARCH)
+ emit_jump_insn (gen_doloop_si64 (operands[4], operands[0], operands[0]));
else if (GET_MODE (operands[0]) == DImode && TARGET_64BIT)
emit_jump_insn (gen_doloop_di (operands[4], operands[0], operands[0]));
else
@@ -6631,50 +6745,99 @@
DONE;
})
-(define_insn "doloop_si"
+(define_insn_and_split "doloop_si64"
[(set (pc)
(if_then_else
- (ne (match_operand:SI 1 "register_operand" "d,d")
+ (ne (match_operand:SI 1 "register_operand" "d,d,d")
(const_int 1))
(label_ref (match_operand 0 "" ""))
(pc)))
- (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+ (set (match_operand:SI 2 "nonimmediate_operand" "=1,?X,?X")
(plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,&d"))
- (clobber (reg:CC 33))]
- ""
+ (clobber (match_scratch:SI 3 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_CPU_ZARCH"
{
if (which_alternative != 0)
return "#";
else if (get_attr_length (insn) == 4)
return "brct\t%1,%l0";
- else if (TARGET_CPU_ZARCH)
+ else
return "ahi\t%1,-1\;jgne\t%l0";
+}
+ "&& reload_completed
+ && (! REG_P (operands[2])
+ || ! rtx_equal_p (operands[1], operands[2]))"
+ [(set (match_dup 3) (match_dup 1))
+ (parallel [(set (reg:CCAN CC_REGNUM)
+ (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
+ (const_int 0)))
+ (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
+ (set (match_dup 2) (match_dup 3))
+ (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
+ (label_ref (match_dup 0))
+ (pc)))]
+ ""
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 10)))])
+
+(define_insn_and_split "doloop_si31"
+ [(set (pc)
+ (if_then_else
+ (ne (match_operand:SI 1 "register_operand" "d,d,d")
+ (const_int 1))
+ (label_ref (match_operand 0 "" ""))
+ (pc)))
+ (set (match_operand:SI 2 "nonimmediate_operand" "=1,?X,?X")
+ (plus:SI (match_dup 1) (const_int -1)))
+ (clobber (match_scratch:SI 3 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_CPU_ZARCH"
+{
+ if (which_alternative != 0)
+ return "#";
+ else if (get_attr_length (insn) == 4)
+ return "brct\t%1,%l0";
else
- abort ();
+ gcc_unreachable ();
}
+ "&& reload_completed
+ && (! REG_P (operands[2])
+ || ! rtx_equal_p (operands[1], operands[2]))"
+ [(set (match_dup 3) (match_dup 1))
+ (parallel [(set (reg:CCAN CC_REGNUM)
+ (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
+ (const_int 0)))
+ (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
+ (set (match_dup 2) (match_dup 3))
+ (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
+ (label_ref (match_dup 0))
+ (pc)))]
+ ""
[(set_attr "op_type" "RI")
(set_attr "type" "branch")
(set (attr "length")
- (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4)
- (ne (symbol_ref "TARGET_CPU_ZARCH") (const_int 0))
- (const_int 10)
- (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 6)] (const_int 8)))])
+ (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 8))))])
(define_insn "*doloop_si_long"
[(set (pc)
(if_then_else
- (ne (match_operand:SI 1 "register_operand" "d,d")
+ (ne (match_operand:SI 1 "register_operand" "d")
(const_int 1))
- (match_operand 0 "address_operand" "U,U")
+ (match_operand 0 "address_operand" "U")
(pc)))
- (set (match_operand:SI 2 "register_operand" "=1,?*m*d")
+ (set (match_operand:SI 2 "register_operand" "=1")
(plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 "=X,&d"))
- (clobber (reg:CC 33))]
- ""
+ (clobber (match_scratch:SI 3 "=X"))
+ (clobber (reg:CC CC_REGNUM))]
+ "!TARGET_CPU_ZARCH"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "bctr\t%1,%0";
@@ -6687,41 +6850,17 @@
(set_attr "type" "branch")
(set_attr "atype" "agen")])
-(define_split
- [(set (pc)
- (if_then_else (ne (match_operand:SI 1 "register_operand" "")
- (const_int 1))
- (match_operand 0 "" "")
- (pc)))
- (set (match_operand:SI 2 "nonimmediate_operand" "")
- (plus:SI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:SI 3 ""))
- (clobber (reg:CC 33))]
- "reload_completed
- && (! REG_P (operands[2])
- || ! rtx_equal_p (operands[1], operands[2]))"
- [(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN 33)
- (compare:CCAN (plus:SI (match_dup 3) (const_int -1))
- (const_int 0)))
- (set (match_dup 3) (plus:SI (match_dup 3) (const_int -1)))])
- (set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
- (match_dup 0)
- (pc)))]
- "")
-
-(define_insn "doloop_di"
+(define_insn_and_split "doloop_di"
[(set (pc)
(if_then_else
- (ne (match_operand:DI 1 "register_operand" "d,d")
+ (ne (match_operand:DI 1 "register_operand" "d,d,d")
(const_int 1))
(label_ref (match_operand 0 "" ""))
(pc)))
- (set (match_operand:DI 2 "register_operand" "=1,?*m*r")
+ (set (match_operand:DI 2 "nonimmediate_operand" "=1,?X,?X")
(plus:DI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:DI 3 "=X,&d"))
- (clobber (reg:CC 33))]
+ (clobber (match_scratch:DI 3 "=X,&1,&?d"))
+ (clobber (reg:CC CC_REGNUM))]
"TARGET_64BIT"
{
if (which_alternative != 0)
@@ -6731,35 +6870,24 @@
else
return "aghi\t%1,-1\;jgne\t%l0";
}
- [(set_attr "op_type" "RI")
- (set_attr "type" "branch")
- (set (attr "length")
- (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4) (const_int 10)))])
-
-(define_split
- [(set (pc)
- (if_then_else (ne (match_operand:DI 1 "register_operand" "")
- (const_int 1))
- (match_operand 0 "" "")
- (pc)))
- (set (match_operand:DI 2 "nonimmediate_operand" "")
- (plus:DI (match_dup 1) (const_int -1)))
- (clobber (match_scratch:DI 3 ""))
- (clobber (reg:CC 33))]
- "reload_completed
+ "&& reload_completed
&& (! REG_P (operands[2])
|| ! rtx_equal_p (operands[1], operands[2]))"
[(set (match_dup 3) (match_dup 1))
- (parallel [(set (reg:CCAN 33)
+ (parallel [(set (reg:CCAN CC_REGNUM)
(compare:CCAN (plus:DI (match_dup 3) (const_int -1))
(const_int 0)))
(set (match_dup 3) (plus:DI (match_dup 3) (const_int -1)))])
(set (match_dup 2) (match_dup 3))
- (set (pc) (if_then_else (ne (reg:CCAN 33) (const_int 0))
- (match_dup 0)
+ (set (pc) (if_then_else (ne (reg:CCAN CC_REGNUM) (const_int 0))
+ (label_ref (match_dup 0))
(pc)))]
- "")
+ ""
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 10)))])
;;
;;- Unconditional jump instructions.
@@ -6769,26 +6897,41 @@
; jump instruction pattern(s).
;
-(define_insn "jump"
- [(set (pc) (label_ref (match_operand 0 "" "")))]
+(define_expand "jump"
+ [(match_operand 0 "" "")]
""
+ "s390_emit_jump (operands[0], NULL_RTX); DONE;")
+
+(define_insn "*jump64"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ "TARGET_CPU_ZARCH"
{
if (get_attr_length (insn) == 4)
return "j\t%l0";
- else if (TARGET_CPU_ZARCH)
- return "jg\t%l0";
else
- abort ();
+ return "jg\t%l0";
}
[(set_attr "op_type" "RI")
(set_attr "type" "branch")
(set (attr "length")
- (cond [(lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
- (const_int 4)
- (ne (symbol_ref "TARGET_CPU_ZARCH") (const_int 0))
- (const_int 6)
- (eq (symbol_ref "flag_pic") (const_int 0))
- (const_int 6)] (const_int 8)))])
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6)))])
+
+(define_insn "*jump31"
+ [(set (pc) (label_ref (match_operand 0 "" "")))]
+ "!TARGET_CPU_ZARCH"
+{
+ gcc_assert (get_attr_length (insn) == 4);
+ return "j\t%l0";
+}
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")
+ (set (attr "length")
+ (if_then_else (eq (symbol_ref "flag_pic") (const_int 0))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 6))
+ (if_then_else (lt (abs (minus (pc) (match_dup 0))) (const_int 60000))
+ (const_int 4) (const_int 8))))])
;
; indirect-jump instruction pattern(s).
@@ -6854,11 +6997,11 @@
if (TARGET_64BIT)
emit_insn (gen_ashldi3 (index, index, GEN_INT (3)));
else
- emit_insn (gen_ashlsi3 (index, index, GEN_INT (2)));
+ emit_insn (gen_ashlsi3 (index, index, const2_rtx));
emit_move_insn (base, gen_rtx_LABEL_REF (Pmode, operands[3]));
- index = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, base, index));
+ index = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, base, index));
emit_move_insn (target, index);
if (flag_pic)
@@ -6915,71 +7058,111 @@
[(set_attr "type" "none")
(set_attr "length" "0")])
-
-
;
-; call instruction pattern(s).
+; sibcall patterns
;
-(define_expand "call"
+(define_expand "sibcall"
[(call (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (use (match_operand 2 "" ""))]
+ (match_operand 1 "" ""))]
""
{
- bool plt_call = false;
- rtx insn;
-
- /* Direct function calls need special treatment. */
- if (GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
- {
- rtx sym = XEXP (operands[0], 0);
+ s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX, NULL_RTX);
+ DONE;
+})
- /* When calling a global routine in PIC mode, we must
- replace the symbol itself with the PLT stub. */
- if (flag_pic && !SYMBOL_REF_LOCAL_P (sym))
- {
- sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
- sym = gen_rtx_CONST (Pmode, sym);
- plt_call = true;
- }
+(define_insn "*sibcall_br"
+ [(call (mem:QI (reg SIBCALL_REGNUM))
+ (match_operand 0 "const_int_operand" "n"))]
+ "SIBLING_CALL_P (insn)
+ && GET_MODE (XEXP (XEXP (PATTERN (insn), 0), 0)) == Pmode"
+ "br\t%%r1"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
- /* Unless we can use the bras(l) insn, force the
- routine address into a register. */
- if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
- {
- if (flag_pic)
- sym = legitimize_pic_address (sym, 0);
- else
- sym = force_reg (Pmode, sym);
- }
+(define_insn "*sibcall_brc"
+ [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
+ (match_operand 1 "const_int_operand" "n"))]
+ "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
+ "j\t%0"
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")])
- operands[0] = gen_rtx_MEM (QImode, sym);
- }
+(define_insn "*sibcall_brcl"
+ [(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
+ (match_operand 1 "const_int_operand" "n"))]
+ "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
+ "jg\t%0"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "branch")])
- /* Emit insn. */
- insn = emit_call_insn (gen_call_exp (operands[0], operands[1],
- gen_rtx_REG (Pmode, RETURN_REGNUM)));
+;
+; sibcall_value patterns
+;
- /* 31-bit PLT stubs use the GOT register implicitly. */
- if (!TARGET_64BIT && plt_call)
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
-
+(define_expand "sibcall_value"
+ [(set (match_operand 0 "" "")
+ (call (match_operand 1 "" "")
+ (match_operand 2 "" "")))]
+ ""
+{
+ s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0], NULL_RTX);
DONE;
})
-(define_expand "call_exp"
- [(parallel [(call (match_operand 0 "" "")
- (match_operand 1 "" ""))
- (clobber (match_operand 2 "" ""))])]
+(define_insn "*sibcall_value_br"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (reg SIBCALL_REGNUM))
+ (match_operand 1 "const_int_operand" "n")))]
+ "SIBLING_CALL_P (insn)
+ && GET_MODE (XEXP (XEXP (XEXP (PATTERN (insn), 1), 0), 0)) == Pmode"
+ "br\t%%r1"
+ [(set_attr "op_type" "RR")
+ (set_attr "type" "branch")
+ (set_attr "atype" "agen")])
+
+(define_insn "*sibcall_value_brc"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
+ (match_operand 2 "const_int_operand" "n")))]
+ "SIBLING_CALL_P (insn) && TARGET_SMALL_EXEC"
+ "j\t%1"
+ [(set_attr "op_type" "RI")
+ (set_attr "type" "branch")])
+
+(define_insn "*sibcall_value_brcl"
+ [(set (match_operand 0 "" "")
+ (call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
+ (match_operand 2 "const_int_operand" "n")))]
+ "SIBLING_CALL_P (insn) && TARGET_CPU_ZARCH"
+ "jg\t%1"
+ [(set_attr "op_type" "RIL")
+ (set_attr "type" "branch")])
+
+
+;
+; call instruction pattern(s).
+;
+
+(define_expand "call"
+ [(call (match_operand 0 "" "")
+ (match_operand 1 "" ""))
+ (use (match_operand 2 "" ""))]
""
- "")
+{
+ s390_emit_call (XEXP (operands[0], 0), NULL_RTX, NULL_RTX,
+ gen_rtx_REG (Pmode, RETURN_REGNUM));
+ DONE;
+})
(define_insn "*bras"
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
(match_operand 1 "const_int_operand" "n"))
(clobber (match_operand 2 "register_operand" "=r"))]
- "TARGET_SMALL_EXEC && GET_MODE (operands[2]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_SMALL_EXEC
+ && GET_MODE (operands[2]) == Pmode"
"bras\t%2,%0"
[(set_attr "op_type" "RI")
(set_attr "type" "jsr")])
@@ -6988,7 +7171,9 @@
[(call (mem:QI (match_operand 0 "bras_sym_operand" "X"))
(match_operand 1 "const_int_operand" "n"))
(clobber (match_operand 2 "register_operand" "=r"))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[2]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_CPU_ZARCH
+ && GET_MODE (operands[2]) == Pmode"
"brasl\t%2,%0"
[(set_attr "op_type" "RIL")
(set_attr "type" "jsr")])
@@ -6997,7 +7182,7 @@
[(call (mem:QI (match_operand 0 "address_operand" "U"))
(match_operand 1 "const_int_operand" "n"))
(clobber (match_operand 2 "register_operand" "=r"))]
- "GET_MODE (operands[2]) == Pmode"
+ "!SIBLING_CALL_P (insn) && GET_MODE (operands[2]) == Pmode"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "basr\t%2,%0";
@@ -7021,62 +7206,19 @@
(use (match_operand 3 "" ""))]
""
{
- bool plt_call = false;
- rtx insn;
-
- /* 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_LOCAL_P (sym))
- {
- sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
- sym = gen_rtx_CONST (Pmode, sym);
- plt_call = true;
- }
-
- /* Unless we can use the bras(l) insn, force the
- routine address into a register. */
- if (!TARGET_SMALL_EXEC && !TARGET_CPU_ZARCH)
- {
- if (flag_pic)
- sym = legitimize_pic_address (sym, 0);
- else
- sym = force_reg (Pmode, sym);
- }
-
- operands[1] = gen_rtx_MEM (QImode, sym);
- }
-
- /* Emit insn. */
- insn = emit_call_insn (
- gen_call_value_exp (operands[0], operands[1], operands[2],
- gen_rtx_REG (Pmode, RETURN_REGNUM)));
-
- /* 31-bit PLT stubs use the GOT register implicitly. */
- if (!TARGET_64BIT && plt_call)
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
-
+ s390_emit_call (XEXP (operands[1], 0), NULL_RTX, operands[0],
+ gen_rtx_REG (Pmode, RETURN_REGNUM));
DONE;
})
-(define_expand "call_value_exp"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "" "")
- (match_operand 2 "" "")))
- (clobber (match_operand 3 "" ""))])]
- ""
- "")
-
(define_insn "*bras_r"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
(match_operand:SI 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))]
- "TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_SMALL_EXEC
+ && GET_MODE (operands[3]) == Pmode"
"bras\t%3,%1"
[(set_attr "op_type" "RI")
(set_attr "type" "jsr")])
@@ -7086,7 +7228,9 @@
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_CPU_ZARCH
+ && GET_MODE (operands[3]) == Pmode"
"brasl\t%3,%1"
[(set_attr "op_type" "RIL")
(set_attr "type" "jsr")])
@@ -7096,7 +7240,7 @@
(call (mem:QI (match_operand 1 "address_operand" "U"))
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))]
- "GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "basr\t%3,%1";
@@ -7113,46 +7257,34 @@
;;- Thread-local storage support.
;;
-(define_insn "get_tp_64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=??d,Q")
- (unspec:DI [(const_int 0)] UNSPEC_TP))]
+(define_expand "get_tp_64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "") (reg:DI TP_REGNUM))]
"TARGET_64BIT"
- "@
- ear\t%0,%%a0\;sllg\t%0,%0,32\;ear\t%0,%%a1
- stam\t%%a0,%%a1,%0"
- [(set_attr "op_type" "NN,RS")
- (set_attr "atype" "reg,*")
- (set_attr "type" "o3,*")
- (set_attr "length" "14,*")])
+ "")
-(define_insn "get_tp_31"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d,Q")
- (unspec:SI [(const_int 0)] UNSPEC_TP))]
+(define_expand "get_tp_31"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "") (reg:SI TP_REGNUM))]
"!TARGET_64BIT"
- "@
- ear\t%0,%%a0
- stam\t%%a0,%%a0,%0"
- [(set_attr "op_type" "RRE,RS")])
+ "")
-(define_insn "set_tp_64"
- [(unspec_volatile [(match_operand:DI 0 "general_operand" "??d,Q")] UNSPECV_SET_TP)
- (clobber (match_scratch:SI 1 "=d,X"))]
+(define_expand "set_tp_64"
+ [(set (reg:DI TP_REGNUM) (match_operand:DI 0 "nonimmediate_operand" ""))
+ (set (reg:DI TP_REGNUM) (unspec_volatile:DI [(reg:DI TP_REGNUM)] UNSPECV_SET_TP))]
"TARGET_64BIT"
- "@
- sar\t%%a1,%0\;srlg\t%1,%0,32\;sar\t%%a0,%1
- lam\t%%a0,%%a1,%0"
- [(set_attr "op_type" "NN,RS")
- (set_attr "atype" "reg,*")
- (set_attr "type" "o3,*")
- (set_attr "length" "14,*")])
+ "")
-(define_insn "set_tp_31"
- [(unspec_volatile [(match_operand:SI 0 "general_operand" "d,Q")] UNSPECV_SET_TP)]
+(define_expand "set_tp_31"
+ [(set (reg:SI TP_REGNUM) (match_operand:SI 0 "nonimmediate_operand" ""))
+ (set (reg:SI TP_REGNUM) (unspec_volatile:SI [(reg:SI TP_REGNUM)] UNSPECV_SET_TP))]
"!TARGET_64BIT"
- "@
- sar\t%%a0,%0
- lam\t%%a0,%%a0,%0"
- [(set_attr "op_type" "RRE,RS")])
+ "")
+
+(define_insn "*set_tp"
+ [(set (reg TP_REGNUM) (unspec_volatile [(reg TP_REGNUM)] UNSPECV_SET_TP))]
+ ""
+ ""
+ [(set_attr "type" "none")
+ (set_attr "length" "0")])
(define_insn "*tls_load_64"
[(set (match_operand:DI 0 "register_operand" "=d")
@@ -7174,64 +7306,15 @@
ly\t%0,%1%J2"
[(set_attr "op_type" "RX,RXY")])
-(define_expand "call_value_tls"
- [(set (match_operand 0 "" "")
- (call (const_int 0) (const_int 0)))
- (use (match_operand 1 "" ""))]
- ""
-{
- rtx insn, sym;
-
- if (!flag_pic)
- abort ();
-
- sym = s390_tls_get_offset ();
- sym = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, sym), UNSPEC_PLT);
- 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_CPU_ZARCH)
- {
- if (flag_pic)
- sym = legitimize_pic_address (sym, 0);
- else
- sym = force_reg (Pmode, sym);
- }
-
- sym = gen_rtx_MEM (QImode, sym);
-
- /* Emit insn. */
- insn = emit_call_insn (
- gen_call_value_tls_exp (operands[0], sym, const0_rtx,
- gen_rtx_REG (Pmode, RETURN_REGNUM),
- operands[1]));
-
- /* The calling convention of __tls_get_offset uses the
- GOT register implicitly. */
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx);
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), operands[0]);
- CONST_OR_PURE_CALL_P (insn) = 1;
-
- DONE;
-})
-
-(define_expand "call_value_tls_exp"
- [(parallel [(set (match_operand 0 "" "")
- (call (match_operand 1 "" "")
- (match_operand 2 "" "")))
- (clobber (match_operand 3 "" ""))
- (use (match_operand 4 "" ""))])]
- ""
- "")
-
(define_insn "*bras_tls"
[(set (match_operand 0 "" "")
(call (mem:QI (match_operand 1 "bras_sym_operand" "X"))
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))
(use (match_operand 4 "" ""))]
- "TARGET_SMALL_EXEC && GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_SMALL_EXEC
+ && GET_MODE (operands[3]) == Pmode"
"bras\t%3,%1%J4"
[(set_attr "op_type" "RI")
(set_attr "type" "jsr")])
@@ -7242,7 +7325,9 @@
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))
(use (match_operand 4 "" ""))]
- "TARGET_CPU_ZARCH && GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn)
+ && TARGET_CPU_ZARCH
+ && GET_MODE (operands[3]) == Pmode"
"brasl\t%3,%1%J4"
[(set_attr "op_type" "RIL")
(set_attr "type" "jsr")])
@@ -7253,7 +7338,7 @@
(match_operand 2 "const_int_operand" "n")))
(clobber (match_operand 3 "register_operand" "=r"))
(use (match_operand 4 "" ""))]
- "GET_MODE (operands[3]) == Pmode"
+ "!SIBLING_CALL_P (insn) && GET_MODE (operands[3]) == Pmode"
{
if (get_attr_op_type (insn) == OP_TYPE_RR)
return "basr\t%3,%1%J4";
@@ -7267,6 +7352,159 @@
(set_attr "atype" "agen")])
;;
+;;- Atomic operations
+;;
+
+;
+; memory barrier pattern.
+;
+
+(define_expand "memory_barrier"
+ [(set (mem:BLK (match_dup 0))
+ (unspec_volatile:BLK [(mem:BLK (match_dup 0))] UNSPECV_MB))]
+ ""
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+})
+
+(define_insn "*memory_barrier"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec_volatile:BLK [(match_operand:BLK 1 "" "")] UNSPECV_MB))]
+ ""
+ "bcr\t15,0"
+ [(set_attr "op_type" "RR")])
+
+;
+; compare and swap patterns.
+;
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(parallel
+ [(set (match_operand:TDSI 0 "register_operand" "")
+ (match_operand:TDSI 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:TDSI
+ [(match_dup 1)
+ (match_operand:TDSI 2 "register_operand" "")
+ (match_operand:TDSI 3 "register_operand" "")]
+ UNSPECV_CAS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
+ "")
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(parallel
+ [(set (match_operand:HQI 0 "register_operand" "")
+ (match_operand:HQI 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:HQI
+ [(match_dup 1)
+ (match_operand:HQI 2 "general_operand" "")
+ (match_operand:HQI 3 "general_operand" "")]
+ UNSPECV_CAS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
+ ""
+ "s390_expand_cs_hqi (<MODE>mode, operands[0], operands[1],
+ operands[2], operands[3]); DONE;")
+
+(define_expand "sync_compare_and_swap_cc<mode>"
+ [(parallel
+ [(set (match_operand:TDSI 0 "register_operand" "")
+ (match_operand:TDSI 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:TDSI
+ [(match_dup 1)
+ (match_operand:TDSI 2 "register_operand" "")
+ (match_operand:TDSI 3 "register_operand" "")]
+ UNSPECV_CAS))
+ (set (match_dup 4)
+ (compare:CCZ1 (match_dup 1) (match_dup 2)))])]
+ ""
+{
+ /* Emulate compare. */
+ operands[4] = gen_rtx_REG (CCZ1mode, CC_REGNUM);
+ s390_compare_op0 = operands[1];
+ s390_compare_op1 = operands[2];
+ s390_compare_emitted = operands[4];
+})
+
+; cds, cdsg
+(define_insn "*sync_compare_and_swap<mode>"
+ [(set (match_operand:DP 0 "register_operand" "=r")
+ (match_operand:DP 1 "memory_operand" "+Q"))
+ (set (match_dup 1)
+ (unspec_volatile:DP
+ [(match_dup 1)
+ (match_operand:DP 2 "register_operand" "0")
+ (match_operand:DP 3 "register_operand" "r")]
+ UNSPECV_CAS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 1) (match_dup 2)))]
+ ""
+ "cds<tg>\t%0,%3,%S1"
+ [(set_attr "op_type" "RS<TE>")
+ (set_attr "type" "sem")])
+
+; cs, csg
+(define_insn "*sync_compare_and_swap<mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=r")
+ (match_operand:GPR 1 "memory_operand" "+Q"))
+ (set (match_dup 1)
+ (unspec_volatile:GPR
+ [(match_dup 1)
+ (match_operand:GPR 2 "register_operand" "0")
+ (match_operand:GPR 3 "register_operand" "r")]
+ UNSPECV_CAS))
+ (set (reg:CCZ1 CC_REGNUM)
+ (compare:CCZ1 (match_dup 1) (match_dup 2)))]
+ ""
+ "cs<g>\t%0,%3,%S1"
+ [(set_attr "op_type" "RS<E>")
+ (set_attr "type" "sem")])
+
+
+;
+; Other atomic instruction patterns.
+;
+
+(define_expand "sync_lock_test_and_set<mode>"
+ [(match_operand:HQI 0 "register_operand")
+ (match_operand:HQI 1 "memory_operand")
+ (match_operand:HQI 2 "general_operand")]
+ ""
+ "s390_expand_atomic (<MODE>mode, SET, operands[0], operands[1],
+ operands[2], false); DONE;")
+
+(define_expand "sync_<atomic><mode>"
+ [(set (match_operand:HQI 0 "memory_operand")
+ (ATOMIC:HQI (match_dup 0)
+ (match_operand:HQI 1 "general_operand")))]
+ ""
+ "s390_expand_atomic (<MODE>mode, <CODE>, NULL_RTX, operands[0],
+ operands[1], false); DONE;")
+
+(define_expand "sync_old_<atomic><mode>"
+ [(set (match_operand:HQI 0 "register_operand")
+ (match_operand:HQI 1 "memory_operand"))
+ (set (match_dup 1)
+ (ATOMIC:HQI (match_dup 1)
+ (match_operand:HQI 2 "general_operand")))]
+ ""
+ "s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
+ operands[2], false); DONE;")
+
+(define_expand "sync_new_<atomic><mode>"
+ [(set (match_operand:HQI 0 "register_operand")
+ (ATOMIC:HQI (match_operand:HQI 1 "memory_operand")
+ (match_operand:HQI 2 "general_operand")))
+ (set (match_dup 1) (ATOMIC:HQI (match_dup 1) (match_dup 2)))]
+ ""
+ "s390_expand_atomic (<MODE>mode, <CODE>, operands[0], operands[1],
+ operands[2], true); DONE;")
+
+;;
;;- Miscellaneous instructions.
;;
@@ -7275,27 +7513,18 @@
;
(define_expand "allocate_stack"
- [(set (reg 15)
- (plus (reg 15) (match_operand 1 "general_operand" "")))
- (set (match_operand 0 "general_operand" "")
- (reg 15))]
+ [(match_operand 0 "general_operand" "")
+ (match_operand 1 "general_operand" "")]
"TARGET_BACKCHAIN"
{
- 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])));
+ rtx temp = gen_reg_rtx (Pmode);
- emit_move_insn (chain, temp);
+ emit_move_insn (temp, s390_back_chain_rtx ());
+ anti_adjust_stack (operands[1]);
+ emit_move_insn (s390_back_chain_rtx (), temp);
- emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
- DONE;
+ emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+ DONE;
})
@@ -7307,7 +7536,7 @@
[(match_operand 0 "" "")]
"flag_pic"
{
- s390_load_got (false);
+ emit_insn (s390_load_got ());
emit_insn (gen_rtx_USE (VOIDmode, pic_offset_table_rtx));
DONE;
})
@@ -7334,14 +7563,17 @@
"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))]
- ""
+ [(match_operand 0 "register_operand" "")
+ (match_operand 1 "register_operand" "")]
+ "TARGET_BACKCHAIN"
{
- operands[2] = gen_reg_rtx (Pmode);
- operands[3] = gen_rtx_MEM (Pmode, operands[0]);
+ rtx temp = gen_reg_rtx (Pmode);
+
+ emit_move_insn (temp, s390_back_chain_rtx ());
+ emit_move_insn (operands[0], operands[1]);
+ emit_move_insn (s390_back_chain_rtx (), temp);
+
+ DONE;
})
(define_expand "save_stack_nonlocal"
@@ -7349,20 +7581,21 @@
(match_operand 1 "register_operand" "")]
""
{
- rtx temp = gen_reg_rtx (Pmode);
+ enum machine_mode mode = TARGET_64BIT ? OImode : TImode;
+ rtx base = gen_rtx_REG (Pmode, BASE_REGNUM);
+
+ /* Copy the backchain to the first word, sp to the second and the
+ literal pool base to the third. */
+
+ if (TARGET_BACKCHAIN)
+ {
+ rtx temp = force_reg (Pmode, s390_back_chain_rtx ());
+ emit_move_insn (operand_subword (operands[0], 0, 0, mode), temp);
+ }
+
+ emit_move_insn (operand_subword (operands[0], 1, 0, mode), operands[1]);
+ emit_move_insn (operand_subword (operands[0], 2, 0, mode), base);
- /* Copy the backchain to the first word, sp to the second and the literal pool
- base to the third. */
- emit_move_insn (operand_subword (operands[0], 2, 0,
- TARGET_64BIT ? OImode : TImode),
- gen_rtx_REG (Pmode, BASE_REGISTER));
- emit_move_insn (temp, gen_rtx_MEM (Pmode, operands[1]));
- emit_move_insn (operand_subword (operands[0], 0, 0,
- TARGET_64BIT ? OImode : TImode),
- temp);
- emit_move_insn (operand_subword (operands[0], 1, 0,
- TARGET_64BIT ? OImode : TImode),
- operands[1]);
DONE;
})
@@ -7371,26 +7604,33 @@
(match_operand 1 "memory_operand" "")]
""
{
- rtx temp = gen_reg_rtx (Pmode);
- rtx base = gen_rtx_REG (Pmode, BASE_REGISTER);
+ enum machine_mode mode = TARGET_64BIT ? OImode : TImode;
+ rtx base = gen_rtx_REG (Pmode, BASE_REGNUM);
+ rtx temp = NULL_RTX;
/* Restore the backchain from the first word, sp from the second and the
- literal pool base from the third. */
- emit_move_insn (temp,
- operand_subword (operands[1], 0, 0,
- TARGET_64BIT ? OImode : TImode));
- emit_move_insn (operands[0],
- operand_subword (operands[1], 1, 0,
- TARGET_64BIT ? OImode : TImode));
- emit_move_insn (gen_rtx_MEM (Pmode, operands[0]), temp);
- emit_move_insn (base,
- operand_subword (operands[1], 2, 0,
- TARGET_64BIT ? OImode : TImode));
- emit_insn (gen_rtx_USE (VOIDmode, base));
+ literal pool base from the third. */
+
+ if (TARGET_BACKCHAIN)
+ temp = force_reg (Pmode, operand_subword (operands[1], 0, 0, mode));
+
+ emit_move_insn (base, operand_subword (operands[1], 2, 0, mode));
+ emit_move_insn (operands[0], operand_subword (operands[1], 1, 0, mode));
+ if (temp)
+ emit_move_insn (s390_back_chain_rtx (), temp);
+
+ emit_insn (gen_rtx_USE (VOIDmode, base));
DONE;
})
+(define_expand "exception_receiver"
+ [(const_int 0)]
+ ""
+{
+ s390_set_has_landing_pad_p (true);
+ DONE;
+})
;
; nop instruction pattern(s).
@@ -7414,40 +7654,30 @@
{
enum machine_mode mode = GET_MODE (PATTERN (insn));
unsigned int align = GET_MODE_BITSIZE (mode);
- s390_output_pool_entry (asm_out_file, operands[0], mode, align);
+ s390_output_pool_entry (operands[0], mode, align);
return "";
}
- [(set_attr "op_type" "NN")
- (set (attr "length")
+ [(set (attr "length")
(symbol_ref "GET_MODE_SIZE (GET_MODE (PATTERN (insn)))"))])
-(define_insn "pool_start_31"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
- "!TARGET_CPU_ZARCH"
- ".align\t4"
- [(set_attr "op_type" "NN")
- (set_attr "length" "2")])
-
-(define_insn "pool_end_31"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
- "!TARGET_CPU_ZARCH"
- ".align\t2"
- [(set_attr "op_type" "NN")
- (set_attr "length" "2")])
+(define_insn "pool_align"
+ [(unspec_volatile [(match_operand 0 "const_int_operand" "n")]
+ UNSPECV_POOL_ALIGN)]
+ ""
+ ".align\t%0"
+ [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
-(define_insn "pool_start_64"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_START)]
- "TARGET_CPU_ZARCH"
- ".section\t.rodata\;.align\t8"
- [(set_attr "op_type" "NN")
- (set_attr "length" "0")])
+(define_insn "pool_section_start"
+ [(unspec_volatile [(const_int 1)] UNSPECV_POOL_SECTION)]
+ ""
+ ".section\t.rodata"
+ [(set_attr "length" "0")])
-(define_insn "pool_end_64"
- [(unspec_volatile [(const_int 0)] UNSPECV_POOL_END)]
- "TARGET_CPU_ZARCH"
+(define_insn "pool_section_end"
+ [(unspec_volatile [(const_int 0)] UNSPECV_POOL_SECTION)]
+ ""
".previous"
- [(set_attr "op_type" "NN")
- (set_attr "length" "0")])
+ [(set_attr "length" "0")])
(define_insn "main_base_31_small"
[(set (match_operand 0 "register_operand" "=a")
@@ -7474,19 +7704,23 @@
(set_attr "type" "larl")])
(define_insn "main_pool"
- [(unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL)]
- ""
- "* abort ();"
- [(set_attr "op_type" "NN")])
+ [(set (match_operand 0 "register_operand" "=a")
+ (unspec_volatile [(const_int 0)] UNSPECV_MAIN_POOL))]
+ "GET_MODE (operands[0]) == Pmode"
+{
+ gcc_unreachable ();
+}
+ [(set (attr "type")
+ (if_then_else (ne (symbol_ref "TARGET_CPU_ZARCH") (const_int 0))
+ (const_string "larl") (const_string "la")))])
(define_insn "reload_base_31"
[(set (match_operand 0 "register_operand" "=a")
(unspec [(label_ref (match_operand 1 "" ""))] UNSPEC_RELOAD_BASE))]
"!TARGET_CPU_ZARCH && GET_MODE (operands[0]) == Pmode"
"basr\t%0,0\;la\t%0,%1-.(%0)"
- [(set_attr "op_type" "NN")
- (set_attr "type" "la")
- (set_attr "length" "6")])
+ [(set_attr "length" "6")
+ (set_attr "type" "la")])
(define_insn "reload_base_64"
[(set (match_operand 0 "register_operand" "=a")
@@ -7499,9 +7733,10 @@
(define_insn "pool"
[(unspec_volatile [(match_operand 0 "const_int_operand" "n")] UNSPECV_POOL)]
""
- "* abort ();"
- [(set_attr "op_type" "NN")
- (set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
+{
+ gcc_unreachable ();
+}
+ [(set (attr "length") (symbol_ref "INTVAL (operands[0])"))])
;;
;; Insns related to generating the function prologue and epilogue.
@@ -7516,7 +7751,12 @@
(define_expand "epilogue"
[(use (const_int 1))]
""
- "s390_emit_epilogue (); DONE;")
+ "s390_emit_epilogue (false); DONE;")
+
+(define_expand "sibcall_epilogue"
+ [(use (const_int 0))]
+ ""
+ "s390_emit_epilogue (true); DONE;")
(define_insn "*return"
[(return)
@@ -7541,3 +7781,77 @@
GEN_INT (0x7fffffff)));
DONE;
})
+
+;; Instruction definition to expand eh_return macro to support
+;; swapping in special linkage return addresses.
+
+(define_expand "eh_return"
+ [(use (match_operand 0 "register_operand" ""))]
+ "TARGET_TPF"
+{
+ s390_emit_tpf_eh_return (operands[0]);
+ DONE;
+})
+
+;
+; Stack Protector Patterns
+;
+
+(define_expand "stack_protect_set"
+ [(set (match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" ""))]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ operands[1]
+ = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+#endif
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+
+ DONE;
+})
+
+(define_insn "stack_protect_set<mode>"
+ [(set (match_operand:DSI 0 "memory_operand" "=Q")
+ (unspec:DSI [(match_operand:DSI 1 "memory_operand" "Q")] UNSPEC_SP_SET))]
+ ""
+ "mvc\t%O0(%G0,%R0),%S1"
+ [(set_attr "op_type" "SS")])
+
+(define_expand "stack_protect_test"
+ [(set (reg:CC CC_REGNUM)
+ (compare (match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")))
+ (match_operand 2 "" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ operands[1]
+ = gen_rtx_MEM (Pmode, gen_rtx_PLUS (Pmode, s390_get_thread_pointer (),
+ GEN_INT (TARGET_THREAD_SSP_OFFSET)));
+#endif
+ s390_compare_op0 = operands[0];
+ s390_compare_op1 = operands[1];
+ s390_compare_emitted = gen_rtx_REG (CCZmode, CC_REGNUM);
+
+ if (TARGET_64BIT)
+ emit_insn (gen_stack_protect_testdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
+
+ emit_jump_insn (gen_beq (operands[2]));
+
+ DONE;
+})
+
+(define_insn "stack_protect_test<mode>"
+ [(set (reg:CCZ CC_REGNUM)
+ (unspec:CCZ [(match_operand:DSI 0 "memory_operand" "Q")
+ (match_operand:DSI 1 "memory_operand" "Q")] UNSPEC_SP_TEST))]
+ ""
+ "clc\t%O0(%G0,%R0),%S1"
+ [(set_attr "op_type" "SS")])
diff --git a/contrib/gcc/config/s390/s390.opt b/contrib/gcc/config/s390/s390.opt
new file mode 100644
index 0000000..21ef4f3
--- /dev/null
+++ b/contrib/gcc/config/s390/s390.opt
@@ -0,0 +1,100 @@
+; Options for the S/390 / zSeries port of the compiler.
+
+; Copyright (C) 2005, 2006 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+m31
+Target Report RejectNegative InverseMask(64BIT)
+31 bit ABI
+
+m64
+Target Report RejectNegative Mask(64BIT)
+64 bit ABI
+
+march=
+Target RejectNegative Joined Var(s390_arch_string)
+Generate code for given CPU
+
+mbackchain
+Target Report Mask(BACKCHAIN)
+Maintain backchain pointer
+
+mdebug
+Target Report Mask(DEBUG_ARG)
+Additional debug prints
+
+mesa
+Target Report RejectNegative InverseMask(ZARCH)
+ESA/390 architecture
+
+mfused-madd
+Target Report Mask(FUSED_MADD)
+Enable fused multiply/add instructions
+
+mhard-float
+Target Report RejectNegative Mask(HARD_FLOAT)
+Use hardware fp
+
+mlong-double-128
+Target Report RejectNegative Mask(LONG_DOUBLE_128)
+Use 128-bit long double
+
+mlong-double-64
+Target Report RejectNegative InverseMask(LONG_DOUBLE_128)
+Use 64-bit long double
+
+mpacked-stack
+Target Report Mask(PACKED_STACK)
+Use packed stack layout
+
+msmall-exec
+Target Report Mask(SMALL_EXEC)
+Use bras for executable < 64k
+
+msoft-float
+Target Report RejectNegative InverseMask(HARD_FLOAT, SOFT_FLOAT)
+Don't use hardware fp
+
+mstack-guard=
+Target RejectNegative Joined
+Set the max. number of bytes which has to be left to stack size before a trap instruction is triggered
+
+mstack-size=
+Target RejectNegative Joined
+Emit extra code in the function prologue in order to trap if the stack size exceeds the given limit
+
+mtune=
+Target RejectNegative Joined
+Schedule code for given CPU
+
+mmvcle
+Target Report Mask(MVCLE)
+mvcle use
+
+mwarn-dynamicstack
+Target RejectNegative Var(s390_warn_dynamicstack_p)
+Warn if a function uses alloca or creates an array with dynamic size
+
+mwarn-framesize=
+Target RejectNegative Joined
+Warn if a single function's framesize exceeds the given framesize
+
+mzarch
+Target Report RejectNegative Mask(ZARCH)
+z/Architecture
diff --git a/contrib/gcc/config/s390/s390x.h b/contrib/gcc/config/s390/s390x.h
index f9177c1..cbfb45c 100644
--- a/contrib/gcc/config/s390/s390x.h
+++ b/contrib/gcc/config/s390/s390x.h
@@ -17,8 +17,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef _S390X_H
#define _S390X_H
diff --git a/contrib/gcc/config/s390/t-crtstuff b/contrib/gcc/config/s390/t-crtstuff
index 5572e6b..39b0eba 100644
--- a/contrib/gcc/config/s390/t-crtstuff
+++ b/contrib/gcc/config/s390/t-crtstuff
@@ -2,3 +2,4 @@
# because then __FRAME_END__ might not be the last thing in .eh_frame
# section.
CRTSTUFF_T_CFLAGS = -fno-asynchronous-unwind-tables
+TARGET_LIBGCC2_CFLAGS += -mlong-double-128
diff --git a/contrib/gcc/config/s390/t-linux b/contrib/gcc/config/s390/t-linux
new file mode 100644
index 0000000..d5a9278
--- /dev/null
+++ b/contrib/gcc/config/s390/t-linux
@@ -0,0 +1,3 @@
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/s390/libgcc-glibc.ver
diff --git a/contrib/gcc/config/s390/t-linux64 b/contrib/gcc/config/s390/t-linux64
index db839c6..0ffb690 100644
--- a/contrib/gcc/config/s390/t-linux64
+++ b/contrib/gcc/config/s390/t-linux64
@@ -6,7 +6,3 @@ LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o
-
-# Override t-slibgcc-elf-ver to export some libgcc symbols with
-# the symbol versions that glibc used.
-SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver $(srcdir)/config/s390/libgcc-glibc.ver
diff --git a/contrib/gcc/config/s390/t-tpf b/contrib/gcc/config/s390/t-tpf
index c04d562..6e4c377 100644
--- a/contrib/gcc/config/s390/t-tpf
+++ b/contrib/gcc/config/s390/t-tpf
@@ -3,11 +3,7 @@ CRTSTUFF_T_CFLAGS_S = $(CRTSTUFF_T_CFLAGS) -fPIC
# Compile libgcc2.a with pic.
TARGET_LIBGCC2_CFLAGS = -fPIC
-# Override t-slibgcc-elf-ver to export some libgcc symbols with
-# the symbol versions that glibc used.
-SHLIB_MAPFILES += $(srcdir)/config/s390/libgcc-glibc.ver
-
-# Use unwind-dw2-fde-glibc
+# Use unwind-dw2-fde-glibc.
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
$(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
-LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c gthr-gnat.c
+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h
diff --git a/contrib/gcc/config/s390/tpf-unwind.h b/contrib/gcc/config/s390/tpf-unwind.h
new file mode 100644
index 0000000..87b6892
--- /dev/null
+++ b/contrib/gcc/config/s390/tpf-unwind.h
@@ -0,0 +1,257 @@
+/* DWARF2 EH unwinding support for TPF OS.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by P.J. Darcy (darcypj@us.ibm.com).
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+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 combined
+executable.)
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+#include <dlfcn.h>
+
+/* Function Name: __isPATrange
+ Parameters passed into it: address to check
+ Return Value: A 1 if address is in pat code "range", 0 if not
+ Description: This function simply checks to see if the address
+ passed to it is in the CP pat code range. */
+
+#define MIN_PATRANGE 0x10000
+#define MAX_PATRANGE 0x800000
+
+static inline unsigned int
+__isPATrange (void *addr)
+{
+ if (addr > (void *)MIN_PATRANGE && addr < (void *)MAX_PATRANGE)
+ return 1;
+ else
+ return 0;
+}
+
+/* TPF return address offset from start of stack frame. */
+#define TPFRA_OFFSET 168
+
+/* Exceptions macro defined for TPF so that functions without
+ dwarf frame information can be used with exceptions. */
+#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
+
+static _Unwind_Reason_Code
+s390_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned long int regs;
+ unsigned long int new_cfa;
+ int i;
+
+ regs = *((unsigned long int *)
+ (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
+
+ /* Are we going through special linkage code? */
+ if (__isPATrange (context->ra))
+ {
+
+ /* Our return register isn't zero for end of stack, so
+ check backward stackpointer to see if it is zero. */
+ if (regs == NULL)
+ return _URC_END_OF_STACK;
+
+ /* No stack frame. */
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 15;
+ fs->cfa_offset = STACK_POINTER_OFFSET;
+
+ /* All registers remain unchanged ... */
+ for (i = 0; i < 32; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_REG;
+ fs->regs.reg[i].loc.reg = i;
+ }
+
+ /* ... except for %r14, which is stored at CFA-112
+ and used as return address. */
+ fs->regs.reg[14].how = REG_SAVED_OFFSET;
+ fs->regs.reg[14].loc.offset = TPFRA_OFFSET - STACK_POINTER_OFFSET;
+ fs->retaddr_column = 14;
+
+ return _URC_NO_REASON;
+ }
+
+ regs = *((unsigned long int *)
+ (((unsigned long int) context->cfa) - STACK_POINTER_OFFSET));
+ new_cfa = regs + STACK_POINTER_OFFSET;
+
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 15;
+ fs->cfa_offset = new_cfa -
+ (unsigned long int) context->cfa + STACK_POINTER_OFFSET;
+
+ for (i = 0; i < 16; i++)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset = regs + i*8 - new_cfa;
+ }
+
+ for (i = 0; i < 4; i++)
+ {
+ fs->regs.reg[16 + i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[16 + i].loc.offset = regs + 16*8 + i*8 - new_cfa;
+ }
+
+ fs->retaddr_column = 14;
+
+ return _URC_NO_REASON;
+}
+
+/* Function Name: __tpf_eh_return
+ Parameters passed into it: Destination address to jump to.
+ Return Value: Converted Destination address if a Pat Stub exists.
+ Description: This function swaps the unwinding return address
+ with the cp stub code. The original target return address is
+ then stored into the tpf return address field. The cp stub
+ code is searched for by climbing back up the stack and
+ comparing the tpf stored return address object address to
+ that of the targets object address. */
+
+#define CURRENT_STACK_PTR() \
+ ({ register unsigned long int *stack_ptr asm ("%r15"); stack_ptr; })
+
+#define PREVIOUS_STACK_PTR() \
+ ((unsigned long int *)(*(CURRENT_STACK_PTR())))
+
+#define RA_OFFSET 112
+#define R15_OFFSET 120
+#define TPFAREA_OFFSET 160
+#define TPFAREA_SIZE STACK_POINTER_OFFSET-TPFAREA_OFFSET
+#define INVALID_RETURN 0
+
+void * __tpf_eh_return (void *target);
+
+void *
+__tpf_eh_return (void *target)
+{
+ Dl_info targetcodeInfo, currentcodeInfo;
+ int retval;
+ void *current, *stackptr, *destination_frame;
+ unsigned long int shifter, is_a_stub;
+
+ is_a_stub = 0;
+
+ /* Get code info for target return's address. */
+ retval = dladdr (target, &targetcodeInfo);
+
+ /* Ensure the code info is valid (for target). */
+ if (retval != INVALID_RETURN)
+ {
+
+ /* Get the stack pointer of the stack frame to be modified by
+ the exception unwinder. So that we can begin our climb
+ there. */
+ stackptr = (void *) *((unsigned long int *) (*(PREVIOUS_STACK_PTR())));
+
+ /* Begin looping through stack frames. Stop if invalid
+ code information is retrieved or if a match between the
+ current stack frame iteration shared object's address
+ matches that of the target, calculated above. */
+ do
+ {
+ /* Get return address based on our stackptr iterator. */
+ current = (void *) *((unsigned long int *)
+ (stackptr+RA_OFFSET));
+
+ /* Is it a Pat Stub? */
+ if (__isPATrange (current))
+ {
+ /* Yes it was, get real return address
+ in TPF stack area. */
+ current = (void *) *((unsigned long int *)
+ (stackptr+TPFRA_OFFSET));
+ is_a_stub = 1;
+ }
+
+ /* Get codeinfo on RA so that we can figure out
+ the module address. */
+ retval = dladdr (current, &currentcodeInfo);
+
+ /* Check that codeinfo for current stack frame is valid.
+ Then compare the module address of current stack frame
+ to target stack frame to determine if we have the pat
+ stub address we want. Also ensure we are dealing
+ with a module crossing, stub return address. */
+ if (is_a_stub && retval != INVALID_RETURN
+ && targetcodeInfo.dli_fbase == currentcodeInfo.dli_fbase)
+ {
+ /* Yes! They are in the same module.
+ Force copy of TPF private stack area to
+ destination stack frame TPF private area. */
+ destination_frame = (void *) *((unsigned long int *)
+ (*PREVIOUS_STACK_PTR() + R15_OFFSET));
+
+ /* Copy TPF linkage area from current frame to
+ destination frame. */
+ memcpy((void *) (destination_frame + TPFAREA_OFFSET),
+ (void *) (stackptr + TPFAREA_OFFSET), TPFAREA_SIZE);
+
+ /* Now overlay the
+ real target address into the TPF stack area of
+ the target frame we are jumping to. */
+ *((unsigned long int *) (destination_frame +
+ TPFRA_OFFSET)) = (unsigned long int) target;
+
+ /* Before returning the desired pat stub address to
+ the exception handling unwinder so that it can
+ actually do the "leap" shift out the low order
+ bit designated to determine if we are in 64BIT mode.
+ This is necessary for CTOA stubs.
+ Otherwise we leap one byte past where we want to
+ go to in the TPF pat stub linkage code. */
+ shifter = *((unsigned long int *)
+ (stackptr + RA_OFFSET));
+
+ shifter &= ~1ul;
+
+ /* Store Pat Stub Address in destination Stack Frame. */
+ *((unsigned long int *) (destination_frame +
+ RA_OFFSET)) = shifter;
+
+ /* Re-adjust pat stub address to go to correct place
+ in linkage. */
+ shifter = shifter - 4;
+
+ return (void *) shifter;
+ }
+
+ /* Desired module pat stub not found ...
+ Bump stack frame iterator. */
+ stackptr = (void *) *(unsigned long int *) stackptr;
+
+ is_a_stub = 0;
+
+ } while (stackptr && retval != INVALID_RETURN
+ && targetcodeInfo.dli_fbase != currentcodeInfo.dli_fbase);
+ }
+
+ /* No pat stub found, could be a problem? Simply return unmodified
+ target address. */
+ return target;
+}
+
diff --git a/contrib/gcc/config/s390/tpf.h b/contrib/gcc/config/s390/tpf.h
index 3015827..f0a63f7 100644
--- a/contrib/gcc/config/s390/tpf.h
+++ b/contrib/gcc/config/s390/tpf.h
@@ -1,5 +1,5 @@
/* Definitions for target OS TPF for GNU compiler, for IBM S/390 hardware
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by P.J. Darcy (darcypj@us.ibm.com),
Hartmut Penner (hpenner@de.ibm.com), and
Ulrich Weigand (uweigand@de.ibm.com).
@@ -18,21 +18,21 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
#ifndef _TPF_H
#define _TPF_H
/* TPF wants the following macros defined/undefined as follows. */
+#undef TARGET_TPF
+#define TARGET_TPF 1
#undef ASM_APP_ON
#define ASM_APP_ON "#APP\n"
#undef ASM_APP_OFF
#define ASM_APP_OFF "#NO_APP\n"
#define NO_IMPLICIT_EXTERN_C
-#define TARGET_HAS_F_SETLKW
-#undef MD_EXEC_PREFIX
-#undef MD_STARTFILE_PREFIX
+#define TARGET_POSIX_IO
#undef SIZE_TYPE
#define SIZE_TYPE ("long unsigned int")
@@ -50,11 +50,19 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
/* TPF OS specific stack-pointer offset. */
#undef STACK_POINTER_OFFSET
-#define STACK_POINTER_OFFSET 280
+#define STACK_POINTER_OFFSET 448
-/* When building for TPF, set a generic default target that is 64 bits. */
+/* When building for TPF, set a generic default target that is 64 bits. Also
+ enable TPF profiling support and the standard backchain by default. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT 0x33
+#define TARGET_DEFAULT (MASK_TPF_PROFILING | MASK_64BIT | MASK_ZARCH \
+ | MASK_HARD_FLOAT | MASK_BACKCHAIN)
+
+/* Exception handling. */
+
+/* Select a format to encode pointers in exception handling data. */
+#undef ASM_PREFERRED_EH_DATA_FORMAT
+#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) DW_EH_PE_absptr
/* TPF OS specific compiler settings. */
#undef TARGET_OS_CPP_BUILTINS
@@ -64,52 +72,59 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
builtin_define_std ("tpf"); \
builtin_assert ("system=tpf"); \
builtin_define ("__ELF__"); \
- if (flag_pic) \
- { \
- builtin_define ("__PIC__"); \
- builtin_define ("__pic__"); \
- } \
} \
while (0)
+#define EXTRA_SPECS \
+ { "entry_spec", ENTRY_SPEC }
+
/* Make TPF specific spec file settings here. */
-#undef STARTFILE_SPEC
+#undef STARTFILE_SPEC
#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} \
- %{!p:%{profile:gcrt1.o%s} \
- %{!profile:crt1.o%s}}}} \
- crti.o%s %{static:crtbeginT.o%s} \
- %{!static:%{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}}"
+ "%{mmain:crt0%O%s} crtbeginS%O%s crt3%O%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC "crtendS%O%s"
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC \
- "%{!shared:crtend.o%s} %{shared:crtendS.o%s} crtn.o%s"
+#undef CC1_SPEC
+#define CC1_SPEC "%{!fverbose-asm: -fverbose-asm}"
/* The GNU C++ standard library requires that these macros be defined. */
#undef CPLUSPLUS_CPP_SPEC
#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
-#undef ASM_SPEC
-#define ASM_SPEC "%{m31&m64}%{mesa&mzarch}%{march=*}"
+#undef ASM_SPEC
+#define ASM_SPEC "%{m31&m64}%{mesa&mzarch}%{march=*} \
+ -alshd=%b.lst"
-#undef LIB_SPEC
-#define LIB_SPEC "%{pthread:-lpthread} -lc"
+/* It would be nice to get the system linker script define the ones that it
+ needed. */
+#undef LIB_SPEC
+#define LIB_SPEC "-lCTIS -lCISO -lCLBM -lCTAL -lCFVS -lCTBX -lCTXO \
+ -lCJ00 -lCTDF -lCOMX -lCOMS -lCTHD -lCTAD -lTPFSTUB"
#undef TARGET_C99_FUNCTIONS
#define TARGET_C99_FUNCTIONS 1
+#define ENTRY_SPEC "%{mmain:-entry=_start} \
+ %{!mmain:-entry=0}"
+
+/* All linking is done shared on TPF-OS. */
+/* FIXME: When binutils patch for new emulation is committed
+ then change emulation to elf64_s390_tpf. */
#undef LINK_SPEC
#define LINK_SPEC \
"-m elf64_s390 \
- %{shared:-shared} \
- %{!shared: \
- %{static:-static} \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld64.so}}}"
+ %{static:%estatic is not supported on TPF-OS} \
+ %{shared: -shared} \
+ %{!shared:-shared} \
+ %(entry_spec)"
-#endif /* ! _TPF_H */
+#define MD_UNWIND_SUPPORT "config/s390/tpf-unwind.h"
+/* IBM copies these libraries over with these names. */
+#define MATH_LIBRARY "-lCLBM"
+#define LIBSTDCXX "-lCPP1"
+#endif /* ! _TPF_H */
diff --git a/contrib/gcc/config/s390/tpf.md b/contrib/gcc/config/s390/tpf.md
new file mode 100644
index 0000000..87a2616
--- /dev/null
+++ b/contrib/gcc/config/s390/tpf.md
@@ -0,0 +1,34 @@
+;; S390 TPF-OS specific machine patterns
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_insn "prologue_tpf"
+ [(unspec_volatile [(const_int 0)] UNSPECV_TPF_PROLOGUE)
+ (clobber (reg:DI 1))]
+ "TARGET_TPF_PROFILING"
+ "larl\t%%r1,.+14\;tm\t4065,255\;bnz\t4064"
+ [(set_attr "length" "14")])
+
+
+(define_insn "epilogue_tpf"
+ [(unspec_volatile [(const_int 0)] UNSPECV_TPF_EPILOGUE)
+ (clobber (reg:DI 1))]
+ "TARGET_TPF_PROFILING"
+ "larl\t%%r1,.+14\;tm\t4071,255\;bnz\t4070"
+ [(set_attr "length" "14")])
diff --git a/contrib/gcc/config/s390/tpf.opt b/contrib/gcc/config/s390/tpf.opt
new file mode 100644
index 0000000..7f12402
--- /dev/null
+++ b/contrib/gcc/config/s390/tpf.opt
@@ -0,0 +1,28 @@
+; Options for the TPF-OS port of the compiler.
+
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mtpf-trace
+Target Report Mask(TPF_PROFILING)
+Enable TPF-OS tracing code
+
+mmain
+Target Report
+Specify main object for TPF-OS
diff --git a/contrib/gcc/config/soft-fp/README b/contrib/gcc/config/soft-fp/README
new file mode 100644
index 0000000..870025c
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/README
@@ -0,0 +1,4 @@
+Except for t-softfp, the files in this directory are part of the GNU C
+Library, not part of GCC. As described at
+<http://gcc.gnu.org/codingconventions.html>, changes should be made to
+the GNU C Library and the changed files then imported into GCC.
diff --git a/contrib/gcc/config/soft-fp/adddf3.c b/contrib/gcc/config/soft-fp/adddf3.c
new file mode 100644
index 0000000..24c03db
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/adddf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a + b
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __adddf3(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_D(A, a);
+ FP_UNPACK_SEMIRAW_D(B, b);
+ FP_ADD_D(R, A, B);
+ FP_PACK_SEMIRAW_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/addsf3.c b/contrib/gcc/config/soft-fp/addsf3.c
new file mode 100644
index 0000000..b86991e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/addsf3.c
@@ -0,0 +1,50 @@
+/* Software floating-point emulation.
+ Return a + b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __addsf3(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_S(A, a);
+ FP_UNPACK_SEMIRAW_S(B, b);
+ FP_ADD_S(R, A, B);
+ FP_PACK_SEMIRAW_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
diff --git a/contrib/gcc/config/soft-fp/addtf3.c b/contrib/gcc/config/soft-fp/addtf3.c
new file mode 100644
index 0000000..49b67f0
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/addtf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a + b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __addtf3(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(A, a);
+ FP_UNPACK_SEMIRAW_Q(B, b);
+ FP_ADD_Q(R, A, B);
+ FP_PACK_SEMIRAW_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/divdf3.c b/contrib/gcc/config/soft-fp/divdf3.c
new file mode 100644
index 0000000..c3bb0d2
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/divdf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a / b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __divdf3(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_D(A, a);
+ FP_UNPACK_D(B, b);
+ FP_DIV_D(R, A, B);
+ FP_PACK_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/divsf3.c b/contrib/gcc/config/soft-fp/divsf3.c
new file mode 100644
index 0000000..176bb3c
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/divsf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a / b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __divsf3(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_S(A, a);
+ FP_UNPACK_S(B, b);
+ FP_DIV_S(R, A, B);
+ FP_PACK_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/divtf3.c b/contrib/gcc/config/soft-fp/divtf3.c
new file mode 100644
index 0000000..916fbfe
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/divtf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a / b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __divtf3(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_Q(A, a);
+ FP_UNPACK_Q(B, b);
+ FP_DIV_Q(R, A, B);
+ FP_PACK_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/double.h b/contrib/gcc/config/soft-fp/double.h
new file mode 100644
index 0000000..c8f4420
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/double.h
@@ -0,0 +1,264 @@
+/* Software floating-point emulation.
+ Definitions for IEEE Double Precision
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
+#endif
+
+#define _FP_FRACBITS_D 53
+#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D)
+#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D)
+#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
+#define _FP_EXPBITS_D 11
+#define _FP_EXPBIAS_D 1023
+#define _FP_EXPMAX_D 2047
+
+#define _FP_QNANBIT_D \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
+#define _FP_QNANBIT_SH_D \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_D \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_SH_D \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_D \
+ ((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
+
+typedef float DFtype __attribute__((mode(DF)));
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_D
+{
+ DFtype flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+ unsigned frac0 : _FP_W_TYPE_SIZE;
+#else
+ unsigned frac0 : _FP_W_TYPE_SIZE;
+ unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X) _FP_DECL(2,X)
+#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val)
+#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
+#define FP_PACK_RAW_DP(val,X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(D,val,X); \
+ } while (0)
+
+#define FP_UNPACK_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,2,X); \
+ } while (0)
+
+#define FP_UNPACK_DP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2_P(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(D,X,val); \
+ _FP_UNPACK_SEMIRAW(D,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_DP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2_P(D,X,val); \
+ _FP_UNPACK_SEMIRAW(D,2,X); \
+ } while (0)
+
+#define FP_PACK_D(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,2,X); \
+ _FP_PACK_RAW_2(D,val,X); \
+ } while (0)
+
+#define FP_PACK_DP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,2,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(D,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_D(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(D,2,X); \
+ _FP_PACK_RAW_2(D,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_DP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(D,2,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(D,val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X)
+#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
+#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
+#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
+#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
+#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
+#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
+
+#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
+#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,2,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X)
+#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X)
+
+#else
+
+union _FP_UNION_D
+{
+ DFtype flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+#else
+ unsigned long frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
+ unsigned exp : _FP_EXPBITS_D;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_D(X) _FP_DECL(1,X)
+#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
+#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val)
+#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
+#define FP_PACK_RAW_DP(val,X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(D,val,X); \
+ } while (0)
+
+#define FP_UNPACK_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,1,X); \
+ } while (0)
+
+#define FP_UNPACK_DP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1_P(D,X,val); \
+ _FP_UNPACK_CANONICAL(D,1,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_D(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(1,X,val); \
+ _FP_UNPACK_SEMIRAW(D,1,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_DP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2_P(1,X,val); \
+ _FP_UNPACK_SEMIRAW(D,1,X); \
+ } while (0)
+
+#define FP_PACK_D(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,1,X); \
+ _FP_PACK_RAW_1(D,val,X); \
+ } while (0)
+
+#define FP_PACK_DP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(D,1,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(D,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_D(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(D,1,X); \
+ _FP_PACK_RAW_1(D,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_DP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(D,1,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(D,val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X)
+#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
+#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
+#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
+#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
+#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
+#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
+#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
+
+/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
+ the target machine. */
+
+#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
+#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
+#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,1,r,X,Y)
+
+#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
+#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X)
+#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
+
+#endif /* W_TYPE_SIZE < 64 */
diff --git a/contrib/gcc/config/soft-fp/eqdf2.c b/contrib/gcc/config/soft-fp/eqdf2.c
new file mode 100644
index 0000000..efa769e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/eqdf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 otherwise
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+int __eqdf2(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B);
+ int r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_UNPACK_RAW_D(B, b);
+ FP_CMP_EQ_D(r, A, B);
+ if (r && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__eqdf2, __nedf2);
diff --git a/contrib/gcc/config/soft-fp/eqsf2.c b/contrib/gcc/config/soft-fp/eqsf2.c
new file mode 100644
index 0000000..7e01c01
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/eqsf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 otherwise
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+int __eqsf2(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B);
+ int r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_UNPACK_RAW_S(B, b);
+ FP_CMP_EQ_S(r, A, B);
+ if (r && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__eqsf2, __nesf2);
diff --git a/contrib/gcc/config/soft-fp/eqtf2.c b/contrib/gcc/config/soft-fp/eqtf2.c
new file mode 100644
index 0000000..fd6ffd1
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/eqtf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 otherwise
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+int __eqtf2(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B);
+ int r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_UNPACK_RAW_Q(B, b);
+ FP_CMP_EQ_Q(r, A, B);
+ if (r && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__eqtf2, __netf2);
diff --git a/contrib/gcc/config/soft-fp/extenddftf2.c b/contrib/gcc/config/soft-fp/extenddftf2.c
new file mode 100644
index 0000000..4101639
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/extenddftf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Return a converted to IEEE quad
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+#include "quad.h"
+
+TFtype __extenddftf2(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_RAW_D(A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_EXTEND(Q,D,4,2,R,A);
+#else
+ FP_EXTEND(Q,D,2,1,R,A);
+#endif
+ FP_PACK_RAW_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/extended.h b/contrib/gcc/config/soft-fp/extended.h
new file mode 100644
index 0000000..bbf3942
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/extended.h
@@ -0,0 +1,453 @@
+/* Software floating-point emulation.
+ Definitions for IEEE Extended Precision.
+ Copyright (C) 1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel, kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
+#endif
+
+#define _FP_FRACBITS_E 64
+#define _FP_FRACXBITS_E (_FP_FRACTBITS_E - _FP_FRACBITS_E)
+#define _FP_WFRACBITS_E (_FP_WORKBITS + _FP_FRACBITS_E)
+#define _FP_WFRACXBITS_E (_FP_FRACTBITS_E - _FP_WFRACBITS_E)
+#define _FP_EXPBITS_E 15
+#define _FP_EXPBIAS_E 16383
+#define _FP_EXPMAX_E 32767
+
+#define _FP_QNANBIT_E \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
+#define _FP_QNANBIT_SH_E \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_E \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_SH_E \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_E \
+ ((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
+
+typedef float XFtype __attribute__((mode(XF)));
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_E
+{
+ XFtype flt;
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned long pad1 : _FP_W_TYPE_SIZE;
+ unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+ unsigned long sign : 1;
+ unsigned long exp : _FP_EXPBITS_E;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_E;
+ unsigned sign : 1;
+#endif /* not bigendian */
+ } bits __attribute__((packed));
+};
+
+
+#define FP_DECL_E(X) _FP_DECL(4,X)
+
+#define FP_UNPACK_RAW_E(X, val) \
+ do { \
+ union _FP_UNION_E _flo; _flo.flt = (val); \
+ \
+ X##_f[2] = 0; X##_f[3] = 0; \
+ X##_f[0] = _flo.bits.frac0; \
+ X##_f[1] = _flo.bits.frac1; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ if (!X##_e && (X##_f[1] || X##_f[0]) \
+ && !(X##_f[1] & _FP_IMPLBIT_E)) \
+ { \
+ X##_e++; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val) \
+ do { \
+ union _FP_UNION_E *_flo = \
+ (union _FP_UNION_E *)(val); \
+ \
+ X##_f[2] = 0; X##_f[3] = 0; \
+ X##_f[0] = _flo->bits.frac0; \
+ X##_f[1] = _flo->bits.frac1; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ if (!X##_e && (X##_f[1] || X##_f[0]) \
+ && !(X##_f[1] & _FP_IMPLBIT_E)) \
+ { \
+ X##_e++; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ } while (0)
+
+#define FP_PACK_RAW_E(val, X) \
+ do { \
+ union _FP_UNION_E _flo; \
+ \
+ if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
+ else X##_f[1] &= ~(_FP_IMPLBIT_E); \
+ _flo.bits.frac0 = X##_f[0]; \
+ _flo.bits.frac1 = X##_f[1]; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+#define FP_PACK_RAW_EP(val, X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ { \
+ union _FP_UNION_E *_flo = \
+ (union _FP_UNION_E *)(val); \
+ \
+ if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
+ else X##_f[1] &= ~(_FP_IMPLBIT_E); \
+ _flo->bits.frac0 = X##_f[0]; \
+ _flo->bits.frac1 = X##_f[1]; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ } while (0)
+
+#define FP_UNPACK_E(X,val) \
+ do { \
+ FP_UNPACK_RAW_E(X,val); \
+ _FP_UNPACK_CANONICAL(E,4,X); \
+ } while (0)
+
+#define FP_UNPACK_EP(X,val) \
+ do { \
+ FP_UNPACK_RAW_EP(X,val); \
+ _FP_UNPACK_CANONICAL(E,4,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_E(X,val) \
+ do { \
+ _FP_UNPACK_RAW_E(X,val); \
+ _FP_UNPACK_SEMIRAW(E,4,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_EP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_EP(X,val); \
+ _FP_UNPACK_SEMIRAW(E,4,X); \
+ } while (0)
+
+#define FP_PACK_E(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(E,4,X); \
+ FP_PACK_RAW_E(val,X); \
+ } while (0)
+
+#define FP_PACK_EP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(E,4,X); \
+ FP_PACK_RAW_EP(val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_E(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(E,4,X); \
+ _FP_PACK_RAW_E(val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_EP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(E,4,X); \
+ _FP_PACK_RAW_EP(val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X)
+#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X)
+#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y)
+#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y)
+#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y)
+#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y)
+#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * This has special _E version because standard _4 square
+ * root would not work (it has to start normally with the
+ * second word and not the first), but as we have to do it
+ * anyway, we optimize it by doing most of the calculations
+ * in two UWtype registers instead of four.
+ */
+
+#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
+ do { \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \
+ while (q) \
+ { \
+ T##_f[1] = S##_f[1] + q; \
+ if (T##_f[1] <= X##_f[1]) \
+ { \
+ S##_f[1] = T##_f[1] + q; \
+ X##_f[1] -= T##_f[1]; \
+ R##_f[1] += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[0] = S##_f[0] + q; \
+ T##_f[1] = S##_f[1]; \
+ if (T##_f[1] < X##_f[1] || \
+ (T##_f[1] == X##_f[1] && \
+ T##_f[0] <= X##_f[0])) \
+ { \
+ S##_f[0] = T##_f[0] + q; \
+ S##_f[1] += (T##_f[0] > S##_f[0]); \
+ _FP_FRAC_DEC_2(X, T); \
+ R##_f[0] += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ _FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \
+ if (X##_f[0] | X##_f[1]) \
+ { \
+ if (S##_f[1] < X##_f[1] || \
+ (S##_f[1] == X##_f[1] && \
+ S##_f[0] < X##_f[0])) \
+ R##_f[0] |= _FP_WORK_ROUND; \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y)
+#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,4,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X) (X##_f[2])
+#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
+
+#else /* not _FP_W_TYPE_SIZE < 64 */
+union _FP_UNION_E
+{
+ XFtype flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned long pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_E;
+ unsigned long frac : _FP_W_TYPE_SIZE;
+#else
+ unsigned long frac : _FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_E;
+ unsigned sign : 1;
+#endif
+ } bits;
+};
+
+#define FP_DECL_E(X) _FP_DECL(2,X)
+
+#define FP_UNPACK_RAW_E(X, val) \
+ do { \
+ union _FP_UNION_E _flo; _flo.flt = (val); \
+ \
+ X##_f0 = _flo.bits.frac; \
+ X##_f1 = 0; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
+ { \
+ X##_e++; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ } while (0)
+
+#define FP_UNPACK_RAW_EP(X, val) \
+ do { \
+ union _FP_UNION_E *_flo = \
+ (union _FP_UNION_E *)(val); \
+ \
+ X##_f0 = _flo->bits.frac; \
+ X##_f1 = 0; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ if (!X##_e && X##_f0 && !(X##_f0 & _FP_IMPLBIT_E)) \
+ { \
+ X##_e++; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ } while (0)
+
+#define FP_PACK_RAW_E(val, X) \
+ do { \
+ union _FP_UNION_E _flo; \
+ \
+ if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
+ else X##_f0 &= ~(_FP_IMPLBIT_E); \
+ _flo.bits.frac = X##_f0; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+#define FP_PACK_RAW_EP(fs, val, X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ { \
+ union _FP_UNION_E *_flo = \
+ (union _FP_UNION_E *)(val); \
+ \
+ if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
+ else X##_f0 &= ~(_FP_IMPLBIT_E); \
+ _flo->bits.frac = X##_f0; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } \
+ } while (0)
+
+
+#define FP_UNPACK_E(X,val) \
+ do { \
+ FP_UNPACK_RAW_E(X,val); \
+ _FP_UNPACK_CANONICAL(E,2,X); \
+ } while (0)
+
+#define FP_UNPACK_EP(X,val) \
+ do { \
+ FP_UNPACK_RAW_EP(X,val); \
+ _FP_UNPACK_CANONICAL(E,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_E(X,val) \
+ do { \
+ _FP_UNPACK_RAW_E(X,val); \
+ _FP_UNPACK_SEMIRAW(E,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_EP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_EP(X,val); \
+ _FP_UNPACK_SEMIRAW(E,2,X); \
+ } while (0)
+
+#define FP_PACK_E(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(E,2,X); \
+ FP_PACK_RAW_E(val,X); \
+ } while (0)
+
+#define FP_PACK_EP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(E,2,X); \
+ FP_PACK_RAW_EP(val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_E(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(E,2,X); \
+ _FP_PACK_RAW_E(val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_EP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(E,2,X); \
+ _FP_PACK_RAW_EP(val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X)
+#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X)
+#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y)
+#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y)
+#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y)
+#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y)
+#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X)
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ * We optimize it by doing most of the calculations
+ * in one UWtype registers instead of two, although we don't
+ * have to.
+ */
+#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
+ do { \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \
+ while (q) \
+ { \
+ T##_f0 = S##_f0 + q; \
+ if (T##_f0 <= X##_f0) \
+ { \
+ S##_f0 = T##_f0 + q; \
+ X##_f0 -= T##_f0; \
+ R##_f0 += q; \
+ } \
+ _FP_FRAC_SLL_1(X, 1); \
+ q >>= 1; \
+ } \
+ _FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \
+ if (X##_f0) \
+ { \
+ if (S##_f0 < X##_f0) \
+ R##_f0 |= _FP_WORK_ROUND; \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un)
+#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y)
+#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,2,r,X,Y)
+
+#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg)
+#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_E(X) (X##_f1)
+#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
+
+#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/contrib/gcc/config/soft-fp/extendsfdf2.c b/contrib/gcc/config/soft-fp/extendsfdf2.c
new file mode 100644
index 0000000..fba22d5
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/extendsfdf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Return a converted to IEEE double
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+
+DFtype __extendsfdf2(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_RAW_S(A, a);
+#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
+ FP_EXTEND(D,S,2,1,R,A);
+#else
+ FP_EXTEND(D,S,1,1,R,A);
+#endif
+ FP_PACK_RAW_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/extendsftf2.c b/contrib/gcc/config/soft-fp/extendsftf2.c
new file mode 100644
index 0000000..c43cf1e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/extendsftf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Return a converted to IEEE quad
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+#include "quad.h"
+
+TFtype __extendsftf2(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_RAW_S(A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_EXTEND(Q,S,4,1,R,A);
+#else
+ FP_EXTEND(Q,S,2,1,R,A);
+#endif
+ FP_PACK_RAW_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixdfdi.c b/contrib/gcc/config/soft-fp/fixdfdi.c
new file mode 100644
index 0000000..fdfe35a
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixdfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DItype __fixdfdi(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_TO_INT_D(r, A, DI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixdfsi.c b/contrib/gcc/config/soft-fp/fixdfsi.c
new file mode 100644
index 0000000..a05f3e3
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixdfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+SItype __fixdfsi(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ USItype r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_TO_INT_D(r, A, SI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixsfdi.c b/contrib/gcc/config/soft-fp/fixsfdi.c
new file mode 100644
index 0000000..384d9bd
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixsfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+DItype __fixsfdi(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_TO_INT_S(r, A, DI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixsfsi.c b/contrib/gcc/config/soft-fp/fixsfsi.c
new file mode 100644
index 0000000..1d40ed0
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixsfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SItype __fixsfsi(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ USItype r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_TO_INT_S(r, A, SI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixtfdi.c b/contrib/gcc/config/soft-fp/fixtfdi.c
new file mode 100644
index 0000000..ea10ce2
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixtfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+DItype __fixtfdi(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_TO_INT_Q(r, A, DI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixtfsi.c b/contrib/gcc/config/soft-fp/fixtfsi.c
new file mode 100644
index 0000000..eb71038
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixtfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit signed integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+SItype __fixtfsi(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ USItype r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_TO_INT_Q(r, A, SI_BITS, 1);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunsdfdi.c b/contrib/gcc/config/soft-fp/fixunsdfdi.c
new file mode 100644
index 0000000..d85198f
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunsdfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+UDItype __fixunsdfdi(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_TO_INT_D(r, A, DI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunsdfsi.c b/contrib/gcc/config/soft-fp/fixunsdfsi.c
new file mode 100644
index 0000000..492ffde
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunsdfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+USItype __fixunsdfsi(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ USItype r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_TO_INT_D(r, A, SI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunssfdi.c b/contrib/gcc/config/soft-fp/fixunssfdi.c
new file mode 100644
index 0000000..5484153
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunssfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+UDItype __fixunssfdi(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_TO_INT_S(r, A, DI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunssfsi.c b/contrib/gcc/config/soft-fp/fixunssfsi.c
new file mode 100644
index 0000000..ac9d4b9
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunssfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+USItype __fixunssfsi(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ USItype r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_TO_INT_S(r, A, SI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunstfdi.c b/contrib/gcc/config/soft-fp/fixunstfdi.c
new file mode 100644
index 0000000..86f1fc8
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunstfdi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 64bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+UDItype __fixunstfdi(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ UDItype r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_TO_INT_Q(r, A, DI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/fixunstfsi.c b/contrib/gcc/config/soft-fp/fixunstfsi.c
new file mode 100644
index 0000000..e0335da
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/fixunstfsi.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a to 32bit unsigned integer
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+USItype __fixunstfsi(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ USItype r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_TO_INT_Q(r, A, SI_BITS, 0);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/floatdidf.c b/contrib/gcc/config/soft-fp/floatdidf.c
new file mode 100644
index 0000000..21e9fb1
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatdidf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 64bit signed integer to IEEE double
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __floatdidf(DItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ DFtype a;
+
+ FP_FROM_INT_D(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_D(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatdisf.c b/contrib/gcc/config/soft-fp/floatdisf.c
new file mode 100644
index 0000000..ee57915
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatdisf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 64bit signed integer to IEEE single
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __floatdisf(DItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ SFtype a;
+
+ FP_FROM_INT_S(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_S(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatditf.c b/contrib/gcc/config/soft-fp/floatditf.c
new file mode 100644
index 0000000..564800b
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatditf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 64bit signed integer to IEEE quad
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __floatditf(DItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ TFtype a;
+
+ FP_FROM_INT_Q(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_Q(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatsidf.c b/contrib/gcc/config/soft-fp/floatsidf.c
new file mode 100644
index 0000000..b6d5f8d
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatsidf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 32bit signed integer to IEEE double
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __floatsidf(SItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ DFtype a;
+
+ FP_FROM_INT_D(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_D(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatsisf.c b/contrib/gcc/config/soft-fp/floatsisf.c
new file mode 100644
index 0000000..76217fe
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatsisf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 32bit signed integer to IEEE single
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __floatsisf(SItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ SFtype a;
+
+ FP_FROM_INT_S(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_S(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatsitf.c b/contrib/gcc/config/soft-fp/floatsitf.c
new file mode 100644
index 0000000..8c3d9cc
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatsitf.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Convert a 32bit signed integer to IEEE quad
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __floatsitf(SItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ TFtype a;
+
+ FP_FROM_INT_Q(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_Q(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatundidf.c b/contrib/gcc/config/soft-fp/floatundidf.c
new file mode 100644
index 0000000..2169a3f
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatundidf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 64bit unsigned integer to IEEE double
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+double
+__floatundidf(UDItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ DFtype a;
+
+ FP_FROM_INT_D(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_D(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatundisf.c b/contrib/gcc/config/soft-fp/floatundisf.c
new file mode 100644
index 0000000..5f08764
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatundisf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 64bit unsigned integer to IEEE single
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+float
+__floatundisf(UDItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ SFtype a;
+
+ FP_FROM_INT_S(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_S(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatunditf.c b/contrib/gcc/config/soft-fp/floatunditf.c
new file mode 100644
index 0000000..ab357f0
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatunditf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 64bit unsigned integer to IEEE quad
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype
+__floatunditf(UDItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ TFtype a;
+
+ FP_FROM_INT_Q(A, i, DI_BITS, UDItype);
+ FP_PACK_RAW_Q(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatunsidf.c b/contrib/gcc/config/soft-fp/floatunsidf.c
new file mode 100644
index 0000000..97b488a
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatunsidf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 32bit unsigned integer to IEEE double
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+double
+__floatunsidf(USItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ DFtype a;
+
+ FP_FROM_INT_D(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_D(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatunsisf.c b/contrib/gcc/config/soft-fp/floatunsisf.c
new file mode 100644
index 0000000..2ec16ba
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatunsisf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 32bit unsigned integer to IEEE single
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+float
+__floatunsisf(USItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A);
+ SFtype a;
+
+ FP_FROM_INT_S(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_S(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/floatunsitf.c b/contrib/gcc/config/soft-fp/floatunsitf.c
new file mode 100644
index 0000000..c993716
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/floatunsitf.c
@@ -0,0 +1,47 @@
+/* Software floating-point emulation.
+ Convert a 32bit unsigned integer to IEEE quad
+ Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype
+__floatunsitf(USItype i)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ TFtype a;
+
+ FP_FROM_INT_Q(A, i, SI_BITS, USItype);
+ FP_PACK_RAW_Q(a, A);
+ FP_HANDLE_EXCEPTIONS;
+
+ return a;
+}
diff --git a/contrib/gcc/config/soft-fp/gedf2.c b/contrib/gcc/config/soft-fp/gedf2.c
new file mode 100644
index 0000000..e0dc862
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/gedf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+int __gedf2(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B);
+ int r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_UNPACK_RAW_D(B, b);
+ FP_CMP_D(r, A, B, -2);
+ if (r == -2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__gedf2, __gtdf2);
diff --git a/contrib/gcc/config/soft-fp/gesf2.c b/contrib/gcc/config/soft-fp/gesf2.c
new file mode 100644
index 0000000..d1f3ba2
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/gesf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+int __gesf2(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B);
+ int r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_UNPACK_RAW_S(B, b);
+ FP_CMP_S(r, A, B, -2);
+ if (r == -2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__gesf2, __gtsf2);
diff --git a/contrib/gcc/config/soft-fp/getf2.c b/contrib/gcc/config/soft-fp/getf2.c
new file mode 100644
index 0000000..82ff283
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/getf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+int __getf2(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B);
+ int r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_UNPACK_RAW_Q(B, b);
+ FP_CMP_Q(r, A, B, -2);
+ if (r == -2 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__getf2, __gttf2);
diff --git a/contrib/gcc/config/soft-fp/ledf2.c b/contrib/gcc/config/soft-fp/ledf2.c
new file mode 100644
index 0000000..528a981
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/ledf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+int __ledf2(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B);
+ int r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_UNPACK_RAW_D(B, b);
+ FP_CMP_D(r, A, B, 2);
+ if (r == 2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__ledf2, __ltdf2);
diff --git a/contrib/gcc/config/soft-fp/lesf2.c b/contrib/gcc/config/soft-fp/lesf2.c
new file mode 100644
index 0000000..c564bd9
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/lesf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+int __lesf2(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B);
+ int r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_UNPACK_RAW_S(B, b);
+ FP_CMP_S(r, A, B, 2);
+ if (r == 2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__lesf2, __ltsf2);
diff --git a/contrib/gcc/config/soft-fp/letf2.c b/contrib/gcc/config/soft-fp/letf2.c
new file mode 100644
index 0000000..35e03aa
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/letf2.c
@@ -0,0 +1,51 @@
+/* Software floating-point emulation.
+ Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+int __letf2(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B);
+ int r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_UNPACK_RAW_Q(B, b);
+ FP_CMP_Q(r, A, B, 2);
+ if (r == 2 && (FP_ISSIGNAN_Q(A) || FP_ISSIGNAN_Q(B)))
+ FP_SET_EXCEPTION(FP_EX_INVALID);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
+
+strong_alias(__letf2, __lttf2);
diff --git a/contrib/gcc/config/soft-fp/muldf3.c b/contrib/gcc/config/soft-fp/muldf3.c
new file mode 100644
index 0000000..7eb2015
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/muldf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a * b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __muldf3(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_D(A, a);
+ FP_UNPACK_D(B, b);
+ FP_MUL_D(R, A, B);
+ FP_PACK_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/mulsf3.c b/contrib/gcc/config/soft-fp/mulsf3.c
new file mode 100644
index 0000000..5df4406
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/mulsf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a * b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __mulsf3(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_S(A, a);
+ FP_UNPACK_S(B, b);
+ FP_MUL_S(R, A, B);
+ FP_PACK_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/multf3.c b/contrib/gcc/config/soft-fp/multf3.c
new file mode 100644
index 0000000..0abab6d
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/multf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a * b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __multf3(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_Q(A, a);
+ FP_UNPACK_Q(B, b);
+ FP_MUL_Q(R, A, B);
+ FP_PACK_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/negdf2.c b/contrib/gcc/config/soft-fp/negdf2.c
new file mode 100644
index 0000000..54869e9
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/negdf2.c
@@ -0,0 +1,48 @@
+/* Software floating-point emulation.
+ Return -a
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __negdf2(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(R);
+ DFtype r;
+
+ FP_UNPACK_D(A, a);
+ FP_NEG_D(R, A);
+ FP_PACK_D(r, R);
+ FP_CLEAR_EXCEPTIONS;
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/negsf2.c b/contrib/gcc/config/soft-fp/negsf2.c
new file mode 100644
index 0000000..bf5db7a
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/negsf2.c
@@ -0,0 +1,48 @@
+/* Software floating-point emulation.
+ Return -a
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __negsf2(SFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(R);
+ SFtype r;
+
+ FP_UNPACK_S(A, a);
+ FP_NEG_S(R, A);
+ FP_PACK_S(r, R);
+ FP_CLEAR_EXCEPTIONS;
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/negtf2.c b/contrib/gcc/config/soft-fp/negtf2.c
new file mode 100644
index 0000000..5524c82
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/negtf2.c
@@ -0,0 +1,48 @@
+/* Software floating-point emulation.
+ Return -a
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __negtf2(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(R);
+ TFtype r;
+
+ FP_UNPACK_Q(A, a);
+ FP_NEG_Q(R, A);
+ FP_PACK_Q(r, R);
+ FP_CLEAR_EXCEPTIONS;
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/op-1.h b/contrib/gcc/config/soft-fp/op-1.h
new file mode 100644
index 0000000..35cd0ba
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/op-1.h
@@ -0,0 +1,302 @@
+/* Software floating-point emulation.
+ Basic one-word fraction declaration and manipulation.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
+#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
+#define _FP_FRAC_SET_1(X,I) (X##_f = I)
+#define _FP_FRAC_HIGH_1(X) (X##_f)
+#define _FP_FRAC_LOW_1(X) (X##_f)
+#define _FP_FRAC_WORD_1(X,w) (X##_f)
+
+#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
+#define _FP_FRAC_SLL_1(X,N) \
+ do { \
+ if (__builtin_constant_p(N) && (N) == 1) \
+ X##_f += X##_f; \
+ else \
+ X##_f <<= (N); \
+ } while (0)
+#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
+
+/* Right shift with sticky-lsb. */
+#define _FP_FRAC_SRST_1(X,S,N,sz) __FP_FRAC_SRST_1(X##_f, S, N, sz)
+#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
+
+#define __FP_FRAC_SRST_1(X,S,N,sz) \
+do { \
+ S = (__builtin_constant_p(N) && (N) == 1 \
+ ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \
+ X = X >> (N); \
+} while (0)
+
+#define __FP_FRAC_SRS_1(X,N,sz) \
+ (X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
+ ? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
+
+#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
+#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
+#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
+#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
+#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
+#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
+#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
+#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
+
+#define _FP_ZEROFRAC_1 0
+#define _FP_MINFRAC_1 1
+#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
+
+/*
+ * Unpack the raw bits of a native fp value. Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_1(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ \
+ X##_f = _flo.bits.frac; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+#define _FP_UNPACK_RAW_1_P(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ X##_f = _flo->bits.frac; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } while (0)
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_1(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac = X##_f; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+#define _FP_PACK_RAW_1_P(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ _flo->bits.frac = X##_f; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
+ multiplication immediately. */
+
+#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \
+ do { \
+ R##_f = X##_f * Y##_f; \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \
+ } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+
+#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \
+ do { \
+ _FP_W_TYPE _Z_f0, _Z_f1; \
+ doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \
+ R##_f = _Z_f0; \
+ } while (0)
+
+/* Finally, a simple widening multiply algorithm. What fun! */
+
+#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
+ do { \
+ _FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
+ \
+ /* split the words in half */ \
+ _xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
+ _xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+ _yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
+ _yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
+ \
+ /* multiply the pieces */ \
+ _z_f0 = _xl * _yl; \
+ _a_f0 = _xh * _yl; \
+ _a_f1 = _xl * _yh; \
+ _z_f1 = _xh * _yh; \
+ \
+ /* reassemble into two full words */ \
+ if ((_a_f0 += _a_f1) < _a_f1) \
+ _z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
+ _a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
+ _a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
+ _FP_FRAC_ADD_2(_z, _z, _a); \
+ \
+ /* normalize */ \
+ _FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \
+ R##_f = _z_f0; \
+ } while (0)
+
+
+/*
+ * Division algorithms:
+ */
+
+/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
+ division immediately. Give this macro either _FP_DIV_HELP_imm for
+ C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
+ choose will depend on what the compiler does with divrem4. */
+
+#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
+ do { \
+ _FP_W_TYPE _q, _r; \
+ X##_f <<= (X##_f < Y##_f \
+ ? R##_e--, _FP_WFRACBITS_##fs \
+ : _FP_WFRACBITS_##fs - 1); \
+ doit(_q, _r, X##_f, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
+ that may be useful in this situation. This first is for a primitive
+ that requires normalization, the second for one that does not. Look
+ for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
+
+#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _nh, _nl, _q, _r, _y; \
+ \
+ /* Normalize Y -- i.e. make the most significant bit set. */ \
+ _y = Y##_f << _FP_WFRACXBITS_##fs; \
+ \
+ /* Shift X op correspondingly high, that is, up one full word. */ \
+ if (X##_f < Y##_f) \
+ { \
+ R##_e--; \
+ _nl = 0; \
+ _nh = X##_f; \
+ } \
+ else \
+ { \
+ _nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
+ _nh = X##_f >> 1; \
+ } \
+ \
+ udiv_qrnnd(_q, _r, _nh, _nl, _y); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _nh, _nl, _q, _r; \
+ if (X##_f < Y##_f) \
+ { \
+ R##_e--; \
+ _nl = X##_f << _FP_WFRACBITS_##fs; \
+ _nh = X##_f >> _FP_WFRACXBITS_##fs; \
+ } \
+ else \
+ { \
+ _nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
+ _nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
+ } \
+ udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
+ R##_f = _q | (_r != 0); \
+ } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+
+#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
+ do { \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f = S##_f + q; \
+ if (T##_f <= X##_f) \
+ { \
+ S##_f = T##_f + q; \
+ X##_f -= T##_f; \
+ R##_f += q; \
+ } \
+ _FP_FRAC_SLL_1(X, 1); \
+ q >>= 1; \
+ } \
+ if (X##_f) \
+ { \
+ if (S##_f < X##_f) \
+ R##_f |= _FP_WORK_ROUND; \
+ R##_f |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+/*
+ * Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
+#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
+
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_COPY_1_1(D, S) (D##_f = S##_f)
diff --git a/contrib/gcc/config/soft-fp/op-2.h b/contrib/gcc/config/soft-fp/op-2.h
new file mode 100644
index 0000000..5c9bce4
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/op-2.h
@@ -0,0 +1,615 @@
+/* Software floating-point emulation.
+ Basic two-word fraction declaration and manipulation.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
+#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
+#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
+#define _FP_FRAC_HIGH_2(X) (X##_f1)
+#define _FP_FRAC_LOW_2(X) (X##_f0)
+#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
+
+#define _FP_FRAC_SLL_2(X,N) \
+(void)(((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ if (__builtin_constant_p(N) && (N) == 1) \
+ { \
+ X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
+ X##_f0 += X##_f0; \
+ } \
+ else \
+ { \
+ X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
+ X##_f0 <<= (N); \
+ } \
+ 0; \
+ }) \
+ : ({ \
+ X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
+ X##_f0 = 0; \
+ }))
+
+
+#define _FP_FRAC_SRL_2(X,N) \
+(void)(((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
+ X##_f1 = 0; \
+ }))
+
+/* Right shift with sticky-lsb. */
+#define _FP_FRAC_SRST_2(X,S, N,sz) \
+(void)(((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ S = (__builtin_constant_p(N) && (N) == 1 \
+ ? X##_f0 & 1 \
+ : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \
+ X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ S = ((((N) == _FP_W_TYPE_SIZE \
+ ? 0 \
+ : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
+ | X##_f0) != 0); \
+ X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \
+ X##_f1 = 0; \
+ }))
+
+#define _FP_FRAC_SRS_2(X,N,sz) \
+(void)(((N) < _FP_W_TYPE_SIZE) \
+ ? ({ \
+ X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
+ (__builtin_constant_p(N) && (N) == 1 \
+ ? X##_f0 & 1 \
+ : (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
+ X##_f1 >>= (N); \
+ }) \
+ : ({ \
+ X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
+ ((((N) == _FP_W_TYPE_SIZE \
+ ? 0 \
+ : (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
+ | X##_f0) != 0)); \
+ X##_f1 = 0; \
+ }))
+
+#define _FP_FRAC_ADDI_2(X,I) \
+ __FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
+
+#define _FP_FRAC_ADD_2(R,X,Y) \
+ __FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_SUB_2(R,X,Y) \
+ __FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_DEC_2(X,Y) \
+ __FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
+
+#define _FP_FRAC_CLZ_2(R,X) \
+ do { \
+ if (X##_f1) \
+ __FP_CLZ(R,X##_f1); \
+ else \
+ { \
+ __FP_CLZ(R,X##_f0); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } while(0)
+
+/* Predicates */
+#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
+#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
+#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
+#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
+#define _FP_FRAC_GT_2(X, Y) \
+ (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
+#define _FP_FRAC_GE_2(X, Y) \
+ (X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
+
+#define _FP_ZEROFRAC_2 0, 0
+#define _FP_MINFRAC_2 0, 1
+#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+
+/*
+ * Internals
+ */
+
+#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
+
+#define __FP_CLZ_2(R, xh, xl) \
+ do { \
+ if (xh) \
+ __FP_CLZ(R,xh); \
+ else \
+ { \
+ __FP_CLZ(R,xl); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ } while(0)
+
+#if 0
+
+#ifndef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i) \
+ (xh += ((xl += i) < i))
+#endif
+#ifndef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
+ (rh = xh + yh + ((rl = xl + yl) < xl))
+#endif
+#ifndef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
+ (rh = xh - yh - ((rl = xl - yl) > xl))
+#endif
+#ifndef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
+ do { \
+ UWtype _t = xl; \
+ xh -= yh + ((xl -= yl) > _t); \
+ } while (0)
+#endif
+
+#else
+
+#undef __FP_FRAC_ADDI_2
+#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
+#undef __FP_FRAC_ADD_2
+#define __FP_FRAC_ADD_2 add_ssaaaa
+#undef __FP_FRAC_SUB_2
+#define __FP_FRAC_SUB_2 sub_ddmmss
+#undef __FP_FRAC_DEC_2
+#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl)
+
+#endif
+
+/*
+ * Unpack the raw bits of a native fp value. Do not classify or
+ * normalize the data.
+ */
+
+#define _FP_UNPACK_RAW_2(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ \
+ X##_f0 = _flo.bits.frac0; \
+ X##_f1 = _flo.bits.frac1; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+#define _FP_UNPACK_RAW_2_P(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ X##_f0 = _flo->bits.frac0; \
+ X##_f1 = _flo->bits.frac1; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } while (0)
+
+
+/*
+ * Repack the raw bits of a native fp value.
+ */
+
+#define _FP_PACK_RAW_2(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ \
+ _flo.bits.frac0 = X##_f0; \
+ _flo.bits.frac1 = X##_f1; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ \
+ (val) = _flo.flt; \
+ } while (0)
+
+#define _FP_PACK_RAW_2_P(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ _flo->bits.frac0 = X##_f0; \
+ _flo->bits.frac1 = X##_f1; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+
+#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \
+ do { \
+ _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
+ \
+ doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
+ doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
+ doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
+ doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
+ \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \
+ _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \
+ _FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1)); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _FP_FRAC_WORD_4(_z,0); \
+ R##_f1 = _FP_FRAC_WORD_4(_z,1); \
+ } while (0)
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
+ Do only 3 multiplications instead of four. This one is for machines
+ where multiplication is much more expensive than subtraction. */
+
+#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \
+ do { \
+ _FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
+ _FP_W_TYPE _d; \
+ int _c1, _c2; \
+ \
+ _b_f0 = X##_f0 + X##_f1; \
+ _c1 = _b_f0 < X##_f0; \
+ _b_f1 = Y##_f0 + Y##_f1; \
+ _c2 = _b_f1 < Y##_f0; \
+ doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
+ doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \
+ doit(_c_f1, _c_f0, X##_f1, Y##_f1); \
+ \
+ _b_f0 &= -_c2; \
+ _b_f1 &= -_c1; \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \
+ 0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \
+ __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _b_f0); \
+ __FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _b_f1); \
+ __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1), \
+ 0, _d, _FP_FRAC_WORD_4(_z,0)); \
+ __FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
+ _FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \
+ __FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \
+ _c_f1, _c_f0, \
+ _FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _FP_FRAC_WORD_4(_z,0); \
+ R##_f1 = _FP_FRAC_WORD_4(_z,1); \
+ } while (0)
+
+#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \
+ do { \
+ _FP_FRAC_DECL_4(_z); \
+ _FP_W_TYPE _x[2], _y[2]; \
+ _x[0] = X##_f0; _x[1] = X##_f1; \
+ _y[0] = Y##_f0; _y[1] = Y##_f1; \
+ \
+ mpn_mul_n(_z_f, _x, _y, 2); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
+ R##_f0 = _z_f[0]; \
+ R##_f1 = _z_f[1]; \
+ } while (0)
+
+/* Do at most 120x120=240 bits multiplication using double floating
+ point multiplication. This is useful if floating point
+ multiplication has much bigger throughput than integer multiply.
+ It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
+ between 106 and 120 only.
+ Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
+ SETFETZ is a macro which will disable all FPU exceptions and set rounding
+ towards zero, RESETFE should optionally reset it back. */
+
+#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \
+ do { \
+ static const double _const[] = { \
+ /* 2^-24 */ 5.9604644775390625e-08, \
+ /* 2^-48 */ 3.5527136788005009e-15, \
+ /* 2^-72 */ 2.1175823681357508e-22, \
+ /* 2^-96 */ 1.2621774483536189e-29, \
+ /* 2^28 */ 2.68435456e+08, \
+ /* 2^4 */ 1.600000e+01, \
+ /* 2^-20 */ 9.5367431640625e-07, \
+ /* 2^-44 */ 5.6843418860808015e-14, \
+ /* 2^-68 */ 3.3881317890172014e-21, \
+ /* 2^-92 */ 2.0194839173657902e-28, \
+ /* 2^-116 */ 1.2037062152420224e-35}; \
+ double _a240, _b240, _c240, _d240, _e240, _f240, \
+ _g240, _h240, _i240, _j240, _k240; \
+ union { double d; UDItype i; } _l240, _m240, _n240, _o240, \
+ _p240, _q240, _r240, _s240; \
+ UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \
+ \
+ if (wfracbits < 106 || wfracbits > 120) \
+ abort(); \
+ \
+ setfetz; \
+ \
+ _e240 = (double)(long)(X##_f0 & 0xffffff); \
+ _j240 = (double)(long)(Y##_f0 & 0xffffff); \
+ _d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \
+ _i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \
+ _c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \
+ _h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \
+ _b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \
+ _g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \
+ _a240 = (double)(long)(X##_f1 >> 32); \
+ _f240 = (double)(long)(Y##_f1 >> 32); \
+ _e240 *= _const[3]; \
+ _j240 *= _const[3]; \
+ _d240 *= _const[2]; \
+ _i240 *= _const[2]; \
+ _c240 *= _const[1]; \
+ _h240 *= _const[1]; \
+ _b240 *= _const[0]; \
+ _g240 *= _const[0]; \
+ _s240.d = _e240*_j240;\
+ _r240.d = _d240*_j240 + _e240*_i240;\
+ _q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\
+ _p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
+ _o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
+ _n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \
+ _m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \
+ _l240.d = _a240*_g240 + _b240*_f240; \
+ _k240 = _a240*_f240; \
+ _r240.d += _s240.d; \
+ _q240.d += _r240.d; \
+ _p240.d += _q240.d; \
+ _o240.d += _p240.d; \
+ _n240.d += _o240.d; \
+ _m240.d += _n240.d; \
+ _l240.d += _m240.d; \
+ _k240 += _l240.d; \
+ _s240.d -= ((_const[10]+_s240.d)-_const[10]); \
+ _r240.d -= ((_const[9]+_r240.d)-_const[9]); \
+ _q240.d -= ((_const[8]+_q240.d)-_const[8]); \
+ _p240.d -= ((_const[7]+_p240.d)-_const[7]); \
+ _o240.d += _const[7]; \
+ _n240.d += _const[6]; \
+ _m240.d += _const[5]; \
+ _l240.d += _const[4]; \
+ if (_s240.d != 0.0) _y240 = 1; \
+ if (_r240.d != 0.0) _y240 = 1; \
+ if (_q240.d != 0.0) _y240 = 1; \
+ if (_p240.d != 0.0) _y240 = 1; \
+ _t240 = (DItype)_k240; \
+ _u240 = _l240.i; \
+ _v240 = _m240.i; \
+ _w240 = _n240.i; \
+ _x240 = _o240.i; \
+ R##_f1 = (_t240 << (128 - (wfracbits - 1))) \
+ | ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \
+ R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \
+ | ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \
+ | ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \
+ | ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \
+ | _y240; \
+ resetfe; \
+ } while (0)
+
+/*
+ * Division algorithms:
+ */
+
+#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
+ if (_FP_FRAC_GT_2(X, Y)) \
+ { \
+ _n_f2 = X##_f1 >> 1; \
+ _n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
+ _n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
+ } \
+ else \
+ { \
+ R##_e--; \
+ _n_f2 = X##_f1; \
+ _n_f1 = X##_f0; \
+ _n_f0 = 0; \
+ } \
+ \
+ /* Normalize, i.e. make the most significant bit of the \
+ denominator set. */ \
+ _FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \
+ \
+ udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
+ umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \
+ _r_f0 = _n_f0; \
+ if (_FP_FRAC_GT_2(_m, _r)) \
+ { \
+ R##_f1--; \
+ _FP_FRAC_ADD_2(_r, Y, _r); \
+ if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
+ { \
+ R##_f1--; \
+ _FP_FRAC_ADD_2(_r, Y, _r); \
+ } \
+ } \
+ _FP_FRAC_DEC_2(_r, _m); \
+ \
+ if (_r_f1 == Y##_f1) \
+ { \
+ /* This is a special case, not an optimization \
+ (_r/Y##_f1 would not fit into UWtype). \
+ As _r is guaranteed to be < Y, R##_f0 can be either \
+ (UWtype)-1 or (UWtype)-2. But as we know what kind \
+ of bits it is (sticky, guard, round), we don't care. \
+ We also don't care what the reminder is, because the \
+ guard bit will be set anyway. -jj */ \
+ R##_f0 = -1; \
+ } \
+ else \
+ { \
+ udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
+ umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \
+ _r_f0 = 0; \
+ if (_FP_FRAC_GT_2(_m, _r)) \
+ { \
+ R##_f0--; \
+ _FP_FRAC_ADD_2(_r, Y, _r); \
+ if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
+ { \
+ R##_f0--; \
+ _FP_FRAC_ADD_2(_r, Y, _r); \
+ } \
+ } \
+ if (!_FP_FRAC_EQ_2(_r, _m)) \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+
+#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
+ do { \
+ _FP_W_TYPE _x[4], _y[2], _z[4]; \
+ _y[0] = Y##_f0; _y[1] = Y##_f1; \
+ _x[0] = _x[3] = 0; \
+ if (_FP_FRAC_GT_2(X, Y)) \
+ { \
+ R##_e++; \
+ _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \
+ X##_f1 >> (_FP_W_TYPE_SIZE - \
+ (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \
+ _x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \
+ } \
+ else \
+ { \
+ _x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \
+ X##_f1 >> (_FP_W_TYPE_SIZE - \
+ (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \
+ _x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \
+ } \
+ \
+ (void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
+ R##_f1 = _z[1]; \
+ R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
+ } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+
+#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
+ do { \
+ while (q) \
+ { \
+ T##_f1 = S##_f1 + q; \
+ if (T##_f1 <= X##_f1) \
+ { \
+ S##_f1 = T##_f1 + q; \
+ X##_f1 -= T##_f1; \
+ R##_f1 += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f0 = S##_f0 + q; \
+ T##_f1 = S##_f1; \
+ if (T##_f1 < X##_f1 || \
+ (T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
+ { \
+ S##_f0 = T##_f0 + q; \
+ S##_f1 += (T##_f0 > S##_f0); \
+ _FP_FRAC_DEC_2(X, T); \
+ R##_f0 += q; \
+ } \
+ _FP_FRAC_SLL_2(X, 1); \
+ q >>= 1; \
+ } \
+ if (X##_f0 | X##_f1) \
+ { \
+ if (S##_f1 < X##_f1 || \
+ (S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
+ R##_f0 |= _FP_WORK_ROUND; \
+ R##_f0 |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+
+/*
+ * Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+
+#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
+(void)((rsize <= _FP_W_TYPE_SIZE) \
+ ? ({ r = X##_f0; }) \
+ : ({ \
+ r = X##_f1; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f0; \
+ }))
+
+#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
+ do { \
+ X##_f0 = r; \
+ X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ } while (0)
+
+/*
+ * Convert FP values between word sizes
+ */
+
+#define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0)
+
+#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0))
diff --git a/contrib/gcc/config/soft-fp/op-4.h b/contrib/gcc/config/soft-fp/op-4.h
new file mode 100644
index 0000000..1b90535
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/op-4.h
@@ -0,0 +1,686 @@
+/* Software floating-point emulation.
+ Basic four-word fraction declaration and manipulation.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
+#define _FP_FRAC_COPY_4(D,S) \
+ (D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
+ D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
+#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
+#define _FP_FRAC_HIGH_4(X) (X##_f[3])
+#define _FP_FRAC_LOW_4(X) (X##_f[0])
+#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
+
+#define _FP_FRAC_SLL_4(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _up = (N) % _FP_W_TYPE_SIZE; \
+ _down = _FP_W_TYPE_SIZE - _up; \
+ if (!_up) \
+ for (_i = 3; _i >= _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip]; \
+ else \
+ { \
+ for (_i = 3; _i > _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip] << _up \
+ | X##_f[_i-_skip-1] >> _down; \
+ X##_f[_i--] = X##_f[0] << _up; \
+ } \
+ for (; _i >= 0; --_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+/* This one was broken too */
+#define _FP_FRAC_SRL_4(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ if (!_down) \
+ for (_i = 0; _i <= 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i++] = X##_f[3] >> _down; \
+ } \
+ for (; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+
+/* Right shift with sticky-lsb.
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRST_4(X,S,N,size) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _FP_W_TYPE _s; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_s = _i = 0; _i < _skip; ++_i) \
+ _s |= X##_f[_i]; \
+ if (!_down) \
+ for (_i = 0; _i <= 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ _s |= X##_f[_i] << _up; \
+ for (_i = 0; _i < 3-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i++] = X##_f[3] >> _down; \
+ } \
+ for (; _i < 4; ++_i) \
+ X##_f[_i] = 0; \
+ S = (_s != 0); \
+ } while (0)
+
+#define _FP_FRAC_SRS_4(X,N,size) \
+ do { \
+ int _sticky; \
+ _FP_FRAC_SRST_4(X, _sticky, N, size); \
+ X##_f[0] |= _sticky; \
+ } while (0)
+
+#define _FP_FRAC_ADD_4(R,X,Y) \
+ __FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_SUB_4(R,X,Y) \
+ __FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
+ X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_DEC_4(X,Y) \
+ __FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
+
+#define _FP_FRAC_ADDI_4(X,I) \
+ __FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
+
+#define _FP_ZEROFRAC_4 0,0,0,0
+#define _FP_MINFRAC_4 0,0,0,1
+#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
+
+#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
+#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
+#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
+#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
+
+#define _FP_FRAC_EQ_4(X,Y) \
+ (X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
+ && X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
+
+#define _FP_FRAC_GT_4(X,Y) \
+ (X##_f[3] > Y##_f[3] || \
+ (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
+ (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
+ (X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
+ )) \
+ )) \
+ )
+
+#define _FP_FRAC_GE_4(X,Y) \
+ (X##_f[3] > Y##_f[3] || \
+ (X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
+ (X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
+ (X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
+ )) \
+ )) \
+ )
+
+
+#define _FP_FRAC_CLZ_4(R,X) \
+ do { \
+ if (X##_f[3]) \
+ { \
+ __FP_CLZ(R,X##_f[3]); \
+ } \
+ else if (X##_f[2]) \
+ { \
+ __FP_CLZ(R,X##_f[2]); \
+ R += _FP_W_TYPE_SIZE; \
+ } \
+ else if (X##_f[1]) \
+ { \
+ __FP_CLZ(R,X##_f[1]); \
+ R += _FP_W_TYPE_SIZE*2; \
+ } \
+ else \
+ { \
+ __FP_CLZ(R,X##_f[0]); \
+ R += _FP_W_TYPE_SIZE*3; \
+ } \
+ } while(0)
+
+
+#define _FP_UNPACK_RAW_4(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs _flo; _flo.flt = (val); \
+ X##_f[0] = _flo.bits.frac0; \
+ X##_f[1] = _flo.bits.frac1; \
+ X##_f[2] = _flo.bits.frac2; \
+ X##_f[3] = _flo.bits.frac3; \
+ X##_e = _flo.bits.exp; \
+ X##_s = _flo.bits.sign; \
+ } while (0)
+
+#define _FP_UNPACK_RAW_4_P(fs, X, val) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ X##_f[0] = _flo->bits.frac0; \
+ X##_f[1] = _flo->bits.frac1; \
+ X##_f[2] = _flo->bits.frac2; \
+ X##_f[3] = _flo->bits.frac3; \
+ X##_e = _flo->bits.exp; \
+ X##_s = _flo->bits.sign; \
+ } while (0)
+
+#define _FP_PACK_RAW_4(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs _flo; \
+ _flo.bits.frac0 = X##_f[0]; \
+ _flo.bits.frac1 = X##_f[1]; \
+ _flo.bits.frac2 = X##_f[2]; \
+ _flo.bits.frac3 = X##_f[3]; \
+ _flo.bits.exp = X##_e; \
+ _flo.bits.sign = X##_s; \
+ (val) = _flo.flt; \
+ } while (0)
+
+#define _FP_PACK_RAW_4_P(fs, val, X) \
+ do { \
+ union _FP_UNION_##fs *_flo = \
+ (union _FP_UNION_##fs *)(val); \
+ \
+ _flo->bits.frac0 = X##_f[0]; \
+ _flo->bits.frac1 = X##_f[1]; \
+ _flo->bits.frac2 = X##_f[2]; \
+ _flo->bits.frac3 = X##_f[3]; \
+ _flo->bits.exp = X##_e; \
+ _flo->bits.sign = X##_s; \
+ } while (0)
+
+/*
+ * Multiplication algorithms:
+ */
+
+/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
+
+#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \
+ do { \
+ _FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
+ _FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \
+ \
+ doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
+ doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
+ doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
+ doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
+ doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
+ doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
+ _FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \
+ 0,0,_FP_FRAC_WORD_8(_z,1)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
+ _FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \
+ _FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
+ _FP_FRAC_WORD_8(_z,1)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
+ _FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \
+ 0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
+ _FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \
+ _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
+ _FP_FRAC_WORD_8(_z,2)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
+ _FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \
+ _FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
+ _FP_FRAC_WORD_8(_z,2)); \
+ doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
+ doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
+ doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
+ doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \
+ 0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \
+ _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \
+ _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \
+ _FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
+ _FP_FRAC_WORD_8(_z,3)); \
+ doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
+ doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
+ doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
+ doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
+ doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
+ _FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \
+ 0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
+ _FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \
+ _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
+ _FP_FRAC_WORD_8(_z,4)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
+ _FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \
+ _FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
+ _FP_FRAC_WORD_8(_z,4)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
+ _FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \
+ 0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \
+ __FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
+ _FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \
+ _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
+ _FP_FRAC_WORD_8(_z,5)); \
+ doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
+ __FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
+ _b_f1,_b_f0, \
+ _FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
+ __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
+ _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
+ } while (0)
+
+#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \
+ do { \
+ _FP_FRAC_DECL_8(_z); \
+ \
+ mpn_mul_n(_z_f, _x_f, _y_f, 4); \
+ \
+ /* Normalize since we know where the msb of the multiplicands \
+ were (bit B), we know that the msb of the of the product is \
+ at either 2B or 2B-1. */ \
+ _FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
+ __FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
+ _FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
+ } while (0)
+
+/*
+ * Helper utility for _FP_DIV_MEAT_4_udiv:
+ * pppp = m * nnn
+ */
+#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \
+ do { \
+ UWtype _t; \
+ umul_ppmm(p1,p0,m,n0); \
+ umul_ppmm(p2,_t,m,n1); \
+ __FP_FRAC_ADDI_2(p2,p1,_t); \
+ umul_ppmm(p3,_t,m,n2); \
+ __FP_FRAC_ADDI_2(p3,p2,_t); \
+ } while (0)
+
+/*
+ * Division algorithms:
+ */
+
+#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
+ do { \
+ int _i; \
+ _FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \
+ _FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \
+ if (_FP_FRAC_GT_4(X, Y)) \
+ { \
+ _n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
+ _FP_FRAC_SRL_4(X, 1); \
+ } \
+ else \
+ R##_e--; \
+ \
+ /* Normalize, i.e. make the most significant bit of the \
+ denominator set. */ \
+ _FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \
+ \
+ for (_i = 3; ; _i--) \
+ { \
+ if (X##_f[3] == Y##_f[3]) \
+ { \
+ /* This is a special case, not an optimization \
+ (X##_f[3]/Y##_f[3] would not fit into UWtype). \
+ As X## is guaranteed to be < Y, R##_f[_i] can be either \
+ (UWtype)-1 or (UWtype)-2. */ \
+ R##_f[_i] = -1; \
+ if (!_i) \
+ break; \
+ __FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
+ Y##_f[2], Y##_f[1], Y##_f[0], 0, \
+ X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
+ _FP_FRAC_SUB_4(X, Y, X); \
+ if (X##_f[3] > Y##_f[3]) \
+ { \
+ R##_f[_i] = -2; \
+ _FP_FRAC_ADD_4(X, Y, X); \
+ } \
+ } \
+ else \
+ { \
+ udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
+ umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
+ R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
+ X##_f[2] = X##_f[1]; \
+ X##_f[1] = X##_f[0]; \
+ X##_f[0] = _n_f[_i]; \
+ if (_FP_FRAC_GT_4(_m, X)) \
+ { \
+ R##_f[_i]--; \
+ _FP_FRAC_ADD_4(X, Y, X); \
+ if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \
+ { \
+ R##_f[_i]--; \
+ _FP_FRAC_ADD_4(X, Y, X); \
+ } \
+ } \
+ _FP_FRAC_DEC_4(X, _m); \
+ if (!_i) \
+ { \
+ if (!_FP_FRAC_EQ_4(X, _m)) \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ break; \
+ } \
+ } \
+ } \
+ } while (0)
+
+
+/*
+ * Square root algorithms:
+ * We have just one right now, maybe Newton approximation
+ * should be added for those machines where division is fast.
+ */
+
+#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
+ do { \
+ while (q) \
+ { \
+ T##_f[3] = S##_f[3] + q; \
+ if (T##_f[3] <= X##_f[3]) \
+ { \
+ S##_f[3] = T##_f[3] + q; \
+ X##_f[3] -= T##_f[3]; \
+ R##_f[3] += q; \
+ } \
+ _FP_FRAC_SLL_4(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[2] = S##_f[2] + q; \
+ T##_f[3] = S##_f[3]; \
+ if (T##_f[3] < X##_f[3] || \
+ (T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
+ { \
+ S##_f[2] = T##_f[2] + q; \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ __FP_FRAC_DEC_2(X##_f[3], X##_f[2], \
+ T##_f[3], T##_f[2]); \
+ R##_f[2] += q; \
+ } \
+ _FP_FRAC_SLL_4(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q) \
+ { \
+ T##_f[1] = S##_f[1] + q; \
+ T##_f[2] = S##_f[2]; \
+ T##_f[3] = S##_f[3]; \
+ if (T##_f[3] < X##_f[3] || \
+ (T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \
+ (T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \
+ { \
+ S##_f[1] = T##_f[1] + q; \
+ S##_f[2] += (T##_f[1] > S##_f[1]); \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ __FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \
+ T##_f[3], T##_f[2], T##_f[1]); \
+ R##_f[1] += q; \
+ } \
+ _FP_FRAC_SLL_4(X, 1); \
+ q >>= 1; \
+ } \
+ q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
+ while (q != _FP_WORK_ROUND) \
+ { \
+ T##_f[0] = S##_f[0] + q; \
+ T##_f[1] = S##_f[1]; \
+ T##_f[2] = S##_f[2]; \
+ T##_f[3] = S##_f[3]; \
+ if (_FP_FRAC_GE_4(X,T)) \
+ { \
+ S##_f[0] = T##_f[0] + q; \
+ S##_f[1] += (T##_f[0] > S##_f[0]); \
+ S##_f[2] += (T##_f[1] > S##_f[1]); \
+ S##_f[3] += (T##_f[2] > S##_f[2]); \
+ _FP_FRAC_DEC_4(X, T); \
+ R##_f[0] += q; \
+ } \
+ _FP_FRAC_SLL_4(X, 1); \
+ q >>= 1; \
+ } \
+ if (!_FP_FRAC_ZEROP_4(X)) \
+ { \
+ if (_FP_FRAC_GT_4(X,S)) \
+ R##_f[0] |= _FP_WORK_ROUND; \
+ R##_f[0] |= _FP_WORK_STICKY; \
+ } \
+ } while (0)
+
+
+/*
+ * Internals
+ */
+
+#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
+ (X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
+
+#ifndef __FP_FRAC_ADD_3
+#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
+ do { \
+ _FP_W_TYPE _c1, _c2; \
+ r0 = x0 + y0; \
+ _c1 = r0 < x0; \
+ r1 = x1 + y1; \
+ _c2 = r1 < x1; \
+ r1 += _c1; \
+ _c2 |= r1 < _c1; \
+ r2 = x2 + y2 + _c2; \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_ADD_4
+#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ do { \
+ _FP_W_TYPE _c1, _c2, _c3; \
+ r0 = x0 + y0; \
+ _c1 = r0 < x0; \
+ r1 = x1 + y1; \
+ _c2 = r1 < x1; \
+ r1 += _c1; \
+ _c2 |= r1 < _c1; \
+ r2 = x2 + y2; \
+ _c3 = r2 < x2; \
+ r2 += _c2; \
+ _c3 |= r2 < _c2; \
+ r3 = x3 + y3 + _c3; \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_SUB_3
+#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
+ do { \
+ _FP_W_TYPE _c1, _c2; \
+ r0 = x0 - y0; \
+ _c1 = r0 > x0; \
+ r1 = x1 - y1; \
+ _c2 = r1 > x1; \
+ r1 -= _c1; \
+ _c2 |= _c1 && (y1 == x1); \
+ r2 = x2 - y2 - _c2; \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_SUB_4
+#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
+ do { \
+ _FP_W_TYPE _c1, _c2, _c3; \
+ r0 = x0 - y0; \
+ _c1 = r0 > x0; \
+ r1 = x1 - y1; \
+ _c2 = r1 > x1; \
+ r1 -= _c1; \
+ _c2 |= _c1 && (y1 == x1); \
+ r2 = x2 - y2; \
+ _c3 = r2 > x2; \
+ r2 -= _c2; \
+ _c3 |= _c2 && (y2 == x2); \
+ r3 = x3 - y3 - _c3; \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_DEC_3
+#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \
+ do { \
+ UWtype _t0, _t1, _t2; \
+ _t0 = x0, _t1 = x1, _t2 = x2; \
+ __FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_DEC_4
+#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \
+ do { \
+ UWtype _t0, _t1, _t2, _t3; \
+ _t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \
+ __FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \
+ } while (0)
+#endif
+
+#ifndef __FP_FRAC_ADDI_4
+#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
+ do { \
+ UWtype _t; \
+ _t = ((x0 += i) < i); \
+ x1 += _t; _t = (x1 < _t); \
+ x2 += _t; _t = (x2 < _t); \
+ x3 += _t; \
+ } while (0)
+#endif
+
+/* Convert FP values between word sizes. This appears to be more
+ * complicated than I'd have expected it to be, so these might be
+ * wrong... These macros are in any case somewhat bogus because they
+ * use information about what various FRAC_n variables look like
+ * internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
+ * the ones in op-2.h and op-1.h.
+ */
+#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0])
+
+#define _FP_FRAC_COPY_2_4(D, S) \
+do { \
+ D##_f0 = S##_f[0]; \
+ D##_f1 = S##_f[1]; \
+} while (0)
+
+/* Assembly/disassembly for converting to/from integral types.
+ * No shifting or overflow handled here.
+ */
+/* Put the FP value X into r, which is an integer of size rsize. */
+#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
+ do { \
+ if (rsize <= _FP_W_TYPE_SIZE) \
+ r = X##_f[0]; \
+ else if (rsize <= 2*_FP_W_TYPE_SIZE) \
+ { \
+ r = X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
+ else \
+ { \
+ /* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
+ /* and int == 4words as a single case. */ \
+ r = X##_f[3]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[2]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[1]; \
+ r <<= _FP_W_TYPE_SIZE; \
+ r += X##_f[0]; \
+ } \
+ } while (0)
+
+/* "No disassemble Number Five!" */
+/* move an integer of size rsize into X's fractional part. We rely on
+ * the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
+ * having to mask the values we store into it.
+ */
+#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
+ do { \
+ X##_f[0] = r; \
+ X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
+ X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
+ X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
+ } while (0);
+
+#define _FP_FRAC_COPY_4_1(D, S) \
+do { \
+ D##_f[0] = S##_f; \
+ D##_f[1] = D##_f[2] = D##_f[3] = 0; \
+} while (0)
+
+#define _FP_FRAC_COPY_4_2(D, S) \
+do { \
+ D##_f[0] = S##_f0; \
+ D##_f[1] = S##_f1; \
+ D##_f[2] = D##_f[3] = 0; \
+} while (0)
diff --git a/contrib/gcc/config/soft-fp/op-8.h b/contrib/gcc/config/soft-fp/op-8.h
new file mode 100644
index 0000000..e0612a5
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/op-8.h
@@ -0,0 +1,111 @@
+/* Software floating-point emulation.
+ Basic eight-word fraction declaration and manipulation.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+/* We need just a few things from here for op-4, if we ever need some
+ other macros, they can be added. */
+#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
+#define _FP_FRAC_HIGH_8(X) (X##_f[7])
+#define _FP_FRAC_LOW_8(X) (X##_f[0])
+#define _FP_FRAC_WORD_8(X,w) (X##_f[w])
+
+#define _FP_FRAC_SLL_8(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _up = (N) % _FP_W_TYPE_SIZE; \
+ _down = _FP_W_TYPE_SIZE - _up; \
+ if (!_up) \
+ for (_i = 7; _i >= _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip]; \
+ else \
+ { \
+ for (_i = 7; _i > _skip; --_i) \
+ X##_f[_i] = X##_f[_i-_skip] << _up \
+ | X##_f[_i-_skip-1] >> _down; \
+ X##_f[_i--] = X##_f[0] << _up; \
+ } \
+ for (; _i >= 0; --_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+#define _FP_FRAC_SRL_8(X,N) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ if (!_down) \
+ for (_i = 0; _i <= 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ for (_i = 0; _i < 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i++] = X##_f[7] >> _down; \
+ } \
+ for (; _i < 8; ++_i) \
+ X##_f[_i] = 0; \
+ } while (0)
+
+
+/* Right shift with sticky-lsb.
+ * What this actually means is that we do a standard right-shift,
+ * but that if any of the bits that fall off the right hand side
+ * were one then we always set the LSbit.
+ */
+#define _FP_FRAC_SRS_8(X,N,size) \
+ do { \
+ _FP_I_TYPE _up, _down, _skip, _i; \
+ _FP_W_TYPE _s; \
+ _skip = (N) / _FP_W_TYPE_SIZE; \
+ _down = (N) % _FP_W_TYPE_SIZE; \
+ _up = _FP_W_TYPE_SIZE - _down; \
+ for (_s = _i = 0; _i < _skip; ++_i) \
+ _s |= X##_f[_i]; \
+ if (!_down) \
+ for (_i = 0; _i <= 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip]; \
+ else \
+ { \
+ _s |= X##_f[_i] << _up; \
+ for (_i = 0; _i < 7-_skip; ++_i) \
+ X##_f[_i] = X##_f[_i+_skip] >> _down \
+ | X##_f[_i+_skip+1] << _up; \
+ X##_f[_i++] = X##_f[7] >> _down; \
+ } \
+ for (; _i < 8; ++_i) \
+ X##_f[_i] = 0; \
+ /* don't fix the LSB until the very end when we're sure f[0] is stable */ \
+ X##_f[0] |= (_s != 0); \
+ } while (0)
+
diff --git a/contrib/gcc/config/soft-fp/op-common.h b/contrib/gcc/config/soft-fp/op-common.h
new file mode 100644
index 0000000..0aa6e3e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/op-common.h
@@ -0,0 +1,1333 @@
+/* Software floating-point emulation. Common operations.
+ Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#define _FP_DECL(wc, X) \
+ _FP_I_TYPE X##_c __attribute__((unused)), X##_s, X##_e; \
+ _FP_FRAC_DECL_##wc(X)
+
+/*
+ * Finish truely unpacking a native fp value by classifying the kind
+ * of fp value and normalizing both the exponent and the fraction.
+ */
+
+#define _FP_UNPACK_CANONICAL(fs, wc, X) \
+do { \
+ switch (X##_e) \
+ { \
+ default: \
+ _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
+ _FP_FRAC_SLL_##wc(X, _FP_WORKBITS); \
+ X##_e -= _FP_EXPBIAS_##fs; \
+ X##_c = FP_CLS_NORMAL; \
+ break; \
+ \
+ case 0: \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ X##_c = FP_CLS_ZERO; \
+ else \
+ { \
+ /* a denormalized number */ \
+ _FP_I_TYPE _shift; \
+ _FP_FRAC_CLZ_##wc(_shift, X); \
+ _shift -= _FP_FRACXBITS_##fs; \
+ _FP_FRAC_SLL_##wc(X, (_shift+_FP_WORKBITS)); \
+ X##_e -= _FP_EXPBIAS_##fs - 1 + _shift; \
+ X##_c = FP_CLS_NORMAL; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ break; \
+ \
+ case _FP_EXPMAX_##fs: \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ X##_c = FP_CLS_INF; \
+ else \
+ { \
+ X##_c = FP_CLS_NAN; \
+ /* Check for signaling NaN */ \
+ if (!(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ } \
+ break; \
+ } \
+} while (0)
+
+/* Finish unpacking an fp value in semi-raw mode: the mantissa is
+ shifted by _FP_WORKBITS but the implicit MSB is not inserted and
+ other classification is not done. */
+#define _FP_UNPACK_SEMIRAW(fs, wc, X) _FP_FRAC_SLL_##wc(X, _FP_WORKBITS)
+
+/* A semi-raw value has overflowed to infinity. Adjust the mantissa
+ and exponent appropriately. */
+#define _FP_OVERFLOW_SEMIRAW(fs, wc, X) \
+do { \
+ if (FP_ROUNDMODE == FP_RND_NEAREST \
+ || (FP_ROUNDMODE == FP_RND_PINF && !X##_s) \
+ || (FP_ROUNDMODE == FP_RND_MINF && X##_s)) \
+ { \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ X##_e = _FP_EXPMAX_##fs - 1; \
+ _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
+ } \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
+} while (0)
+
+/* Check for a semi-raw value being a signaling NaN and raise the
+ invalid exception if so. */
+#define _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X) \
+do { \
+ if (X##_e == _FP_EXPMAX_##fs \
+ && !_FP_FRAC_ZEROP_##wc(X) \
+ && !(_FP_FRAC_HIGH_##fs(X) & _FP_QNANBIT_SH_##fs)) \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+} while (0)
+
+/* Choose a NaN result from an operation on two semi-raw NaN
+ values. */
+#define _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP) \
+do { \
+ /* _FP_CHOOSENAN expects raw values, so shift as required. */ \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
+ _FP_FRAC_SRL_##wc(Y, _FP_WORKBITS); \
+ _FP_CHOOSENAN(fs, wc, R, X, Y, OP); \
+ _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \
+} while (0)
+
+/* Test whether a biased exponent is normal (not zero or maximum). */
+#define _FP_EXP_NORMAL(fs, wc, X) (((X##_e + 1) & _FP_EXPMAX_##fs) > 1)
+
+/* Prepare to pack an fp value in semi-raw mode: the mantissa is
+ rounded and shifted right, with the rounding possibly increasing
+ the exponent (including changing a finite value to infinity). */
+#define _FP_PACK_SEMIRAW(fs, wc, X) \
+do { \
+ _FP_ROUND(wc, X); \
+ if (_FP_FRAC_HIGH_##fs(X) \
+ & (_FP_OVERFLOW_##fs >> 1)) \
+ { \
+ _FP_FRAC_HIGH_##fs(X) &= ~(_FP_OVERFLOW_##fs >> 1); \
+ X##_e++; \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ _FP_OVERFLOW_SEMIRAW(fs, wc, X); \
+ } \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
+ if (!_FP_EXP_NORMAL(fs, wc, X) && !_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ if (X##_e == 0) \
+ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
+ else \
+ { \
+ if (!_FP_KEEPNANFRACP) \
+ { \
+ _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
+ X##_s = _FP_NANSIGN_##fs; \
+ } \
+ else \
+ _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
+ } \
+ } \
+} while (0)
+
+/*
+ * Before packing the bits back into the native fp result, take care
+ * of such mundane things as rounding and overflow. Also, for some
+ * kinds of fp values, the original parts may not have been fully
+ * extracted -- but that is ok, we can regenerate them now.
+ */
+
+#define _FP_PACK_CANONICAL(fs, wc, X) \
+do { \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NORMAL: \
+ X##_e += _FP_EXPBIAS_##fs; \
+ if (X##_e > 0) \
+ { \
+ _FP_ROUND(wc, X); \
+ if (_FP_FRAC_OVERP_##wc(fs, X)) \
+ { \
+ _FP_FRAC_CLEAR_OVERP_##wc(fs, X); \
+ X##_e++; \
+ } \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
+ if (X##_e >= _FP_EXPMAX_##fs) \
+ { \
+ /* overflow */ \
+ switch (FP_ROUNDMODE) \
+ { \
+ case FP_RND_NEAREST: \
+ X##_c = FP_CLS_INF; \
+ break; \
+ case FP_RND_PINF: \
+ if (!X##_s) X##_c = FP_CLS_INF; \
+ break; \
+ case FP_RND_MINF: \
+ if (X##_s) X##_c = FP_CLS_INF; \
+ break; \
+ } \
+ if (X##_c == FP_CLS_INF) \
+ { \
+ /* Overflow to infinity */ \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ /* Overflow to maximum normal */ \
+ X##_e = _FP_EXPMAX_##fs - 1; \
+ _FP_FRAC_SET_##wc(X, _FP_MAXFRAC_##wc); \
+ } \
+ FP_SET_EXCEPTION(FP_EX_OVERFLOW); \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ } \
+ } \
+ else \
+ { \
+ /* we've got a denormalized number */ \
+ X##_e = -X##_e + 1; \
+ if (X##_e <= _FP_WFRACBITS_##fs) \
+ { \
+ _FP_FRAC_SRS_##wc(X, X##_e, _FP_WFRACBITS_##fs); \
+ _FP_ROUND(wc, X); \
+ if (_FP_FRAC_HIGH_##fs(X) \
+ & (_FP_OVERFLOW_##fs >> 1)) \
+ { \
+ X##_e = 1; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ } \
+ else \
+ { \
+ X##_e = 0; \
+ _FP_FRAC_SRL_##wc(X, _FP_WORKBITS); \
+ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
+ } \
+ } \
+ else \
+ { \
+ /* underflow to zero */ \
+ X##_e = 0; \
+ if (!_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
+ _FP_ROUND(wc, X); \
+ _FP_FRAC_LOW_##wc(X) >>= (_FP_WORKBITS); \
+ } \
+ FP_SET_EXCEPTION(FP_EX_UNDERFLOW); \
+ } \
+ } \
+ break; \
+ \
+ case FP_CLS_ZERO: \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_INF: \
+ X##_e = _FP_EXPMAX_##fs; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ break; \
+ \
+ case FP_CLS_NAN: \
+ X##_e = _FP_EXPMAX_##fs; \
+ if (!_FP_KEEPNANFRACP) \
+ { \
+ _FP_FRAC_SET_##wc(X, _FP_NANFRAC_##fs); \
+ X##_s = _FP_NANSIGN_##fs; \
+ } \
+ else \
+ _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_QNANBIT_##fs; \
+ break; \
+ } \
+} while (0)
+
+/* This one accepts raw argument and not cooked, returns
+ * 1 if X is a signaling NaN.
+ */
+#define _FP_ISSIGNAN(fs, wc, X) \
+({ \
+ int __ret = 0; \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ if (!_FP_FRAC_ZEROP_##wc(X) \
+ && !(_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs)) \
+ __ret = 1; \
+ } \
+ __ret; \
+})
+
+
+
+
+
+/* Addition on semi-raw values. */
+#define _FP_ADD_INTERNAL(fs, wc, R, X, Y, OP) \
+do { \
+ if (X##_s == Y##_s) \
+ { \
+ /* Addition. */ \
+ R##_s = X##_s; \
+ int ediff = X##_e - Y##_e; \
+ if (ediff > 0) \
+ { \
+ R##_e = X##_e; \
+ if (Y##_e == 0) \
+ { \
+ /* Y is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_ADD_##wc(R, X, Y); \
+ goto add3; \
+ } \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto add_done; \
+ } \
+ goto add1; \
+ } \
+ } \
+ else if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* X is NaN or Inf, Y is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto add_done; \
+ } \
+ \
+ /* Insert implicit MSB of Y. */ \
+ _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ add1: \
+ /* Shift the mantissa of Y to the right EDIFF steps; \
+ remember to account later for the implicit MSB of X. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(Y)) \
+ _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
+ _FP_FRAC_ADD_##wc(R, X, Y); \
+ } \
+ else if (ediff < 0) \
+ { \
+ ediff = -ediff; \
+ R##_e = Y##_e; \
+ if (X##_e == 0) \
+ { \
+ /* X is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_ADD_##wc(R, Y, X); \
+ goto add3; \
+ } \
+ if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto add_done; \
+ } \
+ goto add2; \
+ } \
+ } \
+ else if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* Y is NaN or Inf, X is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto add_done; \
+ } \
+ \
+ /* Insert implicit MSB of X. */ \
+ _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ add2: \
+ /* Shift the mantissa of X to the right EDIFF steps; \
+ remember to account later for the implicit MSB of Y. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(X)) \
+ _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
+ _FP_FRAC_ADD_##wc(R, Y, X); \
+ } \
+ else \
+ { \
+ /* ediff == 0. */ \
+ if (!_FP_EXP_NORMAL(fs, wc, X)) \
+ { \
+ if (X##_e == 0) \
+ { \
+ /* X and Y are zero or denormalized. */ \
+ R##_e = 0; \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ if (!_FP_FRAC_ZEROP_##wc(Y)) \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto add_done; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto add_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_ADD_##wc(R, X, Y); \
+ if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* Normalized result. */ \
+ _FP_FRAC_HIGH_##fs(R) \
+ &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
+ R##_e = 1; \
+ } \
+ goto add_done; \
+ } \
+ } \
+ else \
+ { \
+ /* X and Y are NaN or Inf. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ R##_e = _FP_EXPMAX_##fs; \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ else if (_FP_FRAC_ZEROP_##wc(Y)) \
+ _FP_FRAC_COPY_##wc(R, X); \
+ else \
+ _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \
+ goto add_done; \
+ } \
+ } \
+ /* The exponents of X and Y, both normal, are equal. The \
+ implicit MSBs will always add to increase the \
+ exponent. */ \
+ _FP_FRAC_ADD_##wc(R, X, Y); \
+ R##_e = X##_e + 1; \
+ _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
+ if (R##_e == _FP_EXPMAX_##fs) \
+ /* Overflow to infinity (depending on rounding mode). */ \
+ _FP_OVERFLOW_SEMIRAW(fs, wc, R); \
+ goto add_done; \
+ } \
+ add3: \
+ if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* Overflow. */ \
+ _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
+ R##_e++; \
+ _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
+ if (R##_e == _FP_EXPMAX_##fs) \
+ /* Overflow to infinity (depending on rounding mode). */ \
+ _FP_OVERFLOW_SEMIRAW(fs, wc, R); \
+ } \
+ add_done: ; \
+ } \
+ else \
+ { \
+ /* Subtraction. */ \
+ int ediff = X##_e - Y##_e; \
+ if (ediff > 0) \
+ { \
+ R##_e = X##_e; \
+ R##_s = X##_s; \
+ if (Y##_e == 0) \
+ { \
+ /* Y is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_SUB_##wc(R, X, Y); \
+ goto sub3; \
+ } \
+ if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto sub_done; \
+ } \
+ goto sub1; \
+ } \
+ } \
+ else if (X##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* X is NaN or Inf, Y is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ goto sub_done; \
+ } \
+ \
+ /* Insert implicit MSB of Y. */ \
+ _FP_FRAC_HIGH_##fs(Y) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ sub1: \
+ /* Shift the mantissa of Y to the right EDIFF steps; \
+ remember to account later for the implicit MSB of X. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(Y, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(Y)) \
+ _FP_FRAC_SET_##wc(Y, _FP_MINFRAC_##wc); \
+ _FP_FRAC_SUB_##wc(R, X, Y); \
+ } \
+ else if (ediff < 0) \
+ { \
+ ediff = -ediff; \
+ R##_e = Y##_e; \
+ R##_s = Y##_s; \
+ if (X##_e == 0) \
+ { \
+ /* X is zero or denormalized. */ \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ ediff--; \
+ if (ediff == 0) \
+ { \
+ _FP_FRAC_SUB_##wc(R, Y, X); \
+ goto sub3; \
+ } \
+ if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto sub_done; \
+ } \
+ goto sub2; \
+ } \
+ } \
+ else if (Y##_e == _FP_EXPMAX_##fs) \
+ { \
+ /* Y is NaN or Inf, X is normal. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ goto sub_done; \
+ } \
+ \
+ /* Insert implicit MSB of X. */ \
+ _FP_FRAC_HIGH_##fs(X) |= _FP_IMPLBIT_SH_##fs; \
+ \
+ sub2: \
+ /* Shift the mantissa of X to the right EDIFF steps; \
+ remember to account later for the implicit MSB of Y. */ \
+ if (ediff <= _FP_WFRACBITS_##fs) \
+ _FP_FRAC_SRS_##wc(X, ediff, _FP_WFRACBITS_##fs); \
+ else if (!_FP_FRAC_ZEROP_##wc(X)) \
+ _FP_FRAC_SET_##wc(X, _FP_MINFRAC_##wc); \
+ _FP_FRAC_SUB_##wc(R, Y, X); \
+ } \
+ else \
+ { \
+ /* ediff == 0. */ \
+ if (!_FP_EXP_NORMAL(fs, wc, X)) \
+ { \
+ if (X##_e == 0) \
+ { \
+ /* X and Y are zero or denormalized. */ \
+ R##_e = 0; \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ if (_FP_FRAC_ZEROP_##wc(Y)) \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ R##_s = Y##_s; \
+ } \
+ goto sub_done; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_s = X##_s; \
+ goto sub_done; \
+ } \
+ else \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_SUB_##wc(R, X, Y); \
+ R##_s = X##_s; \
+ if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* |X| < |Y|, negate result. */ \
+ _FP_FRAC_SUB_##wc(R, Y, X); \
+ R##_s = Y##_s; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc(R)) \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ goto sub_done; \
+ } \
+ } \
+ else \
+ { \
+ /* X and Y are NaN or Inf, of opposite signs. */ \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, X); \
+ _FP_CHECK_SIGNAN_SEMIRAW(fs, wc, Y); \
+ R##_e = _FP_EXPMAX_##fs; \
+ if (_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ /* Inf - Inf. */ \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ _FP_FRAC_SLL_##wc(R, _FP_WORKBITS); \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ } \
+ else \
+ { \
+ /* Inf - NaN. */ \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ } \
+ } \
+ else \
+ { \
+ if (_FP_FRAC_ZEROP_##wc(Y)) \
+ { \
+ /* NaN - Inf. */ \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R, X); \
+ } \
+ else \
+ { \
+ /* NaN - NaN. */ \
+ _FP_CHOOSENAN_SEMIRAW(fs, wc, R, X, Y, OP); \
+ } \
+ } \
+ goto sub_done; \
+ } \
+ } \
+ /* The exponents of X and Y, both normal, are equal. The \
+ implicit MSBs cancel. */ \
+ R##_e = X##_e; \
+ _FP_FRAC_SUB_##wc(R, X, Y); \
+ R##_s = X##_s; \
+ if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ /* |X| < |Y|, negate result. */ \
+ _FP_FRAC_SUB_##wc(R, Y, X); \
+ R##_s = Y##_s; \
+ } \
+ else if (_FP_FRAC_ZEROP_##wc(R)) \
+ { \
+ R##_e = 0; \
+ R##_s = (FP_ROUNDMODE == FP_RND_MINF); \
+ goto sub_done; \
+ } \
+ goto norm; \
+ } \
+ sub3: \
+ if (_FP_FRAC_HIGH_##fs(R) & _FP_IMPLBIT_SH_##fs) \
+ { \
+ int diff; \
+ /* Carry into most significant bit of larger one of X and Y, \
+ canceling it; renormalize. */ \
+ _FP_FRAC_HIGH_##fs(R) &= _FP_IMPLBIT_SH_##fs - 1; \
+ norm: \
+ _FP_FRAC_CLZ_##wc(diff, R); \
+ diff -= _FP_WFRACXBITS_##fs; \
+ _FP_FRAC_SLL_##wc(R, diff); \
+ if (R##_e <= diff) \
+ { \
+ /* R is denormalized. */ \
+ diff = diff - R##_e + 1; \
+ _FP_FRAC_SRS_##wc(R, diff, _FP_WFRACBITS_##fs); \
+ R##_e = 0; \
+ } \
+ else \
+ { \
+ R##_e -= diff; \
+ _FP_FRAC_HIGH_##fs(R) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
+ } \
+ } \
+ sub_done: ; \
+ } \
+} while (0)
+
+#define _FP_ADD(fs, wc, R, X, Y) _FP_ADD_INTERNAL(fs, wc, R, X, Y, '+')
+#define _FP_SUB(fs, wc, R, X, Y) \
+ do { \
+ if (!(Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) Y##_s ^= 1; \
+ _FP_ADD_INTERNAL(fs, wc, R, X, Y, '-'); \
+ } while (0)
+
+
+/*
+ * Main negation routine. FIXME -- when we care about setting exception
+ * bits reliably, this will not do. We should examine all of the fp classes.
+ */
+
+#define _FP_NEG(fs, wc, R, X) \
+ do { \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ R##_e = X##_e; \
+ R##_s = 1 ^ X##_s; \
+ } while (0)
+
+
+/*
+ * Main multiplication routine. The input values should be cooked.
+ */
+
+#define _FP_MUL(fs, wc, R, X, Y) \
+do { \
+ R##_s = X##_s ^ Y##_s; \
+ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ R##_e = X##_e + Y##_e + 1; \
+ \
+ _FP_MUL_MEAT_##fs(R,X,Y); \
+ \
+ if (_FP_FRAC_OVERP_##wc(fs, R)) \
+ _FP_FRAC_SRS_##wc(R, 1, _FP_WFRACBITS_##fs); \
+ else \
+ R##_e--; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
+ _FP_CHOOSENAN(fs, wc, R, X, Y, '*'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ break; \
+ \
+ default: \
+ abort(); \
+ } \
+} while (0)
+
+
+/*
+ * Main division routine. The input values should be cooked.
+ */
+
+#define _FP_DIV(fs, wc, R, X, Y) \
+do { \
+ R##_s = X##_s ^ Y##_s; \
+ switch (_FP_CLS_COMBINE(X##_c, Y##_c)) \
+ { \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_NORMAL; \
+ R##_e = X##_e - Y##_e; \
+ \
+ _FP_DIV_MEAT_##fs(R,X,Y); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NAN): \
+ _FP_CHOOSENAN(fs, wc, R, X, Y, '/'); \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_NORMAL): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_NAN,FP_CLS_ZERO): \
+ R##_s = X##_s; \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_c = X##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NAN): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NAN): \
+ R##_s = Y##_s; \
+ _FP_FRAC_COPY_##wc(R, Y); \
+ R##_c = Y##_c; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_ZERO; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_NORMAL,FP_CLS_ZERO): \
+ FP_SET_EXCEPTION(FP_EX_DIVZERO); \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_ZERO): \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_NORMAL): \
+ R##_c = FP_CLS_INF; \
+ break; \
+ \
+ case _FP_CLS_COMBINE(FP_CLS_INF,FP_CLS_INF): \
+ case _FP_CLS_COMBINE(FP_CLS_ZERO,FP_CLS_ZERO): \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ break; \
+ \
+ default: \
+ abort(); \
+ } \
+} while (0)
+
+
+/*
+ * Main differential comparison routine. The inputs should be raw not
+ * cooked. The return is -1,0,1 for normal values, 2 otherwise.
+ */
+
+#define _FP_CMP(fs, wc, ret, X, Y, un) \
+ do { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
+ { \
+ ret = un; \
+ } \
+ else \
+ { \
+ int __is_zero_x; \
+ int __is_zero_y; \
+ \
+ __is_zero_x = (!X##_e && _FP_FRAC_ZEROP_##wc(X)) ? 1 : 0; \
+ __is_zero_y = (!Y##_e && _FP_FRAC_ZEROP_##wc(Y)) ? 1 : 0; \
+ \
+ if (__is_zero_x && __is_zero_y) \
+ ret = 0; \
+ else if (__is_zero_x) \
+ ret = Y##_s ? 1 : -1; \
+ else if (__is_zero_y) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_s != Y##_s) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e > Y##_e) \
+ ret = X##_s ? -1 : 1; \
+ else if (X##_e < Y##_e) \
+ ret = X##_s ? 1 : -1; \
+ else if (_FP_FRAC_GT_##wc(X, Y)) \
+ ret = X##_s ? -1 : 1; \
+ else if (_FP_FRAC_GT_##wc(Y, X)) \
+ ret = X##_s ? 1 : -1; \
+ else \
+ ret = 0; \
+ } \
+ } while (0)
+
+
+/* Simplification for strict equality. */
+
+#define _FP_CMP_EQ(fs, wc, ret, X, Y) \
+ do { \
+ /* NANs are unordered */ \
+ if ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))) \
+ { \
+ ret = 1; \
+ } \
+ else \
+ { \
+ ret = !(X##_e == Y##_e \
+ && _FP_FRAC_EQ_##wc(X, Y) \
+ && (X##_s == Y##_s || (!X##_e && _FP_FRAC_ZEROP_##wc(X)))); \
+ } \
+ } while (0)
+
+/* Version to test unordered. */
+
+#define _FP_CMP_UNORD(fs, wc, ret, X, Y) \
+ do { \
+ ret = ((X##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(X)) \
+ || (Y##_e == _FP_EXPMAX_##fs && !_FP_FRAC_ZEROP_##wc(Y))); \
+ } while (0)
+
+/*
+ * Main square root routine. The input value should be cooked.
+ */
+
+#define _FP_SQRT(fs, wc, R, X) \
+do { \
+ _FP_FRAC_DECL_##wc(T); _FP_FRAC_DECL_##wc(S); \
+ _FP_W_TYPE q; \
+ switch (X##_c) \
+ { \
+ case FP_CLS_NAN: \
+ _FP_FRAC_COPY_##wc(R, X); \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_NAN; \
+ break; \
+ case FP_CLS_INF: \
+ if (X##_s) \
+ { \
+ R##_s = _FP_NANSIGN_##fs; \
+ R##_c = FP_CLS_NAN; /* NAN */ \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ } \
+ else \
+ { \
+ R##_s = 0; \
+ R##_c = FP_CLS_INF; /* sqrt(+inf) = +inf */ \
+ } \
+ break; \
+ case FP_CLS_ZERO: \
+ R##_s = X##_s; \
+ R##_c = FP_CLS_ZERO; /* sqrt(+-0) = +-0 */ \
+ break; \
+ case FP_CLS_NORMAL: \
+ R##_s = 0; \
+ if (X##_s) \
+ { \
+ R##_c = FP_CLS_NAN; /* sNAN */ \
+ R##_s = _FP_NANSIGN_##fs; \
+ _FP_FRAC_SET_##wc(R, _FP_NANFRAC_##fs); \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ break; \
+ } \
+ R##_c = FP_CLS_NORMAL; \
+ if (X##_e & 1) \
+ _FP_FRAC_SLL_##wc(X, 1); \
+ R##_e = X##_e >> 1; \
+ _FP_FRAC_SET_##wc(S, _FP_ZEROFRAC_##wc); \
+ _FP_FRAC_SET_##wc(R, _FP_ZEROFRAC_##wc); \
+ q = _FP_OVERFLOW_##fs >> 1; \
+ _FP_SQRT_MEAT_##wc(R, S, T, X, q); \
+ } \
+ } while (0)
+
+/*
+ * Convert from FP to integer. Input is raw.
+ */
+
+/* RSIGNED can have following values:
+ * 0: the number is required to be 0..(2^rsize)-1, if not, NV is set plus
+ * the result is either 0 or (2^rsize)-1 depending on the sign in such
+ * case.
+ * 1: the number is required to be -(2^(rsize-1))..(2^(rsize-1))-1, if not,
+ * NV is set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
+ * depending on the sign in such case.
+ * -1: the number is required to be -(2^(rsize-1))..(2^rsize)-1, if not, NV is
+ * set plus the result is either -(2^(rsize-1)) or (2^(rsize-1))-1
+ * depending on the sign in such case.
+ */
+#define _FP_TO_INT(fs, wc, r, X, rsize, rsigned) \
+do { \
+ if (X##_e < _FP_EXPBIAS_##fs) \
+ { \
+ r = 0; \
+ if (X##_e == 0) \
+ { \
+ if (!_FP_FRAC_ZEROP_##wc(X)) \
+ { \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ } \
+ } \
+ else \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ } \
+ else if (X##_e >= _FP_EXPBIAS_##fs + rsize - (rsigned > 0 || X##_s) \
+ || (!rsigned && X##_s)) \
+ { \
+ /* Overflow or converting to the most negative integer. */ \
+ if (rsigned) \
+ { \
+ r = 1; \
+ r <<= rsize - 1; \
+ r -= 1 - X##_s; \
+ } else { \
+ r = 0; \
+ if (X##_s) \
+ r = ~r; \
+ } \
+ \
+ if (rsigned && X##_s && X##_e == _FP_EXPBIAS_##fs + rsize - 1) \
+ { \
+ /* Possibly converting to most negative integer; check the \
+ mantissa. */ \
+ int inexact = 0; \
+ (void)((_FP_FRACBITS_##fs > rsize) \
+ ? ({ _FP_FRAC_SRST_##wc(X, inexact, \
+ _FP_FRACBITS_##fs - rsize, \
+ _FP_FRACBITS_##fs); 0; }) \
+ : 0); \
+ if (!_FP_FRAC_ZEROP_##wc(X)) \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ else if (inexact) \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ } \
+ else \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ } \
+ else \
+ { \
+ _FP_FRAC_HIGH_RAW_##fs(X) |= _FP_IMPLBIT_##fs; \
+ if (X##_e >= _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs - 1) \
+ { \
+ _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
+ r <<= X##_e - _FP_EXPBIAS_##fs - _FP_FRACBITS_##fs + 1; \
+ } \
+ else \
+ { \
+ int inexact; \
+ _FP_FRAC_SRST_##wc(X, inexact, \
+ (_FP_FRACBITS_##fs + _FP_EXPBIAS_##fs - 1 \
+ - X##_e), \
+ _FP_FRACBITS_##fs); \
+ if (inexact) \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ _FP_FRAC_ASSEMBLE_##wc(r, X, rsize); \
+ } \
+ if (rsigned && X##_s) \
+ r = -r; \
+ } \
+} while (0)
+
+/* Convert integer to fp. Output is raw. RTYPE is unsigned even if
+ input is signed. */
+#define _FP_FROM_INT(fs, wc, X, r, rsize, rtype) \
+ do { \
+ if (r) \
+ { \
+ rtype ur_; \
+ \
+ if ((X##_s = (r < 0))) \
+ r = -(rtype)r; \
+ \
+ ur_ = (rtype) r; \
+ (void)((rsize <= _FP_W_TYPE_SIZE) \
+ ? ({ \
+ int lz_; \
+ __FP_CLZ(lz_, (_FP_W_TYPE)ur_); \
+ X##_e = _FP_EXPBIAS_##fs + _FP_W_TYPE_SIZE - 1 - lz_; \
+ }) \
+ : ((rsize <= 2 * _FP_W_TYPE_SIZE) \
+ ? ({ \
+ int lz_; \
+ __FP_CLZ_2(lz_, (_FP_W_TYPE)(ur_ >> _FP_W_TYPE_SIZE), \
+ (_FP_W_TYPE)ur_); \
+ X##_e = (_FP_EXPBIAS_##fs + 2 * _FP_W_TYPE_SIZE - 1 \
+ - lz_); \
+ }) \
+ : (abort(), 0))); \
+ \
+ if (rsize - 1 + _FP_EXPBIAS_##fs >= _FP_EXPMAX_##fs \
+ && X##_e >= _FP_EXPMAX_##fs) \
+ { \
+ /* Exponent too big; overflow to infinity. (May also \
+ happen after rounding below.) */ \
+ _FP_OVERFLOW_SEMIRAW(fs, wc, X); \
+ goto pack_semiraw; \
+ } \
+ \
+ if (rsize <= _FP_FRACBITS_##fs \
+ || X##_e < _FP_EXPBIAS_##fs + _FP_FRACBITS_##fs) \
+ { \
+ /* Exactly representable; shift left. */ \
+ _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
+ _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \
+ + _FP_FRACBITS_##fs - 1 - X##_e)); \
+ } \
+ else \
+ { \
+ /* More bits in integer than in floating type; need to \
+ round. */ \
+ if (_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 < X##_e) \
+ ur_ = ((ur_ >> (X##_e - _FP_EXPBIAS_##fs \
+ - _FP_WFRACBITS_##fs + 1)) \
+ | ((ur_ << (rsize - (X##_e - _FP_EXPBIAS_##fs \
+ - _FP_WFRACBITS_##fs + 1))) \
+ != 0)); \
+ _FP_FRAC_DISASSEMBLE_##wc(X, ur_, rsize); \
+ if ((_FP_EXPBIAS_##fs + _FP_WFRACBITS_##fs - 1 - X##_e) > 0) \
+ _FP_FRAC_SLL_##wc(X, (_FP_EXPBIAS_##fs \
+ + _FP_WFRACBITS_##fs - 1 - X##_e)); \
+ _FP_FRAC_HIGH_##fs(X) &= ~(_FP_W_TYPE)_FP_IMPLBIT_SH_##fs; \
+ pack_semiraw: \
+ _FP_PACK_SEMIRAW(fs, wc, X); \
+ } \
+ } \
+ else \
+ { \
+ X##_s = 0; \
+ X##_e = 0; \
+ _FP_FRAC_SET_##wc(X, _FP_ZEROFRAC_##wc); \
+ } \
+ } while (0)
+
+
+/* Extend from a narrower floating-point format to a wider one. Input
+ and output are raw. */
+#define FP_EXTEND(dfs,sfs,dwc,swc,D,S) \
+do { \
+ if (_FP_FRACBITS_##dfs < _FP_FRACBITS_##sfs \
+ || (_FP_EXPMAX_##dfs - _FP_EXPBIAS_##dfs \
+ < _FP_EXPMAX_##sfs - _FP_EXPBIAS_##sfs) \
+ || _FP_EXPBIAS_##dfs < _FP_EXPBIAS_##sfs + _FP_FRACBITS_##sfs - 1) \
+ abort(); \
+ D##_s = S##_s; \
+ _FP_FRAC_COPY_##dwc##_##swc(D, S); \
+ if (_FP_EXP_NORMAL(sfs, swc, S)) \
+ { \
+ D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
+ _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs - _FP_FRACBITS_##sfs)); \
+ } \
+ else \
+ { \
+ if (S##_e == 0) \
+ { \
+ if (_FP_FRAC_ZEROP_##swc(S)) \
+ D##_e = 0; \
+ else \
+ { \
+ int _lz; \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ _FP_FRAC_CLZ_##swc(_lz, S); \
+ _FP_FRAC_SLL_##dwc(D, \
+ _lz + _FP_FRACBITS_##dfs \
+ - _FP_FRACTBITS_##sfs); \
+ D##_e = (_FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs + 1 \
+ + _FP_FRACXBITS_##sfs - _lz); \
+ } \
+ } \
+ else \
+ { \
+ D##_e = _FP_EXPMAX_##dfs; \
+ if (!_FP_FRAC_ZEROP_##swc(S)) \
+ { \
+ if (!(_FP_FRAC_HIGH_RAW_##sfs(S) & _FP_QNANBIT_##sfs)) \
+ FP_SET_EXCEPTION(FP_EX_INVALID); \
+ _FP_FRAC_SLL_##dwc(D, (_FP_FRACBITS_##dfs \
+ - _FP_FRACBITS_##sfs)); \
+ } \
+ } \
+ } \
+} while (0)
+
+/* Truncate from a wider floating-point format to a narrower one.
+ Input and output are semi-raw. */
+#define FP_TRUNC(dfs,sfs,dwc,swc,D,S) \
+do { \
+ if (_FP_FRACBITS_##sfs < _FP_FRACBITS_##dfs \
+ || _FP_EXPBIAS_##sfs < _FP_EXPBIAS_##dfs + _FP_FRACBITS_##dfs - 1) \
+ abort(); \
+ D##_s = S##_s; \
+ if (_FP_EXP_NORMAL(sfs, swc, S)) \
+ { \
+ D##_e = S##_e + _FP_EXPBIAS_##dfs - _FP_EXPBIAS_##sfs; \
+ if (D##_e >= _FP_EXPMAX_##dfs) \
+ _FP_OVERFLOW_SEMIRAW(dfs, dwc, D); \
+ else \
+ { \
+ if (D##_e <= 0) \
+ { \
+ if (D##_e <= 1 - _FP_FRACBITS_##dfs) \
+ _FP_FRAC_SET_##swc(S, _FP_ZEROFRAC_##swc); \
+ else \
+ { \
+ _FP_FRAC_HIGH_##sfs(S) |= _FP_IMPLBIT_SH_##sfs; \
+ _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs + 1 - D##_e), \
+ _FP_WFRACBITS_##sfs); \
+ } \
+ D##_e = 0; \
+ } \
+ else \
+ _FP_FRAC_SRS_##swc(S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs), \
+ _FP_WFRACBITS_##sfs); \
+ _FP_FRAC_COPY_##dwc##_##swc(D, S); \
+ } \
+ } \
+ else \
+ { \
+ if (S##_e == 0) \
+ { \
+ D##_e = 0; \
+ _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \
+ if (!_FP_FRAC_ZEROP_##swc(S)) \
+ { \
+ FP_SET_EXCEPTION(FP_EX_DENORM); \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ } \
+ } \
+ else \
+ { \
+ D##_e = _FP_EXPMAX_##dfs; \
+ if (_FP_FRAC_ZEROP_##swc(S)) \
+ _FP_FRAC_SET_##dwc(D, _FP_ZEROFRAC_##dwc); \
+ else \
+ { \
+ _FP_CHECK_SIGNAN_SEMIRAW(sfs, swc, S); \
+ _FP_FRAC_SRL_##swc(S, (_FP_WFRACBITS_##sfs \
+ - _FP_WFRACBITS_##dfs)); \
+ _FP_FRAC_COPY_##dwc##_##swc(D, S); \
+ /* Semi-raw NaN must have all workbits cleared. */ \
+ _FP_FRAC_LOW_##dwc(D) \
+ &= ~(_FP_W_TYPE) ((1 << _FP_WORKBITS) - 1); \
+ _FP_FRAC_HIGH_##dfs(D) |= _FP_QNANBIT_SH_##dfs; \
+ } \
+ } \
+ } \
+} while (0)
+
+/*
+ * Helper primitives.
+ */
+
+/* Count leading zeros in a word. */
+
+#ifndef __FP_CLZ
+/* GCC 3.4 and later provide the builtins for us. */
+#define __FP_CLZ(r, x) \
+ do { \
+ if (sizeof (_FP_W_TYPE) == sizeof (unsigned int)) \
+ r = __builtin_clz (x); \
+ else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long)) \
+ r = __builtin_clzl (x); \
+ else if (sizeof (_FP_W_TYPE) == sizeof (unsigned long long)) \
+ r = __builtin_clzll (x); \
+ else \
+ abort (); \
+ } while (0)
+#endif /* ndef __FP_CLZ */
+
+#define _FP_DIV_HELP_imm(q, r, n, d) \
+ do { \
+ q = n / d, r = n % d; \
+ } while (0)
+
+
+/* A restoring bit-by-bit division primitive. */
+
+#define _FP_DIV_MEAT_N_loop(fs, wc, R, X, Y) \
+ do { \
+ int count = _FP_WFRACBITS_##fs; \
+ _FP_FRAC_DECL_##wc (u); \
+ _FP_FRAC_DECL_##wc (v); \
+ _FP_FRAC_COPY_##wc (u, X); \
+ _FP_FRAC_COPY_##wc (v, Y); \
+ _FP_FRAC_SET_##wc (R, _FP_ZEROFRAC_##wc); \
+ /* Normalize U and V. */ \
+ _FP_FRAC_SLL_##wc (u, _FP_WFRACXBITS_##fs); \
+ _FP_FRAC_SLL_##wc (v, _FP_WFRACXBITS_##fs); \
+ /* First round. Since the operands are normalized, either the \
+ first or second bit will be set in the fraction. Produce a \
+ normalized result by checking which and adjusting the loop \
+ count and exponent accordingly. */ \
+ if (_FP_FRAC_GE_1 (u, v)) \
+ { \
+ _FP_FRAC_SUB_##wc (u, u, v); \
+ _FP_FRAC_LOW_##wc (R) |= 1; \
+ count--; \
+ } \
+ else \
+ R##_e--; \
+ /* Subsequent rounds. */ \
+ do { \
+ int msb = (_FP_WS_TYPE) _FP_FRAC_HIGH_##wc (u) < 0; \
+ _FP_FRAC_SLL_##wc (u, 1); \
+ _FP_FRAC_SLL_##wc (R, 1); \
+ if (msb || _FP_FRAC_GE_1 (u, v)) \
+ { \
+ _FP_FRAC_SUB_##wc (u, u, v); \
+ _FP_FRAC_LOW_##wc (R) |= 1; \
+ } \
+ } while (--count > 0); \
+ /* If there's anything left in U, the result is inexact. */ \
+ _FP_FRAC_LOW_##wc (R) |= !_FP_FRAC_ZEROP_##wc (u); \
+ } while (0)
+
+#define _FP_DIV_MEAT_1_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 1, R, X, Y)
+#define _FP_DIV_MEAT_2_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 2, R, X, Y)
+#define _FP_DIV_MEAT_4_loop(fs, R, X, Y) _FP_DIV_MEAT_N_loop (fs, 4, R, X, Y)
diff --git a/contrib/gcc/config/soft-fp/quad.h b/contrib/gcc/config/soft-fp/quad.h
new file mode 100644
index 0000000..d7840ff
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/quad.h
@@ -0,0 +1,271 @@
+/* Software floating-point emulation.
+ Definitions for IEEE Quad Precision.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel, kid. Go buy yourself a real computer."
+#endif
+
+#if _FP_W_TYPE_SIZE < 64
+#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
+#else
+#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
+#endif
+
+#define _FP_FRACBITS_Q 113
+#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
+#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q)
+#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
+#define _FP_EXPBITS_Q 15
+#define _FP_EXPBIAS_Q 16383
+#define _FP_EXPMAX_Q 32767
+
+#define _FP_QNANBIT_Q \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
+#define _FP_QNANBIT_SH_Q \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_Q \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
+#define _FP_IMPLBIT_SH_Q \
+ ((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
+#define _FP_OVERFLOW_Q \
+ ((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
+
+typedef float TFtype __attribute__((mode(TF)));
+
+#if _FP_W_TYPE_SIZE < 64
+
+union _FP_UNION_Q
+{
+ TFtype flt;
+ struct
+ {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+ unsigned long frac2 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_W_TYPE_SIZE;
+ unsigned long frac2 : _FP_W_TYPE_SIZE;
+ unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned sign : 1;
+#endif /* not bigendian */
+ } bits __attribute__((packed));
+};
+
+
+#define FP_DECL_Q(X) _FP_DECL(4,X)
+#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val)
+#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val)
+#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X)
+#define FP_PACK_RAW_QP(val,X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P(Q,val,X); \
+ } while (0)
+
+#define FP_UNPACK_Q(X,val) \
+ do { \
+ _FP_UNPACK_RAW_4(Q,X,val); \
+ _FP_UNPACK_CANONICAL(Q,4,X); \
+ } while (0)
+
+#define FP_UNPACK_QP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_4_P(Q,X,val); \
+ _FP_UNPACK_CANONICAL(Q,4,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_Q(X,val) \
+ do { \
+ _FP_UNPACK_RAW_4(Q,X,val); \
+ _FP_UNPACK_SEMIRAW(Q,4,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_QP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_4_P(Q,X,val); \
+ _FP_UNPACK_SEMIRAW(Q,4,X); \
+ } while (0)
+
+#define FP_PACK_Q(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(Q,4,X); \
+ _FP_PACK_RAW_4(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_QP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(Q,4,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_Q(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(Q,4,X); \
+ _FP_PACK_RAW_4(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_QP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(Q,4,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_4_P(Q,val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X)
+#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X)
+#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y)
+#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y)
+#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y)
+#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y)
+#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X)
+#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q)
+
+#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un)
+#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y)
+#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,4,r,X,Y)
+
+#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg)
+#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X)
+#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X)
+
+#else /* not _FP_W_TYPE_SIZE < 64 */
+union _FP_UNION_Q
+{
+ TFtype flt /* __attribute__((mode(TF))) */ ;
+ struct {
+ _FP_W_TYPE a, b;
+ } longs;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+#else
+ unsigned long frac0 : _FP_W_TYPE_SIZE;
+ unsigned long frac1 : _FP_FRACBITS_Q-(_FP_IMPLBIT_Q != 0)-_FP_W_TYPE_SIZE;
+ unsigned exp : _FP_EXPBITS_Q;
+ unsigned sign : 1;
+#endif
+ } bits;
+};
+
+#define FP_DECL_Q(X) _FP_DECL(2,X)
+#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val)
+#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val)
+#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X)
+#define FP_PACK_RAW_QP(val,X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(Q,val,X); \
+ } while (0)
+
+#define FP_UNPACK_Q(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(Q,X,val); \
+ _FP_UNPACK_CANONICAL(Q,2,X); \
+ } while (0)
+
+#define FP_UNPACK_QP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2_P(Q,X,val); \
+ _FP_UNPACK_CANONICAL(Q,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_Q(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2(Q,X,val); \
+ _FP_UNPACK_SEMIRAW(Q,2,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_QP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_2_P(Q,X,val); \
+ _FP_UNPACK_SEMIRAW(Q,2,X); \
+ } while (0)
+
+#define FP_PACK_Q(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(Q,2,X); \
+ _FP_PACK_RAW_2(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_QP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(Q,2,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_Q(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(Q,2,X); \
+ _FP_PACK_RAW_2(Q,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_QP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(Q,2,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_2_P(Q,val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X)
+#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X)
+#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y)
+#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y)
+#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y)
+#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y)
+#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X)
+#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
+
+#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un)
+#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y)
+#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,2,r,X,Y)
+
+#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg)
+#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X)
+#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
+
+#endif /* not _FP_W_TYPE_SIZE < 64 */
diff --git a/contrib/gcc/config/soft-fp/single.h b/contrib/gcc/config/soft-fp/single.h
new file mode 100644
index 0000000..9c3734a
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/single.h
@@ -0,0 +1,151 @@
+/* Software floating-point emulation.
+ Definitions for IEEE Single Precision.
+ Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#if _FP_W_TYPE_SIZE < 32
+#error "Here's a nickel kid. Go buy yourself a real computer."
+#endif
+
+#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE
+
+#define _FP_FRACBITS_S 24
+#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S)
+#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
+#define _FP_WFRACXBITS_S (_FP_FRACTBITS_S - _FP_WFRACBITS_S)
+#define _FP_EXPBITS_S 8
+#define _FP_EXPBIAS_S 127
+#define _FP_EXPMAX_S 255
+#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
+#define _FP_QNANBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS))
+#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
+#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS))
+#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
+
+/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
+ chosen by the target machine. */
+
+typedef float SFtype __attribute__((mode(SF)));
+
+union _FP_UNION_S
+{
+ SFtype flt;
+ struct {
+#if __BYTE_ORDER == __BIG_ENDIAN
+ unsigned sign : 1;
+ unsigned exp : _FP_EXPBITS_S;
+ unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+#else
+ unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
+ unsigned exp : _FP_EXPBITS_S;
+ unsigned sign : 1;
+#endif
+ } bits __attribute__((packed));
+};
+
+#define FP_DECL_S(X) _FP_DECL(1,X)
+#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
+#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val)
+#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
+#define FP_PACK_RAW_SP(val,X) \
+ do { \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(S,val,X); \
+ } while (0)
+
+#define FP_UNPACK_S(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1(S,X,val); \
+ _FP_UNPACK_CANONICAL(S,1,X); \
+ } while (0)
+
+#define FP_UNPACK_SP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1_P(S,X,val); \
+ _FP_UNPACK_CANONICAL(S,1,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_S(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1(S,X,val); \
+ _FP_UNPACK_SEMIRAW(S,1,X); \
+ } while (0)
+
+#define FP_UNPACK_SEMIRAW_SP(X,val) \
+ do { \
+ _FP_UNPACK_RAW_1_P(S,X,val); \
+ _FP_UNPACK_SEMIRAW(S,1,X); \
+ } while (0)
+
+#define FP_PACK_S(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(S,1,X); \
+ _FP_PACK_RAW_1(S,val,X); \
+ } while (0)
+
+#define FP_PACK_SP(val,X) \
+ do { \
+ _FP_PACK_CANONICAL(S,1,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(S,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_S(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(S,1,X); \
+ _FP_PACK_RAW_1(S,val,X); \
+ } while (0)
+
+#define FP_PACK_SEMIRAW_SP(val,X) \
+ do { \
+ _FP_PACK_SEMIRAW(S,1,X); \
+ if (!FP_INHIBIT_RESULTS) \
+ _FP_PACK_RAW_1_P(S,val,X); \
+ } while (0)
+
+#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X)
+#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
+#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
+#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
+#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
+#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
+#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
+#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
+
+#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
+#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
+#define FP_CMP_UNORD_S(r,X,Y) _FP_CMP_UNORD(S,1,r,X,Y)
+
+#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
+#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
+
+#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X)
+#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X)
diff --git a/contrib/gcc/config/soft-fp/soft-fp.h b/contrib/gcc/config/soft-fp/soft-fp.h
new file mode 100644
index 0000000..dbf080e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/soft-fp.h
@@ -0,0 +1,209 @@
+/* Software floating-point emulation.
+ Copyright (C) 1997,1998,1999,2000,2002,2003,2005,2006
+ Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com),
+ Jakub Jelinek (jj@ultra.linux.cz),
+ David S. Miller (davem@redhat.com) and
+ Peter Maydell (pmaydell@chiark.greenend.org.uk).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#ifndef SOFT_FP_H
+#define SOFT_FP_H
+
+#ifdef _LIBC
+#include <sfp-machine.h>
+#else
+#include "sfp-machine.h"
+#endif
+
+/* Allow sfp-machine to have its own byte order definitions. */
+#ifndef __BYTE_ORDER
+#ifdef _LIBC
+#include <endian.h>
+#else
+#error "endianness not defined by sfp-machine.h"
+#endif
+#endif
+
+#define _FP_WORKBITS 3
+#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
+#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
+#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
+#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
+
+#ifndef FP_RND_NEAREST
+# define FP_RND_NEAREST 0
+# define FP_RND_ZERO 1
+# define FP_RND_PINF 2
+# define FP_RND_MINF 3
+#endif
+#ifndef FP_ROUNDMODE
+# define FP_ROUNDMODE FP_RND_NEAREST
+#endif
+
+/* By default don't care about exceptions. */
+#ifndef FP_EX_INVALID
+#define FP_EX_INVALID 0
+#endif
+#ifndef FP_EX_OVERFLOW
+#define FP_EX_OVERFLOW 0
+#endif
+#ifndef FP_EX_UNDERFLOW
+#define FP_EX_UNDERFLOW 0
+#endif
+#ifndef FP_EX_DIVZERO
+#define FP_EX_DIVZERO 0
+#endif
+#ifndef FP_EX_INEXACT
+#define FP_EX_INEXACT 0
+#endif
+#ifndef FP_EX_DENORM
+#define FP_EX_DENORM 0
+#endif
+
+#ifdef _FP_DECL_EX
+#define FP_DECL_EX \
+ int _fex = 0; \
+ _FP_DECL_EX
+#else
+#define FP_DECL_EX int _fex = 0
+#endif
+
+#ifndef FP_INIT_ROUNDMODE
+#define FP_INIT_ROUNDMODE do {} while (0)
+#endif
+
+#ifndef FP_HANDLE_EXCEPTIONS
+#define FP_HANDLE_EXCEPTIONS do {} while (0)
+#endif
+
+#ifndef FP_INHIBIT_RESULTS
+/* By default we write the results always.
+ * sfp-machine may override this and e.g.
+ * check if some exceptions are unmasked
+ * and inhibit it in such a case.
+ */
+#define FP_INHIBIT_RESULTS 0
+#endif
+
+#define FP_SET_EXCEPTION(ex) \
+ _fex |= (ex)
+
+#define FP_UNSET_EXCEPTION(ex) \
+ _fex &= ~(ex)
+
+#define FP_CLEAR_EXCEPTIONS \
+ _fex = 0
+
+#define _FP_ROUND_NEAREST(wc, X) \
+do { \
+ if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
+} while (0)
+
+#define _FP_ROUND_ZERO(wc, X) (void)0
+
+#define _FP_ROUND_PINF(wc, X) \
+do { \
+ if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
+} while (0)
+
+#define _FP_ROUND_MINF(wc, X) \
+do { \
+ if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
+ _FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
+} while (0)
+
+#define _FP_ROUND(wc, X) \
+do { \
+ if (_FP_FRAC_LOW_##wc(X) & 7) \
+ FP_SET_EXCEPTION(FP_EX_INEXACT); \
+ switch (FP_ROUNDMODE) \
+ { \
+ case FP_RND_NEAREST: \
+ _FP_ROUND_NEAREST(wc,X); \
+ break; \
+ case FP_RND_ZERO: \
+ _FP_ROUND_ZERO(wc,X); \
+ break; \
+ case FP_RND_PINF: \
+ _FP_ROUND_PINF(wc,X); \
+ break; \
+ case FP_RND_MINF: \
+ _FP_ROUND_MINF(wc,X); \
+ break; \
+ } \
+} while (0)
+
+#define FP_CLS_NORMAL 0
+#define FP_CLS_ZERO 1
+#define FP_CLS_INF 2
+#define FP_CLS_NAN 3
+
+#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
+
+#include "op-1.h"
+#include "op-2.h"
+#include "op-4.h"
+#include "op-8.h"
+#include "op-common.h"
+
+/* Sigh. Silly things longlong.h needs. */
+#define UWtype _FP_W_TYPE
+#define W_TYPE_SIZE _FP_W_TYPE_SIZE
+
+typedef int QItype __attribute__((mode(QI)));
+typedef int SItype __attribute__((mode(SI)));
+typedef int DItype __attribute__((mode(DI)));
+typedef unsigned int UQItype __attribute__((mode(QI)));
+typedef unsigned int USItype __attribute__((mode(SI)));
+typedef unsigned int UDItype __attribute__((mode(DI)));
+#if _FP_W_TYPE_SIZE == 32
+typedef unsigned int UHWtype __attribute__((mode(HI)));
+#elif _FP_W_TYPE_SIZE == 64
+typedef USItype UHWtype;
+#endif
+
+#define SI_BITS (__CHAR_BIT__ * (int)sizeof(SItype))
+#define DI_BITS (__CHAR_BIT__ * (int)sizeof(DItype))
+
+#ifndef umul_ppmm
+#ifdef _LIBC
+#include <stdlib/longlong.h>
+#else
+#include "longlong.h"
+#endif
+#endif
+
+#ifdef _LIBC
+#include <stdlib.h>
+#else
+extern void abort (void);
+#endif
+
+#endif
diff --git a/contrib/gcc/config/soft-fp/subdf3.c b/contrib/gcc/config/soft-fp/subdf3.c
new file mode 100644
index 0000000..3978b52
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/subdf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a - b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+DFtype __subdf3(DFtype a, DFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_D(A, a);
+ FP_UNPACK_SEMIRAW_D(B, b);
+ FP_SUB_D(R, A, B);
+ FP_PACK_SEMIRAW_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/subsf3.c b/contrib/gcc/config/soft-fp/subsf3.c
new file mode 100644
index 0000000..f1cbdd1
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/subsf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a - b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+SFtype __subsf3(SFtype a, SFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_S(A, a);
+ FP_UNPACK_SEMIRAW_S(B, b);
+ FP_SUB_S(R, A, B);
+ FP_PACK_SEMIRAW_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/subtf3.c b/contrib/gcc/config/soft-fp/subtf3.c
new file mode 100644
index 0000000..7ba4c8c
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/subtf3.c
@@ -0,0 +1,49 @@
+/* Software floating-point emulation.
+ Return a - b
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+TFtype __subtf3(TFtype a, TFtype b)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A); FP_DECL_Q(B); FP_DECL_Q(R);
+ TFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(A, a);
+ FP_UNPACK_SEMIRAW_Q(B, b);
+ FP_SUB_Q(R, A, B);
+ FP_PACK_SEMIRAW_Q(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/t-softfp b/contrib/gcc/config/soft-fp/t-softfp
new file mode 100644
index 0000000..4a3f91e
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/t-softfp
@@ -0,0 +1,108 @@
+# Copyright (C) 2006 Free Software Foundation, Inc.
+
+# This file is part of GCC.
+
+# GCC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# GCC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GCC; see the file COPYING. If not, write to
+# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+# Boston MA 02110-1301, USA.
+
+# Targets using soft-fp should define the following variables:
+#
+# softfp_float_modes: a list of soft-float floating-point modes,
+# e.g. sf df
+# softfp_int_modes: a list of integer modes for which to define conversions,
+# e.g. si di
+# softfp_extensions: a list of extensions between floating-point modes,
+# e.g. sfdf
+# softfp_truncations: a list of truncations between floating-point modes,
+# e.g. dfsf
+# softfp_machine_header: the target sfp-machine.h file (relative to config/),
+# e.g. rs6000/sfp-machine.h
+#
+# Extensions and truncations should include those where only one mode
+# is a soft-float mode; for example, sftf where sf is hard-float and
+# tf is soft-float.
+#
+# If the libgcc2.c functions should not be replaced, also define:
+#
+# softfp_exclude_libgcc2 := y
+#
+# Avoiding replacing the libgcc2.c functions is a temporary measure
+# for targets with both hard-float and soft-float multilibs, since
+# these variables apply for all multilibs. With toplevel libgcc,
+# soft-fp can be used conditionally on the multilib instead.
+#
+# If the code should not be compiled at all for some multilibs, define:
+#
+# softfp_wrap_start: text to put at the start of wrapper source files,
+# output with echo
+# e.g. '#ifndef __powerpc64__'
+# softfp_wrap_end: text to put at the end of wrapper source files,
+# e.g. '#endif'
+#
+# This is another temporary measure.
+
+softfp_float_funcs = add$(m)3 div$(m)3 eq$(m)2 ge$(m)2 le$(m)2 mul$(m)3 \
+ neg$(m)2 sub$(m)3 unord$(m)2
+softfp_floatint_funcs = fix$(m)$(i) fixuns$(m)$(i) \
+ float$(i)$(m) floatun$(i)$(m)
+
+softfp_func_list := \
+ $(foreach m,$(softfp_float_modes), \
+ $(softfp_float_funcs) \
+ $(foreach i,$(softfp_int_modes), \
+ $(softfp_floatint_funcs))) \
+ $(foreach e,$(softfp_extensions),extend$(e)2) \
+ $(foreach t,$(softfp_truncations),trunc$(t)2)
+
+ifeq ($(softfp_exclude_libgcc2),y)
+# This list is taken from mklibgcc.in and doesn't presently allow for
+# 64-bit targets where si should become di and di should become ti.
+softfp_func_list := $(filter-out floatdidf floatdisf fixunsdfsi fixunssfsi \
+ fixunsdfdi fixdfdi fixunssfdi fixsfdi fixxfdi fixunsxfdi \
+ floatdixf fixunsxfsi fixtfdi fixunstfdi floatditf \
+ floatundidf floatundisf floatundixf floatunditf,$(softfp_func_list))
+endif
+
+ifeq ($(softfp_wrap_start),)
+softfp_file_list := \
+ $(addsuffix .c,$(addprefix $(srcdir)/config/soft-fp/,$(softfp_func_list)))
+else
+softfp_file_list := $(addsuffix .c,$(softfp_func_list))
+
+$(softfp_file_list):
+ echo $(softfp_wrap_start) > $@
+ echo '#include "config/soft-fp/$@"' >> $@
+ echo $(softfp_wrap_end) >> $@
+endif
+
+LIB2FUNCS_EXTRA += $(softfp_file_list)
+
+ifneq ($(softfp_exclude_libgcc2),y)
+# Functions in libgcc2.c are excluded for each soft-float mode (a
+# target may have both soft-float and hard-float modes), for the fixed
+# list of integer modes (si and di) for which libgcc2.c defines any
+# such functions. Depending on the target, the si and di symbols may
+# in fact define di and ti functions.
+
+LIB2FUNCS_EXCLUDE += \
+ $(addprefix _,$(foreach m,$(softfp_float_modes), \
+ $(foreach i,si di, \
+ $(softfp_floatint_funcs))))
+endif
+
+SFP_MACHINE := sfp-machine.h
+
+$(SFP_MACHINE): $(srcdir)/config/$(softfp_machine_header)
+ cp $(srcdir)/config/$(softfp_machine_header) $(SFP_MACHINE)
diff --git a/contrib/gcc/config/soft-fp/truncdfsf2.c b/contrib/gcc/config/soft-fp/truncdfsf2.c
new file mode 100644
index 0000000..bd95391
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/truncdfsf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Truncate IEEE double into IEEE single
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+#include "double.h"
+
+SFtype __truncdfsf2(DFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_D(A);
+ FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_D(A, a);
+#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
+ FP_TRUNC(S,D,1,2,R,A);
+#else
+ FP_TRUNC(S,D,1,1,R,A);
+#endif
+ FP_PACK_SEMIRAW_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/trunctfdf2.c b/contrib/gcc/config/soft-fp/trunctfdf2.c
new file mode 100644
index 0000000..c3827b0
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/trunctfdf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Truncate IEEE quad into IEEE double
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+#include "quad.h"
+
+DFtype __trunctfdf2(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ FP_DECL_D(R);
+ DFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_TRUNC(D,Q,2,4,R,A);
+#else
+ FP_TRUNC(D,Q,1,2,R,A);
+#endif
+ FP_PACK_SEMIRAW_D(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/trunctfsf2.c b/contrib/gcc/config/soft-fp/trunctfsf2.c
new file mode 100644
index 0000000..676c937
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/trunctfsf2.c
@@ -0,0 +1,54 @@
+/* Software floating-point emulation.
+ Truncate IEEE quad into IEEE single
+ Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Richard Henderson (rth@cygnus.com) and
+ Jakub Jelinek (jj@ultra.linux.cz).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+#include "quad.h"
+
+SFtype __trunctfsf2(TFtype a)
+{
+ FP_DECL_EX;
+ FP_DECL_Q(A);
+ FP_DECL_S(R);
+ SFtype r;
+
+ FP_INIT_ROUNDMODE;
+ FP_UNPACK_SEMIRAW_Q(A, a);
+#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
+ FP_TRUNC(S,Q,1,4,R,A);
+#else
+ FP_TRUNC(S,Q,1,2,R,A);
+#endif
+ FP_PACK_SEMIRAW_S(r, R);
+ FP_HANDLE_EXCEPTIONS;
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/unorddf2.c b/contrib/gcc/config/soft-fp/unorddf2.c
new file mode 100644
index 0000000..c83a563
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/unorddf2.c
@@ -0,0 +1,45 @@
+/* Software floating-point emulation.
+ Return 1 iff a or b is a NaN, 0 otherwise.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Joseph Myers (joseph@codesourcery.com).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "double.h"
+
+int
+__unorddf2(DFtype a, DFtype b)
+{
+ FP_DECL_D(A); FP_DECL_D(B);
+ int r;
+
+ FP_UNPACK_RAW_D(A, a);
+ FP_UNPACK_RAW_D(B, b);
+ FP_CMP_UNORD_D(r, A, B);
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/unordsf2.c b/contrib/gcc/config/soft-fp/unordsf2.c
new file mode 100644
index 0000000..8de7563
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/unordsf2.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Return 1 iff a or b is a NaN, 0 otherwise.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Joseph Myers (joseph@codesourcery.com).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "single.h"
+
+int
+__unordsf2(SFtype a, SFtype b)
+{
+ FP_DECL_S(A);
+ FP_DECL_S(B);
+ int r;
+
+ FP_UNPACK_RAW_S(A, a);
+ FP_UNPACK_RAW_S(B, b);
+ FP_CMP_UNORD_S(r, A, B);
+
+ return r;
+}
diff --git a/contrib/gcc/config/soft-fp/unordtf2.c b/contrib/gcc/config/soft-fp/unordtf2.c
new file mode 100644
index 0000000..134b1d0
--- /dev/null
+++ b/contrib/gcc/config/soft-fp/unordtf2.c
@@ -0,0 +1,46 @@
+/* Software floating-point emulation.
+ Return 1 iff a or b is a NaN, 0 otherwise.
+ Copyright (C) 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Joseph Myers (joseph@codesourcery.com).
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ In addition to the permissions in the GNU Lesser 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 Lesser 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.)
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+#include "soft-fp.h"
+#include "quad.h"
+
+int
+__unordtf2(TFtype a, TFtype b)
+{
+ FP_DECL_Q(A);
+ FP_DECL_Q(B);
+ int r;
+
+ FP_UNPACK_RAW_Q(A, a);
+ FP_UNPACK_RAW_Q(B, b);
+ FP_CMP_UNORD_Q(r, A, B);
+
+ return r;
+}
diff --git a/contrib/gcc/config/sol2-10.h b/contrib/gcc/config/sol2-10.h
new file mode 100644
index 0000000..1da6bee
--- /dev/null
+++ b/contrib/gcc/config/sol2-10.h
@@ -0,0 +1,24 @@
+/* Operating system specific defines to be used when targeting GCC for any
+ Solaris 2 system starting from Solaris 10.
+ Copyright 2006 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Solaris 10 has the float and long double forms of math functions. */
+#undef TARGET_C99_FUNCTIONS
+#define TARGET_C99_FUNCTIONS 1
diff --git a/contrib/gcc/config/sol2-6.h b/contrib/gcc/config/sol2-6.h
new file mode 100644
index 0000000..d5b7dda
--- /dev/null
+++ b/contrib/gcc/config/sol2-6.h
@@ -0,0 +1,27 @@
+/* Operating system specific defines to be used when targeting GCC for any
+ Solaris 2 system up to Solaris 2.6.
+ Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef CPP_SUBTARGET_SPEC
+#define CPP_SUBTARGET_SPEC "\
+%{pthreads|pthread:-D_REENTRANT -D_PTHREADS95} \
+%{!pthreads:%{!pthread:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}}} \
+%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
+"
diff --git a/contrib/gcc/config/sol2-c.c b/contrib/gcc/config/sol2-c.c
new file mode 100644
index 0000000..173583b
--- /dev/null
+++ b/contrib/gcc/config/sol2-c.c
@@ -0,0 +1,272 @@
+/* Solaris support needed only by C/C++ frontends.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "tm_p.h"
+#include "toplev.h"
+
+#include "c-format.h"
+#include "intl.h"
+
+#include "cpplib.h"
+#include "c-pragma.h"
+#include "c-common.h"
+
+/* cmn_err only accepts "l" and "ll". */
+static const format_length_info cmn_err_length_specs[] =
+{
+ { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89 },
+ { NULL, 0, 0, NULL, 0, 0 }
+};
+
+static const format_flag_spec cmn_err_flag_specs[] =
+{
+ { 'w', 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 },
+ { 'L', 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 },
+ { 0, 0, 0, NULL, NULL, 0 }
+};
+
+
+static const format_flag_pair cmn_err_flag_pairs[] =
+{
+ { 0, 0, 0, 0 }
+};
+
+static const format_char_info bitfield_string_type =
+ { "b", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL };
+
+static const format_char_info cmn_err_char_table[] =
+{
+ /* C89 conversion specifiers. */
+ { "dD", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL },
+ { "oOxX",0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL },
+ { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL },
+ { "c", 0, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL },
+ { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "c", NULL },
+ { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "cR", NULL },
+ { "b", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", &bitfield_string_type },
+ { NULL, 0, 0, NOLENGTHS, NULL, NULL, NULL }
+};
+
+const format_kind_info solaris_format_types[] = {
+ { "cmn_err", cmn_err_length_specs, cmn_err_char_table, "", NULL,
+ cmn_err_flag_specs, cmn_err_flag_pairs,
+ FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK,
+ 'w', 0, 0, 0, 'L',
+ &integer_type_node, &integer_type_node
+ }
+};
+
+/* Handle #pragma align ALIGNMENT (VAR [, VAR]...) */
+
+static void
+solaris_pragma_align (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t, x;
+ enum cpp_ttype ttype;
+ HOST_WIDE_INT low;
+
+ if (pragma_lex (&x) != CPP_NUMBER
+ || pragma_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning (0, "malformed %<#pragma align%>, ignoring");
+ return;
+ }
+
+ low = TREE_INT_CST_LOW (x);
+ if (TREE_INT_CST_HIGH (x) != 0
+ || (low != 1 && low != 2 && low != 4 && low != 8 && low != 16
+ && low != 32 && low != 64 && low != 128))
+ {
+ warning (0, "invalid alignment for %<#pragma align%>, ignoring");
+ return;
+ }
+
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma align%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && DECL_P (decl))
+ warning (0, "%<#pragma align%> must appear before the declaration of "
+ "%D, ignoring", decl);
+ else
+ solaris_pending_aligns = tree_cons (t, build_tree_list (NULL, x),
+ solaris_pending_aligns);
+
+ ttype = pragma_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma align%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (pragma_lex (&t) != CPP_EOF)
+ warning (0, "junk at end of %<#pragma align%>");
+ return;
+ }
+ else
+ {
+ warning (0, "malformed %<#pragma align%>");
+ return;
+ }
+ }
+}
+
+/* Handle #pragma init (function [, function]...) */
+
+static void
+solaris_pragma_init (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t;
+ enum cpp_ttype ttype;
+
+ if (pragma_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning (0, "malformed %<#pragma init%>, ignoring");
+ return;
+ }
+
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma init%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && DECL_P (decl))
+ {
+ tree init_list = build_tree_list (get_identifier ("init"),
+ NULL);
+ tree attrs = tree_cons (get_identifier ("used"), NULL, init_list);
+ decl_attributes (&decl, attrs, 0);
+ }
+ else
+ solaris_pending_inits = tree_cons (t, NULL, solaris_pending_inits);
+
+ ttype = pragma_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma init%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (pragma_lex (&t) != CPP_EOF)
+ warning (0, "junk at end of %<#pragma init%>");
+ return;
+ }
+ else
+ {
+ warning (0, "malformed %<#pragma init%>");
+ return;
+ }
+ }
+}
+
+/* Handle #pragma fini (function [, function]...) */
+
+static void
+solaris_pragma_fini (cpp_reader *pfile ATTRIBUTE_UNUSED)
+{
+ tree t;
+ enum cpp_ttype ttype;
+
+ if (pragma_lex (&t) != CPP_OPEN_PAREN)
+ {
+ warning (0, "malformed %<#pragma fini%>, ignoring");
+ return;
+ }
+
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma fini%>, ignoring");
+ return;
+ }
+
+ while (1)
+ {
+ tree decl = identifier_global_value (t);
+ if (decl && DECL_P (decl))
+ {
+ tree fini_list = build_tree_list (get_identifier ("fini"),
+ NULL);
+ tree attrs = tree_cons (get_identifier ("used"), NULL, fini_list);
+ decl_attributes (&decl, attrs, 0);
+ }
+ else
+ solaris_pending_finis = tree_cons (t, NULL, solaris_pending_finis);
+
+ ttype = pragma_lex (&t);
+ if (ttype == CPP_COMMA)
+ {
+ ttype = pragma_lex (&t);
+ if (ttype != CPP_NAME)
+ {
+ warning (0, "malformed %<#pragma fini%>");
+ return;
+ }
+ }
+ else if (ttype == CPP_CLOSE_PAREN)
+ {
+ if (pragma_lex (&t) != CPP_EOF)
+ warning (0, "junk at end of %<#pragma fini%>");
+ return;
+ }
+ else
+ {
+ warning (0, "malformed %<#pragma fini%>");
+ return;
+ }
+ }
+}
+
+/* Register Solaris-specific #pragma directives. */
+
+void
+solaris_register_pragmas (void)
+{
+ c_register_pragma_with_expansion (0, "align", solaris_pragma_align);
+ c_register_pragma (0, "init", solaris_pragma_init);
+ c_register_pragma (0, "fini", solaris_pragma_fini);
+}
diff --git a/contrib/gcc/config/sol2-protos.h b/contrib/gcc/config/sol2-protos.h
new file mode 100644
index 0000000..757c6f8
--- /dev/null
+++ b/contrib/gcc/config/sol2-protos.h
@@ -0,0 +1,24 @@
+/* Operating system specific prototypes to be used when targeting GCC for any
+ Solaris 2 system.
+ Copyright 2004 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+extern void solaris_insert_attributes (tree, tree *);
+extern void solaris_register_pragmas (void);
+extern void solaris_output_init_fini (FILE *, tree);
diff --git a/contrib/gcc/config/sol2.c b/contrib/gcc/config/sol2.c
new file mode 100644
index 0000000..e3d3147
--- /dev/null
+++ b/contrib/gcc/config/sol2.c
@@ -0,0 +1,120 @@
+/* General Solaris system support.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tree.h"
+#include "tm.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "toplev.h"
+#include "ggc.h"
+
+tree solaris_pending_aligns, solaris_pending_inits, solaris_pending_finis;
+
+/* Attach any pending attributes for DECL to the list in *ATTRIBUTES.
+ Pending attributes come from #pragma or _Pragma, so this code is
+ only useful in the C family front ends, but it is included in
+ all languages to avoid changing the target machine initializer
+ depending on the language. */
+
+void
+solaris_insert_attributes (tree decl, tree *attributes)
+{
+ tree *x, next;
+
+ if (solaris_pending_aligns != NULL && TREE_CODE (decl) == VAR_DECL)
+ for (x = &solaris_pending_aligns; *x; x = &TREE_CHAIN (*x))
+ {
+ tree name = TREE_PURPOSE (*x);
+ tree value = TREE_VALUE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ if (lookup_attribute ("aligned", DECL_ATTRIBUTES (decl))
+ || lookup_attribute ("aligned", *attributes))
+ warning (0, "ignoring %<#pragma align%> for explicitly "
+ "aligned %q+D", decl);
+ else
+ *attributes = tree_cons (get_identifier ("aligned"), value,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+
+ if (solaris_pending_inits != NULL && TREE_CODE (decl) == FUNCTION_DECL)
+ for (x = &solaris_pending_inits; *x; x = &TREE_CHAIN (*x))
+ {
+ tree name = TREE_PURPOSE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ *attributes = tree_cons (get_identifier ("init"), NULL,
+ *attributes);
+ *attributes = tree_cons (get_identifier ("used"), NULL,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+
+ if (solaris_pending_finis != NULL && TREE_CODE (decl) == FUNCTION_DECL)
+ for (x = &solaris_pending_finis; *x; x = &TREE_CHAIN (*x))
+ {
+ tree name = TREE_PURPOSE (*x);
+ if (DECL_NAME (decl) == name)
+ {
+ *attributes = tree_cons (get_identifier ("fini"), NULL,
+ *attributes);
+ *attributes = tree_cons (get_identifier ("used"), NULL,
+ *attributes);
+ next = TREE_CHAIN (*x);
+ ggc_free (*x);
+ *x = next;
+ break;
+ }
+ }
+}
+
+/* Output initializer or finalizer entries for DECL to FILE. */
+
+void
+solaris_output_init_fini (FILE *file, tree decl)
+{
+ if (lookup_attribute ("init", DECL_ATTRIBUTES (decl)))
+ {
+ fprintf (file, "\t.pushsection\t\".init\"\n");
+ ASM_OUTPUT_CALL (file, decl);
+ fprintf (file, "\t.popsection\n");
+ }
+
+ if (lookup_attribute ("fini", DECL_ATTRIBUTES (decl)))
+ {
+ fprintf (file, "\t.pushsection\t\".fini\"\n");
+ ASM_OUTPUT_CALL (file, decl);
+ fprintf (file, "\t.popsection\n");
+ }
+}
+
diff --git a/contrib/gcc/config/sol2.h b/contrib/gcc/config/sol2.h
index 955cd0e..5ffaf57 100644
--- a/contrib/gcc/config/sol2.h
+++ b/contrib/gcc/config/sol2.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for any
Solaris 2 system.
- Copyright 2002, 2003 Free Software Foundation, Inc.
+ Copyright 2002, 2003, 2004 Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* We use stabs-in-elf for debugging, because that is what the native
toolchain uses. */
@@ -39,7 +39,7 @@ Boston, MA 02111-1307, USA. */
#undef WINT_TYPE_SIZE
#define WINT_TYPE_SIZE BITS_PER_WORD
-#define HANDLE_PRAGMA_REDEFINE_EXTNAME 1
+#define TARGET_HANDLE_PRAGMA_REDEFINE_EXTNAME 1
/* ??? Note: in order for -compat-bsd to work fully,
we must somehow arrange to fixincludes /usr/ucbinclude
@@ -47,8 +47,8 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
-%{pthreads:-D_REENTRANT -D_PTHREADS} \
-%{!pthreads:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}} \
+%{pthreads|pthread:-D_REENTRANT -D_PTHREADS} \
+%{!pthreads:%{!pthread:%{threads:-D_REENTRANT -D_SOLARIS_THREADS}}} \
%{compat-bsd:-iwithprefixbefore ucbinclude -I/usr/ucbinclude} \
"
@@ -60,7 +60,6 @@ Boston, MA 02111-1307, USA. */
builtin_define_std ("sun"); \
builtin_define ("__svr4__"); \
builtin_define ("__SVR4"); \
- builtin_define ("__PRAGMA_REDEFINE_EXTNAME"); \
builtin_assert ("system=unix"); \
builtin_assert ("system=svr4"); \
/* For C++ we need to add some additional macro \
@@ -94,8 +93,8 @@ Boston, MA 02111-1307, USA. */
"%{compat-bsd:-lucb -lsocket -lnsl -lelf -laio} \
%{!shared:\
%{!symbolic:\
- %{pthreads:-lpthread} \
- %{!pthreads:%{threads:-lthread}} \
+ %{pthreads|pthread:-lpthread} \
+ %{!pthreads:%{!pthread:%{threads:-lthread}}} \
%{p|pg:-ldl} -lc}}"
#undef ENDFILE_SPEC
@@ -142,13 +141,19 @@ Boston, MA 02111-1307, USA. */
#undef LINK_SPEC
#define LINK_SPEC \
"%{h*} %{v:-V} \
- %{b} %{Wl,*:%*} \
+ %{b} \
%{static:-dn -Bstatic} \
%{shared:-G -dy %{!mimpure-text:-z text}} \
%{symbolic:-Bsymbolic -G -dy -z text} \
%(link_arch) \
%{Qy:} %{!Qn:-Qy}"
+/* The Solaris linker doesn't understand constructor priorities. (The
+ GNU linker does support constructor priorities, so GNU ld
+ configuration files for Solaris override this setting.) */
+#undef SUPPORTS_INIT_PRIORITY
+#define SUPPORTS_INIT_PRIORITY 0
+
/* This defines which switch letters take arguments.
It is as in svr4.h but with -R added. */
#undef SWITCH_TAKES_ARG
@@ -193,7 +198,7 @@ extern void __enable_execute_stack (void *); \
void \
__enable_execute_stack (void *addr) \
{ \
- extern int mprotect (void *, size_t, int); \
+ extern int mprotect(void *, size_t, int); \
if (!need_enable_exec_stack) \
return; \
else { \
@@ -206,3 +211,35 @@ __enable_execute_stack (void *addr) \
perror ("mprotect of trampoline code"); \
} \
}
+
+/* Support Solaris-specific format checking for cmn_err. */
+#define TARGET_N_FORMAT_TYPES 1
+#define TARGET_FORMAT_TYPES solaris_format_types
+
+/* #pragma init and #pragma fini are implemented on top of init and
+ fini attributes. */
+#define SOLARIS_ATTRIBUTE_TABLE \
+ { "init", 0, 0, true, false, false, NULL }, \
+ { "fini", 0, 0, true, false, false, NULL }
+
+/* This is how to declare the size of a function. For Solaris, we output
+ any .init or .fini entries here. */
+#undef ASM_DECLARE_FUNCTION_SIZE
+#define ASM_DECLARE_FUNCTION_SIZE(FILE, FNAME, DECL) \
+ do \
+ { \
+ if (!flag_inhibit_size_directive) \
+ ASM_OUTPUT_MEASURED_SIZE (FILE, FNAME); \
+ solaris_output_init_fini (FILE, DECL); \
+ } \
+ while (0)
+
+/* Register the Solaris-specific #pragma directives. */
+#define REGISTER_TARGET_PRAGMAS() solaris_register_pragmas ()
+
+extern GTY(()) tree solaris_pending_aligns;
+extern GTY(()) tree solaris_pending_inits;
+extern GTY(()) tree solaris_pending_finis;
+
+/* Allow macro expansion in #pragma pack. */
+#define HANDLE_PRAGMA_PACK_WITH_EXPANSION
diff --git a/contrib/gcc/config/sparc/biarch64.h b/contrib/gcc/config/sparc/biarch64.h
index b825f4f..097831f 100644
--- a/contrib/gcc/config/sparc/biarch64.h
+++ b/contrib/gcc/config/sparc/biarch64.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Specify this in a cover file to provide bi-architecture (32/64) support. */
diff --git a/contrib/gcc/config/sparc/crtfastmath.c b/contrib/gcc/config/sparc/crtfastmath.c
index df3f907..d46a16a 100644
--- a/contrib/gcc/config/sparc/crtfastmath.c
+++ b/contrib/gcc/config/sparc/crtfastmath.c
@@ -22,8 +22,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
- * the Free Software Foundation, 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
*
* As a special exception, if you link this library with files
* compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/sparc/cypress.md b/contrib/gcc/config/sparc/cypress.md
index c234594..67596b0 100644
--- a/contrib/gcc/config/sparc/cypress.md
+++ b/contrib/gcc/config/sparc/cypress.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; The Cypress is a pretty simple single-issue processor.
diff --git a/contrib/gcc/config/sparc/hypersparc.md b/contrib/gcc/config/sparc/hypersparc.md
index d617efd..185be6f 100644
--- a/contrib/gcc/config/sparc/hypersparc.md
+++ b/contrib/gcc/config/sparc/hypersparc.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; The HyperSPARC is a dual-issue processor. It is not all that fancy.
diff --git a/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver b/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver
index e3ba0bb..ed280fe 100644
--- a/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver
+++ b/contrib/gcc/config/sparc/libgcc-sparc-glibc.ver
@@ -26,3 +26,36 @@ GLIBC_VER {
__frame_state_for
__register_frame_info_table
}
+
+%if !defined (__arch64__) && defined (__LONG_DOUBLE_128__)
+
+# long double 128 bit support from 32-bit libgcc_s.so.1 is only available
+# when configured with --with-long-double-128. Make sure all the
+# symbols are available at @@GCC_LDBL_* versions to make it clear
+# there is a configurable symbol set.
+
+%exclude {
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+
+ __divtc3
+ __multc3
+ __powitf2
+}
+
+%inherit GCC_LDBL_3.0 GCC_3.0
+GCC_LDBL_3.0 {
+ __fixtfdi
+ __fixunstfdi
+ __floatditf
+}
+
+%inherit GCC_LDBL_4.0.0 GCC_4.0.0
+GCC_LDBL_4.0.0 {
+ __divtc3
+ __multc3
+ __powitf2
+}
+
+%endif
diff --git a/contrib/gcc/config/sparc/linux-unwind.h b/contrib/gcc/config/sparc/linux-unwind.h
new file mode 100644
index 0000000..958cb2d
--- /dev/null
+++ b/contrib/gcc/config/sparc/linux-unwind.h
@@ -0,0 +1,158 @@
+/* DWARF2 EH unwinding support for SPARC Linux.
+ Copyright 2004, 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 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 with other programs, and to distribute
+those programs 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 another program.)
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+/* Do code reading to identify a signal frame, and set the frame
+ state data appropriately. See unwind-dw2.c for the structs. */
+
+/* Handle multilib correctly. */
+#if defined(__arch64__)
+
+/* 64-bit SPARC version */
+#define MD_FALLBACK_FRAME_STATE_FOR sparc64_fallback_frame_state
+
+static _Unwind_Reason_Code
+sparc64_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned int *pc = context->ra;
+ long new_cfa, i;
+ long regs_off, fpu_save_off;
+ long this_cfa, fpu_save;
+
+ if (pc[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */
+ || pc[1] != 0x91d0206d) /* ta 0x6d */
+ return _URC_END_OF_STACK;
+ regs_off = 192 + 128;
+ fpu_save_off = regs_off + (16 * 8) + (3 * 8) + (2 * 4);
+ this_cfa = (long) context->cfa;
+ new_cfa = *(long *)((context->cfa) + (regs_off + (14 * 8)));
+ new_cfa += 2047; /* Stack bias */
+ fpu_save = *(long *)((this_cfa) + (fpu_save_off));
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 14;
+ fs->cfa_offset = new_cfa - (long) context->cfa;
+ for (i = 1; i < 16; ++i)
+ {
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset =
+ this_cfa + (regs_off + (i * 8)) - new_cfa;
+ }
+ for (i = 0; i < 16; ++i)
+ {
+ fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 16].loc.offset =
+ this_cfa + (i * 8) - new_cfa;
+ }
+ if (fpu_save)
+ {
+ for (i = 0; i < 64; ++i)
+ {
+ if (i > 32 && (i & 0x1))
+ continue;
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset =
+ (fpu_save + (i * 4)) - new_cfa;
+ }
+ }
+ /* Stick return address into %g0, same trick Alpha uses. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset =
+ this_cfa + (regs_off + (16 * 8) + 8) - new_cfa;
+ fs->retaddr_column = 0;
+ return _URC_NO_REASON;
+}
+
+#else
+
+/* 32-bit SPARC version */
+#define MD_FALLBACK_FRAME_STATE_FOR sparc_fallback_frame_state
+
+static _Unwind_Reason_Code
+sparc_fallback_frame_state (struct _Unwind_Context *context,
+ _Unwind_FrameState *fs)
+{
+ unsigned int *pc = context->ra;
+ int new_cfa, i, oldstyle;
+ int regs_off, fpu_save_off;
+ int fpu_save, this_cfa;
+
+ if (pc[1] != 0x91d02010) /* ta 0x10 */
+ return _URC_END_OF_STACK;
+ if (pc[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */
+ oldstyle = 1;
+ else if (pc[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */
+ oldstyle = 0;
+ else
+ return _URC_END_OF_STACK;
+ if (oldstyle)
+ {
+ regs_off = 96;
+ fpu_save_off = regs_off + (4 * 4) + (16 * 4);
+ }
+ else
+ {
+ regs_off = 96 + 128;
+ fpu_save_off = regs_off + (4 * 4) + (16 * 4) + (2 * 4);
+ }
+ this_cfa = (int) context->cfa;
+ new_cfa = *(int *)((context->cfa) + (regs_off+(4*4)+(14 * 4)));
+ fpu_save = *(int *)((this_cfa) + (fpu_save_off));
+ fs->cfa_how = CFA_REG_OFFSET;
+ fs->cfa_reg = 14;
+ fs->cfa_offset = new_cfa - (int) context->cfa;
+ for (i = 1; i < 16; ++i)
+ {
+ if (i == 14)
+ continue;
+ fs->regs.reg[i].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i].loc.offset =
+ this_cfa + (regs_off+(4 * 4)+(i * 4)) - new_cfa;
+ }
+ for (i = 0; i < 16; ++i)
+ {
+ fs->regs.reg[i + 16].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 16].loc.offset =
+ this_cfa + (i * 4) - new_cfa;
+ }
+ if (fpu_save)
+ {
+ for (i = 0; i < 32; ++i)
+ {
+ fs->regs.reg[i + 32].how = REG_SAVED_OFFSET;
+ fs->regs.reg[i + 32].loc.offset =
+ (fpu_save + (i * 4)) - new_cfa;
+ }
+ }
+ /* Stick return address into %g0, same trick Alpha uses. */
+ fs->regs.reg[0].how = REG_SAVED_OFFSET;
+ fs->regs.reg[0].loc.offset = this_cfa+(regs_off+4)-new_cfa;
+ fs->retaddr_column = 0;
+ return _URC_NO_REASON;
+}
+
+#endif
diff --git a/contrib/gcc/config/sparc/linux.h b/contrib/gcc/config/sparc/linux.h
index 7ddf2a3..5af67a6 100644
--- a/contrib/gcc/config/sparc/linux.h
+++ b/contrib/gcc/config/sparc/linux.h
@@ -1,5 +1,5 @@
/* Definitions for SPARC running Linux-based GNU systems with ELF.
- Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004
+ Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by Eddie C. Dost (ecd@skynet.be)
@@ -17,18 +17,20 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define_std ("unix"); \
- builtin_define_std ("linux"); \
- builtin_define ("__gnu_linux__"); \
- builtin_assert ("system=linux"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=posix"); \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ if (TARGET_LONG_DOUBLE_128) \
+ builtin_define ("__LONG_DOUBLE_128__"); \
} \
while (0)
@@ -44,12 +46,7 @@ Boston, MA 02111-1307, USA. */
object constructed before entering `main'. */
#undef STARTFILE_SPEC
-#ifdef USE_GNULIBC_1
-#define STARTFILE_SPEC \
- "%{!shared: \
- %{pg:gcrt1.o%s} %{!pg:%{p:gcrt1.o%s} %{!p:crt1.o%s}}}\
- crti.o%s %{!shared:crtbegin.o%s} %{shared:crtbeginS.o%s}"
-#elif defined HAVE_LD_PIE
+#if defined HAVE_LD_PIE
#define STARTFILE_SPEC \
"%{!shared: %{pg|p:gcrt1.o%s;pie:Scrt1.o%s;:crt1.o%s}}\
crti.o%s %{static:crtbeginT.o%s;shared|pie:crtbeginS.o%s;:crtbegin.o%s}"
@@ -86,11 +83,6 @@ Boston, MA 02111-1307, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc GNU/Linux with ELF)");
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
-{"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
-
#undef SIZE_TYPE
#define SIZE_TYPE "unsigned int"
@@ -104,37 +96,14 @@ Boston, MA 02111-1307, USA. */
#define WCHAR_TYPE_SIZE 32
#undef CPP_SUBTARGET_SPEC
-#ifdef USE_GNULIBC_1
#define CPP_SUBTARGET_SPEC \
-"%{fPIC|fPIE|fpic|fpie:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
-%{mlong-double-128:-D__LONG_DOUBLE_128__}"
-#else
-#define CPP_SUBTARGET_SPEC \
-"%{fPIC|fPIE|fpic|fpie:-D__PIC__ -D__pic__} %{posix:-D_POSIX_SOURCE} \
-%{pthread:-D_REENTRANT} %{mlong-double-128:-D__LONG_DOUBLE_128__}"
-#endif
+"%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
#undef LIB_SPEC
-/* We no longer link with libc_p.a or libg.a by default. If you
- want to profile or debug the GNU/Linux C library, please add
- -lc_p or -ggdb to LDFLAGS at the link time, respectively. */
-#if 1
-#ifdef USE_GNULIBC_1
-#define LIB_SPEC \
- "%{!shared: %{p:-lgmon} %{pg:-lgmon} %{profile:-lgmon -lc_p} \
- %{!profile:%{!ggdb:-lc} %{ggdb:-lg}}}"
-#else
#define LIB_SPEC \
"%{pthread:-lpthread} \
%{shared:-lc} \
%{!shared:%{mieee-fp:-lieee} %{profile:-lc_p}%{!profile:-lc}}"
-#endif
-#else
-#define LIB_SPEC \
- "%{!shared: \
- %{mieee-fp:-lieee} %{p:-lgmon -lc_p} %{pg:-lgmon -lc_p} \
- %{!p:%{!pg:%{!g*:-lc} %{g*:-lg}}}}"
-#endif
/* Provide a LINK_SPEC appropriate for GNU/Linux. Here we provide support
for the special GCC options -static and -shared, which allow us to
@@ -152,25 +121,26 @@ Boston, MA 02111-1307, USA. */
/* If ELF is the default format, we should not use /lib/elf. */
-#undef LINK_SPEC
-#ifdef USE_GNULIBC_1
-#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
- %{!shared: \
- %{!ibcs: \
- %{!static: \
- %{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.1}} \
- %{static:-static}}}"
+#define GLIBC_DYNAMIC_LINKER "/lib/ld-linux.so.2"
+#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
+#if UCLIBC_DEFAULT
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
#else
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}" U ";:" G "}"
+#endif
+#define LINUX_DYNAMIC_LINKER \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER)
+
+
+#undef LINK_SPEC
#define LINK_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
%{!mno-relax:%{!r:-relax}} \
%{!shared: \
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER "}} \
%{static:-static}}}"
-#endif
/* 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. */
@@ -198,13 +168,6 @@ do { \
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to output a reference to an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-#undef ASM_OUTPUT_INTERNAL_LABELREF
-#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
- fprintf (FILE, ".L%s%d", PREFIX, NUM)
-
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class.
@@ -219,9 +182,6 @@ do { \
SPARC ABI says that long double is 4 words. */
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
-/* Constant which presents upper bound of the above value. */
-#define MAX_LONG_DOUBLE_TYPE_SIZE 128
-
/* Define this to set long double type size to use in libgcc2.c, which can
not depend on target_flags. */
#ifdef __LONG_DOUBLE_128__
@@ -233,7 +193,7 @@ do { \
#undef DITF_CONVERSION_LIBFUNCS
#define DITF_CONVERSION_LIBFUNCS 1
-#if !defined(USE_GNULIBC_1) && defined(HAVE_LD_EH_FRAME_HDR)
+#if defined(HAVE_LD_EH_FRAME_HDR)
#define LINK_EH_SPEC "%{!static:--eh-frame-hdr} "
#endif
@@ -251,78 +211,36 @@ do { \
#undef CTORS_SECTION_ASM_OP
#undef DTORS_SECTION_ASM_OP
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-
-/* Determine whether the the entire c99 runtime is present in the
+/* Determine whether the entire c99 runtime is present in the
runtime library. */
-#define TARGET_C99_FUNCTIONS 1
+#define TARGET_C99_FUNCTIONS (OPTION_GLIBC)
-#define TARGET_HAS_F_SETLKW
+#define TARGET_POSIX_IO
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- int new_cfa_, i_, oldstyle_; \
- int regs_off_, fpu_save_off_; \
- int fpu_save_, this_cfa_; \
- \
- if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
- break; \
- if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
- oldstyle_ = 1; \
- else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
- oldstyle_ = 0; \
- else \
- break; \
- if (oldstyle_) \
- { \
- regs_off_ = 96; \
- fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \
- } \
- else \
- { \
- regs_off_ = 96 + 128; \
- fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \
- } \
- this_cfa_ = (int) (CONTEXT)->cfa; \
- new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
- fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- if (i_ == 14) \
- continue; \
- (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_].loc.offset = \
- this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \
- } \
- for (i_ = 0; i_ < 16; ++i_) \
- { \
- (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 16].loc.offset = \
- this_cfa_ + (i_ * 4) - new_cfa_; \
- } \
- if (fpu_save_) \
- { \
- for (i_ = 0; i_ < 32; ++i_) \
- { \
- (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 32].loc.offset = \
- (fpu_save_ + (i_ * 4)) - new_cfa_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
+#endif
+
+#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h"
+
+/* Linux currently uses RMO in uniprocessor mode, which is equivalent to
+ TMO, and TMO in multiprocessor mode. But they reserve the right to
+ change their minds. */
+#undef SPARC_RELAXED_ORDERING
+#define SPARC_RELAXED_ORDERING true
+
+#undef NEED_INDICATE_EXEC_STACK
+#define NEED_INDICATE_EXEC_STACK 1
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* sparc glibc provides __stack_chk_guard in [%g7 + 0x14]. */
+#define TARGET_THREAD_SSP_OFFSET 0x14
+#endif
+
+/* Define if long doubles should be mangled as 'g'. */
+#define TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
diff --git a/contrib/gcc/config/sparc/linux64.h b/contrib/gcc/config/sparc/linux64.h
index bb1c591..b0ddf4b 100644
--- a/contrib/gcc/config/sparc/linux64.h
+++ b/contrib/gcc/config/sparc/linux64.h
@@ -1,5 +1,5 @@
/* Definitions for 64-bit SPARC running Linux-based GNU systems with ELF.
- Copyright 1996, 1997, 1998, 2000, 2002, 2003, 2004
+ Copyright 1996, 1997, 1998, 2000, 2002, 2003, 2004, 2005, 2006
Free Software Foundation, Inc.
Contributed by David S. Miller (davem@caip.rutgers.edu)
@@ -17,20 +17,22 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-#define TARGET_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("unix"); \
- builtin_define_std ("linux"); \
- builtin_define ("_LONGLONG"); \
- builtin_define ("__gnu_linux__"); \
- builtin_assert ("system=linux"); \
- builtin_assert ("system=unix"); \
- builtin_assert ("system=posix"); \
- } \
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#define TARGET_OS_CPP_BUILTINS() \
+ do \
+ { \
+ builtin_define_std ("unix"); \
+ builtin_define_std ("linux"); \
+ builtin_define ("_LONGLONG"); \
+ builtin_define ("__gnu_linux__"); \
+ builtin_assert ("system=linux"); \
+ builtin_assert ("system=unix"); \
+ builtin_assert ("system=posix"); \
+ if (TARGET_ARCH32 && TARGET_LONG_DOUBLE_128) \
+ builtin_define ("__LONG_DOUBLE_128__"); \
+ } \
while (0)
/* Don't assume anything about the header files. */
@@ -41,7 +43,8 @@ Boston, MA 02111-1307, USA. */
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_niagara
/* A 64 bit v9 compiler with stack-bias,
in a Medium/Low code model environment. */
@@ -54,13 +57,6 @@ Boston, MA 02111-1307, USA. */
#undef ASM_CPU_DEFAULT_SPEC
#define ASM_CPU_DEFAULT_SPEC "-Av9a"
-#ifdef SPARC_BI_ARCH
-
-#undef CPP_ARCH32_SPEC
-#define CPP_ARCH32_SPEC "%{mlong-double-128:-D__LONG_DOUBLE_128__}"
-
-#endif
-
/* 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
@@ -101,11 +97,6 @@ Boston, MA 02111-1307, USA. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_MEDLOW
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
-{"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
-
#undef WCHAR_TYPE
#define WCHAR_TYPE "int"
@@ -117,10 +108,6 @@ Boston, MA 02111-1307, USA. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
-/* Constant which presents upper bound of the above value. */
-#undef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE 128
-
/* Define this to set long double type size to use in libgcc2.c, which can
not depend on target_flags. */
#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
@@ -131,7 +118,6 @@ Boston, MA 02111-1307, USA. */
#undef CPP_SUBTARGET_SPEC
#define CPP_SUBTARGET_SPEC "\
-%{fPIC|fpic|fPIE|fpie:-D__PIC__ -D__pic__} \
%{posix:-D_POSIX_SOURCE} \
%{pthread:-D_REENTRANT} \
"
@@ -158,6 +144,20 @@ Boston, MA 02111-1307, USA. */
/* If ELF is the default format, we should not use /lib/elf. */
+#define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
+#define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux.so.2"
+#define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#if UCLIBC_DEFAULT
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{mglibc:%{muclibc:%e-mglibc and -muclibc used together}" G ";:" U "}"
+#else
+#define CHOOSE_DYNAMIC_LINKER(G, U) "%{muclibc:%{mglibc:%e-mglibc and -muclibc used together}" U ";:" G "}"
+#endif
+#define LINUX_DYNAMIC_LINKER32 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER32, UCLIBC_DYNAMIC_LINKER32)
+#define LINUX_DYNAMIC_LINKER64 \
+ CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64)
+
#ifdef SPARC_BI_ARCH
#undef SUBTARGET_EXTRA_SPECS
@@ -166,13 +166,13 @@ Boston, MA 02111-1307, USA. */
{ "link_arch64", LINK_ARCH64_SPEC }, \
{ "link_arch_default", LINK_ARCH_DEFAULT_SPEC }, \
{ "link_arch", LINK_ARCH_SPEC },
-
+
#define LINK_ARCH32_SPEC "-m elf32_sparc -Y P,/usr/lib %{shared:-shared} \
%{!shared: \
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib/ld-linux.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER32 "}} \
%{static:-static}}} \
"
@@ -181,7 +181,7 @@ Boston, MA 02111-1307, USA. */
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib64/ld-linux.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}} \
%{static:-static}}} \
"
@@ -262,7 +262,7 @@ Boston, MA 02111-1307, USA. */
%{!ibcs: \
%{!static: \
%{rdynamic:-export-dynamic} \
- %{!dynamic-linker:-dynamic-linker /lib64/ld-linux.so.2}} \
+ %{!dynamic-linker:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}} \
%{static:-static}}} \
%{mlittle-endian:-EL} \
%{!mno-relax:%{!r:-relax}} \
@@ -289,9 +289,6 @@ Boston, MA 02111-1307, USA. */
#undef DBX_REGISTER_NUMBER
#define DBX_REGISTER_NUMBER(REGNO) (REGNO)
-#define DWARF2_DEBUGGING_INFO 1
-#define DBX_DEBUGGING_INFO 1
-
#undef ASM_OUTPUT_ALIGNED_LOCAL
#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
do { \
@@ -307,13 +304,6 @@ do { \
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to output a reference to an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-#undef ASM_OUTPUT_INTERNAL_LABELREF
-#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
- fprintf (FILE, ".L%s%d", PREFIX, NUM)
-
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class.
@@ -353,133 +343,37 @@ do { \
#undef CTORS_SECTION_ASM_OP
#undef DTORS_SECTION_ASM_OP
-#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
-
-/* Determine whether the the entire c99 runtime is present in the
+/* Determine whether the entire c99 runtime is present in the
runtime library. */
-#define TARGET_C99_FUNCTIONS 1
+#define TARGET_C99_FUNCTIONS (OPTION_GLIBC)
-#define TARGET_HAS_F_SETLKW
+#define TARGET_POSIX_IO
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
"%{static:--start-group} %G %L %{static:--end-group}%{!static:%G}"
-/* Do code reading to identify a signal frame, and set the frame
- state data appropriately. See unwind-dw2.c for the structs. */
-
-/* Handle multilib correctly. */
-#if defined(__arch64__)
-/* 64-bit SPARC version */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- long new_cfa_, i_; \
- long regs_off_, fpu_save_off_; \
- long this_cfa_, fpu_save_; \
- \
- if (pc_[0] != 0x82102065 /* mov NR_rt_sigreturn, %g1 */ \
- || pc_[1] != 0x91d0206d) /* ta 0x6d */ \
- break; \
- regs_off_ = 192 + 128; \
- fpu_save_off_ = regs_off_ + (16 * 8) + (3 * 8) + (2 * 4); \
- this_cfa_ = (long) (CONTEXT)->cfa; \
- new_cfa_ = *(long *)(((CONTEXT)->cfa) + (regs_off_ + (14 * 8))); \
- new_cfa_ += 2047; /* Stack bias */ \
- fpu_save_ = *(long *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (long) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_].loc.offset = \
- this_cfa_ + (regs_off_ + (i_ * 8)) - new_cfa_; \
- } \
- for (i_ = 0; i_ < 16; ++i_) \
- { \
- (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 16].loc.offset = \
- this_cfa_ + (i_ * 8) - new_cfa_; \
- } \
- if (fpu_save_) \
- { \
- for (i_ = 0; i_ < 64; ++i_) \
- { \
- if (i_ > 32 && (i_ & 0x1)) \
- continue; \
- (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 32].loc.offset = \
- (fpu_save_ + (i_ * 4)) - new_cfa_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = \
- this_cfa_ + (regs_off_ + (16 * 8) + 8) - new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
-#else
-/* 32-bit SPARC version */
-#define MD_FALLBACK_FRAME_STATE_FOR(CONTEXT, FS, SUCCESS) \
- do { \
- unsigned int *pc_ = (CONTEXT)->ra; \
- int new_cfa_, i_, oldstyle_; \
- int regs_off_, fpu_save_off_; \
- int fpu_save_, this_cfa_; \
- \
- if (pc_[1] != 0x91d02010) /* ta 0x10 */ \
- break; \
- if (pc_[0] == 0x821020d8) /* mov NR_sigreturn, %g1 */ \
- oldstyle_ = 1; \
- else if (pc_[0] == 0x82102065) /* mov NR_rt_sigreturn, %g1 */ \
- oldstyle_ = 0; \
- else \
- break; \
- if (oldstyle_) \
- { \
- regs_off_ = 96; \
- fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4); \
- } \
- else \
- { \
- regs_off_ = 96 + 128; \
- fpu_save_off_ = regs_off_ + (4 * 4) + (16 * 4) + (2 * 4); \
- } \
- this_cfa_ = (int) (CONTEXT)->cfa; \
- new_cfa_ = *(int *)(((CONTEXT)->cfa) + (regs_off_+(4*4)+(14 * 4))); \
- fpu_save_ = *(int *)((this_cfa_) + (fpu_save_off_)); \
- (FS)->cfa_how = CFA_REG_OFFSET; \
- (FS)->cfa_reg = 14; \
- (FS)->cfa_offset = new_cfa_ - (int) (CONTEXT)->cfa; \
- for (i_ = 1; i_ < 16; ++i_) \
- { \
- if (i_ == 14) \
- continue; \
- (FS)->regs.reg[i_].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_].loc.offset = \
- this_cfa_ + (regs_off_+(4 * 4)+(i_ * 4)) - new_cfa_; \
- } \
- for (i_ = 0; i_ < 16; ++i_) \
- { \
- (FS)->regs.reg[i_ + 16].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 16].loc.offset = \
- this_cfa_ + (i_ * 4) - new_cfa_; \
- } \
- if (fpu_save_) \
- { \
- for (i_ = 0; i_ < 32; ++i_) \
- { \
- (FS)->regs.reg[i_ + 32].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[i_ + 32].loc.offset = \
- (fpu_save_ + (i_ * 4)) - new_cfa_; \
- } \
- } \
- /* Stick return address into %g0, same trick Alpha uses. */ \
- (FS)->regs.reg[0].how = REG_SAVED_OFFSET; \
- (FS)->regs.reg[0].loc.offset = this_cfa_+(regs_off_+4)-new_cfa_; \
- (FS)->retaddr_column = 0; \
- goto SUCCESS; \
- } while (0)
+/* Use --as-needed -lgcc_s for eh support. */
+#ifdef HAVE_LD_AS_NEEDED
+#define USE_LD_AS_NEEDED 1
#endif
+
+#define MD_UNWIND_SUPPORT "config/sparc/linux-unwind.h"
+
+/* Linux currently uses RMO in uniprocessor mode, which is equivalent to
+ TMO, and TMO in multiprocessor mode. But they reserve the right to
+ change their minds. */
+#undef SPARC_RELAXED_ORDERING
+#define SPARC_RELAXED_ORDERING true
+
+#undef NEED_INDICATE_EXEC_STACK
+#define NEED_INDICATE_EXEC_STACK 1
+
+#ifdef TARGET_LIBC_PROVIDES_SSP
+/* sparc glibc provides __stack_chk_guard in [%g7 + 0x14],
+ sparc64 glibc provides it at [%g7 + 0x28]. */
+#define TARGET_THREAD_SSP_OFFSET (TARGET_ARCH64 ? 0x28 : 0x14)
+#endif
+
+/* Define if long doubles should be mangled as 'g'. */
+#define TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
diff --git a/contrib/gcc/config/sparc/little-endian.opt b/contrib/gcc/config/sparc/little-endian.opt
new file mode 100644
index 0000000..eb039fd
--- /dev/null
+++ b/contrib/gcc/config/sparc/little-endian.opt
@@ -0,0 +1,28 @@
+; Options for the SPARC port of the compiler
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mlittle-endian
+Target Report RejectNegative Mask(LITTLE_ENDIAN) MaskExists
+Generate code for little-endian
+
+mbig-endian
+Target Report RejectNegative InverseMask(LITTLE_ENDIAN)
+Generate code for big-endian
diff --git a/contrib/gcc/config/sparc/long-double-switch.opt b/contrib/gcc/config/sparc/long-double-switch.opt
new file mode 100644
index 0000000..ffbecbe
--- /dev/null
+++ b/contrib/gcc/config/sparc/long-double-switch.opt
@@ -0,0 +1,28 @@
+; Options for the SPARC port of the compiler
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mlong-double-128
+Target Report RejectNegative Mask(LONG_DOUBLE_128) MaskExists
+Use 128-bit long double
+
+mlong-double-64
+Target Report RejectNegative InverseMask(LONG_DOUBLE_128)
+Use 64-bit long double
diff --git a/contrib/gcc/config/sparc/netbsd-elf.h b/contrib/gcc/config/sparc/netbsd-elf.h
index bc92eb2..b07fee3 100644
--- a/contrib/gcc/config/sparc/netbsd-elf.h
+++ b/contrib/gcc/config/sparc/netbsd-elf.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GCC, for ELF on NetBSD/sparc
and NetBSD/sparc64.
- Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Matthew Green (mrg@eterna.com.au).
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
@@ -51,28 +51,14 @@ Boston, MA 02111-1307, USA. */
#undef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
/* This is the char to use for continuation (in case we need to turn
continuation back on). */
#undef DBX_CONTIN_CHAR
#define DBX_CONTIN_CHAR '?'
-#undef DBX_REGISTER_NUMBER
-#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && REGNO == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
-
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to output a reference to an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-#undef ASM_OUTPUT_INTERNAL_LABELREF
-#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
- fprintf (FILE, ".L%s%d", PREFIX, NUM)
-
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class.
@@ -209,13 +195,6 @@ Boston, MA 02111-1307, USA. */
{ "netbsd_entry_point", NETBSD_ENTRY_POINT },
-/* What extra switches do we need? */
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
- {"long-double-64", -MASK_LONG_DOUBLE_128, N_("Use 64 bit long doubles") }, \
- {"long-double-128", MASK_LONG_DOUBLE_128, N_("Use 128 bit long doubles") },
-
-
/* Build a compiler that supports -m32 and -m64? */
#ifdef SPARC_BI_ARCH
@@ -223,9 +202,6 @@ Boston, MA 02111-1307, USA. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (TARGET_LONG_DOUBLE_128 ? 128 : 64)
-#undef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE 128
-
#if defined(__arch64__) || defined(__LONG_DOUBLE_128__)
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
#else
@@ -245,7 +221,7 @@ Boston, MA 02111-1307, USA. */
#define MULTILIB_DEFAULTS { "m64" }
#endif
-/* Name the port. */
+/* Name the port. */
#undef TARGET_NAME
#define TARGET_NAME (DEFAULT_ARCH32_P ? TARGET_NAME32 : TARGET_NAME64)
@@ -257,9 +233,6 @@ Boston, MA 02111-1307, USA. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 128
-#undef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE 128
-
#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 128
@@ -278,9 +251,6 @@ Boston, MA 02111-1307, USA. */
#undef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE 64
-#undef MAX_LONG_DOUBLE_TYPE_SIZE
-#define MAX_LONG_DOUBLE_TYPE_SIZE 64
-
#undef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
#define LIBGCC2_LONG_DOUBLE_TYPE_SIZE 64
diff --git a/contrib/gcc/config/sparc/niagara.md b/contrib/gcc/config/sparc/niagara.md
new file mode 100644
index 0000000..ea431b5
--- /dev/null
+++ b/contrib/gcc/config/sparc/niagara.md
@@ -0,0 +1,119 @@
+;; Scheduling description for Niagara.
+;; Copyright (C) 2006 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Niagara is a single-issue processor.
+
+(define_automaton "niagara_0")
+
+(define_cpu_unit "niag_pipe" "niagara_0")
+
+(define_insn_reservation "niag_5cycle" 5
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "multi,flushw,iflush,trap"))
+ "niag_pipe*5")
+
+(define_insn_reservation "niag_4cycle" 4
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "savew"))
+ "niag_pipe*4")
+
+/* Most basic operations are single-cycle. */
+(define_insn_reservation "niag_ialu" 1
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "ialu,shift,compare,cmove"))
+ "niag_pipe")
+
+(define_insn_reservation "niag_imul" 11
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "imul"))
+ "niag_pipe*11")
+
+(define_insn_reservation "niag_idiv" 72
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "idiv"))
+ "niag_pipe*72")
+
+(define_insn_reservation "niag_branch" 3
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "call,sibcall,call_no_delay_slot,uncond_branch,branch"))
+ "niag_pipe*3")
+
+(define_insn_reservation "niag_3cycle_load" 3
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "load"))
+ "niag_pipe*3")
+
+(define_insn_reservation "niag_9cycle_load" 9
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpload"))
+ "niag_pipe*9")
+
+(define_insn_reservation "niag_1cycle_store" 1
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "store"))
+ "niag_pipe")
+
+(define_insn_reservation "niag_8cycle_store" 8
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpstore"))
+ "niag_pipe*8")
+
+/* Things incorrectly modelled here:
+ * FPADD{s,d}: 26 cycles
+ * FPSUB{s,d}: 26 cycles
+ * FABSD: 26 cycles
+ * F{s,d}TO{s,d}: 26 cycles
+ * F{s,d}TO{i,x}: 26 cycles
+ * FSMULD: 29 cycles
+ */
+(define_insn_reservation "niag_fmov" 8
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpmove,fpcmove,fpcrmove"))
+ "niag_pipe*8")
+
+(define_insn_reservation "niag_fpcmp" 26
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpcmp"))
+ "niag_pipe*26")
+
+(define_insn_reservation "niag_fmult" 29
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpmul"))
+ "niag_pipe*29")
+
+(define_insn_reservation "niag_fdivs" 54
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpdivs"))
+ "niag_pipe*54")
+
+(define_insn_reservation "niag_fdivd" 83
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fpdivd"))
+ "niag_pipe*83")
+
+/* Things incorrectly modelled here:
+ * FPADD{16,32}: 10 cycles
+ * FPSUB{16,32}: 10 cycles
+ * FALIGNDATA: 10 cycles
+ */
+(define_insn_reservation "niag_vis" 8
+ (and (eq_attr "cpu" "niagara")
+ (eq_attr "type" "fga,fgm_pack,fgm_mul,fgm_cmp,fgm_pdist"))
+ "niag_pipe*8")
diff --git a/contrib/gcc/config/sparc/openbsd1-64.h b/contrib/gcc/config/sparc/openbsd1-64.h
index 1310538..4af8c44 100644
--- a/contrib/gcc/config/sparc/openbsd1-64.h
+++ b/contrib/gcc/config/sparc/openbsd1-64.h
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#define OBSD_HAS_DECLARE_FUNCTION_NAME
#define OBSD_HAS_DECLARE_FUNCTION_SIZE
diff --git a/contrib/gcc/config/sparc/openbsd64.h b/contrib/gcc/config/sparc/openbsd64.h
index e13c886..49f8d28 100644
--- a/contrib/gcc/config/sparc/openbsd64.h
+++ b/contrib/gcc/config/sparc/openbsd64.h
@@ -1,5 +1,5 @@
/* Configuration file for sparc64 OpenBSD target.
- Copyright (C) 1999 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2005 Free Software Foundation, Inc.
This file is part of GCC.
@@ -15,8 +15,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64 OpenBSD ELF)")
@@ -51,6 +51,9 @@ Boston, MA 02111-1307, USA. */
#undef MD_EXEC_PREFIX
#undef MD_STARTFILE_PREFIX
+/* Inherited from sp64-elf. */
+#undef NO_IMPLICIT_EXTERN_C
+
#undef ASM_SPEC
#define ASM_SPEC "\
%{v:-V} -s %{fpic|fPIC|fpie|fPIE:-K PIC} \
diff --git a/contrib/gcc/config/sparc/predicates.md b/contrib/gcc/config/sparc/predicates.md
new file mode 100644
index 0000000..048d651
--- /dev/null
+++ b/contrib/gcc/config/sparc/predicates.md
@@ -0,0 +1,478 @@
+;; Predicate definitions for SPARC.
+;; Copyright (C) 2005 Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;; Predicates for numerical constants.
+
+;; Return true if OP is the zero constant for MODE.
+(define_predicate "const_zero_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST0_RTX (mode)")))
+
+;; Return true if OP is the one constant for MODE.
+(define_predicate "const_one_operand"
+ (and (match_code "const_int,const_double,const_vector")
+ (match_test "op == CONST1_RTX (mode)")))
+
+;; Return true if OP is the integer constant 4096.
+(define_predicate "const_4096_operand"
+ (and (match_code "const_int")
+ (match_test "INTVAL (op) == 4096")))
+
+;; Return true if OP is a constant that is representable by a 13-bit
+;; signed field. This is an acceptable immediate operand for most
+;; 3-address instructions.
+(define_predicate "small_int_operand"
+ (and (match_code "const_int")
+ (match_test "SPARC_SIMM13_P (INTVAL (op))")))
+
+;; Return true if OP is a constant operand for the umul instruction. That
+;; instruction sign-extends immediate values just like all other SPARC
+;; instructions, but interprets the extended result as an unsigned number.
+(define_predicate "uns_small_int_operand"
+ (match_code "const_int,const_double")
+{
+#if HOST_BITS_PER_WIDE_INT == 32
+ return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
+ || (GET_CODE (op) == CONST_DOUBLE
+ && CONST_DOUBLE_HIGH (op) == 0
+ && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
+#else
+ return (GET_CODE (op) == CONST_INT
+ && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
+ || (INTVAL (op) >= 0xFFFFF000
+ && INTVAL (op) <= 0xFFFFFFFF)));
+#endif
+})
+
+;; Return true if OP is a constant that can be loaded by the sethi instruction.
+;; The first test avoids emitting sethi to load zero for example.
+(define_predicate "const_high_operand"
+ (and (match_code "const_int")
+ (and (not (match_operand 0 "small_int_operand"))
+ (match_test "SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))"))))
+
+;; Return true if OP is a constant whose 1's complement can be loaded by the
+;; sethi instruction.
+(define_predicate "const_compl_high_operand"
+ (and (match_code "const_int")
+ (and (not (match_operand 0 "small_int_operand"))
+ (match_test "SPARC_SETHI_P (~INTVAL (op) & GET_MODE_MASK (mode))"))))
+
+;; Return true if OP is a FP constant that needs to be loaded by the sethi/losum
+;; pair of instructions.
+(define_predicate "fp_const_high_losum_operand"
+ (match_operand 0 "const_double_operand")
+{
+ gcc_assert (mode == SFmode);
+ return fp_high_losum_p (op);
+})
+
+
+;; Predicates for symbolic constants.
+
+;; Return true if OP is either a symbol reference or a sum of a symbol
+;; reference and a constant.
+(define_predicate "symbolic_operand"
+ (match_code "symbol_ref,label_ref,const")
+{
+ enum machine_mode omode = GET_MODE (op);
+
+ if (omode != mode && omode != VOIDmode && mode != VOIDmode)
+ return false;
+
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF:
+ return !SYMBOL_REF_TLS_MODEL (op);
+
+ case LABEL_REF:
+ return true;
+
+ case CONST:
+ op = XEXP (op, 0);
+ return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
+ || GET_CODE (XEXP (op, 0)) == LABEL_REF)
+ && GET_CODE (XEXP (op, 1)) == CONST_INT);
+
+ default:
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a symbolic operand for the TLS Global Dynamic model.
+(define_predicate "tgd_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_GLOBAL_DYNAMIC")))
+
+;; Return true if OP is a symbolic operand for the TLS Local Dynamic model.
+(define_predicate "tld_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_DYNAMIC")))
+
+;; Return true if OP is a symbolic operand for the TLS Initial Exec model.
+(define_predicate "tie_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_INITIAL_EXEC")))
+
+;; Return true if OP is a symbolic operand for the TLS Local Exec model.
+(define_predicate "tle_symbolic_operand"
+ (and (match_code "symbol_ref")
+ (match_test "SYMBOL_REF_TLS_MODEL (op) == TLS_MODEL_LOCAL_EXEC")))
+
+;; Return true if the operand is an argument used in generating PIC references
+;; in either the medium/low or embedded medium/anywhere code models on V9.
+;; Check for (const (minus (symbol_ref:GOT)
+;; (const (minus (label) (pc)))))
+(define_predicate "medium_pic_operand"
+ (match_code "const")
+{
+ /* Check for (const (minus (symbol_ref:GOT)
+ (const (minus (label) (pc))))). */
+ op = XEXP (op, 0);
+ return GET_CODE (op) == MINUS
+ && GET_CODE (XEXP (op, 0)) == SYMBOL_REF
+ && GET_CODE (XEXP (op, 1)) == CONST
+ && GET_CODE (XEXP (XEXP (op, 1), 0)) == MINUS;
+})
+
+;; Return true if OP is a LABEL_REF of mode MODE.
+(define_predicate "label_ref_operand"
+ (and (match_code "label_ref")
+ (match_test "GET_MODE (op) == mode")))
+
+;; Return true if OP is a data segment reference. This includes the readonly
+;; data segment or, in other words, anything but the text segment.
+;; This is needed in the embedded medium/anywhere code model on V9. These
+;; values are accessed with EMBMEDANY_BASE_REG. */
+(define_predicate "data_segment_operand"
+ (match_code "symbol_ref,plus,const")
+{
+ switch (GET_CODE (op))
+ {
+ case SYMBOL_REF :
+ return ! SYMBOL_REF_FUNCTION_P (op);
+ case PLUS :
+ /* Assume canonical format of symbol + constant.
+ Fall through. */
+ case CONST :
+ return data_segment_operand (XEXP (op, 0), VOIDmode);
+ default :
+ gcc_unreachable ();
+ }
+})
+
+;; Return true if OP is a text segment reference.
+;; This is needed in the embedded medium/anywhere code model on V9.
+(define_predicate "text_segment_operand"
+ (match_code "label_ref,symbol_ref,plus,const")
+{
+ switch (GET_CODE (op))
+ {
+ case LABEL_REF :
+ return true;
+ case SYMBOL_REF :
+ return SYMBOL_REF_FUNCTION_P (op);
+ case PLUS :
+ /* Assume canonical format of symbol + constant.
+ Fall through. */
+ case CONST :
+ return text_segment_operand (XEXP (op, 0), VOIDmode);
+ default :
+ gcc_unreachable ();
+ }
+})
+
+
+;; Predicates for registers.
+
+;; Return true if OP is either the zero constant or a register.
+(define_predicate "register_or_zero_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "const_zero_operand")))
+
+;; Return true if OP is a register operand in a floating point register.
+(define_predicate "fp_register_operand"
+ (match_operand 0 "register_operand")
+{
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op); /* Possibly a MEM */
+ return REG_P (op) && SPARC_FP_REG_P (REGNO (op));
+})
+
+;; Return true if OP is an integer register.
+(define_special_predicate "int_register_operand"
+ (ior (match_test "register_operand (op, SImode)")
+ (match_test "TARGET_ARCH64 && register_operand (op, DImode)")))
+
+;; Return true if OP is a floating point condition code register.
+(define_predicate "fcc_register_operand"
+ (match_code "reg")
+{
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return false;
+ if (mode == VOIDmode
+ && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
+ return false;
+
+#if 0 /* ??? 1 when %fcc0-3 are pseudos first. See gen_compare_reg(). */
+ if (reg_renumber == 0)
+ return REGNO (op) >= FIRST_PSEUDO_REGISTER;
+ return REGNO_OK_FOR_CCFP_P (REGNO (op));
+#else
+ return ((unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG) < 4;
+#endif
+})
+
+;; Return true if OP is the floating point condition code register fcc0.
+(define_predicate "fcc0_register_operand"
+ (match_code "reg")
+{
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return false;
+ if (mode == VOIDmode
+ && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
+ return false;
+
+ return REGNO (op) == SPARC_FCC_REG;
+})
+
+;; Return true if OP is an integer or floating point condition code register.
+(define_predicate "icc_or_fcc_register_operand"
+ (match_code "reg")
+{
+ if (REGNO (op) == SPARC_ICC_REG)
+ {
+ if (mode != VOIDmode && mode != GET_MODE (op))
+ return false;
+ if (mode == VOIDmode
+ && GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode)
+ return false;
+
+ return true;
+ }
+
+ return fcc_register_operand (op, mode);
+})
+
+
+;; Predicates for arithmetic instructions.
+
+;; Return true if OP is a register, or is a constant that is representable
+;; by a 13-bit signed field. This is an acceptable operand for most
+;; 3-address instructions.
+(define_predicate "arith_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "small_int_operand")))
+
+;; 64-bit: Same as above.
+;; 32-bit: Return true if OP is a register, or is a constant that is
+;; representable by a couple of 13-bit signed fields. This is an
+;; acceptable operand for most 3-address splitters.
+(define_predicate "arith_double_operand"
+ (match_code "const_int,const_double,reg,subreg")
+{
+ bool arith_simple_operand = arith_operand (op, mode);
+ HOST_WIDE_INT m1, m2;
+
+ if (TARGET_ARCH64 || arith_simple_operand)
+ return arith_simple_operand;
+
+#if HOST_BITS_PER_WIDE_INT == 32
+ if (GET_CODE (op) != CONST_DOUBLE)
+ return false;
+ m1 = CONST_DOUBLE_LOW (op);
+ m2 = CONST_DOUBLE_HIGH (op);
+#else
+ if (GET_CODE (op) != CONST_INT)
+ return false;
+ m1 = trunc_int_for_mode (INTVAL (op), SImode);
+ m2 = trunc_int_for_mode (INTVAL (op) >> 32, SImode);
+#endif
+
+ return SPARC_SIMM13_P (m1) && SPARC_SIMM13_P (m2);
+})
+
+;; Return true if OP is suitable as second operand for add/sub.
+(define_predicate "arith_add_operand"
+ (ior (match_operand 0 "arith_operand")
+ (match_operand 0 "const_4096_operand")))
+
+;; Return true if OP is suitable as second double operand for add/sub.
+(define_predicate "arith_double_add_operand"
+ (match_code "const_int,const_double,reg,subreg")
+{
+ bool _arith_double_operand = arith_double_operand (op, mode);
+
+ if (_arith_double_operand)
+ return true;
+
+ return TARGET_ARCH64 && const_4096_operand (op, mode);
+})
+
+;; Return true if OP is a register, or is a CONST_INT that can fit in a
+;; signed 10-bit immediate field. This is an acceptable SImode operand for
+;; the movrcc instructions.
+(define_predicate "arith10_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "const_int")
+ (match_test "SPARC_SIMM10_P (INTVAL (op))"))))
+
+;; Return true if OP is a register, or is a CONST_INT that can fit in a
+;; signed 11-bit immediate field. This is an acceptable SImode operand for
+;; the movcc instructions.
+(define_predicate "arith11_operand"
+ (ior (match_operand 0 "register_operand")
+ (and (match_code "const_int")
+ (match_test "SPARC_SIMM11_P (INTVAL (op))"))))
+
+;; Return true if OP is a register or a constant for the umul instruction.
+(define_predicate "uns_arith_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "uns_small_int_operand")))
+
+
+;; Predicates for miscellaneous instructions.
+
+;; Return true if OP is valid for the lhs of a comparison insn.
+(define_predicate "compare_operand"
+ (match_code "reg,subreg,zero_extract")
+{
+ if (GET_CODE (op) == ZERO_EXTRACT)
+ return (register_operand (XEXP (op, 0), mode)
+ && small_int_operand (XEXP (op, 1), mode)
+ && small_int_operand (XEXP (op, 2), mode)
+ /* This matches cmp_zero_extract. */
+ && ((mode == SImode
+ && INTVAL (XEXP (op, 2)) > 19)
+ /* This matches cmp_zero_extract_sp64. */
+ || (TARGET_ARCH64
+ && mode == DImode
+ && INTVAL (XEXP (op, 2)) > 51)));
+ else
+ return register_operand (op, mode);
+})
+
+;; Return true if OP is a valid operand for the source of a move insn.
+(define_predicate "input_operand"
+ (match_code "const_int,const_double,const_vector,reg,subreg,mem")
+{
+ enum mode_class mclass;
+
+ /* If both modes are non-void they must be the same. */
+ if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
+ return false;
+
+ mclass = GET_MODE_CLASS (mode);
+
+ /* Allow any 1-instruction integer constant. */
+ if (mclass == MODE_INT
+ && (small_int_operand (op, mode) || const_high_operand (op, mode)))
+ return true;
+
+ /* If 32-bit mode and this is a DImode constant, allow it
+ so that the splits can be generated. */
+ if (TARGET_ARCH32
+ && mode == DImode
+ && (GET_CODE (op) == CONST_DOUBLE || GET_CODE (op) == CONST_INT))
+ return true;
+
+ if ((mclass == MODE_FLOAT && GET_CODE (op) == CONST_DOUBLE)
+ || (mclass == MODE_VECTOR_INT && GET_CODE (op) == CONST_VECTOR))
+ return true;
+
+ if (register_operand (op, mode))
+ return true;
+
+ /* If this is a SUBREG, look inside so that we handle paradoxical ones. */
+ if (GET_CODE (op) == SUBREG)
+ op = SUBREG_REG (op);
+
+ /* Check for valid MEM forms. */
+ if (GET_CODE (op) == MEM)
+ return memory_address_p (mode, XEXP (op, 0));
+
+ return false;
+})
+
+;; Return true if OP is an address suitable for a call insn.
+;; Call insn on SPARC can take a PC-relative constant address
+;; or any regular memory address.
+(define_predicate "call_address_operand"
+ (ior (match_operand 0 "symbolic_operand")
+ (match_test "memory_address_p (Pmode, op)")))
+
+;; Return true if OP is an operand suitable for a call insn.
+(define_predicate "call_operand"
+ (and (match_code "mem")
+ (match_test "call_address_operand (XEXP (op, 0), mode)")))
+
+
+;; Predicates for operators.
+
+;; Return true if OP is a comparison operator. This allows the use of
+;; MATCH_OPERATOR to recognize all the branch insns.
+(define_predicate "noov_compare_operator"
+ (match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
+{
+ enum rtx_code code = GET_CODE (op);
+ if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
+ || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
+ /* These are the only branches which work with CC_NOOVmode. */
+ return (code == EQ || code == NE || code == GE || code == LT);
+ return true;
+})
+
+;; Return true if OP is a 64-bit comparison operator. This allows the use of
+;; MATCH_OPERATOR to recognize all the branch insns.
+(define_predicate "noov_compare64_operator"
+ (and (match_code "ne,eq,ge,gt,le,lt,geu,gtu,leu,ltu")
+ (match_test "TARGET_V9"))
+{
+ enum rtx_code code = GET_CODE (op);
+ if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
+ /* These are the only branches which work with CCX_NOOVmode. */
+ return (code == EQ || code == NE || code == GE || code == LT);
+ return (GET_MODE (XEXP (op, 0)) == CCXmode);
+})
+
+;; Return true if OP is a comparison operator suitable for use in V9
+;; conditional move or branch on register contents instructions.
+(define_predicate "v9_register_compare_operator"
+ (match_code "eq,ne,ge,lt,le,gt"))
+
+;; Return true if OP is an operator which can set the condition codes
+;; explicitly. We do not include PLUS and MINUS because these
+;; require CC_NOOVmode, which we handle explicitly.
+(define_predicate "cc_arith_operator"
+ (match_code "and,ior,xor"))
+
+;; Return true if OP is an operator which can bitwise complement its
+;; second operand and set the condition codes explicitly.
+;; XOR is not here because combine canonicalizes (xor (not ...) ...)
+;; and (xor ... (not ...)) to (not (xor ...)). */
+(define_predicate "cc_arith_not_operator"
+ (match_code "and,ior"))
+
+;; Return true if OP is memory operand with just [%reg] addressing mode.
+(define_predicate "memory_reg_operand"
+ (and (match_code "mem")
+ (and (match_operand 0 "memory_operand")
+ (match_test "REG_P (XEXP (op, 0))"))))
diff --git a/contrib/gcc/config/sparc/rtemself.h b/contrib/gcc/config/sparc/rtemself.h
index ffb2a72..f94b0a2 100644
--- a/contrib/gcc/config/sparc/rtemself.h
+++ b/contrib/gcc/config/sparc/rtemself.h
@@ -1,5 +1,5 @@
/* Definitions for rtems targeting a SPARC using ELF.
- Copyright (C) 1996, 1997, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1996, 1997, 2000, 2002, 2005 Free Software Foundation, Inc.
Contributed by Joel Sherrill (joel@OARcorp.com).
This file is part of GCC.
@@ -16,16 +16,19 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Target OS builtins. */
-#define TARGET_SUB_OS_CPP_BUILTINS() \
+#undef TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define_std ("sparc"); \
builtin_define ("__rtems__"); \
builtin_define ("__USE_INIT_FINI__"); \
builtin_assert ("system=rtems"); \
} \
while (0)
+
+/* Use the default */
+#undef LINK_GCC_C_SEQUENCE_SPEC
diff --git a/contrib/gcc/config/sparc/sol2-64.h b/contrib/gcc/config/sparc/sol2-64.h
index d53747a..d0dd284 100644
--- a/contrib/gcc/config/sparc/sol2-64.h
+++ b/contrib/gcc/config/sparc/sol2-64.h
@@ -4,13 +4,4 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT /* + MASK_HARD_QUAD */ + \
- MASK_STACK_BIAS + MASK_FPU + MASK_LONG_DOUBLE_128)
-
-/* Target OS builtins. */
-#undef TARGET_SUB_OS_CPP_BUILTINS
-#define TARGET_SUB_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("sparc"); \
- } \
- while (0)
+ MASK_STACK_BIAS + MASK_APP_REGS + MASK_FPU + MASK_LONG_DOUBLE_128)
diff --git a/contrib/gcc/config/sparc/sol2-bi.h b/contrib/gcc/config/sparc/sol2-bi.h
index 80ec1da..87d14f0 100644
--- a/contrib/gcc/config/sparc/sol2-bi.h
+++ b/contrib/gcc/config/sparc/sol2-bi.h
@@ -1,9 +1,11 @@
/* Definitions of target machine for GCC, for bi-arch SPARC
running Solaris 2 using the system assembler and linker. */
-/* The default code model. */
+/* The default code model used to be CM_MEDANY on Solaris
+ but even Sun eventually found it to be quite wasteful
+ and changed it to CM_MEDMID in the Studio 9 compiler. */
#undef SPARC_DEFAULT_CMODEL
-#define SPARC_DEFAULT_CMODEL CM_MEDANY
+#define SPARC_DEFAULT_CMODEL CM_MEDMID
#define AS_SPARC64_FLAG "-xarch=v9"
@@ -37,6 +39,15 @@
#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
+#undef CPP_CPU64_DEFAULT_SPEC
+#define CPP_CPU64_DEFAULT_SPEC ""
+#undef ASM_CPU32_DEFAULT_SPEC
+#define ASM_CPU32_DEFAULT_SPEC "-xarch=v8plusb"
+#undef ASM_CPU64_DEFAULT_SPEC
+#define ASM_CPU64_DEFAULT_SPEC AS_SPARC64_FLAG "b"
+#endif
+
#if DEFAULT_ARCH32_P
#define DEF_ARCH32_SPEC(__str) "%{!m64:" __str "}"
#define DEF_ARCH64_SPEC(__str) "%{m64:" __str "}"
@@ -55,7 +66,7 @@
%{mcpu=sparclite|mcpu-f930|mcpu=f934:-D__sparclite__} \
%{mcpu=v8:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{mcpu=supersparc:-D__supersparc__ " DEF_ARCH32_SPEC("-D__sparcv8") "} \
-%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
+%{mcpu=v9|mcpu=ultrasparc|mcpu=ultrasparc3|mcpu=niagara:" DEF_ARCH32_SPEC("-D__sparcv8") "} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
"
@@ -64,7 +75,8 @@
%{mcpu=v9:" DEF_ARCH32_SPEC("-xarch=v8plus") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "} \
%{mcpu=ultrasparc:" DEF_ARCH32_SPEC("-xarch=v8plusa") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "a") "} \
%{mcpu=ultrasparc3:" DEF_ARCH32_SPEC("-xarch=v8plusb") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
-%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}} \
+%{mcpu=niagara:" DEF_ARCH32_SPEC("-xarch=v8plusb") DEF_ARCH64_SPEC(AS_SPARC64_FLAG "b") "} \
+%{!mcpu=niagara:%{!mcpu=ultrasparc3:%{!mcpu=ultrasparc:%{!mcpu=v9:%{mcpu*:" DEF_ARCH32_SPEC("-xarch=v8") DEF_ARCH64_SPEC(AS_SPARC64_FLAG) "}}}}} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -236,10 +248,3 @@
#else
#define MULTILIB_DEFAULTS { "m64" }
#endif
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
-
-#if defined(HAVE_AS_GDWARF2_DEBUG_FLAG) && defined(HAVE_AS_GSTABS_DEBUG_FLAG)
-# define ASM_DEBUG_SPEC "%{gstabs*:--gstabs}%{!gstabs*:%{g*:--gdwarf2}}"
-#endif
diff --git a/contrib/gcc/config/sparc/sol2-c1.asm b/contrib/gcc/config/sparc/sol2-c1.asm
index a1cc68d..fdd6e2b 100644
--- a/contrib/gcc/config/sparc/sol2-c1.asm
+++ b/contrib/gcc/config/sparc/sol2-c1.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/sparc/sol2-ci.asm b/contrib/gcc/config/sparc/sol2-ci.asm
index 3dc793c..5726d62 100644
--- a/contrib/gcc/config/sparc/sol2-ci.asm
+++ b/contrib/gcc/config/sparc/sol2-ci.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/sparc/sol2-cn.asm b/contrib/gcc/config/sparc/sol2-cn.asm
index 49e070f..6e2fb2c 100644
--- a/contrib/gcc/config/sparc/sol2-cn.asm
+++ b/contrib/gcc/config/sparc/sol2-cn.asm
@@ -23,8 +23,8 @@
!
! You should have received a copy of the GNU General Public License
! along with this program; see the file COPYING. If not, write to
-! the Free Software Foundation, 59 Temple Place - Suite 330,
-! Boston, MA 02111-1307, USA.
+! the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+! Boston, MA 02110-1301, USA.
!
! As a special exception, if you link this library with files
! compiled with GCC to produce an executable, this does not cause
diff --git a/contrib/gcc/config/sparc/sol2-gas-bi.h b/contrib/gcc/config/sparc/sol2-gas-bi.h
index bea2b3c..88b3954 100644
--- a/contrib/gcc/config/sparc/sol2-gas-bi.h
+++ b/contrib/gcc/config/sparc/sol2-gas-bi.h
@@ -3,9 +3,3 @@
#undef AS_SPARC64_FLAG
#define AS_SPARC64_FLAG "-TSO -64 -Av9"
-
-/* Emit a DTP-relative reference to a TLS variable. */
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- sparc_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
diff --git a/contrib/gcc/config/sparc/sol2-gas.h b/contrib/gcc/config/sparc/sol2-gas.h
new file mode 100644
index 0000000..942e39d
--- /dev/null
+++ b/contrib/gcc/config/sparc/sol2-gas.h
@@ -0,0 +1,13 @@
+/* Definitions of target machine for GCC, for SPARC running Solaris 2
+ using the GNU assembler. */
+
+/* Undefine this so that BNSYM/ENSYM pairs are emitted by STABS+. */
+#undef NO_DBX_BNSYM_ENSYM
+
+/* Use GNU extensions to TLS support. */
+#ifdef HAVE_AS_TLS
+#undef TARGET_SUN_TLS
+#undef TARGET_GNU_TLS
+#define TARGET_SUN_TLS 0
+#define TARGET_GNU_TLS 1
+#endif
diff --git a/contrib/gcc/config/sparc/sol2.h b/contrib/gcc/config/sparc/sol2.h
index e5ed818..d07e0c6 100644
--- a/contrib/gcc/config/sparc/sol2.h
+++ b/contrib/gcc/config/sparc/sol2.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GCC, for SPARC running Solaris 2
- Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004
- Free Software Foundation, Inc.
+ Copyright 1992, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2005,
+ 2006 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@netcom.com).
Additional changes by David V. Henkel-Wallace (gumby@cygnus.com).
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Supposedly the same as vanilla sparc svr4, except for the stuff below: */
@@ -41,11 +41,17 @@ Boston, MA 02111-1307, USA. */
#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusb"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
+#undef ASM_CPU_DEFAULT_SPEC
+#define ASM_CPU_DEFAULT_SPEC "-xarch=v8plusb"
+#endif
+
#undef ASM_CPU_SPEC
#define ASM_CPU_SPEC "\
%{mcpu=v9:-xarch=v8plus} \
%{mcpu=ultrasparc:-xarch=v8plusa} \
%{mcpu=ultrasparc3:-xarch=v8plusb} \
+%{mcpu=niagara:-xarch=v8plusb} \
%{!mcpu*:%(asm_cpu_default)} \
"
@@ -57,11 +63,6 @@ Boston, MA 02111-1307, USA. */
/* However it appears that Solaris 2.0 uses the same reg numbering as
the old BSD-style system did. */
-/* Same as sparc.h */
-#undef DBX_REGISTER_NUMBER
-#define DBX_REGISTER_NUMBER(REGNO) \
- (TARGET_FLAT && (REGNO) == HARD_FRAME_POINTER_REGNUM ? 31 : REGNO)
-
/* The Solaris 2 assembler uses .skip, not .zero, so put this back. */
#undef ASM_OUTPUT_SKIP
#define ASM_OUTPUT_SKIP(FILE,SIZE) \
@@ -70,13 +71,6 @@ Boston, MA 02111-1307, USA. */
#undef LOCAL_LABEL_PREFIX
#define LOCAL_LABEL_PREFIX "."
-/* This is how to output a reference to an internal numbered label where
- PREFIX is the class of label and NUM is the number within the class. */
-
-#undef ASM_OUTPUT_INTERNAL_LABELREF
-#define ASM_OUTPUT_INTERNAL_LABELREF(FILE,PREFIX,NUM) \
- fprintf (FILE, ".L%s%d", PREFIX, NUM)
-
/* This is how to store into the string LABEL
the symbol_ref name of an internal numbered label where
PREFIX is the class of label and NUM is the number within the class.
@@ -95,7 +89,7 @@ Boston, MA 02111-1307, USA. */
{ \
HOST_WIDE_INT size; \
\
- if (DECL_THREAD_LOCAL (DECL)) \
+ if (DECL_THREAD_LOCAL_P (DECL)) \
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "tls_object"); \
else \
ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
@@ -113,12 +107,9 @@ Boston, MA 02111-1307, USA. */
} \
while (0)
-/* The Solaris assembler cannot grok r_tls_dtpoff. This is
- a kludge as ASM_OUTPUT_DWARF_DTPREL is defined in sparc.h,
- undefined here and defined again in sol2-gas-bi.h. */
-#ifdef HAVE_AS_TLS
-#undef ASM_OUTPUT_DWARF_DTPREL
-#endif
+/* The Solaris assembler cannot grok .stabd directives. */
+#undef NO_DBX_BNSYM_ENSYM
+#define NO_DBX_BNSYM_ENSYM 1
#undef ENDFILE_SPEC
@@ -137,12 +128,7 @@ Boston, MA 02111-1307, USA. */
((flag_pic || GLOBAL) ? DW_EH_PE_aligned : DW_EH_PE_absptr)
#endif
-/* The Solaris linker doesn't understand constructor priorities. */
-#undef SUPPORTS_INIT_PRIORITY
-#define SUPPORTS_INIT_PRIORITY 0
-/* ??? This does not work in SunOS 4.x, so it is not enabled in sparc.h.
- Instead, it is enabled here, because it does work under Solaris. */
/* Define for support of TFmode long double.
SPARC ABI says that long double is 4 words. */
#define LONG_DOUBLE_TYPE_SIZE 128
@@ -168,4 +154,20 @@ Boston, MA 02111-1307, USA. */
/* Solaris allows 64 bit out and global registers in 32 bit mode.
sparc_override_options will disable V8+ if not generating V9 code. */
#undef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_V8PLUS + MASK_FPU + MASK_LONG_DOUBLE_128)
+#define TARGET_DEFAULT (MASK_V8PLUS + MASK_APP_REGS + MASK_FPU \
+ + MASK_LONG_DOUBLE_128)
+
+/* Solaris-specific #pragmas are implemented on top of attributes. Hook in
+ the bits from config/sol2.c. */
+#define SUBTARGET_INSERT_ATTRIBUTES solaris_insert_attributes
+#define SUBTARGET_ATTRIBUTE_TABLE SOLARIS_ATTRIBUTE_TABLE
+
+/* Output a simple call for .init/.fini. */
+#define ASM_OUTPUT_CALL(FILE, FN) \
+ do \
+ { \
+ fprintf (FILE, "\tcall\t"); \
+ print_operand (FILE, XEXP (DECL_RTL (FN), 0), 0); \
+ fprintf (FILE, "\n\tnop\n"); \
+ } \
+ while (0)
diff --git a/contrib/gcc/config/sparc/sp-elf.h b/contrib/gcc/config/sparc/sp-elf.h
new file mode 100644
index 0000000..ef49b82
--- /dev/null
+++ b/contrib/gcc/config/sparc/sp-elf.h
@@ -0,0 +1,80 @@
+/* Definitions of target machine for GCC,
+ for SPARC running in an embedded environment using the ELF file format.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
+
+#undef TARGET_VERSION
+#define TARGET_VERSION fprintf (stderr, " (sparc-elf)")
+
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
+
+/* 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
+#define ASM_SPEC \
+ "%{v:-V} %{Qy:} %{!Qn:-Qy} %{n} %{T} %{Ym,*} %{Wa,*:%*} -s \
+ %{fpic|fpie|fPIC|fPIE:-K PIC} %(asm_cpu)"
+
+/* Use the default. */
+#undef LINK_SPEC
+
+#undef STARTFILE_SPEC
+#define STARTFILE_SPEC "crt0.o%s crti.o%s crtbegin.o%s"
+
+#undef ENDFILE_SPEC
+#define ENDFILE_SPEC \
+ "%{ffast-math|funsafe-math-optimizations:crtfastmath.o%s} \
+ crtend.o%s crtn.o%s"
+
+/* Don't set the target flags, this is done by the linker script */
+#undef LIB_SPEC
+#define LIB_SPEC ""
+
+/* This defines which switch letters take arguments.
+ It is as in svr4.h but with -R added. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+ || (CHAR) == 'R' \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'z')
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM))
+
+/* ??? Inherited from sol2.h. Probably wrong. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "long int"
+
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE BITS_PER_WORD
+
+/* ??? until fixed. */
+#undef LONG_DOUBLE_TYPE_SIZE
+#define LONG_DOUBLE_TYPE_SIZE 64
diff --git a/contrib/gcc/config/sparc/sp64-elf.h b/contrib/gcc/config/sparc/sp64-elf.h
index 650c3ff..53f2144 100644
--- a/contrib/gcc/config/sparc/sp64-elf.h
+++ b/contrib/gcc/config/sparc/sp64-elf.h
@@ -1,5 +1,5 @@
/* Definitions of target machine for GCC, for SPARC64, ELF.
- Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000
+ Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2004, 2005
Free Software Foundation, Inc.
Contributed by Doug Evans, dje@cygnus.com.
@@ -17,19 +17,13 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
-
-/* ??? We're taking the scheme of including another file and then overriding
- the values we don't like a bit too far here. The alternative is to more or
- less duplicate all of svr4.h, sparc/sysv4.h, and sparc/sol2.h here
- (suitably cleaned up). */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#undef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc64-elf)")
/* A 64 bit v9 compiler in a Medium/Anywhere code model environment. */
-
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
(MASK_V9 + MASK_PTR64 + MASK_64BIT + MASK_HARD_QUAD \
@@ -38,14 +32,8 @@ Boston, MA 02111-1307, USA. */
#undef SPARC_DEFAULT_CMODEL
#define SPARC_DEFAULT_CMODEL CM_EMBMEDANY
-/* Target OS builtins for config/sol.h. */
-#undef TARGET_SUB_OS_CPP_BUILTINS
-#define TARGET_SUB_OS_CPP_BUILTINS() \
- do \
- { \
- builtin_define_std ("sparc"); \
- } \
- while (0)
+/* Don't assume anything about the header files. */
+#define NO_IMPLICIT_EXTERN_C
/* __svr4__ is used by the C library (FIXME) */
#undef CPP_SUBTARGET_SPEC
@@ -84,18 +72,33 @@ crtbegin.o%s \
/* Use the default (for now). */
#undef LIB_SPEC
-/* V9 chips can handle either endianness. */
-#undef SUBTARGET_SWITCHES
-#define SUBTARGET_SWITCHES \
-{"big-endian", -MASK_LITTLE_ENDIAN, N_("Generate code for big endian") }, \
-{"little-endian", MASK_LITTLE_ENDIAN, N_("Generate code for little endian") },
+/* This defines which switch letters take arguments.
+ It is as in svr4.h but with -R added. */
+#undef SWITCH_TAKES_ARG
+#define SWITCH_TAKES_ARG(CHAR) \
+ (DEFAULT_SWITCH_TAKES_ARG(CHAR) \
+ || (CHAR) == 'R' \
+ || (CHAR) == 'h' \
+ || (CHAR) == 'z')
#undef BYTES_BIG_ENDIAN
#define BYTES_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
#undef WORDS_BIG_ENDIAN
#define WORDS_BIG_ENDIAN (! TARGET_LITTLE_ENDIAN)
-
+
+#undef LOCAL_LABEL_PREFIX
+#define LOCAL_LABEL_PREFIX "."
+
+/* This is how to store into the string LABEL
+ the symbol_ref name of an internal numbered label where
+ PREFIX is the class of label and NUM is the number within the class.
+ This is suitable for output with `assemble_name'. */
+
+#undef ASM_GENERATE_INTERNAL_LABEL
+#define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \
+ sprintf ((LABEL), "*.L%s%ld", (PREFIX), (long)(NUM))
+
/* ??? This should be 32 bits for v9 but what can we do? */
#undef WCHAR_TYPE
#define WCHAR_TYPE "short unsigned int"
@@ -113,12 +116,3 @@ crtbegin.o%s \
this 0 to not confuse the branch shortening code. */
#undef JUMP_TABLES_IN_TEXT_SECTION
#define JUMP_TABLES_IN_TEXT_SECTION 0
-
-/* System V Release 4 uses DWARF debugging info.
- GDB doesn't support 64 bit stabs yet and the desired debug format is DWARF
- anyway so it is the default. */
-
-#define DBX_DEBUGGING_INFO 1
-
-#undef PREFERRED_DEBUGGING_TYPE
-#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
diff --git a/contrib/gcc/config/sparc/sparc-modes.def b/contrib/gcc/config/sparc/sparc-modes.def
index ea2a99d..5687a44 100644
--- a/contrib/gcc/config/sparc/sparc-modes.def
+++ b/contrib/gcc/config/sparc/sparc-modes.def
@@ -1,5 +1,5 @@
/* Definitions of target machine for GCC, for Sun SPARC.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2004 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64 bit SPARC V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* 128-bit floating point */
FLOAT_MODE (TF, 16, ieee_quad_format);
@@ -42,3 +42,7 @@ CC_MODE (CC_NOOV);
CC_MODE (CCX_NOOV);
CC_MODE (CCFP);
CC_MODE (CCFPE);
+
+/* Vector modes. */
+VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI */
+VECTOR_MODES (INT, 4); /* V4QI V2HI */
diff --git a/contrib/gcc/config/sparc/sparc-protos.h b/contrib/gcc/config/sparc/sparc-protos.h
index 3216f38..4fb862c 100644
--- a/contrib/gcc/config/sparc/sparc-protos.h
+++ b/contrib/gcc/config/sparc/sparc-protos.h
@@ -1,5 +1,5 @@
/* Prototypes of target machine for SPARC.
- Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -18,30 +18,22 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#ifndef __SPARC_PROTOS_H__
#define __SPARC_PROTOS_H__
-extern bool sparc_emitting_epilogue;
-
#ifdef TREE_CODE
extern struct rtx_def *function_value (tree, enum machine_mode, int);
extern void function_arg_advance (CUMULATIVE_ARGS *,
enum machine_mode, tree, int);
extern struct rtx_def *function_arg (const CUMULATIVE_ARGS *,
enum machine_mode, tree, int, int);
-extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern int function_arg_pass_by_reference (const CUMULATIVE_ARGS *,
- enum machine_mode, tree, int);
-extern struct rtx_def *sparc_builtin_saveregs (void);
#ifdef RTX_CODE
extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree);
extern void sparc_va_start (tree, rtx);
#endif
-extern struct rtx_def *sparc_va_arg (tree, tree);
extern unsigned long sparc_type_code (tree);
#ifdef ARGS_SIZE_RTX
/* expr.h defines ARGS_SIZE_RTX and `enum direction' */
@@ -49,24 +41,24 @@ extern enum direction function_arg_padding (enum machine_mode, tree);
#endif /* ARGS_SIZE_RTX */
#endif /* TREE_CODE */
-extern void load_pic_register (void);
extern void order_regs_for_local_alloc (void);
-extern HOST_WIDE_INT compute_frame_size (HOST_WIDE_INT, int);
+extern HOST_WIDE_INT sparc_compute_frame_size (HOST_WIDE_INT, int);
+extern void sparc_expand_prologue (void);
+extern void sparc_expand_epilogue (void);
+extern bool sparc_can_use_return_insn_p (void);
extern int check_pic (int);
extern int short_branch (int, int);
-extern int sparc_flat_epilogue_delay_slots (void);
-extern HOST_WIDE_INT sparc_flat_compute_frame_size (HOST_WIDE_INT);
extern void sparc_profile_hook (int);
extern void sparc_override_options (void);
-extern int leaf_return_peephole_ok (void);
extern void sparc_output_scratch_registers (FILE *);
#ifdef RTX_CODE
extern enum machine_mode select_cc_mode (enum rtx_code, rtx, rtx);
/* Define the function that build the compare insn for scc and bcc. */
-extern rtx gen_compare_reg (enum rtx_code code, rtx, rtx);
+extern rtx gen_compare_reg (enum rtx_code code);
extern void sparc_emit_float_lib_cmp (rtx, rtx, enum rtx_code);
-extern void sparc_emit_floatunsdi (rtx [2]);
+extern void sparc_emit_floatunsdi (rtx [2], enum machine_mode);
+extern void sparc_emit_fixunsdi (rtx [2], enum machine_mode);
extern void emit_tfmode_binop (enum rtx_code, rtx *);
extern void emit_tfmode_unop (enum rtx_code, rtx *);
extern void emit_tfmode_cvt (enum rtx_code, rtx *);
@@ -82,15 +74,18 @@ extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern rtx legitimize_tls_address (rtx);
extern rtx legitimize_address (rtx, rtx, enum machine_mode);
extern void sparc_defer_case_vector (rtx, rtx, int);
+extern bool sparc_expand_move (enum machine_mode, rtx *);
extern void sparc_emit_set_const32 (rtx, rtx);
extern void sparc_emit_set_const64 (rtx, rtx);
extern void sparc_emit_set_symbolic_const64 (rtx, rtx, rtx);
extern int sparc_splitdi_legitimate (rtx, rtx);
extern int sparc_absnegfloat_split_legitimate (rtx, rtx);
extern const char *output_ubranch (rtx, int, rtx);
-extern char *output_cbranch (rtx, rtx, int, int, int, int, rtx);
+extern const char *output_cbranch (rtx, rtx, int, int, int, rtx);
+extern const char *output_return (rtx);
extern const char *output_sibcall (rtx, rtx);
-extern char *output_v9branch (rtx, rtx, int, int, int, int, int, rtx);
+extern const char *output_v8plus_shift (rtx *, rtx, const char *);
+extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx);
extern void emit_v9_brxx_insn (enum rtx_code, rtx, rtx);
extern void print_operand (FILE *, rtx, int);
extern int mems_ok_for_ldd_peep (rtx, rtx, rtx);
@@ -99,29 +94,27 @@ extern int arith_4096_operand (rtx, enum machine_mode);
extern int zero_operand (rtx, enum machine_mode);
extern int fp_zero_operand (rtx, enum machine_mode);
extern int reg_or_0_operand (rtx, enum machine_mode);
-extern int tls_symbolic_operand (rtx);
extern int empty_delay_slot (rtx);
-extern int eligible_for_epilogue_delay (rtx, int);
+extern int eligible_for_return_delay (rtx);
extern int eligible_for_sibcall_delay (rtx);
extern int tls_call_delay (rtx);
extern int emit_move_sequence (rtx, enum machine_mode);
extern int fp_sethi_p (rtx);
extern int fp_mov_p (rtx);
extern int fp_high_losum_p (rtx);
+extern bool sparc_tls_referenced_p (rtx);
extern int mem_min_alignment (rtx, int);
extern int pic_address_needs_scratch (rtx);
extern int reg_unused_after (rtx, rtx);
extern int register_ok_for_ldd (rtx);
extern int registers_ok_for_ldd_peep (rtx, rtx);
-extern int sparc_flat_eligible_for_epilogue_delay (rtx, int);
extern int v9_regcmp_p (enum rtx_code);
-extern char *sparc_v8plus_shift (rtx *, rtx, const char *);
/* Function used for V8+ code generation. Returns 1 if the high
32 bits of REG are 0 before INSN. */
extern int sparc_check_64 (rtx, rtx);
extern rtx gen_df_reg (rtx, int);
extern int sparc_extra_constraint_check (rtx, int, int);
-extern void sparc_output_dwarf_dtprel (FILE*, int, rtx);
+extern void sparc_expand_compare_and_swap_12 (rtx, rtx, rtx, rtx);
#endif /* RTX_CODE */
#endif /* __SPARC_PROTOS_H__ */
diff --git a/contrib/gcc/config/sparc/sparc.c b/contrib/gcc/config/sparc/sparc.c
index 86524cc..692e46e 100644
--- a/contrib/gcc/config/sparc/sparc.c
+++ b/contrib/gcc/config/sparc/sparc.c
@@ -1,6 +1,7 @@
/* Subroutines for insn-output.c for SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -19,8 +20,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include "config.h"
#include "system.h"
@@ -32,6 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "hard-reg-set.h"
#include "real.h"
#include "insn-config.h"
+#include "insn-codes.h"
#include "conditions.h"
#include "output.h"
#include "insn-attr.h"
@@ -47,24 +49,197 @@ Boston, MA 02111-1307, USA. */
#include "target.h"
#include "target-def.h"
#include "cfglayout.h"
+#include "tree-gimple.h"
+#include "langhooks.h"
+
+/* Processor costs */
+static const
+struct processor_costs cypress_costs = {
+ COSTS_N_INSNS (2), /* int load */
+ COSTS_N_INSNS (2), /* int signed load */
+ COSTS_N_INSNS (2), /* int zeroed load */
+ COSTS_N_INSNS (2), /* float load */
+ COSTS_N_INSNS (5), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (5), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (7), /* fmul */
+ COSTS_N_INSNS (37), /* fdivs */
+ COSTS_N_INSNS (37), /* fdivd */
+ COSTS_N_INSNS (63), /* fsqrts */
+ COSTS_N_INSNS (63), /* fsqrtd */
+ COSTS_N_INSNS (1), /* imul */
+ COSTS_N_INSNS (1), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (1), /* idiv */
+ COSTS_N_INSNS (1), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+static const
+struct processor_costs supersparc_costs = {
+ COSTS_N_INSNS (1), /* int load */
+ COSTS_N_INSNS (1), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (0), /* float load */
+ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (3), /* fadd, fsub */
+ COSTS_N_INSNS (3), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (3), /* fmul */
+ COSTS_N_INSNS (6), /* fdivs */
+ COSTS_N_INSNS (9), /* fdivd */
+ COSTS_N_INSNS (12), /* fsqrts */
+ COSTS_N_INSNS (12), /* fsqrtd */
+ COSTS_N_INSNS (4), /* imul */
+ COSTS_N_INSNS (4), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (4), /* idiv */
+ COSTS_N_INSNS (4), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 1, /* shift penalty */
+};
+
+static const
+struct processor_costs hypersparc_costs = {
+ COSTS_N_INSNS (1), /* int load */
+ COSTS_N_INSNS (1), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (1), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (1), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (1), /* fmul */
+ COSTS_N_INSNS (8), /* fdivs */
+ COSTS_N_INSNS (12), /* fdivd */
+ COSTS_N_INSNS (17), /* fsqrts */
+ COSTS_N_INSNS (17), /* fsqrtd */
+ COSTS_N_INSNS (17), /* imul */
+ COSTS_N_INSNS (17), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (17), /* idiv */
+ COSTS_N_INSNS (17), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+static const
+struct processor_costs sparclet_costs = {
+ COSTS_N_INSNS (3), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (1), /* int zeroed load */
+ COSTS_N_INSNS (1), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (1), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (1), /* fmov, fmovr */
+ COSTS_N_INSNS (1), /* fmul */
+ COSTS_N_INSNS (1), /* fdivs */
+ COSTS_N_INSNS (1), /* fdivd */
+ COSTS_N_INSNS (1), /* fsqrts */
+ COSTS_N_INSNS (1), /* fsqrtd */
+ COSTS_N_INSNS (5), /* imul */
+ COSTS_N_INSNS (5), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (5), /* idiv */
+ COSTS_N_INSNS (5), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
-/* 1 if the caller has placed an "unimp" insn immediately after the call.
- This is used in v8 code when calling a function that returns a structure.
- v9 doesn't have this. Be careful to have this test be the same as that
- used on the call. */
+static const
+struct processor_costs ultrasparc_costs = {
+ COSTS_N_INSNS (2), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (2), /* int zeroed load */
+ COSTS_N_INSNS (2), /* float load */
+ COSTS_N_INSNS (1), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (4), /* fadd, fsub */
+ COSTS_N_INSNS (1), /* fcmp */
+ COSTS_N_INSNS (2), /* fmov, fmovr */
+ COSTS_N_INSNS (4), /* fmul */
+ COSTS_N_INSNS (13), /* fdivs */
+ COSTS_N_INSNS (23), /* fdivd */
+ COSTS_N_INSNS (13), /* fsqrts */
+ COSTS_N_INSNS (23), /* fsqrtd */
+ COSTS_N_INSNS (4), /* imul */
+ COSTS_N_INSNS (4), /* imulX */
+ 2, /* imul bit factor */
+ COSTS_N_INSNS (37), /* idiv */
+ COSTS_N_INSNS (68), /* idivX */
+ COSTS_N_INSNS (2), /* movcc/movr */
+ 2, /* shift penalty */
+};
-#define SKIP_CALLERS_UNIMP_P \
-(!TARGET_ARCH64 && current_function_returns_struct \
- && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))) \
- && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl))) \
- == INTEGER_CST))
+static const
+struct processor_costs ultrasparc3_costs = {
+ COSTS_N_INSNS (2), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (3), /* int zeroed load */
+ COSTS_N_INSNS (2), /* float load */
+ COSTS_N_INSNS (3), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (4), /* fadd, fsub */
+ COSTS_N_INSNS (5), /* fcmp */
+ COSTS_N_INSNS (3), /* fmov, fmovr */
+ COSTS_N_INSNS (4), /* fmul */
+ COSTS_N_INSNS (17), /* fdivs */
+ COSTS_N_INSNS (20), /* fdivd */
+ COSTS_N_INSNS (20), /* fsqrts */
+ COSTS_N_INSNS (29), /* fsqrtd */
+ COSTS_N_INSNS (6), /* imul */
+ COSTS_N_INSNS (6), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (40), /* idiv */
+ COSTS_N_INSNS (71), /* idivX */
+ COSTS_N_INSNS (2), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+static const
+struct processor_costs niagara_costs = {
+ COSTS_N_INSNS (3), /* int load */
+ COSTS_N_INSNS (3), /* int signed load */
+ COSTS_N_INSNS (3), /* int zeroed load */
+ COSTS_N_INSNS (9), /* float load */
+ COSTS_N_INSNS (8), /* fmov, fneg, fabs */
+ COSTS_N_INSNS (8), /* fadd, fsub */
+ COSTS_N_INSNS (26), /* fcmp */
+ COSTS_N_INSNS (8), /* fmov, fmovr */
+ COSTS_N_INSNS (29), /* fmul */
+ COSTS_N_INSNS (54), /* fdivs */
+ COSTS_N_INSNS (83), /* fdivd */
+ COSTS_N_INSNS (100), /* fsqrts - not implemented in hardware */
+ COSTS_N_INSNS (100), /* fsqrtd - not implemented in hardware */
+ COSTS_N_INSNS (11), /* imul */
+ COSTS_N_INSNS (11), /* imulX */
+ 0, /* imul bit factor */
+ COSTS_N_INSNS (72), /* idiv */
+ COSTS_N_INSNS (72), /* idivX */
+ COSTS_N_INSNS (1), /* movcc/movr */
+ 0, /* shift penalty */
+};
+
+const struct processor_costs *sparc_costs = &cypress_costs;
+
+#ifdef HAVE_AS_RELAX_OPTION
+/* If 'as' and 'ld' are relaxing tail call insns into branch always, use
+ "or %o7,%g0,X; call Y; or X,%g0,%o7" always, so that it can be optimized.
+ With sethi/jmp, neither 'as' nor 'ld' has an easy way how to find out if
+ somebody does not branch between the sethi and jmp. */
+#define LEAF_SIBCALL_SLOT_RESERVED_P 1
+#else
+#define LEAF_SIBCALL_SLOT_RESERVED_P \
+ ((TARGET_ARCH64 && !TARGET_CM_MEDLOW) || flag_pic)
+#endif
/* Global variables for machine-dependent things. */
/* Size of frame. Need to know this to emit return insns from leaf procedures.
- ACTUAL_FSIZE is set by compute_frame_size() which is called during the
- reload pass. This is important as the value is later used in insn
- scheduling (to see what can go in a delay slot).
+ ACTUAL_FSIZE is set by sparc_compute_frame_size() which is called during the
+ reload pass. This is important as the value is later used for scheduling
+ (to see what can go in a delay slot).
APPARENT_FSIZE is the size of the stack less the register save area and less
the outgoing argument area. It is used when saving call preserved regs. */
static HOST_WIDE_INT apparent_fsize;
@@ -74,13 +249,15 @@ static HOST_WIDE_INT actual_fsize;
saved (as 4-byte quantities). */
static int num_gfregs;
+/* The alias set for prologue/epilogue register save/restore. */
+static GTY(()) int sparc_sr_alias_set;
+
+/* The alias set for the structure return value. */
+static GTY(()) int struct_value_alias_set;
+
/* Save the operands last given to a compare for use when we
generate a scc or bcc insn. */
-rtx sparc_compare_op0, sparc_compare_op1;
-
-/* Coordinate with the md file wrt special insns created by
- sparc_nonflat_function_epilogue. */
-bool sparc_emitting_epilogue;
+rtx sparc_compare_op0, sparc_compare_op1, sparc_compare_emitted;
/* Vector to say how input registers are mapped to output registers.
HARD_FRAME_POINTER_REGNUM cannot be remapped by this function to
@@ -123,20 +300,32 @@ struct machine_function GTY(())
{
/* Some local-dynamic TLS symbol name. */
const char *some_ld_name;
+
+ /* True if the current function is leaf and uses only leaf regs,
+ so that the SPARC leaf function optimization can be applied.
+ Private version of current_function_uses_only_leaf_regs, see
+ sparc_expand_prologue for the rationale. */
+ int leaf_function_p;
+
+ /* True if the data calculated by sparc_expand_prologue are valid. */
+ bool prologue_data_valid_p;
};
-/* Name of where we pretend to think the frame pointer points.
- Normally, this is "%fp", but if we are in a leaf procedure,
- this is "%sp+something". We record "something" separately as it may be
- too big for reg+constant addressing. */
+#define sparc_leaf_function_p cfun->machine->leaf_function_p
+#define sparc_prologue_data_valid_p cfun->machine->prologue_data_valid_p
-static const char *frame_base_name;
+/* Register we pretend to think the frame pointer is allocated to.
+ Normally, this is %fp, but if we are in a leaf procedure, this
+ is %sp+"something". We record "something" separately as it may
+ be too big for reg+constant addressing. */
+static rtx frame_base_reg;
static HOST_WIDE_INT frame_base_offset;
+/* 1 if the next opcode is to be specially indented. */
+int sparc_indent_opcode = 0;
+
+static bool sparc_handle_option (size_t, const char *, int);
static void sparc_init_modes (void);
-static int save_regs (FILE *, int, int, const char *, int, int, HOST_WIDE_INT);
-static int restore_regs (FILE *, int, int, const char *, int, int);
-static void build_big_number (FILE *, HOST_WIDE_INT, const char *);
static void scan_record_type (tree, int *, int *, int *);
static int function_arg_slotno (const CUMULATIVE_ARGS *, enum machine_mode,
tree, int, int, int *, int *);
@@ -147,34 +336,23 @@ static int hypersparc_adjust_cost (rtx, rtx, rtx, int);
static void sparc_output_addr_vec (rtx);
static void sparc_output_addr_diff_vec (rtx);
static void sparc_output_deferred_case_vectors (void);
-static int check_return_regs (rtx);
+static rtx sparc_builtin_saveregs (void);
static int epilogue_renumber (rtx *, int);
static bool sparc_assemble_integer (rtx, unsigned int, int);
static int set_extends (rtx);
-static void output_restore_regs (FILE *, int);
-static void sparc_output_function_prologue (FILE *, HOST_WIDE_INT);
-static void sparc_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static void sparc_flat_function_epilogue (FILE *, HOST_WIDE_INT);
-static void sparc_flat_function_prologue (FILE *, HOST_WIDE_INT);
-static void sparc_flat_save_restore (FILE *, const char *, int,
- unsigned long, unsigned long,
- const char *, const char *,
- HOST_WIDE_INT);
-static void sparc_nonflat_function_epilogue (FILE *, HOST_WIDE_INT, int);
-static void sparc_nonflat_function_prologue (FILE *, HOST_WIDE_INT, int);
+static void emit_pic_helper (void);
+static void load_pic_register (bool);
+static int save_or_restore_regs (int, int, rtx, int, int);
+static void emit_save_or_restore_regs (int);
+static void sparc_asm_function_prologue (FILE *, HOST_WIDE_INT);
+static void sparc_asm_function_epilogue (FILE *, HOST_WIDE_INT);
#ifdef OBJECT_FORMAT_ELF
-static void sparc_elf_asm_named_section (const char *, unsigned int);
+static void sparc_elf_asm_named_section (const char *, unsigned int, tree);
#endif
-static void sparc_aout_select_section (tree, int, unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
-static void sparc_aout_select_rtx_section (enum machine_mode, rtx,
- unsigned HOST_WIDE_INT)
- ATTRIBUTE_UNUSED;
static int sparc_adjust_cost (rtx, rtx, rtx, int);
static int sparc_issue_rate (void);
static void sparc_sched_init (FILE *, int, int);
-static int sparc_use_dfa_pipeline_interface (void);
static int sparc_use_sched_lookahead (void);
static void emit_soft_tfmode_libcall (const char *, int, rtx *);
@@ -185,6 +363,12 @@ static void emit_hard_tfmode_operation (enum rtx_code, rtx *);
static bool sparc_function_ok_for_sibcall (tree, tree);
static void sparc_init_libfuncs (void);
+static void sparc_init_builtins (void);
+static void sparc_vis_init_builtins (void);
+static rtx sparc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
+static tree sparc_fold_builtin (tree, tree, bool);
+static int sparc_vis_mul8x16 (int, int);
+static tree sparc_handle_vis_mul8x16 (int, tree, tree, tree);
static void sparc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree);
static bool sparc_can_output_mi_thunk (tree, HOST_WIDE_INT,
@@ -196,11 +380,28 @@ static rtx sparc_tls_got (void);
static const char *get_some_local_dynamic_name (void);
static int get_some_local_dynamic_name_1 (rtx *, void *);
static bool sparc_rtx_costs (rtx, int, int, int *);
+static bool sparc_promote_prototypes (tree);
+static rtx sparc_struct_value_rtx (tree, int);
+static bool sparc_return_in_memory (tree, tree);
+static bool sparc_strict_argument_naming (CUMULATIVE_ARGS *);
+static tree sparc_gimplify_va_arg (tree, tree, tree *, tree *);
+static bool sparc_vector_mode_supported_p (enum machine_mode);
+static bool sparc_pass_by_reference (CUMULATIVE_ARGS *,
+ enum machine_mode, tree, bool);
+static int sparc_arg_partial_bytes (CUMULATIVE_ARGS *,
+ enum machine_mode, tree, bool);
+static void sparc_dwarf_handle_frame_unspec (const char *, rtx, int);
+static void sparc_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
+static void sparc_file_end (void);
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+static const char *sparc_mangle_fundamental_type (tree);
+#endif
+#ifdef SUBTARGET_ATTRIBUTE_TABLE
+const struct attribute_spec sparc_attribute_table[];
+#endif
/* Option handling. */
-/* Code model option as passed by user. */
-const char *sparc_cmodel_string;
/* Parsed value. */
enum cmodel sparc_cmodel;
@@ -217,7 +418,10 @@ struct sparc_cpu_select sparc_select[] =
/* CPU type. This is set from TARGET_CPU_DEFAULT and -m{cpu,tune}=xxx. */
enum processor_type sparc_cpu;
-
+
+/* Whether an FPU option was specified. */
+static bool fpu_option_set = false;
+
/* Initialize the GCC target structure. */
/* The sparc default is to use .half rather than .short for aligned
@@ -241,9 +445,9 @@ enum processor_type sparc_cpu;
#define TARGET_ASM_INTEGER sparc_assemble_integer
#undef TARGET_ASM_FUNCTION_PROLOGUE
-#define TARGET_ASM_FUNCTION_PROLOGUE sparc_output_function_prologue
+#define TARGET_ASM_FUNCTION_PROLOGUE sparc_asm_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE
-#define TARGET_ASM_FUNCTION_EPILOGUE sparc_output_function_epilogue
+#define TARGET_ASM_FUNCTION_EPILOGUE sparc_asm_function_epilogue
#undef TARGET_SCHED_ADJUST_COST
#define TARGET_SCHED_ADJUST_COST sparc_adjust_cost
@@ -251,8 +455,6 @@ enum processor_type sparc_cpu;
#define TARGET_SCHED_ISSUE_RATE sparc_issue_rate
#undef TARGET_SCHED_INIT
#define TARGET_SCHED_INIT sparc_sched_init
-#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
-#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE sparc_use_dfa_pipeline_interface
#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD
#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD sparc_use_sched_lookahead
@@ -261,11 +463,19 @@ enum processor_type sparc_cpu;
#undef TARGET_INIT_LIBFUNCS
#define TARGET_INIT_LIBFUNCS sparc_init_libfuncs
+#undef TARGET_INIT_BUILTINS
+#define TARGET_INIT_BUILTINS sparc_init_builtins
-#ifdef HAVE_AS_TLS
+#undef TARGET_EXPAND_BUILTIN
+#define TARGET_EXPAND_BUILTIN sparc_expand_builtin
+#undef TARGET_FOLD_BUILTIN
+#define TARGET_FOLD_BUILTIN sparc_fold_builtin
+
+#if TARGET_TLS
#undef TARGET_HAVE_TLS
#define TARGET_HAVE_TLS true
#endif
+
#undef TARGET_CANNOT_FORCE_CONST_MEM
#define TARGET_CANNOT_FORCE_CONST_MEM sparc_cannot_force_const_mem
@@ -279,8 +489,104 @@ enum processor_type sparc_cpu;
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST hook_int_rtx_0
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
+ no-op for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime
+ test for this value. */
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
+
+/* This is only needed for TARGET_ARCH64, but since PROMOTE_FUNCTION_MODE is a
+ no-op for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime
+ test for this value. */
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
+
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES sparc_promote_prototypes
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX sparc_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY sparc_return_in_memory
+#undef TARGET_MUST_PASS_IN_STACK
+#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
+#undef TARGET_PASS_BY_REFERENCE
+#define TARGET_PASS_BY_REFERENCE sparc_pass_by_reference
+#undef TARGET_ARG_PARTIAL_BYTES
+#define TARGET_ARG_PARTIAL_BYTES sparc_arg_partial_bytes
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS sparc_builtin_saveregs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING sparc_strict_argument_naming
+
+#undef TARGET_GIMPLIFY_VA_ARG_EXPR
+#define TARGET_GIMPLIFY_VA_ARG_EXPR sparc_gimplify_va_arg
+
+#undef TARGET_VECTOR_MODE_SUPPORTED_P
+#define TARGET_VECTOR_MODE_SUPPORTED_P sparc_vector_mode_supported_p
+
+#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
+#define TARGET_DWARF_HANDLE_FRAME_UNSPEC sparc_dwarf_handle_frame_unspec
+
+#ifdef SUBTARGET_INSERT_ATTRIBUTES
+#undef TARGET_INSERT_ATTRIBUTES
+#define TARGET_INSERT_ATTRIBUTES SUBTARGET_INSERT_ATTRIBUTES
+#endif
+
+#ifdef SUBTARGET_ATTRIBUTE_TABLE
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE sparc_attribute_table
+#endif
+
+#undef TARGET_RELAXED_ORDERING
+#define TARGET_RELAXED_ORDERING SPARC_RELAXED_ORDERING
+
+#undef TARGET_DEFAULT_TARGET_FLAGS
+#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION sparc_handle_option
+
+#if TARGET_GNU_TLS
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL sparc_output_dwarf_dtprel
+#endif
+
+#undef TARGET_ASM_FILE_END
+#define TARGET_ASM_FILE_END sparc_file_end
+
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+#undef TARGET_MANGLE_FUNDAMENTAL_TYPE
+#define TARGET_MANGLE_FUNDAMENTAL_TYPE sparc_mangle_fundamental_type
+#endif
+
struct gcc_target targetm = TARGET_INITIALIZER;
-
+
+/* Implement TARGET_HANDLE_OPTION. */
+
+static bool
+sparc_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED)
+{
+ switch (code)
+ {
+ case OPT_mfpu:
+ case OPT_mhard_float:
+ case OPT_msoft_float:
+ fpu_option_set = true;
+ break;
+
+ case OPT_mcpu_:
+ sparc_select[1].string = arg;
+ break;
+
+ case OPT_mtune_:
+ sparc_select[2].string = arg;
+ break;
+ }
+
+ return true;
+}
+
/* Validate and override various options, and do some machine dependent
initialization. */
@@ -315,6 +621,7 @@ sparc_override_options (void)
{ TARGET_CPU_v9, "v9" },
{ TARGET_CPU_ultrasparc, "ultrasparc" },
{ TARGET_CPU_ultrasparc3, "ultrasparc3" },
+ { TARGET_CPU_niagara, "niagara" },
{ 0, 0 }
};
const struct cpu_default *def;
@@ -350,6 +657,8 @@ sparc_override_options (void)
/* TI ultrasparc III */
/* ??? Check if %y issue still holds true in ultra3. */
{ "ultrasparc3", PROCESSOR_ULTRASPARC3, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
+ /* UltraSPARC T1 */
+ { "niagara", PROCESSOR_NIAGARA, MASK_ISA, MASK_V9|MASK_DEPRECATED_V8_INSNS},
{ 0, 0, 0, 0 }
};
const struct cpu_table *cpu;
@@ -400,8 +709,7 @@ sparc_override_options (void)
for (def = &cpu_default[0]; def->name; ++def)
if (def->cpu == TARGET_CPU_DEFAULT)
break;
- if (! def->name)
- abort ();
+ gcc_assert (def->name);
sparc_select[0].string = def->name;
for (sel = &sparc_select[0]; sel->name; ++sel)
@@ -428,13 +736,9 @@ sparc_override_options (void)
}
/* If -mfpu or -mno-fpu was explicitly used, don't override with
- the processor default. Clear MASK_FPU_SET to avoid confusing
- the reverse mapping from switch values to names. */
- if (TARGET_FPU_SET)
- {
- target_flags = (target_flags & ~MASK_FPU) | fpu;
- target_flags &= ~MASK_FPU_SET;
- }
+ the processor default. */
+ if (fpu_option_set)
+ target_flags = (target_flags & ~MASK_FPU) | fpu;
/* Don't allow -mvis if FPU is disabled. */
if (! TARGET_FPU)
@@ -464,7 +768,8 @@ sparc_override_options (void)
/* Supply a default value for align_functions. */
if (align_functions == 0
&& (sparc_cpu == PROCESSOR_ULTRASPARC
- || sparc_cpu == PROCESSOR_ULTRASPARC3))
+ || sparc_cpu == PROCESSOR_ULTRASPARC3
+ || sparc_cpu == PROCESSOR_NIAGARA))
align_functions = 32;
/* Validate PCC_STRUCT_RETURN. */
@@ -478,10 +783,62 @@ sparc_override_options (void)
/* Do various machine dependent initializations. */
sparc_init_modes ();
+ /* Acquire unique alias sets for our private stuff. */
+ sparc_sr_alias_set = new_alias_set ();
+ struct_value_alias_set = new_alias_set ();
+
/* Set up function hooks. */
init_machine_status = sparc_init_machine_status;
+
+ switch (sparc_cpu)
+ {
+ case PROCESSOR_V7:
+ case PROCESSOR_CYPRESS:
+ sparc_costs = &cypress_costs;
+ break;
+ case PROCESSOR_V8:
+ case PROCESSOR_SPARCLITE:
+ case PROCESSOR_SUPERSPARC:
+ sparc_costs = &supersparc_costs;
+ break;
+ case PROCESSOR_F930:
+ case PROCESSOR_F934:
+ case PROCESSOR_HYPERSPARC:
+ case PROCESSOR_SPARCLITE86X:
+ sparc_costs = &hypersparc_costs;
+ break;
+ case PROCESSOR_SPARCLET:
+ case PROCESSOR_TSC701:
+ sparc_costs = &sparclet_costs;
+ break;
+ case PROCESSOR_V9:
+ case PROCESSOR_ULTRASPARC:
+ sparc_costs = &ultrasparc_costs;
+ break;
+ case PROCESSOR_ULTRASPARC3:
+ sparc_costs = &ultrasparc3_costs;
+ break;
+ case PROCESSOR_NIAGARA:
+ sparc_costs = &niagara_costs;
+ break;
+ };
+
+#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
+ if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
+ target_flags |= MASK_LONG_DOUBLE_128;
+#endif
}
+#ifdef SUBTARGET_ATTRIBUTE_TABLE
+/* Table of valid machine attributes. */
+const struct attribute_spec sparc_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ SUBTARGET_ATTRIBUTE_TABLE,
+ { NULL, 0, 0, false, false, false, NULL }
+};
+#endif
+
/* Miscellaneous utilities. */
/* Nonzero if CODE, a comparison, is suitable for use in v9 conditional move
@@ -494,58 +851,6 @@ v9_regcmp_p (enum rtx_code code)
|| code == LE || code == GT);
}
-
-/* Operand constraints. */
-
-/* Return nonzero only if OP is a register of mode MODE,
- or const0_rtx. */
-
-int
-reg_or_0_operand (rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
- if (op == const0_rtx)
- return 1;
- if (GET_MODE (op) == VOIDmode && GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && CONST_DOUBLE_LOW (op) == 0)
- return 1;
- if (fp_zero_operand (op, mode))
- return 1;
- return 0;
-}
-
-/* Return nonzero only if OP is const1_rtx. */
-
-int
-const1_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return op == const1_rtx;
-}
-
-/* Nonzero if OP is a floating point value with value 0.0. */
-
-int
-fp_zero_operand (rtx op, enum machine_mode mode)
-{
- if (GET_MODE_CLASS (GET_MODE (op)) != MODE_FLOAT)
- return 0;
- return op == CONST0_RTX (mode);
-}
-
-/* Nonzero if OP is a register operand in floating point register. */
-
-int
-fp_register_operand (rtx op, enum machine_mode mode)
-{
- if (! register_operand (op, mode))
- return 0;
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- return GET_CODE (op) == REG && SPARC_FP_REG_P (REGNO (op));
-}
-
/* Nonzero if OP is a floating point constant which can
be loaded into an integer register using a single
sethi instruction. */
@@ -559,12 +864,8 @@ fp_sethi_p (rtx op)
long i;
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SETHI_P (i))
- return 1;
+ return !SPARC_SIMM13_P (i) && SPARC_SETHI_P (i);
}
return 0;
@@ -583,12 +884,8 @@ fp_mov_p (rtx op)
long i;
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (SPARC_SIMM13_P (i))
- return 1;
+ return SPARC_SIMM13_P (i);
}
return 0;
@@ -610,763 +907,161 @@ fp_high_losum_p (rtx op)
long i;
REAL_VALUE_FROM_CONST_DOUBLE (r, op);
- if (REAL_VALUES_EQUAL (r, dconst0) &&
- ! REAL_VALUE_MINUS_ZERO (r))
- return 0;
REAL_VALUE_TO_TARGET_SINGLE (r, i);
- if (! SPARC_SETHI_P (i)
- && ! SPARC_SIMM13_P (i))
- return 1;
+ return !SPARC_SIMM13_P (i) && !SPARC_SETHI_P (i);
}
return 0;
}
-/* Nonzero if OP is an integer register. */
+/* Expand a move instruction. Return true if all work is done. */
-int
-intreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (register_operand (op, SImode)
- || (TARGET_ARCH64 && register_operand (op, DImode)));
-}
-
-/* Nonzero if OP is a floating point condition code register. */
-
-int
-fcc_reg_operand (rtx op, enum machine_mode mode)
-{
- /* This can happen when recog is called from combine. Op may be a MEM.
- Fail instead of calling abort in this case. */
- if (GET_CODE (op) != REG)
- return 0;
-
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
- return 0;
-
-#if 0 /* ??? ==> 1 when %fcc0-3 are pseudos first. See gen_compare_reg(). */
- if (reg_renumber == 0)
- return REGNO (op) >= FIRST_PSEUDO_REGISTER;
- return REGNO_OK_FOR_CCFP_P (REGNO (op));
-#else
- return (unsigned) REGNO (op) - SPARC_FIRST_V9_FCC_REG < 4;
-#endif
-}
-
-/* Nonzero if OP is a floating point condition code fcc0 register. */
-
-int
-fcc0_reg_operand (rtx op, enum machine_mode mode)
-{
- /* This can happen when recog is called from combine. Op may be a MEM.
- Fail instead of calling abort in this case. */
- if (GET_CODE (op) != REG)
- return 0;
-
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && (GET_MODE (op) != CCFPmode && GET_MODE (op) != CCFPEmode))
- return 0;
-
- return REGNO (op) == SPARC_FCC_REG;
-}
-
-/* Nonzero if OP is an integer or floating point condition code register. */
-
-int
-icc_or_fcc_reg_operand (rtx op, enum machine_mode mode)
+bool
+sparc_expand_move (enum machine_mode mode, rtx *operands)
{
- if (GET_CODE (op) == REG && REGNO (op) == SPARC_ICC_REG)
+ /* Handle sets of MEM first. */
+ if (GET_CODE (operands[0]) == MEM)
{
- if (mode != VOIDmode && mode != GET_MODE (op))
- return 0;
- if (mode == VOIDmode
- && GET_MODE (op) != CCmode && GET_MODE (op) != CCXmode)
- return 0;
- return 1;
- }
-
- return fcc_reg_operand (op, mode);
-}
-
-/* Nonzero if OP can appear as the dest of a RESTORE insn. */
-int
-restore_operand (rtx op, enum machine_mode mode)
-{
- return (GET_CODE (op) == REG && GET_MODE (op) == mode
- && (REGNO (op) < 8 || (REGNO (op) >= 24 && REGNO (op) < 32)));
-}
-
-/* Call insn on SPARC can take a PC-relative constant address, or any regular
- memory address. */
-
-int
-call_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != MEM)
- abort ();
- op = XEXP (op, 0);
- return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
-}
-
-int
-call_operand_address (rtx op, enum machine_mode mode)
-{
- return (symbolic_operand (op, mode) || memory_address_p (Pmode, op));
-}
-
-/* If OP is a SYMBOL_REF of a thread-local symbol, return its TLS mode,
- otherwise return 0. */
-
-int
-tls_symbolic_operand (rtx op)
-{
- if (GET_CODE (op) != SYMBOL_REF)
- return 0;
- return SYMBOL_REF_TLS_MODEL (op);
-}
-
-int
-tgd_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_GLOBAL_DYNAMIC;
-}
-
-int
-tld_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_DYNAMIC;
-}
-
-int
-tie_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_INITIAL_EXEC;
-}
-
-int
-tle_symbolic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return tls_symbolic_operand (op) == TLS_MODEL_LOCAL_EXEC;
-}
-
-/* Returns 1 if OP is either a symbol reference or a sum of a symbol
- reference and a constant. */
-
-int
-symbolic_operand (register rtx op, enum machine_mode mode)
-{
- enum machine_mode omode = GET_MODE (op);
+ /* 0 is a register (or a pair of registers) on SPARC. */
+ if (register_or_zero_operand (operands[1], mode))
+ return false;
- if (omode != mode && omode != VOIDmode && mode != VOIDmode)
- return 0;
+ if (!reload_in_progress)
+ {
+ operands[0] = validize_mem (operands[0]);
+ operands[1] = force_reg (mode, operands[1]);
+ }
+ }
- switch (GET_CODE (op))
+ /* Fixup TLS cases. */
+ if (TARGET_HAVE_TLS
+ && CONSTANT_P (operands[1])
+ && GET_CODE (operands[1]) != HIGH
+ && sparc_tls_referenced_p (operands [1]))
{
- case SYMBOL_REF:
- return !SYMBOL_REF_TLS_MODEL (op);
+ rtx sym = operands[1];
+ rtx addend = NULL;
- case LABEL_REF:
- return 1;
+ if (GET_CODE (sym) == CONST && GET_CODE (XEXP (sym, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (sym, 0), 1);
+ sym = XEXP (XEXP (sym, 0), 0);
+ }
- case CONST:
- op = XEXP (op, 0);
- return (((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- && !SYMBOL_REF_TLS_MODEL (XEXP (op, 0)))
- || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- && GET_CODE (XEXP (op, 1)) == CONST_INT);
+ gcc_assert (SPARC_SYMBOL_REF_TLS_P (sym));
- default:
- return 0;
+ sym = legitimize_tls_address (sym);
+ if (addend)
+ {
+ sym = gen_rtx_PLUS (mode, sym, addend);
+ sym = force_operand (sym, operands[0]);
+ }
+ operands[1] = sym;
}
-}
-
-/* Return truth value of statement that OP is a symbolic memory
- operand of mode MODE. */
-
-int
-symbolic_memory_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
- if (GET_CODE (op) != MEM)
- return 0;
- op = XEXP (op, 0);
- return ((GET_CODE (op) == SYMBOL_REF && !SYMBOL_REF_TLS_MODEL (op))
- || GET_CODE (op) == CONST || GET_CODE (op) == HIGH
- || GET_CODE (op) == LABEL_REF);
-}
-
-/* Return truth value of statement that OP is a LABEL_REF of mode MODE. */
-
-int
-label_ref_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) != LABEL_REF)
- return 0;
- if (GET_MODE (op) != mode)
- return 0;
- return 1;
-}
-
-/* Return 1 if the operand is an argument used in generating pic references
- in either the medium/low or medium/anywhere code models of sparc64. */
+
+ /* Fixup PIC cases. */
+ if (flag_pic && CONSTANT_P (operands[1]))
+ {
+ if (pic_address_needs_scratch (operands[1]))
+ operands[1] = legitimize_pic_address (operands[1], mode, 0);
-int
-sp64_medium_pic_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* Check for (const (minus (symbol_ref:GOT)
- (const (minus (label) (pc))))). */
- if (GET_CODE (op) != CONST)
- return 0;
- op = XEXP (op, 0);
- if (GET_CODE (op) != MINUS)
- return 0;
- if (GET_CODE (XEXP (op, 0)) != SYMBOL_REF)
- return 0;
- /* ??? Ensure symbol is GOT. */
- if (GET_CODE (XEXP (op, 1)) != CONST)
- return 0;
- if (GET_CODE (XEXP (XEXP (op, 1), 0)) != MINUS)
- return 0;
- return 1;
-}
+ if (GET_CODE (operands[1]) == LABEL_REF && mode == SImode)
+ {
+ emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
-/* Return 1 if the operand is a data segment reference. This includes
- the readonly data segment, or in other words anything but the text segment.
- This is needed in the medium/anywhere code model on v9. These values
- are accessed with EMBMEDANY_BASE_REG. */
+ if (GET_CODE (operands[1]) == LABEL_REF && mode == DImode)
+ {
+ gcc_assert (TARGET_ARCH64);
+ emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
+ return true;
+ }
-int
-data_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
- {
- case SYMBOL_REF :
- return ! SYMBOL_REF_FUNCTION_P (op);
- case PLUS :
- /* Assume canonical format of symbol + constant.
- Fall through. */
- case CONST :
- return data_segment_operand (XEXP (op, 0), VOIDmode);
- default :
- return 0;
+ if (symbolic_operand (operands[1], mode))
+ {
+ operands[1] = legitimize_pic_address (operands[1],
+ mode,
+ (reload_in_progress ?
+ operands[0] :
+ NULL_RTX));
+ return false;
+ }
}
-}
-
-/* Return 1 if the operand is a text segment reference.
- This is needed in the medium/anywhere code model on v9. */
-int
-text_segment_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (op))
+ /* If we are trying to toss an integer constant into FP registers,
+ or loading a FP or vector constant, force it into memory. */
+ if (CONSTANT_P (operands[1])
+ && REG_P (operands[0])
+ && (SPARC_FP_REG_P (REGNO (operands[0]))
+ || SCALAR_FLOAT_MODE_P (mode)
+ || VECTOR_MODE_P (mode)))
{
- case LABEL_REF :
- return 1;
- case SYMBOL_REF :
- return SYMBOL_REF_FUNCTION_P (op);
- case PLUS :
- /* Assume canonical format of symbol + constant.
- Fall through. */
- case CONST :
- return text_segment_operand (XEXP (op, 0), VOIDmode);
- default :
- return 0;
- }
-}
-
-/* Return 1 if the operand is either a register or a memory operand that is
- not symbolic. */
-
-int
-reg_or_nonsymb_mem_operand (register rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
-
- if (memory_operand (op, mode) && ! symbolic_memory_operand (op, mode))
- return 1;
-
- return 0;
-}
-
-int
-splittable_symbolic_memory_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- if (! symbolic_operand (XEXP (op, 0), Pmode))
- return 0;
- return 1;
-}
-
-int
-splittable_immediate_memory_operand (rtx op,
- enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != MEM)
- return 0;
- if (! immediate_operand (XEXP (op, 0), Pmode))
- return 0;
- return 1;
-}
-
-/* Return truth value of whether OP is EQ or NE. */
-
-int
-eq_or_neq (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == EQ || GET_CODE (op) == NE);
-}
-
-/* Return 1 if this is a comparison operator, but not an EQ, NE, GEU,
- or LTU for non-floating-point. We handle those specially. */
-
-int
-normal_comp_operator (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
-
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- if (GET_MODE (XEXP (op, 0)) == CCFPmode
- || GET_MODE (XEXP (op, 0)) == CCFPEmode)
- return 1;
-
- return (code != NE && code != EQ && code != GEU && code != LTU);
-}
-
-/* Return 1 if this is a comparison operator. This allows the use of
- MATCH_OPERATOR to recognize all the branch insns. */
-
-int
-noov_compare_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
+ /* emit_group_store will send such bogosity to us when it is
+ not storing directly into memory. So fix this up to avoid
+ crashes in output_constant_pool. */
+ if (operands [1] == const0_rtx)
+ operands[1] = CONST0_RTX (mode);
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- if (GET_MODE (XEXP (op, 0)) == CC_NOOVmode
- || GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
- /* These are the only branches which work with CC_NOOVmode. */
- return (code == EQ || code == NE || code == GE || code == LT);
- return 1;
-}
-
-/* Return 1 if this is a 64-bit comparison operator. This allows the use of
- MATCH_OPERATOR to recognize all the branch insns. */
-
-int
-noov_compare64_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
-
- if (! TARGET_V9)
- return 0;
-
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- if (GET_MODE (XEXP (op, 0)) == CCX_NOOVmode)
- /* These are the only branches which work with CCX_NOOVmode. */
- return (code == EQ || code == NE || code == GE || code == LT);
- return (GET_MODE (XEXP (op, 0)) == CCXmode);
-}
-
-/* Nonzero if OP is a comparison operator suitable for use in v9
- conditional move or branch on register contents instructions. */
-
-int
-v9_regcmp_op (register rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- enum rtx_code code = GET_CODE (op);
-
- if (GET_RTX_CLASS (code) != '<')
- return 0;
-
- return v9_regcmp_p (code);
-}
-
-/* Return 1 if this is a SIGN_EXTEND or ZERO_EXTEND operation. */
-
-int
-extend_op (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return GET_CODE (op) == SIGN_EXTEND || GET_CODE (op) == ZERO_EXTEND;
-}
-
-/* Return nonzero if OP is an operator of mode MODE which can set
- the condition codes explicitly. We do not include PLUS and MINUS
- because these require CC_NOOVmode, which we handle explicitly. */
-
-int
-cc_arithop (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) == AND
- || GET_CODE (op) == IOR
- || GET_CODE (op) == XOR)
- return 1;
-
- return 0;
-}
-
-/* Return nonzero if OP is an operator of mode MODE which can bitwise
- complement its second operand and set the condition codes explicitly. */
-
-int
-cc_arithopn (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- /* XOR is not here because combine canonicalizes (xor (not ...) ...)
- and (xor ... (not ...)) to (not (xor ...)). */
- return (GET_CODE (op) == AND
- || GET_CODE (op) == IOR);
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 13 bit immediate field. This is an acceptable SImode operand for
- most 3 address instructions. */
-
-int
-arith_operand (rtx op, enum machine_mode mode)
-{
- if (register_operand (op, mode))
- return 1;
- if (GET_CODE (op) != CONST_INT)
- return 0;
- return SMALL_INT32 (op);
-}
-
-/* Return true if OP is a constant 4096 */
-
-int
-arith_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- if (GET_CODE (op) != CONST_INT)
- return 0;
- else
- return INTVAL (op) == 4096;
-}
-
-/* Return true if OP is suitable as second operand for add/sub */
-
-int
-arith_add_operand (rtx op, enum machine_mode mode)
-{
- return arith_operand (op, mode) || arith_4096_operand (op, mode);
-}
-
-/* Return true if OP is a CONST_INT or a CONST_DOUBLE which can fit in the
- immediate field of OR and XOR instructions. Used for 64-bit
- constant formation patterns. */
-int
-const64_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT
- && SPARC_SIMM13_P (INTVAL (op)))
-#if HOST_BITS_PER_WIDE_INT != 64
- || (GET_CODE (op) == CONST_DOUBLE
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
- && (CONST_DOUBLE_HIGH (op) ==
- ((CONST_DOUBLE_LOW (op) & 0x80000000) != 0 ?
- (HOST_WIDE_INT)-1 : 0)))
-#endif
- );
-}
-
-/* The same, but only for sethi instructions. */
-int
-const64_high_operand (rtx op, enum machine_mode mode)
-{
- return ((GET_CODE (op) == CONST_INT
- && (INTVAL (op) & ~(HOST_WIDE_INT)0x3ff) != 0
- && SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
- )
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & ~(HOST_WIDE_INT)0x3ff) != 0
- && SPARC_SETHI_P (CONST_DOUBLE_LOW (op))));
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 11 bit immediate field. This is an acceptable SImode operand for
- the movcc instructions. */
-
-int
-arith11_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SPARC_SIMM11_P (INTVAL (op))));
-}
-
-/* Return true if OP is a register, or is a CONST_INT that can fit in a
- signed 10 bit immediate field. This is an acceptable SImode operand for
- the movrcc instructions. */
-
-int
-arith10_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SPARC_SIMM10_P (INTVAL (op))));
-}
-
-/* Return true if OP is a register, is a CONST_INT that fits in a 13 bit
- immediate field, or is a CONST_DOUBLE whose both parts fit in a 13 bit
- immediate field.
- v9: Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in a 13 bit immediate field. This is an acceptable DImode operand
- for most 3 address instructions. */
-
-int
-arith_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || (! TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_HIGH (op) + 0x1000) < 0x2000)
- || (TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x1000) < 0x2000
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x1000) == 0x1000)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x1000) == 0))));
-}
-
-/* Return true if OP is a constant 4096 for DImode on ARCH64 */
-
-int
-arith_double_4096_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (TARGET_ARCH64 &&
- ((GET_CODE (op) == CONST_INT && INTVAL (op) == 4096) ||
- (GET_CODE (op) == CONST_DOUBLE &&
- CONST_DOUBLE_LOW (op) == 4096 &&
- CONST_DOUBLE_HIGH (op) == 0)));
-}
-
-/* Return true if OP is suitable as second operand for add/sub in DImode */
-
-int
-arith_double_add_operand (rtx op, enum machine_mode mode)
-{
- return arith_double_operand (op, mode) || arith_double_4096_operand (op, mode);
-}
-
-/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in an 11 bit immediate field. This is an acceptable DImode
- operand for the movcc instructions. */
-/* ??? Replace with arith11_operand? */
-
-int
-arith11_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_DOUBLE
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (CONST_DOUBLE_LOW (op) + 0x400) < 0x800
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x400) == 0x400)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x400) == 0)))
- || (GET_CODE (op) == CONST_INT
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x400) < 0x800));
-}
-
-/* Return true if OP is a register, or is a CONST_INT or CONST_DOUBLE that
- can fit in an 10 bit immediate field. This is an acceptable DImode
- operand for the movrcc instructions. */
-/* ??? Replace with arith10_operand? */
-
-int
-arith10_double_operand (rtx op, enum machine_mode mode)
-{
- return (register_operand (op, mode)
- || (GET_CODE (op) == CONST_DOUBLE
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned) (CONST_DOUBLE_LOW (op) + 0x200) < 0x400
- && ((CONST_DOUBLE_HIGH (op) == -1
- && (CONST_DOUBLE_LOW (op) & 0x200) == 0x200)
- || (CONST_DOUBLE_HIGH (op) == 0
- && (CONST_DOUBLE_LOW (op) & 0x200) == 0)))
- || (GET_CODE (op) == CONST_INT
- && (GET_MODE (op) == mode || GET_MODE (op) == VOIDmode)
- && (unsigned HOST_WIDE_INT) (INTVAL (op) + 0x200) < 0x400));
-}
-
-/* Return truth value of whether OP is an integer which fits the
- range constraining immediate operands in most three-address insns,
- which have a 13 bit immediate field. */
-
-int
-small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == CONST_INT && SMALL_INT (op));
-}
-
-int
-small_int_or_double (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return ((GET_CODE (op) == CONST_INT && SMALL_INT (op))
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))));
-}
-
-/* Recognize operand values for the umul instruction. That instruction sign
- extends immediate values just like all other sparc instructions, but
- interprets the extended result as an unsigned number. */
-
-int
-uns_small_int (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
-#if HOST_BITS_PER_WIDE_INT > 32
- /* All allowed constants will fit a CONST_INT. */
- return (GET_CODE (op) == CONST_INT
- && ((INTVAL (op) >= 0 && INTVAL (op) < 0x1000)
- || (INTVAL (op) >= 0xFFFFF000
- && INTVAL (op) <= 0xFFFFFFFF)));
-#else
- return ((GET_CODE (op) == CONST_INT && (unsigned) INTVAL (op) < 0x1000)
- || (GET_CODE (op) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (op) == 0
- && (unsigned) CONST_DOUBLE_LOW (op) - 0xFFFFF000 < 0x1000));
-#endif
-}
-
-int
-uns_arith_operand (rtx op, enum machine_mode mode)
-{
- return register_operand (op, mode) || uns_small_int (op, mode);
-}
-
-/* Return truth value of statement that OP is a call-clobbered register. */
-int
-clobbered_register (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
-{
- return (GET_CODE (op) == REG && call_used_regs[REGNO (op)]);
-}
-
-/* Return 1 if OP is a valid operand for the source of a move insn. */
-
-int
-input_operand (rtx op, enum machine_mode mode)
-{
- /* If both modes are non-void they must be the same. */
- if (mode != VOIDmode && GET_MODE (op) != VOIDmode && mode != GET_MODE (op))
- return 0;
-
- /* Accept CONSTANT_P_RTX, since it will be gone by CSE1 and result in 0/1. */
- if (GET_CODE (op) == CONSTANT_P_RTX)
- return 1;
+ /* We can clear FP registers if TARGET_VIS, and always other regs. */
+ if ((TARGET_VIS || REGNO (operands[0]) < SPARC_FIRST_FP_REG)
+ && const_zero_operand (operands[1], mode))
+ return false;
- /* Allow any one instruction integer constant, and all CONST_INT
- variants when we are working in DImode and !arch64. */
- if (GET_MODE_CLASS (mode) == MODE_INT
- && ((GET_CODE (op) == CONST_INT
- && (SPARC_SETHI_P (INTVAL (op) & GET_MODE_MASK (mode))
- || SPARC_SIMM13_P (INTVAL (op))
- || (mode == DImode
- && ! TARGET_ARCH64)))
- || (TARGET_ARCH64
- && GET_CODE (op) == CONST_DOUBLE
- && ((CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SETHI_P (CONST_DOUBLE_LOW (op)))
- ||
-#if HOST_BITS_PER_WIDE_INT == 64
- (CONST_DOUBLE_HIGH (op) == 0
- && SPARC_SIMM13_P (CONST_DOUBLE_LOW (op)))
-#else
- (SPARC_SIMM13_P (CONST_DOUBLE_LOW (op))
- && (((CONST_DOUBLE_LOW (op) & 0x80000000) == 0
- && CONST_DOUBLE_HIGH (op) == 0)
- || (CONST_DOUBLE_HIGH (op) == -1
- && CONST_DOUBLE_LOW (op) & 0x80000000) != 0))
-#endif
- ))))
- return 1;
+ if (REGNO (operands[0]) < SPARC_FIRST_FP_REG
+ /* We are able to build any SF constant in integer registers
+ with at most 2 instructions. */
+ && (mode == SFmode
+ /* And any DF constant in integer registers. */
+ || (mode == DFmode
+ && (reload_completed || reload_in_progress))))
+ return false;
- /* If !arch64 and this is a DImode const, allow it so that
- the splits can be generated. */
- if (! TARGET_ARCH64
- && mode == DImode
- && GET_CODE (op) == CONST_DOUBLE)
- return 1;
+ operands[1] = force_const_mem (mode, operands[1]);
+ if (!reload_in_progress)
+ operands[1] = validize_mem (operands[1]);
+ return false;
+ }
- if (register_operand (op, mode))
- return 1;
+ /* Accept non-constants and valid constants unmodified. */
+ if (!CONSTANT_P (operands[1])
+ || GET_CODE (operands[1]) == HIGH
+ || input_operand (operands[1], mode))
+ return false;
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- && GET_CODE (op) == CONST_DOUBLE)
- return 1;
+ switch (mode)
+ {
+ case QImode:
+ /* All QImode constants require only one insn, so proceed. */
+ break;
- /* If this is a SUBREG, look inside so that we handle
- paradoxical ones. */
- if (GET_CODE (op) == SUBREG)
- op = SUBREG_REG (op);
+ case HImode:
+ case SImode:
+ sparc_emit_set_const32 (operands[0], operands[1]);
+ return true;
- /* Check for valid MEM forms. */
- if (GET_CODE (op) == MEM)
- return memory_address_p (mode, XEXP (op, 0));
+ case DImode:
+ /* input_operand should have filtered out 32-bit mode. */
+ sparc_emit_set_const64 (operands[0], operands[1]);
+ return true;
+
+ default:
+ gcc_unreachable ();
+ }
- return 0;
+ return false;
}
-/* Return 1 if OP is valid for the lhs of a compare insn. */
-
-int
-compare_operand (rtx op, enum machine_mode mode)
-{
- if (GET_CODE (op) == ZERO_EXTRACT)
- return (register_operand (XEXP (op, 0), mode)
- && small_int_or_double (XEXP (op, 1), mode)
- && small_int_or_double (XEXP (op, 2), mode)
- /* This matches cmp_zero_extract. */
- && ((mode == SImode
- && ((GET_CODE (XEXP (op, 2)) == CONST_INT
- && INTVAL (XEXP (op, 2)) > 19)
- || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (XEXP (op, 2)) > 19)))
- /* This matches cmp_zero_extract_sp64. */
- || (mode == DImode
- && TARGET_ARCH64
- && ((GET_CODE (XEXP (op, 2)) == CONST_INT
- && INTVAL (XEXP (op, 2)) > 51)
- || (GET_CODE (XEXP (op, 2)) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (XEXP (op, 2)) > 51)))));
- else
- return register_operand (op, mode);
-}
+/* Load OP1, a 32-bit constant, into OP0, a register.
+ We know it can't be done in one insn when we get
+ here, the move expander guarantees this. */
-
-/* We know it can't be done in one insn when we get here,
- the movsi expander guarantees this. */
void
sparc_emit_set_const32 (rtx op0, rtx op1)
{
enum machine_mode mode = GET_MODE (op0);
rtx temp;
- if (GET_CODE (op1) == CONST_INT)
- {
- HOST_WIDE_INT value = INTVAL (op1);
-
- if (SPARC_SETHI_P (value & GET_MODE_MASK (mode))
- || SPARC_SIMM13_P (value))
- abort ();
- }
-
- /* Full 2-insn decomposition is needed. */
if (reload_in_progress || reload_completed)
temp = op0;
else
@@ -1374,20 +1069,15 @@ sparc_emit_set_const32 (rtx op0, rtx op1)
if (GET_CODE (op1) == CONST_INT)
{
+ gcc_assert (!small_int_operand (op1, mode)
+ && !const_high_operand (op1, mode));
+
/* Emit them as real moves instead of a HIGH/LO_SUM,
this way CSE can see everything and reuse intermediate
values if it wants. */
- if (TARGET_ARCH64
- && HOST_BITS_PER_WIDE_INT != 64
- && (INTVAL (op1) & 0x80000000) != 0)
- emit_insn (gen_rtx_SET
- (VOIDmode, temp,
- immed_double_const (INTVAL (op1) & ~(HOST_WIDE_INT)0x3ff,
- 0, DImode)));
- else
- emit_insn (gen_rtx_SET (VOIDmode, temp,
- GEN_INT (INTVAL (op1)
- & ~(HOST_WIDE_INT)0x3ff)));
+ emit_insn (gen_rtx_SET (VOIDmode, temp,
+ GEN_INT (INTVAL (op1)
+ & ~(HOST_WIDE_INT)0x3ff)));
emit_insn (gen_rtx_SET (VOIDmode,
op0,
@@ -1401,17 +1091,16 @@ sparc_emit_set_const32 (rtx op0, rtx op1)
gen_rtx_HIGH (mode, op1)));
emit_insn (gen_rtx_SET (VOIDmode,
op0, gen_rtx_LO_SUM (mode, temp, op1)));
-
}
}
-
/* Load OP1, a symbolic 64-bit constant, into OP0, a DImode register.
- If TEMP is non-zero, we are forbidden to use any other scratch
+ If TEMP is nonzero, we are forbidden to use any other scratch
registers. Otherwise, we are allowed to generate them as needed.
Note that TEMP may have TImode if the code model is TARGET_CM_MEDANY
or TARGET_CM_EMBMEDANY (see the reload_indi and reload_outdi patterns). */
+
void
sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
{
@@ -1502,10 +1191,8 @@ sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
it TImode). Pick the other one to use as our scratch. */
if (rtx_equal_p (temp, op0))
{
- if (ti_temp)
- temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
- else
- abort();
+ gcc_assert (ti_temp);
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
}
temp1 = op0;
temp2 = temp; /* op0 is _not_ allowed, see above. */
@@ -1576,10 +1263,8 @@ sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
it TImode). Pick the other one to use as our scratch. */
if (rtx_equal_p (temp, op0))
{
- if (ti_temp)
- temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
- else
- abort();
+ gcc_assert (ti_temp);
+ temp = gen_rtx_REG (DImode, REGNO (temp) + 1);
}
temp1 = op0;
temp2 = temp; /* op0 is _not_ allowed, see above. */
@@ -1608,56 +1293,52 @@ sparc_emit_set_symbolic_const64 (rtx op0, rtx op1, rtx temp)
break;
default:
- abort();
+ gcc_unreachable ();
}
}
+#if HOST_BITS_PER_WIDE_INT == 32
+void
+sparc_emit_set_const64 (rtx op0 ATTRIBUTE_UNUSED, rtx op1 ATTRIBUTE_UNUSED)
+{
+ gcc_unreachable ();
+}
+#else
/* These avoid problems when cross compiling. If we do not
go through all this hair then the optimizer will see
invalid REG_EQUAL notes or in some cases none at all. */
-static void sparc_emit_set_safe_HIGH64 (rtx, HOST_WIDE_INT);
+static rtx gen_safe_HIGH64 (rtx, HOST_WIDE_INT);
static rtx gen_safe_SET64 (rtx, HOST_WIDE_INT);
static rtx gen_safe_OR64 (rtx, HOST_WIDE_INT);
static rtx gen_safe_XOR64 (rtx, HOST_WIDE_INT);
-#if HOST_BITS_PER_WIDE_INT == 64
-#define GEN_HIGHINT64(__x) GEN_INT ((__x) & ~(HOST_WIDE_INT)0x3ff)
-#define GEN_INT64(__x) GEN_INT (__x)
-#else
-#define GEN_HIGHINT64(__x) \
- immed_double_const ((__x) & ~(HOST_WIDE_INT)0x3ff, 0, DImode)
-#define GEN_INT64(__x) \
- immed_double_const ((__x) & 0xffffffff, \
- ((__x) & 0x80000000 ? -1 : 0), DImode)
-#endif
-
/* The optimizer is not to assume anything about exactly
which bits are set for a HIGH, they are unspecified.
Unfortunately this leads to many missed optimizations
during CSE. We mask out the non-HIGH bits, and matches
a plain movdi, to alleviate this problem. */
-static void
-sparc_emit_set_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
+static rtx
+gen_safe_HIGH64 (rtx dest, HOST_WIDE_INT val)
{
- emit_insn (gen_rtx_SET (VOIDmode, dest, GEN_HIGHINT64 (val)));
+ return gen_rtx_SET (VOIDmode, dest, GEN_INT (val & ~(HOST_WIDE_INT)0x3ff));
}
static rtx
gen_safe_SET64 (rtx dest, HOST_WIDE_INT val)
{
- return gen_rtx_SET (VOIDmode, dest, GEN_INT64 (val));
+ return gen_rtx_SET (VOIDmode, dest, GEN_INT (val));
}
static rtx
gen_safe_OR64 (rtx src, HOST_WIDE_INT val)
{
- return gen_rtx_IOR (DImode, src, GEN_INT64 (val));
+ return gen_rtx_IOR (DImode, src, GEN_INT (val));
}
static rtx
gen_safe_XOR64 (rtx src, HOST_WIDE_INT val)
{
- return gen_rtx_XOR (DImode, src, GEN_INT64 (val));
+ return gen_rtx_XOR (DImode, src, GEN_INT (val));
}
/* Worker routines for 64-bit constant formation on arch64.
@@ -1682,7 +1363,7 @@ sparc_emit_set_const64_quick1 (rtx op0, rtx temp,
else
high_bits = low_bits;
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if (!is_neg)
{
emit_insn (gen_rtx_SET (VOIDmode, op0,
@@ -1721,7 +1402,7 @@ sparc_emit_set_const64_quick2 (rtx op0, rtx temp,
if ((high_bits & 0xfffffc00) != 0)
{
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if ((high_bits & ~0xfffffc00) != 0)
emit_insn (gen_rtx_SET (VOIDmode, op0,
gen_safe_OR64 (temp, (high_bits & 0x3ff))));
@@ -1765,7 +1446,7 @@ sparc_emit_set_const64_longway (rtx op0, rtx temp,
if ((high_bits & 0xfffffc00) != 0)
{
- sparc_emit_set_safe_HIGH64 (temp, high_bits);
+ emit_insn (gen_safe_HIGH64 (temp, high_bits));
if ((high_bits & ~0xfffffc00) != 0)
emit_insn (gen_rtx_SET (VOIDmode,
sub_temp,
@@ -1789,7 +1470,7 @@ sparc_emit_set_const64_longway (rtx op0, rtx temp,
gen_rtx_ASHIFT (DImode, sub_temp,
GEN_INT (32))));
- sparc_emit_set_safe_HIGH64 (temp2, low_bits);
+ emit_insn (gen_safe_HIGH64 (temp2, low_bits));
if ((low_bits & ~0xfffffc00) != 0)
{
emit_insn (gen_rtx_SET (VOIDmode, temp3,
@@ -1896,9 +1577,7 @@ analyze_64bit_constant (unsigned HOST_WIDE_INT high_bits,
}
/* If there are no bits set this should have gone out
as one instruction! */
- if (lowest_bit_set == -1
- || highest_bit_set == -1)
- abort ();
+ gcc_assert (lowest_bit_set != -1 && highest_bit_set != -1);
all_bits_between_are_set = 1;
for (i = lowest_bit_set; i <= highest_bit_set; i++)
{
@@ -1968,8 +1647,7 @@ create_simple_focus_bits (unsigned HOST_WIDE_INT high_bits,
lo = 0;
hi = ((high_bits >> (lowest_bit_set - 32)) << shift);
}
- if (hi & lo)
- abort ();
+ gcc_assert (! (hi & lo));
return (hi | lo);
}
@@ -1986,22 +1664,14 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
rtx temp = 0;
/* Sanity check that we know what we are working with. */
- if (! TARGET_ARCH64)
- abort ();
-
- if (GET_CODE (op0) != SUBREG)
- {
- if (GET_CODE (op0) != REG
- || (REGNO (op0) >= SPARC_FIRST_FP_REG
- && REGNO (op0) <= SPARC_LAST_V9_FP_REG))
- abort ();
- }
+ gcc_assert (TARGET_ARCH64
+ && (GET_CODE (op0) == SUBREG
+ || (REG_P (op0) && ! SPARC_FP_REG_P (REGNO (op0)))));
if (reload_in_progress || reload_completed)
temp = op0;
- if (GET_CODE (op1) != CONST_DOUBLE
- && GET_CODE (op1) != CONST_INT)
+ if (GET_CODE (op1) != CONST_INT)
{
sparc_emit_set_symbolic_const64 (op0, op1, temp);
return;
@@ -2010,28 +1680,8 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
if (! temp)
temp = gen_reg_rtx (DImode);
- if (GET_CODE (op1) == CONST_DOUBLE)
- {
-#if HOST_BITS_PER_WIDE_INT == 64
- high_bits = (CONST_DOUBLE_LOW (op1) >> 32) & 0xffffffff;
- low_bits = CONST_DOUBLE_LOW (op1) & 0xffffffff;
-#else
- high_bits = CONST_DOUBLE_HIGH (op1);
- low_bits = CONST_DOUBLE_LOW (op1);
-#endif
- }
- else
- {
-#if HOST_BITS_PER_WIDE_INT == 64
- high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
- low_bits = (INTVAL (op1) & 0xffffffff);
-#else
- high_bits = ((INTVAL (op1) < 0) ?
- 0xffffffff :
- 0x00000000);
- low_bits = INTVAL (op1);
-#endif
- }
+ high_bits = ((INTVAL (op1) >> 32) & 0xffffffff);
+ low_bits = (INTVAL (op1) & 0xffffffff);
/* low_bits bits 0 --> 31
high_bits bits 32 --> 63 */
@@ -2070,8 +1720,8 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
else if (lowest_bit_set == 0)
shift = -(63 - highest_bit_set);
- if (! SPARC_SIMM13_P (the_const))
- abort ();
+ gcc_assert (SPARC_SIMM13_P (the_const));
+ gcc_assert (shift != 0);
emit_insn (gen_safe_SET64 (temp, the_const));
if (shift > 0)
@@ -2086,8 +1736,6 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
gen_rtx_LSHIFTRT (DImode,
temp,
GEN_INT (-shift))));
- else
- abort ();
return;
}
@@ -2103,10 +1751,10 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
create_simple_focus_bits (high_bits, low_bits,
lowest_bit_set, 10);
- if (! SPARC_SETHI_P (focus_bits))
- abort ();
+ gcc_assert (SPARC_SETHI_P (focus_bits));
+ gcc_assert (lowest_bit_set != 10);
- sparc_emit_set_safe_HIGH64 (temp, focus_bits);
+ emit_insn (gen_safe_HIGH64 (temp, focus_bits));
/* If lowest_bit_set == 10 then a sethi alone could have done it. */
if (lowest_bit_set < 10)
@@ -2119,8 +1767,6 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
op0,
gen_rtx_ASHIFT (DImode, temp,
GEN_INT (lowest_bit_set - 10))));
- else
- abort ();
return;
}
@@ -2163,26 +1809,20 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
|| (((~high_bits) & 0xffffffff) == 0xffffffff
&& ((~low_bits) & 0x80000000) != 0))
{
- int fast_int = (~low_bits & 0xffffffff);
+ unsigned HOST_WIDE_INT fast_int = (~low_bits & 0xffffffff);
if ((SPARC_SETHI_P (fast_int)
&& (~high_bits & 0xffffffff) == 0)
|| SPARC_SIMM13_P (fast_int))
emit_insn (gen_safe_SET64 (temp, fast_int));
else
- sparc_emit_set_const64 (temp, GEN_INT64 (fast_int));
+ sparc_emit_set_const64 (temp, GEN_INT (fast_int));
}
else
{
rtx negated_const;
-#if HOST_BITS_PER_WIDE_INT == 64
negated_const = GEN_INT (((~low_bits) & 0xfffffc00) |
(((HOST_WIDE_INT)((~high_bits) & 0xffffffff))<<32));
-#else
- negated_const = immed_double_const ((~low_bits) & 0xfffffc00,
- (~high_bits) & 0xffffffff,
- DImode);
-#endif
sparc_emit_set_const64 (temp, negated_const);
}
@@ -2218,9 +1858,7 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
lowest_bit_set, 0);
/* We can't get here in this state. */
- if (highest_bit_set < 32
- || lowest_bit_set >= 32)
- abort ();
+ gcc_assert (highest_bit_set >= 32 && lowest_bit_set < 32);
/* So what we know is that the set bits straddle the
middle of the 64-bit word. */
@@ -2249,6 +1887,7 @@ sparc_emit_set_const64 (rtx op0, rtx op1)
#endif
sparc_emit_set_const64_longway (op0, temp, high_bits, low_bits);
}
+#endif /* HOST_BITS_PER_WIDE_INT == 32 */
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
@@ -2282,7 +1921,7 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
return CCFPEmode;
default:
- abort ();
+ gcc_unreachable ();
}
}
else if (GET_CODE (x) == PLUS || GET_CODE (x) == MINUS
@@ -2306,11 +1945,20 @@ select_cc_mode (enum rtx_code op, rtx x, rtx y ATTRIBUTE_UNUSED)
return the rtx for the cc reg in the proper mode. */
rtx
-gen_compare_reg (enum rtx_code code, rtx x, rtx y)
+gen_compare_reg (enum rtx_code code)
{
+ rtx x = sparc_compare_op0;
+ rtx y = sparc_compare_op1;
enum machine_mode mode = SELECT_CC_MODE (code, x, y);
rtx cc_reg;
+ if (sparc_compare_emitted != NULL_RTX)
+ {
+ cc_reg = sparc_compare_emitted;
+ sparc_compare_emitted = NULL_RTX;
+ return cc_reg;
+ }
+
/* ??? We don't have movcc patterns so we cannot generate pseudo regs for the
fcc regs (cse can't tell they're really call clobbered regs and will
remove a duplicate comparison even if there is an intervening function
@@ -2389,22 +2037,20 @@ gen_compare_reg (enum rtx_code code, rtx x, rtx y)
int
gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
{
- rtx temp, op0, op1;
-
if (! TARGET_ARCH64
&& (GET_MODE (sparc_compare_op0) == DImode
|| GET_MODE (operands[0]) == DImode))
return 0;
- op0 = sparc_compare_op0;
- op1 = sparc_compare_op1;
-
/* Try to use the movrCC insns. */
if (TARGET_ARCH64
- && GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT
- && op1 == const0_rtx
+ && GET_MODE_CLASS (GET_MODE (sparc_compare_op0)) == MODE_INT
+ && sparc_compare_op1 == const0_rtx
&& v9_regcmp_p (compare_code))
{
+ rtx op0 = sparc_compare_op0;
+ rtx temp;
+
/* Special case for op0 != 0. This can be done with one instruction if
operands[0] == sparc_compare_op0. */
@@ -2447,7 +2093,7 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
}
else
{
- operands[1] = gen_compare_reg (compare_code, op0, op1);
+ operands[1] = gen_compare_reg (compare_code);
switch (GET_MODE (operands[1]))
{
@@ -2457,7 +2103,7 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
case CCFPmode :
break;
default :
- abort ();
+ gcc_unreachable ();
}
emit_insn (gen_rtx_SET (VOIDmode, operands[0], const0_rtx));
emit_insn (gen_rtx_SET (VOIDmode, operands[0],
@@ -2477,6 +2123,7 @@ gen_v9_scc (enum rtx_code compare_code, register rtx *operands)
void
emit_v9_brxx_insn (enum rtx_code code, rtx op0, rtx label)
{
+ gcc_assert (sparc_compare_emitted == NULL_RTX);
emit_jump_insn (gen_rtx_SET (VOIDmode,
pc_rtx,
gen_rtx_IF_THEN_ELSE (VOIDmode,
@@ -2511,8 +2158,7 @@ emit_soft_tfmode_libcall (const char *func_name, int nargs, rtx *operands)
int i;
/* We only expect to be called for conversions, unary, and binary ops. */
- if (nargs < 2 || nargs > 3)
- abort ();
+ gcc_assert (nargs == 2 || nargs == 3);
for (i = 0; i < nargs; ++i)
{
@@ -2575,8 +2221,7 @@ emit_soft_tfmode_libcall (const char *func_name, int nargs, rtx *operands)
{
rtx ret;
- if (nargs != 2)
- abort ();
+ gcc_assert (nargs == 2);
ret = emit_library_call_value (func_sym, operands[0], LCT_NORMAL,
GET_MODE (operands[0]), 1,
@@ -2609,7 +2254,7 @@ emit_soft_tfmode_binop (enum rtx_code code, rtx *operands)
func = "_Qp_div";
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_soft_tfmode_libcall (func, 3, operands);
@@ -2620,14 +2265,8 @@ emit_soft_tfmode_unop (enum rtx_code code, rtx *operands)
{
const char *func;
- switch (code)
- {
- case SQRT:
- func = "_Qp_sqrt";
- break;
- default:
- abort ();
- }
+ gcc_assert (code == SQRT);
+ func = "_Qp_sqrt";
emit_soft_tfmode_libcall (func, 2, operands);
}
@@ -2649,7 +2288,7 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_dtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -2663,7 +2302,7 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_qtod";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -2677,7 +2316,7 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_xtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -2691,7 +2330,7 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_uxtoq";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -2705,7 +2344,7 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_qtox";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
@@ -2719,12 +2358,12 @@ emit_soft_tfmode_cvt (enum rtx_code code, rtx *operands)
func = "_Qp_qtoux";
break;
default:
- abort ();
+ gcc_unreachable ();
}
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_soft_tfmode_libcall (func, 2, operands);
@@ -2738,7 +2377,7 @@ emit_hard_tfmode_operation (enum rtx_code code, rtx *operands)
{
rtx op, dest;
- if (GET_RTX_CLASS (code) == '1')
+ if (GET_RTX_CLASS (code) == RTX_UNARY)
{
operands[1] = force_reg (GET_MODE (operands[1]), operands[1]);
op = gen_rtx_fmt_e (code, GET_MODE (operands[0]), operands[1]);
@@ -2789,14 +2428,6 @@ emit_tfmode_cvt (enum rtx_code code, rtx *operands)
emit_soft_tfmode_cvt (code, operands);
}
-/* Return nonzero if a return peephole merging return with
- setting of output register is ok. */
-int
-leaf_return_peephole_ok (void)
-{
- return (actual_fsize == 0);
-}
-
/* Return nonzero if a branch/jump/call instruction will be emitting
nop into its delay slot. */
@@ -2816,69 +2447,56 @@ empty_delay_slot (rtx insn)
return 1;
}
-/* Return nonzero if TRIAL can go into the function epilogue's
- delay slot. SLOT is the slot we are trying to fill. */
+/* Return nonzero if TRIAL can go into the call delay slot. */
int
-eligible_for_epilogue_delay (rtx trial, int slot)
+tls_call_delay (rtx trial)
{
- rtx pat, src;
-
- if (slot >= 1)
- return 0;
-
- if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
- return 0;
-
- if (get_attr_length (trial) != 1)
- return 0;
+ rtx pat;
- /* If there are any call-saved registers, we should scan TRIAL if it
- does not reference them. For now just make it easy. */
- if (num_gfregs)
- return 0;
+ /* Binutils allows
+ call __tls_get_addr, %tgd_call (foo)
+ add %l7, %o0, %o0, %tgd_add (foo)
+ while Sun as/ld does not. */
+ if (TARGET_GNU_TLS || !TARGET_TLS)
+ return 1;
- /* If the function uses __builtin_eh_return, the eh_return machinery
- occupies the delay slot. */
- if (current_function_calls_eh_return)
- return 0;
+ pat = PATTERN (trial);
- /* 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. */
- if (current_function_uses_only_leaf_regs)
+ /* We must reject tgd_add{32|64}, i.e.
+ (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSGD)))
+ and tldm_add{32|64}, i.e.
+ (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSLDM)))
+ for Sun as/ld. */
+ if (GET_CODE (pat) == SET
+ && GET_CODE (SET_SRC (pat)) == PLUS)
{
- if (leaf_return_peephole_ok ())
- return ((get_attr_in_uncond_branch_delay (trial)
- == IN_BRANCH_DELAY_TRUE));
- return 0;
- }
+ rtx unspec = XEXP (SET_SRC (pat), 1);
- pat = PATTERN (trial);
+ if (GET_CODE (unspec) == UNSPEC
+ && (XINT (unspec, 1) == UNSPEC_TLSGD
+ || XINT (unspec, 1) == UNSPEC_TLSLDM))
+ return 0;
+ }
- /* Otherwise, only operations which can be done in tandem with
- a `restore' or `return' insn can go into the delay slot. */
- if (GET_CODE (SET_DEST (pat)) != REG
- || REGNO (SET_DEST (pat)) < 24)
- return 0;
+ return 1;
+}
- /* If this instruction sets up floating point register and we have a return
- instruction, it can probably go in. But restore will not work
- with FP_REGS. */
- if (REGNO (SET_DEST (pat)) >= 32)
- {
- if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
- && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
- return 1;
- return 0;
- }
+/* Return nonzero if TRIAL, an insn, can be combined with a 'restore'
+ instruction. RETURN_P is true if the v9 variant 'return' is to be
+ considered in the test too.
- /* The set of insns matched here must agree precisely with the set of
- patterns paired with a RETURN in sparc.md. */
+ TRIAL must be a SET whose destination is a REG appropriate for the
+ 'restore' instruction or, if RETURN_P is true, for the 'return'
+ instruction. */
- src = SET_SRC (pat);
+static int
+eligible_for_restore_insn (rtx trial, bool return_p)
+{
+ rtx pat = PATTERN (trial);
+ rtx src = SET_SRC (pat);
- /* This matches "*return_[qhs]i" or even "*return_di" on TARGET_ARCH64. */
+ /* The 'restore src,%g0,dest' pattern for word mode and below. */
if (GET_MODE_CLASS (GET_MODE (src)) != MODE_FLOAT
&& arith_operand (src, GET_MODE (src)))
{
@@ -2888,41 +2506,39 @@ eligible_for_epilogue_delay (rtx trial, int slot)
return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
}
- /* This matches "*return_di". */
+ /* The 'restore src,%g0,dest' pattern for double-word mode. */
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". */
- else if (! TARGET_FPU && restore_operand (SET_DEST (pat), SFmode)
- && register_operand (src, SFmode))
+ /* The 'restore src,%g0,dest' pattern for float if no FPU. */
+ else if (! TARGET_FPU && register_operand (src, SFmode))
+ return 1;
+
+ /* The 'restore src,%g0,dest' pattern for double if no FPU. */
+ else if (! TARGET_FPU && TARGET_ARCH64 && register_operand (src, DFmode))
return 1;
- /* If we have return instruction, anything that does not use
+ /* If we have the 'return' instruction, anything that does not use
local or output registers and can go into a delay slot wins. */
- else if (TARGET_V9 && ! epilogue_renumber (&pat, 1)
- && (get_attr_in_uncond_branch_delay (trial) == IN_BRANCH_DELAY_TRUE))
+ else if (return_p && TARGET_V9 && ! epilogue_renumber (&pat, 1)
+ && (get_attr_in_uncond_branch_delay (trial)
+ == IN_UNCOND_BRANCH_DELAY_TRUE))
return 1;
- /* This matches "*return_addsi". */
+ /* The 'restore src1,src2,dest' pattern for SImode. */
else if (GET_CODE (src) == PLUS
- && arith_operand (XEXP (src, 0), SImode)
- && arith_operand (XEXP (src, 1), SImode)
- && (register_operand (XEXP (src, 0), SImode)
- || register_operand (XEXP (src, 1), SImode)))
+ && register_operand (XEXP (src, 0), SImode)
+ && arith_operand (XEXP (src, 1), SImode))
return 1;
- /* This matches "*return_adddi". */
+ /* The 'restore src1,src2,dest' pattern for DImode. */
else if (GET_CODE (src) == PLUS
- && arith_double_operand (XEXP (src, 0), DImode)
- && arith_double_operand (XEXP (src, 1), DImode)
- && (register_operand (XEXP (src, 0), DImode)
- || register_operand (XEXP (src, 1), DImode)))
+ && register_operand (XEXP (src, 0), DImode)
+ && arith_double_operand (XEXP (src, 1), DImode))
return 1;
- /* This can match "*return_losum_[sd]i".
- Catch only some cases, so that return_losum* don't have
- to be too big. */
+ /* The 'restore src1,%lo(src2),dest' pattern. */
else if (GET_CODE (src) == LO_SUM
&& ! TARGET_CM_MEDMID
&& ((register_operand (XEXP (src, 0), SImode)
@@ -2932,7 +2548,7 @@ eligible_for_epilogue_delay (rtx trial, int slot)
&& immediate_operand (XEXP (src, 1), DImode))))
return 1;
- /* sll{,x} reg,1,reg2 is add reg,reg,reg2 as well. */
+ /* The 'restore src,src,dest' pattern. */
else if (GET_CODE (src) == ASHIFT
&& (register_operand (XEXP (src, 0), SImode)
|| register_operand (XEXP (src, 0), DImode))
@@ -2942,47 +2558,62 @@ eligible_for_epilogue_delay (rtx trial, int slot)
return 0;
}
-/* Return nonzero if TRIAL can go into the call delay slot. */
+/* Return nonzero if TRIAL can go into the function return's
+ delay slot. */
+
int
-tls_call_delay (rtx trial)
+eligible_for_return_delay (rtx trial)
{
rtx pat;
- /* Binutils allows
- call __tls_get_addr, %tgd_call (foo)
- add %l7, %o0, %o0, %tgd_add (foo)
- while Sun as/ld does not. */
- if (TARGET_GNU_TLS || !TARGET_TLS)
- return 1;
+ if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
+ return 0;
+
+ if (get_attr_length (trial) != 1)
+ return 0;
+
+ /* If there are any call-saved registers, we should scan TRIAL if it
+ does not reference them. For now just make it easy. */
+ 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 slot. */
+ if (sparc_leaf_function_p)
+ return get_attr_in_uncond_branch_delay (trial)
+ == IN_UNCOND_BRANCH_DELAY_TRUE;
pat = PATTERN (trial);
- /* We must reject tgd_add{32|64}, i.e.
- (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSGD)))
- and tldm_add{32|64}, i.e.
- (set (reg) (plus (reg) (unspec [(reg) (symbol_ref)] UNSPEC_TLSLDM)))
- for Sun as/ld. */
- if (GET_CODE (pat) == SET
- && GET_CODE (SET_SRC (pat)) == PLUS)
- {
- rtx unspec = XEXP (SET_SRC (pat), 1);
+ /* Otherwise, only operations which can be done in tandem with
+ a `restore' or `return' insn can go into the delay slot. */
+ if (GET_CODE (SET_DEST (pat)) != REG
+ || (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24))
+ return 0;
- if (GET_CODE (unspec) == UNSPEC
- && (XINT (unspec, 1) == UNSPEC_TLSGD
- || XINT (unspec, 1) == UNSPEC_TLSLDM))
- return 0;
- }
+ /* If this instruction sets up floating point register and we have a return
+ instruction, it can probably go in. But restore will not work
+ with FP_REGS. */
+ if (REGNO (SET_DEST (pat)) >= 32)
+ return (TARGET_V9
+ && ! epilogue_renumber (&pat, 1)
+ && (get_attr_in_uncond_branch_delay (trial)
+ == IN_UNCOND_BRANCH_DELAY_TRUE));
- return 1;
+ return eligible_for_restore_insn (trial, true);
}
-/* Return nonzero if TRIAL can go into the sibling call
+/* Return nonzero if TRIAL can go into the sibling call's
delay slot. */
int
eligible_for_sibcall_delay (rtx trial)
{
- rtx pat, src;
+ rtx pat;
if (GET_CODE (trial) != INSN || GET_CODE (PATTERN (trial)) != SET)
return 0;
@@ -2992,11 +2623,11 @@ eligible_for_sibcall_delay (rtx trial)
pat = PATTERN (trial);
- if (current_function_uses_only_leaf_regs)
+ if (sparc_leaf_function_p)
{
/* If the tail call is done using the call instruction,
we have to restore %o7 in the delay slot. */
- if ((TARGET_ARCH64 && ! TARGET_CM_MEDLOW) || flag_pic)
+ if (LEAF_SIBCALL_SLOT_RESERVED_P)
return 0;
/* %g1 is used to build the function address */
@@ -3009,7 +2640,7 @@ eligible_for_sibcall_delay (rtx trial)
/* Otherwise, only operations which can be done in tandem with
a `restore' insn can go into the delay slot. */
if (GET_CODE (SET_DEST (pat)) != REG
- || REGNO (SET_DEST (pat)) < 24
+ || (REGNO (SET_DEST (pat)) >= 8 && REGNO (SET_DEST (pat)) < 24)
|| REGNO (SET_DEST (pat)) >= 32)
return 0;
@@ -3018,89 +2649,7 @@ eligible_for_sibcall_delay (rtx trial)
if (reg_mentioned_p (gen_rtx_REG (Pmode, 15), pat))
return 0;
- src = SET_SRC (pat);
-
- 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);
- else
- return GET_MODE_SIZE (GET_MODE (src)) <= GET_MODE_SIZE (SImode);
- }
-
- 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)
- && register_operand (src, SFmode))
- return 1;
-
- else if (GET_CODE (src) == PLUS
- && arith_operand (XEXP (src, 0), SImode)
- && arith_operand (XEXP (src, 1), SImode)
- && (register_operand (XEXP (src, 0), SImode)
- || register_operand (XEXP (src, 1), SImode)))
- return 1;
-
- else if (GET_CODE (src) == PLUS
- && arith_double_operand (XEXP (src, 0), DImode)
- && arith_double_operand (XEXP (src, 1), DImode)
- && (register_operand (XEXP (src, 0), DImode)
- || register_operand (XEXP (src, 1), DImode)))
- return 1;
-
- else if (GET_CODE (src) == LO_SUM
- && ! TARGET_CM_MEDMID
- && ((register_operand (XEXP (src, 0), SImode)
- && immediate_operand (XEXP (src, 1), SImode))
- || (TARGET_ARCH64
- && register_operand (XEXP (src, 0), DImode)
- && immediate_operand (XEXP (src, 1), DImode))))
- return 1;
-
- else if (GET_CODE (src) == ASHIFT
- && (register_operand (XEXP (src, 0), SImode)
- || register_operand (XEXP (src, 0), DImode))
- && XEXP (src, 1) == const1_rtx)
- return 1;
-
- return 0;
-}
-
-static int
-check_return_regs (rtx x)
-{
- switch (GET_CODE (x))
- {
- case REG:
- return IN_OR_GLOBAL_P (x);
-
- case CONST_INT:
- case CONST_DOUBLE:
- case CONST:
- case SYMBOL_REF:
- case LABEL_REF:
- return 1;
-
- case SET:
- case IOR:
- case AND:
- case XOR:
- case PLUS:
- case MINUS:
- if (check_return_regs (XEXP (x, 1)) == 0)
- return 0;
- case NOT:
- case NEG:
- case MEM:
- return check_return_regs (XEXP (x, 0));
-
- default:
- return 0;
- }
-
+ return eligible_for_restore_insn (trial, false);
}
int
@@ -3132,7 +2681,7 @@ reg_unused_after (rtx reg, rtx insn)
if (GET_CODE (insn) == CODE_LABEL)
return 1;
- if (GET_RTX_CLASS (code) == 'i')
+ if (INSN_P (insn))
{
rtx set = single_set (insn);
int in_src = set && reg_overlap_mentioned_p (reg, SET_SRC (set));
@@ -3159,6 +2708,7 @@ sparc_cannot_force_const_mem (rtx x)
{
case CONST_INT:
case CONST_DOUBLE:
+ case CONST_VECTOR:
/* Accept all non-symbolic constants. */
return false;
@@ -3183,17 +2733,16 @@ sparc_cannot_force_const_mem (rtx x)
case UNSPEC:
return true;
default:
- abort ();
+ gcc_unreachable ();
}
}
-/* The table we use to reference PIC data. */
+/* PIC support. */
+static GTY(()) char pic_helper_symbol_name[256];
+static GTY(()) rtx pic_helper_symbol;
+static GTY(()) bool pic_helper_emitted_p = false;
static GTY(()) rtx global_offset_table;
-/* The function we use to get at it. */
-static GTY(()) rtx get_pc_symbol;
-static GTY(()) char get_pc_symbol_name[256];
-
/* Ensure that we are not using patterns that are not OK with PIC. */
int
@@ -3202,14 +2751,13 @@ check_pic (int i)
switch (flag_pic)
{
case 1:
- if (GET_CODE (recog_data.operand[i]) == SYMBOL_REF
- || (GET_CODE (recog_data.operand[i]) == CONST
- && ! (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
- && (XEXP (XEXP (recog_data.operand[i], 0), 0)
- == global_offset_table)
- && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
- == CONST))))
- abort ();
+ gcc_assert (GET_CODE (recog_data.operand[i]) != SYMBOL_REF
+ && (GET_CODE (recog_data.operand[i]) != CONST
+ || (GET_CODE (XEXP (recog_data.operand[i], 0)) == MINUS
+ && (XEXP (XEXP (recog_data.operand[i], 0), 0)
+ == global_offset_table)
+ && (GET_CODE (XEXP (XEXP (recog_data.operand[i], 0), 1))
+ == CONST))));
case 2:
default:
return 1;
@@ -3254,7 +2802,7 @@ legitimate_constant_p (rtx x)
/* Offsets of TLS symbols are never valid.
Discourage CSE from creating them. */
if (GET_CODE (inner) == PLUS
- && tls_symbolic_operand (XEXP (inner, 0)))
+ && SPARC_SYMBOL_REF_TLS_P (XEXP (inner, 0)))
return false;
break;
@@ -3265,10 +2813,17 @@ legitimate_constant_p (rtx x)
/* Floating point constants are generally not ok.
The only exception is 0.0 in VIS. */
if (TARGET_VIS
- && (GET_MODE (x) == SFmode
- || GET_MODE (x) == DFmode
- || GET_MODE (x) == TFmode)
- && fp_zero_operand (x, GET_MODE (x)))
+ && SCALAR_FLOAT_MODE_P (GET_MODE (x))
+ && const_zero_operand (x, GET_MODE (x)))
+ return true;
+
+ return false;
+
+ case CONST_VECTOR:
+ /* Vector constants are generally not ok.
+ The only exception is 0 in VIS. */
+ if (TARGET_VIS
+ && const_zero_operand (x, GET_MODE (x)))
return true;
return false;
@@ -3314,10 +2869,10 @@ legitimate_pic_operand_p (rtx x)
{
if (pic_address_needs_scratch (x))
return false;
- if (tls_symbolic_operand (x)
+ if (SPARC_SYMBOL_REF_TLS_P (x)
|| (GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
- && tls_symbolic_operand (XEXP (XEXP (x, 0), 0))))
+ && SPARC_SYMBOL_REF_TLS_P (XEXP (XEXP (x, 0), 0))))
return false;
return true;
}
@@ -3355,7 +2910,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
&& GET_CODE (rs2) != SUBREG
&& GET_CODE (rs2) != LO_SUM
&& GET_CODE (rs2) != MEM
- && !tls_symbolic_operand (rs2)
+ && ! SPARC_SYMBOL_REF_TLS_P (rs2)
&& (! symbolic_operand (rs2, VOIDmode) || mode == Pmode)
&& (GET_CODE (rs2) != CONST_INT || SMALL_INT (rs2)))
|| ((REG_P (rs1)
@@ -3395,7 +2950,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
rs2 = NULL;
imm1 = XEXP (rs1, 1);
rs1 = XEXP (rs1, 0);
- if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
return 0;
}
}
@@ -3404,7 +2959,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
rs1 = XEXP (addr, 0);
imm1 = XEXP (addr, 1);
- if (! CONSTANT_P (imm1) || tls_symbolic_operand (rs1))
+ if (! CONSTANT_P (imm1) || SPARC_SYMBOL_REF_TLS_P (rs1))
return 0;
/* We can't allow TFmode in 32-bit mode, because an offset greater
@@ -3453,6 +3008,7 @@ legitimate_address_p (enum machine_mode mode, rtx addr, int strict)
/* Construct the SYMBOL_REF for the tls_get_offset function. */
static GTY(()) rtx sparc_tls_symbol;
+
static rtx
sparc_tls_get_addr (void)
{
@@ -3479,6 +3035,24 @@ sparc_tls_got (void)
return temp;
}
+/* Return 1 if *X is a thread-local symbol. */
+
+static int
+sparc_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED)
+{
+ return SPARC_SYMBOL_REF_TLS_P (*x);
+}
+
+/* Return 1 if X contains a thread-local symbol. */
+
+bool
+sparc_tls_referenced_p (rtx x)
+{
+ if (!TARGET_HAVE_TLS)
+ return false;
+
+ return for_each_rtx (&x, &sparc_tls_symbol_ref_1, 0);
+}
/* ADDR contains a thread-local SYMBOL_REF. Generate code to compute
this (thread-local) address. */
@@ -3488,8 +3062,7 @@ legitimize_tls_address (rtx addr)
{
rtx temp1, temp2, temp3, ret, o0, got, insn;
- if (no_new_pseudos)
- abort ();
+ gcc_assert (! no_new_pseudos);
if (GET_CODE (addr) == SYMBOL_REF)
switch (SYMBOL_REF_TLS_MODEL (addr))
@@ -3605,11 +3178,11 @@ legitimize_tls_address (rtx addr)
break;
default:
- abort ();
+ gcc_unreachable ();
}
else
- abort (); /* for now ... */
+ gcc_unreachable (); /* for now ... */
return ret;
}
@@ -3631,10 +3204,8 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
if (reg == 0)
{
- if (reload_in_progress || reload_completed)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (! reload_in_progress && ! reload_completed);
+ reg = gen_reg_rtx (Pmode);
}
if (flag_pic == 2)
@@ -3649,26 +3220,25 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
won't get confused into thinking that these two instructions
are loading in the true address of the symbol. If in the
future a PIC rtx exists, that should be used instead. */
- if (Pmode == SImode)
+ if (TARGET_ARCH64)
{
- emit_insn (gen_movsi_high_pic (temp_reg, orig));
- emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
+ emit_insn (gen_movdi_high_pic (temp_reg, orig));
+ emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
}
else
{
- emit_insn (gen_movdi_high_pic (temp_reg, orig));
- emit_insn (gen_movdi_lo_sum_pic (temp_reg, temp_reg, orig));
+ emit_insn (gen_movsi_high_pic (temp_reg, orig));
+ emit_insn (gen_movsi_lo_sum_pic (temp_reg, temp_reg, orig));
}
address = temp_reg;
}
else
address = orig;
- pic_ref = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode,
- pic_offset_table_rtx, address));
+ pic_ref = gen_const_mem (Pmode,
+ gen_rtx_PLUS (Pmode,
+ pic_offset_table_rtx, address));
current_function_uses_pic_offset_table = 1;
- RTX_UNCHANGING_P (pic_ref) = 1;
insn = emit_move_insn (reg, pic_ref);
/* Put a REG_EQUAL note on this insn, so that it can be optimized
by loop. */
@@ -3686,20 +3256,14 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
if (reg == 0)
{
- if (reload_in_progress || reload_completed)
- abort ();
- else
- reg = gen_reg_rtx (Pmode);
+ gcc_assert (! reload_in_progress && ! reload_completed);
+ reg = gen_reg_rtx (Pmode);
}
- if (GET_CODE (XEXP (orig, 0)) == PLUS)
- {
- base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
- offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
- base == reg ? 0 : reg);
- }
- else
- abort ();
+ gcc_assert (GET_CODE (XEXP (orig, 0)) == PLUS);
+ base = legitimize_pic_address (XEXP (XEXP (orig, 0), 0), Pmode, reg);
+ offset = legitimize_pic_address (XEXP (XEXP (orig, 0), 1), Pmode,
+ base == reg ? 0 : reg);
if (GET_CODE (offset) == CONST_INT)
{
@@ -3709,7 +3273,7 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
offset = force_reg (Pmode, offset);
else
/* If we reach here, then something is seriously wrong. */
- abort ();
+ gcc_unreachable ();
}
return gen_rtx_PLUS (Pmode, base, offset);
}
@@ -3751,7 +3315,7 @@ legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
if (x != orig_x && legitimate_address_p (mode, x, FALSE))
return x;
- if (tls_symbolic_operand (x))
+ if (SPARC_SYMBOL_REF_TLS_P (x))
x = legitimize_tls_address (x);
else if (flag_pic)
x = legitimize_pic_address (x, mode, 0);
@@ -3768,41 +3332,57 @@ legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED, enum machine_mode mode)
return x;
}
-/* Emit special PIC prologues. */
+/* Emit the special PIC helper function. */
-void
-load_pic_register (void)
+static void
+emit_pic_helper (void)
{
- /* Labels to get the PC in the prologue of this function. */
- int orig_flag_pic = flag_pic;
+ const char *pic_name = reg_names[REGNO (pic_offset_table_rtx)];
+ int align;
- if (! flag_pic)
- abort ();
+ switch_to_section (text_section);
- /* If we haven't emitted the special get_pc helper function, do so now. */
- if (get_pc_symbol_name[0] == 0)
- {
- int align;
+ align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+ if (align > 0)
+ ASM_OUTPUT_ALIGN (asm_out_file, align);
+ ASM_OUTPUT_LABEL (asm_out_file, pic_helper_symbol_name);
+ if (flag_delayed_branch)
+ fprintf (asm_out_file, "\tjmp\t%%o7+8\n\t add\t%%o7, %s, %s\n",
+ pic_name, pic_name);
+ else
+ fprintf (asm_out_file, "\tadd\t%%o7, %s, %s\n\tjmp\t%%o7+8\n\t nop\n",
+ pic_name, pic_name);
- ASM_GENERATE_INTERNAL_LABEL (get_pc_symbol_name, "LGETPC", 0);
- text_section ();
+ pic_helper_emitted_p = true;
+}
- align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
- if (align > 0)
- ASM_OUTPUT_ALIGN (asm_out_file, align);
- (*targetm.asm_out.internal_label) (asm_out_file, "LGETPC", 0);
- fputs ("\tretl\n\tadd\t%o7, %l7, %l7\n", asm_out_file);
- }
+/* Emit code to load the PIC register. */
- /* Initialize every time through, since we can't easily
- know this to be permanent. */
- global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
- get_pc_symbol = gen_rtx_SYMBOL_REF (Pmode, get_pc_symbol_name);
- flag_pic = 0;
+static void
+load_pic_register (bool delay_pic_helper)
+{
+ int orig_flag_pic = flag_pic;
+
+ /* If we haven't initialized the special PIC symbols, do so now. */
+ if (!pic_helper_symbol_name[0])
+ {
+ ASM_GENERATE_INTERNAL_LABEL (pic_helper_symbol_name, "LADDPC", 0);
+ pic_helper_symbol = gen_rtx_SYMBOL_REF (Pmode, pic_helper_symbol_name);
+ global_offset_table = gen_rtx_SYMBOL_REF (Pmode, "_GLOBAL_OFFSET_TABLE_");
+ }
- emit_insn (gen_get_pc (pic_offset_table_rtx, global_offset_table,
- get_pc_symbol));
+ /* If we haven't emitted the special PIC helper function, do so now unless
+ we are requested to delay it. */
+ if (!delay_pic_helper && !pic_helper_emitted_p)
+ emit_pic_helper ();
+ flag_pic = 0;
+ if (TARGET_ARCH64)
+ emit_insn (gen_load_pcrel_symdi (pic_offset_table_rtx, global_offset_table,
+ pic_helper_symbol));
+ else
+ emit_insn (gen_load_pcrel_symsi (pic_offset_table_rtx, global_offset_table,
+ pic_helper_symbol));
flag_pic = orig_flag_pic;
/* Need to emit this whether or not we obey regdecls,
@@ -3824,6 +3404,13 @@ mem_min_alignment (rtx mem, int desired)
if (GET_CODE (mem) != MEM)
return 0;
+ /* Obviously... */
+ if (!TARGET_UNALIGNED_DOUBLES
+ && MEM_ALIGN (mem) / BITS_PER_UNIT >= (unsigned)desired)
+ return 1;
+
+ /* ??? The rest of the function predates MEM_ALIGN so
+ there is probably a bit of redundancy. */
addr = XEXP (mem, 0);
base = offset = NULL_RTX;
if (GET_CODE (addr) == PLUS)
@@ -4031,6 +3618,12 @@ sparc_init_modes (void)
else
sparc_mode_class[i] = 0;
break;
+ case MODE_VECTOR_INT:
+ if (GET_MODE_SIZE (i) <= 4)
+ sparc_mode_class[i] = 1 << (int)SF_MODE;
+ else if (GET_MODE_SIZE (i) == 8)
+ sparc_mode_class[i] = 1 << (int)DF_MODE;
+ break;
case MODE_FLOAT:
case MODE_COMPLEX_FLOAT:
if (GET_MODE_SIZE (i) <= 4)
@@ -4079,128 +3672,16 @@ sparc_init_modes (void)
}
}
-/* Save non call used registers from LOW to HIGH at BASE+OFFSET.
- N_REGS is the number of 4-byte regs saved thus far. This applies even to
- v9 int regs as it simplifies the code. */
-
-static int
-save_regs (FILE *file, int low, int high, const char *base,
- int offset, int n_regs, HOST_WIDE_INT real_offset)
-{
- int i;
-
- if (TARGET_ARCH64 && high <= 32)
- {
- for (i = low; i < high; i++)
- {
- if (regs_ever_live[i] && ! call_used_regs[i])
- {
- fprintf (file, "\tstx\t%s, [%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs);
- if (dwarf2out_do_frame ())
- dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
- n_regs += 2;
- }
- }
- }
- else
- {
- for (i = low; i < high; i += 2)
- {
- if (regs_ever_live[i] && ! call_used_regs[i])
- {
- if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- {
- fprintf (file, "\tstd\t%s, [%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs);
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- dwarf2out_reg_save (l, i, real_offset + 4 * n_regs);
- dwarf2out_reg_save (l, i+1, real_offset + 4 * n_regs + 4);
- }
- n_regs += 2;
- }
- else
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[i], base, offset + 4 * n_regs);
- if (dwarf2out_do_frame ())
- dwarf2out_reg_save ("", i, real_offset + 4 * n_regs);
- n_regs += 2;
- }
- }
- else
- {
- if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[i+1], base, offset + 4 * n_regs + 4);
- if (dwarf2out_do_frame ())
- dwarf2out_reg_save ("", i + 1, real_offset + 4 * n_regs + 4);
- n_regs += 2;
- }
- }
- }
- }
- return n_regs;
-}
-
-/* Restore non call used registers from LOW to HIGH at BASE+OFFSET.
-
- N_REGS is the number of 4-byte regs saved thus far. This applies even to
- v9 int regs as it simplifies the code. */
-
-static int
-restore_regs (FILE *file, int low, int high, const char *base,
- int offset, int n_regs)
-{
- int i;
-
- if (TARGET_ARCH64 && high <= 32)
- {
- for (i = low; i < high; i++)
- {
- if (regs_ever_live[i] && ! call_used_regs[i])
- fprintf (file, "\tldx\t[%s+%d], %s\n",
- base, offset + 4 * n_regs, reg_names[i]),
- n_regs += 2;
- }
- }
- else
- {
- for (i = low; i < high; i += 2)
- {
- if (regs_ever_live[i] && ! call_used_regs[i])
- if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tldd\t[%s+%d], %s\n",
- base, offset + 4 * n_regs, reg_names[i]),
- n_regs += 2;
- else
- fprintf (file, "\tld\t[%s+%d], %s\n",
- base, offset + 4 * n_regs, reg_names[i]),
- n_regs += 2;
- else if (regs_ever_live[i+1] && ! call_used_regs[i+1])
- fprintf (file, "\tld\t[%s+%d], %s\n",
- base, offset + 4 * n_regs + 4, reg_names[i+1]),
- n_regs += 2;
- }
- }
- return n_regs;
-}
-
/* Compute the frame size required by the function. This function is called
- during the reload pass and also by output_function_prologue(). */
+ during the reload pass and also by sparc_expand_prologue. */
HOST_WIDE_INT
-compute_frame_size (HOST_WIDE_INT size, int leaf_function)
+sparc_compute_frame_size (HOST_WIDE_INT size, int leaf_function_p)
{
- int n_regs = 0, i;
int outgoing_args_size = (current_function_outgoing_args_size
+ REG_PARM_STACK_SPACE (current_function_decl));
-
- /* N_REGS is the number of 4-byte regs saved thus far. This applies
- even to v9 int regs to be consistent with save_regs/restore_regs. */
+ int n_regs = 0; /* N_REGS is the number of 4-byte regs saved thus far. */
+ int i;
if (TARGET_ARCH64)
{
@@ -4221,14 +3702,14 @@ compute_frame_size (HOST_WIDE_INT size, int leaf_function)
|| (regs_ever_live[i+1] && ! call_used_regs[i+1]))
n_regs += 2;
- /* Set up values for use in `function_epilogue'. */
+ /* Set up values for use in prologue and epilogue. */
num_gfregs = n_regs;
- if (leaf_function && n_regs == 0
- && size == 0 && current_function_outgoing_args_size == 0)
- {
- actual_fsize = apparent_fsize = 0;
- }
+ if (leaf_function_p
+ && n_regs == 0
+ && size == 0
+ && current_function_outgoing_args_size == 0)
+ actual_fsize = apparent_fsize = 0;
else
{
/* We subtract STARTING_FRAME_OFFSET, remember it's negative. */
@@ -4239,108 +3720,15 @@ compute_frame_size (HOST_WIDE_INT size, int leaf_function)
/* Make sure nothing can clobber our register windows.
If a SAVE must be done, or there is a stack-local variable,
- the register window area must be allocated.
- ??? For v8 we apparently need an additional 8 bytes of reserved space. */
- if (leaf_function == 0 || size > 0)
- actual_fsize += (16 * UNITS_PER_WORD) + (TARGET_ARCH64 ? 0 : 8);
+ the register window area must be allocated. */
+ if (! leaf_function_p || size > 0)
+ actual_fsize += FIRST_PARM_OFFSET (current_function_decl);
return SPARC_STACK_ALIGN (actual_fsize);
}
-/* Build big number NUM in register REG and output the result to FILE.
- REG is guaranteed to be the only clobbered register. The function
- will very likely emit several instructions, so it must not be called
- from within a delay slot. */
-
-static void
-build_big_number (FILE *file, HOST_WIDE_INT num, const char *reg)
-{
-#if HOST_BITS_PER_WIDE_INT == 64
- HOST_WIDE_INT high_bits = (num >> 32) & 0xffffffff;
-
- if (high_bits == 0
-#else
- if (num >= 0
-#endif
- || ! TARGET_ARCH64)
- {
- /* We don't use the 'set' macro because it appears to be broken
- in the Solaris 7 assembler. */
- fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
- num, reg);
- if ((num & 0x3ff) != 0)
- fprintf (file, "\tor\t%s, %%lo("HOST_WIDE_INT_PRINT_DEC"), %s\n",
- reg, num, reg);
- }
-#if HOST_BITS_PER_WIDE_INT == 64
- else if (high_bits == 0xffffffff) /* && TARGET_ARCH64 */
-#else
- else /* num < 0 && TARGET_ARCH64 */
-#endif
- {
- /* Sethi does not sign extend, so we must use a little trickery
- to use it for negative numbers. Invert the constant before
- loading it in, then use xor immediate to invert the loaded bits
- (along with the upper 32 bits) to the desired constant. This
- works because the sethi and immediate fields overlap. */
- HOST_WIDE_INT inv = ~num;
- HOST_WIDE_INT low = -0x400 + (num & 0x3ff);
-
- fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
- inv, reg);
- fprintf (file, "\txor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
- reg, low, reg);
- }
-#if HOST_BITS_PER_WIDE_INT == 64
- else /* TARGET_ARCH64 */
- {
- /* We don't use the 'setx' macro because if requires a scratch register.
- This is the translation of sparc_emit_set_const64_longway into asm.
- Hopefully we will soon have prologue/epilogue emitted as RTL. */
- HOST_WIDE_INT low1 = (num >> (32 - 12)) & 0xfff;
- HOST_WIDE_INT low2 = (num >> (32 - 12 - 12)) & 0xfff;
- HOST_WIDE_INT low3 = (num >> (32 - 12 - 12 - 8)) & 0x0ff;
- int to_shift = 12;
-
- /* We don't use the 'set' macro because it appears to be broken
- in the Solaris 7 assembler. */
- fprintf (file, "\tsethi\t%%hi("HOST_WIDE_INT_PRINT_DEC"), %s\n",
- high_bits, reg);
- if ((high_bits & 0x3ff) != 0)
- fprintf (file, "\tor\t%s, %%lo("HOST_WIDE_INT_PRINT_DEC"), %s\n",
- reg, high_bits, reg);
-
- if (low1 != 0)
- {
- fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
- fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
- reg, low1, reg);
- to_shift = 12;
- }
- else
- {
- to_shift += 12;
- }
- if (low2 != 0)
- {
- fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
- fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
- reg, low2, reg);
- to_shift = 8;
- }
- else
- {
- to_shift += 8;
- }
- fprintf (file, "\tsllx\t%s, %d, %s\n", reg, to_shift, reg);
- if (low3 != 0)
- fprintf (file, "\tor\t%s, "HOST_WIDE_INT_PRINT_DEC", %s\n",
- reg, low3, reg);
- }
-#endif
-}
-
/* Output any necessary .register pseudo-ops. */
+
void
sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
{
@@ -4358,341 +3746,469 @@ sparc_output_scratch_registers (FILE *file ATTRIBUTE_UNUSED)
&& ! sparc_hard_reg_printed [i])
{
sparc_hard_reg_printed [i] = 1;
- fprintf (file, "\t.register\t%%g%d, #scratch\n", i);
+ /* %g7 is used as TLS base register, use #ignore
+ for it instead of #scratch. */
+ fprintf (file, "\t.register\t%%g%d, #%s\n", i,
+ i == 7 ? "ignore" : "scratch");
}
if (i == 3) i = 5;
}
#endif
}
-/* This function 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.
- Refer to the array `regs_ever_live' to determine which registers
- to save; `regs_ever_live[I]' is nonzero if register number I
- is ever used in the function. This macro is responsible for
- knowing which registers should not be saved even if used. */
+/* Save/restore call-saved registers from LOW to HIGH at BASE+OFFSET
+ as needed. LOW should be double-word aligned for 32-bit registers.
+ Return the new OFFSET. */
+
+#define SORR_SAVE 0
+#define SORR_RESTORE 1
+
+static int
+save_or_restore_regs (int low, int high, rtx base, int offset, int action)
+{
+ rtx mem, insn;
+ int i;
+
+ if (TARGET_ARCH64 && high <= 32)
+ {
+ for (i = low; i < high; i++)
+ {
+ if (regs_ever_live[i] && ! call_used_regs[i])
+ {
+ mem = gen_rtx_MEM (DImode, plus_constant (base, offset));
+ set_mem_alias_set (mem, sparc_sr_alias_set);
+ if (action == SORR_SAVE)
+ {
+ insn = emit_move_insn (mem, gen_rtx_REG (DImode, i));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else /* action == SORR_RESTORE */
+ emit_move_insn (gen_rtx_REG (DImode, i), mem);
+ offset += 8;
+ }
+ }
+ }
+ else
+ {
+ for (i = low; i < high; i += 2)
+ {
+ bool reg0 = regs_ever_live[i] && ! call_used_regs[i];
+ bool reg1 = regs_ever_live[i+1] && ! call_used_regs[i+1];
+ enum machine_mode mode;
+ int regno;
+
+ if (reg0 && reg1)
+ {
+ mode = i < 32 ? DImode : DFmode;
+ regno = i;
+ }
+ else if (reg0)
+ {
+ mode = i < 32 ? SImode : SFmode;
+ regno = i;
+ }
+ else if (reg1)
+ {
+ mode = i < 32 ? SImode : SFmode;
+ regno = i + 1;
+ offset += 4;
+ }
+ else
+ continue;
+
+ mem = gen_rtx_MEM (mode, plus_constant (base, offset));
+ set_mem_alias_set (mem, sparc_sr_alias_set);
+ if (action == SORR_SAVE)
+ {
+ insn = emit_move_insn (mem, gen_rtx_REG (mode, regno));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else /* action == SORR_RESTORE */
+ emit_move_insn (gen_rtx_REG (mode, regno), mem);
-/* On SPARC, move-double insns between fpu and cpu need an 8-byte block
- of memory. If any fpu reg is used in the function, we allocate
- such a block here, at the bottom of the frame, just in case it's needed.
+ /* Always preserve double-word alignment. */
+ offset = (offset + 7) & -8;
+ }
+ }
- If this function is a leaf procedure, then we may choose not
- to do a "save" insn. The decision about whether or not
- to do this is made in regclass.c. */
+ return offset;
+}
+
+/* Emit code to save call-saved registers. */
static void
-sparc_output_function_prologue (FILE *file, HOST_WIDE_INT size)
+emit_save_or_restore_regs (int action)
{
- if (TARGET_FLAT)
- sparc_flat_function_prologue (file, size);
+ HOST_WIDE_INT offset;
+ rtx base;
+
+ offset = frame_base_offset - apparent_fsize;
+
+ if (offset < -4096 || offset + num_gfregs * 4 > 4095)
+ {
+ /* ??? This might be optimized a little as %g1 might already have a
+ value close enough that a single add insn will do. */
+ /* ??? Although, all of this is probably only a temporary fix
+ because if %g1 can hold a function result, then
+ sparc_expand_epilogue will lose (the result will be
+ clobbered). */
+ base = gen_rtx_REG (Pmode, 1);
+ emit_move_insn (base, GEN_INT (offset));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ base,
+ gen_rtx_PLUS (Pmode, frame_base_reg, base)));
+ offset = 0;
+ }
else
- sparc_nonflat_function_prologue (file, size,
- current_function_uses_only_leaf_regs);
+ base = frame_base_reg;
+
+ offset = save_or_restore_regs (0, 8, base, offset, action);
+ save_or_restore_regs (32, TARGET_V9 ? 96 : 64, base, offset, action);
}
-/* Output code for the function prologue. */
+/* Generate a save_register_window insn. */
-static void
-sparc_nonflat_function_prologue (FILE *file, HOST_WIDE_INT size,
- int leaf_function)
+static rtx
+gen_save_register_window (rtx increment)
{
- sparc_output_scratch_registers (file);
+ if (TARGET_ARCH64)
+ return gen_save_register_windowdi (increment);
+ else
+ return gen_save_register_windowsi (increment);
+}
+
+/* Generate an increment for the stack pointer. */
+
+static rtx
+gen_stack_pointer_inc (rtx increment)
+{
+ return gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode,
+ stack_pointer_rtx,
+ increment));
+}
+
+/* Generate a decrement for the stack pointer. */
+
+static rtx
+gen_stack_pointer_dec (rtx decrement)
+{
+ return gen_rtx_SET (VOIDmode,
+ stack_pointer_rtx,
+ gen_rtx_MINUS (Pmode,
+ stack_pointer_rtx,
+ decrement));
+}
+
+/* Expand the function prologue. The prologue is responsible for reserving
+ storage for the frame, saving the call-saved registers and loading the
+ PIC register if needed. */
+
+void
+sparc_expand_prologue (void)
+{
+ rtx insn;
+ int i;
+
+ /* Compute a snapshot of current_function_uses_only_leaf_regs. Relying
+ on the final value of the flag means deferring the prologue/epilogue
+ expansion until just before the second scheduling pass, which is too
+ late to emit multiple epilogues or return insns.
+
+ Of course we are making the assumption that the value of the flag
+ will not change between now and its final value. Of the three parts
+ of the formula, only the last one can reasonably vary. Let's take a
+ closer look, after assuming that the first two ones are set to true
+ (otherwise the last value is effectively silenced).
+
+ If only_leaf_regs_used returns false, the global predicate will also
+ be false so the actual frame size calculated below will be positive.
+ As a consequence, the save_register_window insn will be emitted in
+ the instruction stream; now this insn explicitly references %fp
+ which is not a leaf register so only_leaf_regs_used will always
+ return false subsequently.
+
+ If only_leaf_regs_used returns true, we hope that the subsequent
+ optimization passes won't cause non-leaf registers to pop up. For
+ example, the regrename pass has special provisions to not rename to
+ non-leaf registers in a leaf function. */
+ sparc_leaf_function_p
+ = optimize > 0 && leaf_function_p () && only_leaf_regs_used ();
/* Need to use actual_fsize, since we are also allocating
space for our callee (and our own register save area). */
- actual_fsize = compute_frame_size (size, leaf_function);
+ actual_fsize
+ = sparc_compute_frame_size (get_frame_size(), sparc_leaf_function_p);
- if (leaf_function)
+ /* Advertise that the data calculated just above are now valid. */
+ sparc_prologue_data_valid_p = true;
+
+ if (sparc_leaf_function_p)
{
- frame_base_name = "%sp";
+ frame_base_reg = stack_pointer_rtx;
frame_base_offset = actual_fsize + SPARC_STACK_BIAS;
}
else
{
- frame_base_name = "%fp";
+ frame_base_reg = hard_frame_pointer_rtx;
frame_base_offset = SPARC_STACK_BIAS;
}
- /* This is only for the human reader. */
- fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
-
if (actual_fsize == 0)
/* do nothing. */ ;
- else if (! leaf_function)
+ else if (sparc_leaf_function_p)
{
if (actual_fsize <= 4096)
- fprintf (file, "\tsave\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- actual_fsize);
+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-actual_fsize)));
else if (actual_fsize <= 8192)
{
- fprintf (file, "\tsave\t%%sp, -4096, %%sp\n");
- fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- actual_fsize - 4096);
+ insn = emit_insn (gen_stack_pointer_inc (GEN_INT (-4096)));
+ /* %sp is still the CFA register. */
+ RTX_FRAME_RELATED_P (insn) = 1;
+ insn
+ = emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
}
else
{
- build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tsave\t%%sp, %%g1, %%sp\n");
+ rtx reg = gen_rtx_REG (Pmode, 1);
+ emit_move_insn (reg, GEN_INT (-actual_fsize));
+ insn = emit_insn (gen_stack_pointer_inc (reg));
+ REG_NOTES (insn) =
+ gen_rtx_EXPR_LIST (REG_FRAME_RELATED_EXPR,
+ gen_stack_pointer_inc (GEN_INT (-actual_fsize)),
+ REG_NOTES (insn));
}
+
+ RTX_FRAME_RELATED_P (insn) = 1;
}
- else /* leaf function */
+ else
{
if (actual_fsize <= 4096)
- fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- actual_fsize);
+ insn = emit_insn (gen_save_register_window (GEN_INT (-actual_fsize)));
else if (actual_fsize <= 8192)
{
- fprintf (file, "\tadd\t%%sp, -4096, %%sp\n");
- fprintf (file, "\tadd\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- actual_fsize - 4096);
+ insn = emit_insn (gen_save_register_window (GEN_INT (-4096)));
+ /* %sp is not the CFA register anymore. */
+ emit_insn (gen_stack_pointer_inc (GEN_INT (4096-actual_fsize)));
}
else
{
- build_big_number (file, -actual_fsize, "%g1");
- fprintf (file, "\tadd\t%%sp, %%g1, %%sp\n");
+ rtx reg = gen_rtx_REG (Pmode, 1);
+ emit_move_insn (reg, GEN_INT (-actual_fsize));
+ insn = emit_insn (gen_save_register_window (reg));
}
+
+ RTX_FRAME_RELATED_P (insn) = 1;
+ for (i=0; i < XVECLEN (PATTERN (insn), 0); i++)
+ RTX_FRAME_RELATED_P (XVECEXP (PATTERN (insn), 0, i)) = 1;
}
- if (dwarf2out_do_frame () && actual_fsize)
- {
- char *label = dwarf2out_cfi_label ();
+ if (num_gfregs)
+ emit_save_or_restore_regs (SORR_SAVE);
- /* The canonical frame address refers to the top of the frame. */
- dwarf2out_def_cfa (label, (leaf_function ? STACK_POINTER_REGNUM
- : HARD_FRAME_POINTER_REGNUM),
- frame_base_offset);
+ /* Load the PIC register if needed. */
+ if (flag_pic && current_function_uses_pic_offset_table)
+ load_pic_register (false);
+}
+
+/* This function generates the assembly code for function entry, which boils
+ down to emitting the necessary .register directives. */
- if (! leaf_function)
- {
- /* Note the register window save. This tells the unwinder that
- it needs to restore the window registers from the previous
- frame's window save area at 0(cfa). */
- dwarf2out_window_save (label);
+static void
+sparc_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
+{
+ /* Check that the assumption we made in sparc_expand_prologue is valid. */
+ gcc_assert (sparc_leaf_function_p == current_function_uses_only_leaf_regs);
- /* The return address (-8) is now in %i7. */
- dwarf2out_return_reg (label, 31);
- }
- }
+ sparc_output_scratch_registers (file);
+}
- /* If doing anything with PIC, do it now. */
- if (! flag_pic)
- fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START);
+/* Expand the function epilogue, either normal or part of a sibcall.
+ We emit all the instructions except the return or the call. */
- /* Call saved registers are saved just above the outgoing argument area. */
+void
+sparc_expand_epilogue (void)
+{
if (num_gfregs)
+ emit_save_or_restore_regs (SORR_RESTORE);
+
+ if (actual_fsize == 0)
+ /* do nothing. */ ;
+ else if (sparc_leaf_function_p)
{
- HOST_WIDE_INT offset, real_offset;
- int n_regs;
- const char *base;
-
- real_offset = -apparent_fsize;
- offset = -apparent_fsize + frame_base_offset;
- if (offset < -4096 || offset + num_gfregs * 4 > 4096)
- {
- /* ??? This might be optimized a little as %g1 might already have a
- value close enough that a single add insn will do. */
- /* ??? Although, all of this is probably only a temporary fix
- because if %g1 can hold a function result, then
- output_function_epilogue will lose (the result will get
- clobbered). */
- build_big_number (file, offset, "%g1");
- fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
- base = "%g1";
- offset = 0;
+ if (actual_fsize <= 4096)
+ emit_insn (gen_stack_pointer_dec (GEN_INT (- actual_fsize)));
+ else if (actual_fsize <= 8192)
+ {
+ emit_insn (gen_stack_pointer_dec (GEN_INT (-4096)));
+ emit_insn (gen_stack_pointer_dec (GEN_INT (4096 - actual_fsize)));
}
else
{
- base = frame_base_name;
+ rtx reg = gen_rtx_REG (Pmode, 1);
+ emit_move_insn (reg, GEN_INT (-actual_fsize));
+ emit_insn (gen_stack_pointer_dec (reg));
}
-
- n_regs = save_regs (file, 0, 8, base, offset, 0, real_offset);
- save_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs,
- real_offset);
}
}
-/* Output code to restore any call saved registers. */
+/* Return true if it is appropriate to emit `return' instructions in the
+ body of a function. */
+bool
+sparc_can_use_return_insn_p (void)
+{
+ return sparc_prologue_data_valid_p
+ && (actual_fsize == 0 || !sparc_leaf_function_p);
+}
+
+/* This function generates the assembly code for function exit. */
+
static void
-output_restore_regs (FILE *file, int leaf_function ATTRIBUTE_UNUSED)
+sparc_asm_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
{
- HOST_WIDE_INT offset;
- int n_regs;
- const char *base;
+ /* If code does not drop into the epilogue, we have to still output
+ a dummy nop for the sake of sane backtraces. Otherwise, if the
+ last two instructions of a function were "call foo; dslot;" this
+ can make the return PC of foo (i.e. address of call instruction
+ plus 8) point to the first instruction in the next function. */
- offset = -apparent_fsize + frame_base_offset;
- if (offset < -4096 || offset + num_gfregs * 4 > 4096 - 8 /*double*/)
- {
- build_big_number (file, offset, "%g1");
- fprintf (file, "\tadd\t%s, %%g1, %%g1\n", frame_base_name);
- base = "%g1";
- offset = 0;
- }
- else
- {
- base = frame_base_name;
- }
+ rtx insn, last_real_insn;
- n_regs = restore_regs (file, 0, 8, base, offset, 0);
- restore_regs (file, 32, TARGET_V9 ? 96 : 64, base, offset, n_regs);
-}
+ insn = get_last_insn ();
-/* This function generates the assembly code for function exit,
- on machines that need it.
+ last_real_insn = prev_real_insn (insn);
+ if (last_real_insn
+ && GET_CODE (last_real_insn) == INSN
+ && GET_CODE (PATTERN (last_real_insn)) == SEQUENCE)
+ last_real_insn = XVECEXP (PATTERN (last_real_insn), 0, 0);
- 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. */
+ if (last_real_insn && GET_CODE (last_real_insn) == CALL_INSN)
+ fputs("\tnop\n", file);
-static void
-sparc_output_function_epilogue (FILE *file, HOST_WIDE_INT size)
-{
- if (TARGET_FLAT)
- sparc_flat_function_epilogue (file, size);
- else
- sparc_nonflat_function_epilogue (file, size,
- current_function_uses_only_leaf_regs);
+ sparc_output_deferred_case_vectors ();
}
-
-/* Output code for the function epilogue. */
-
+
+/* Output a 'restore' instruction. */
+
static void
-sparc_nonflat_function_epilogue (FILE *file,
- HOST_WIDE_INT size ATTRIBUTE_UNUSED,
- int leaf_function)
+output_restore (rtx pat)
{
- const char *ret;
+ rtx operands[3];
- if (current_function_epilogue_delay_list == 0)
+ if (! pat)
{
- /* If code does not drop into the epilogue, we need
- do nothing except output pending case vectors.
-
- We have to still output a dummy nop for the sake of
- sane backtraces. Otherwise, if the last two instructions
- of a function were call foo; dslot; this can make the return
- PC of foo (ie. address of call instruction plus 8) point to
- the first instruction in the next function. */
- rtx insn, last_real_insn;
-
- insn = get_last_insn ();
+ fputs ("\t restore\n", asm_out_file);
+ return;
+ }
- last_real_insn = prev_real_insn (insn);
- if (last_real_insn
- && GET_CODE (last_real_insn) == INSN
- && GET_CODE (PATTERN (last_real_insn)) == SEQUENCE)
- last_real_insn = XVECEXP (PATTERN (last_real_insn), 0, 0);
+ gcc_assert (GET_CODE (pat) == SET);
- if (last_real_insn && GET_CODE (last_real_insn) == CALL_INSN)
- fputs("\tnop\n", file);
+ operands[0] = SET_DEST (pat);
+ pat = SET_SRC (pat);
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- goto output_vectors;
+ switch (GET_CODE (pat))
+ {
+ case PLUS:
+ operands[1] = XEXP (pat, 0);
+ operands[2] = XEXP (pat, 1);
+ output_asm_insn (" restore %r1, %2, %Y0", operands);
+ break;
+ case LO_SUM:
+ operands[1] = XEXP (pat, 0);
+ operands[2] = XEXP (pat, 1);
+ output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
+ break;
+ case ASHIFT:
+ operands[1] = XEXP (pat, 0);
+ gcc_assert (XEXP (pat, 1) == const1_rtx);
+ output_asm_insn (" restore %r1, %r1, %Y0", operands);
+ break;
+ default:
+ operands[1] = pat;
+ output_asm_insn (" restore %%g0, %1, %Y0", operands);
+ break;
}
+}
+
+/* Output a return. */
- if (num_gfregs)
- output_restore_regs (file, leaf_function);
+const char *
+output_return (rtx insn)
+{
+ if (sparc_leaf_function_p)
+ {
+ /* This is a leaf function so we don't have to bother restoring the
+ register window, which frees us from dealing with the convoluted
+ semantics of restore/return. We simply output the jump to the
+ return address and the insn in the delay slot (if any). */
- /* Work out how to skip the caller's unimp instruction if required. */
- if (leaf_function)
- ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%o7+12" : "retl");
- else
- ret = (SKIP_CALLERS_UNIMP_P ? "jmp\t%i7+12" : "ret");
+ gcc_assert (! current_function_calls_eh_return);
- if (! leaf_function)
+ return "jmp\t%%o7+%)%#";
+ }
+ else
{
+ /* This is a regular function so we have to restore the register window.
+ We may have a pending insn for the delay slot, which will be either
+ combined with the 'restore' instruction or put in the delay slot of
+ the 'return' instruction. */
+
if (current_function_calls_eh_return)
{
- if (current_function_epilogue_delay_list)
- abort ();
- if (SKIP_CALLERS_UNIMP_P)
- abort ();
+ /* If the function uses __builtin_eh_return, the eh_return
+ machinery occupies the delay slot. */
+ gcc_assert (! final_sequence);
- fputs ("\trestore\n\tretl\n\tadd\t%sp, %g1, %sp\n", file);
+ if (! flag_delayed_branch)
+ fputs ("\tadd\t%fp, %g1, %fp\n", asm_out_file);
+
+ if (TARGET_V9)
+ fputs ("\treturn\t%i7+8\n", asm_out_file);
+ else
+ fputs ("\trestore\n\tjmp\t%o7+8\n", asm_out_file);
+
+ if (flag_delayed_branch)
+ fputs ("\t add\t%sp, %g1, %sp\n", asm_out_file);
+ else
+ fputs ("\t nop\n", asm_out_file);
}
- /* If we wound up with things in our delay slot, flush them here. */
- else if (current_function_epilogue_delay_list)
+ else if (final_sequence)
{
- rtx delay = PATTERN (XEXP (current_function_epilogue_delay_list, 0));
+ rtx delay, pat;
+
+ delay = NEXT_INSN (insn);
+ gcc_assert (delay);
- if (TARGET_V9 && ! epilogue_renumber (&delay, 1))
+ pat = PATTERN (delay);
+
+ if (TARGET_V9 && ! epilogue_renumber (&pat, 1))
{
- epilogue_renumber (&delay, 0);
- fputs (SKIP_CALLERS_UNIMP_P
- ? "\treturn\t%i7+12\n"
- : "\treturn\t%i7+8\n", file);
- final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
- file, 1, 0, 0, NULL);
+ epilogue_renumber (&pat, 0);
+ return "return\t%%i7+%)%#";
}
else
{
- rtx insn, src;
-
- if (GET_CODE (delay) != SET)
- abort();
-
- src = SET_SRC (delay);
- if (GET_CODE (src) == ASHIFT)
- {
- if (XEXP (src, 1) != const1_rtx)
- abort();
- SET_SRC (delay)
- = gen_rtx_PLUS (GET_MODE (src), XEXP (src, 0),
- XEXP (src, 0));
- }
-
- insn = gen_rtx_PARALLEL (VOIDmode,
- gen_rtvec (2, delay,
- gen_rtx_RETURN (VOIDmode)));
- insn = emit_jump_insn (insn);
-
- sparc_emitting_epilogue = true;
- final_scan_insn (insn, file, 1, 0, 1, NULL);
- sparc_emitting_epilogue = false;
+ output_asm_insn ("jmp\t%%i7+%)", NULL);
+ output_restore (pat);
+ PATTERN (delay) = gen_blockage ();
+ INSN_CODE (delay) = -1;
}
}
- else if (TARGET_V9 && ! SKIP_CALLERS_UNIMP_P)
- fputs ("\treturn\t%i7+8\n\tnop\n", file);
else
- fprintf (file, "\t%s\n\trestore\n", ret);
- }
- /* All of the following cases are for leaf functions. */
- else if (current_function_calls_eh_return)
- abort ();
- else if (current_function_epilogue_delay_list)
- {
- /* eligible_for_epilogue_delay_slot ensures that if this is a
- leaf function, then we will only have insn in the delay slot
- if the frame size is zero, thus no adjust for the stack is
- needed here. */
- if (actual_fsize != 0)
- abort ();
- fprintf (file, "\t%s\n", ret);
- final_scan_insn (XEXP (current_function_epilogue_delay_list, 0),
- file, 1, 0, 1, NULL);
- }
- /* Output 'nop' instead of 'sub %sp,-0,%sp' when no frame, so as to
- avoid generating confusing assembly language output. */
- else if (actual_fsize == 0)
- fprintf (file, "\t%s\n\tnop\n", ret);
- else if (actual_fsize <= 4096)
- fprintf (file, "\t%s\n\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- ret, actual_fsize);
- else if (actual_fsize <= 8192)
- fprintf (file, "\tsub\t%%sp, -4096, %%sp\n\t%s\n\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n",
- ret, actual_fsize - 4096);
- else
- {
- build_big_number (file, actual_fsize, "%g1");
- fprintf (file, "\t%s\n\tadd\t%%sp, %%g1, %%sp\n", ret);
+ {
+ /* The delay slot is empty. */
+ if (TARGET_V9)
+ return "return\t%%i7+%)\n\t nop";
+ else if (flag_delayed_branch)
+ return "jmp\t%%i7+%)\n\t restore";
+ else
+ return "restore\n\tjmp\t%%o7+%)\n\t nop";
+ }
}
- output_vectors:
- sparc_output_deferred_case_vectors ();
+ return "";
}
/* Output a sibling call. */
@@ -4700,144 +4216,61 @@ sparc_nonflat_function_epilogue (FILE *file,
const char *
output_sibcall (rtx insn, rtx call_operand)
{
- int leaf_regs = current_function_uses_only_leaf_regs;
- rtx operands[3];
- int delay_slot = dbr_sequence_length () > 0;
+ rtx operands[1];
- if (num_gfregs)
- {
- /* Call to restore global regs might clobber
- the delay slot. Instead of checking for this
- output the delay slot now. */
- if (delay_slot)
- {
- rtx delay = NEXT_INSN (insn);
+ gcc_assert (flag_delayed_branch);
- if (! delay)
- abort ();
+ operands[0] = call_operand;
- final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
- PATTERN (delay) = gen_blockage ();
- INSN_CODE (delay) = -1;
- delay_slot = 0;
- }
- output_restore_regs (asm_out_file, leaf_regs);
- }
+ if (sparc_leaf_function_p)
+ {
+ /* This is a leaf function so we don't have to bother restoring the
+ register window. We simply output the jump to the function and
+ the insn in the delay slot (if any). */
- operands[0] = call_operand;
+ gcc_assert (!(LEAF_SIBCALL_SLOT_RESERVED_P && final_sequence));
- if (leaf_regs)
+ if (final_sequence)
+ output_asm_insn ("sethi\t%%hi(%a0), %%g1\n\tjmp\t%%g1 + %%lo(%a0)%#",
+ operands);
+ else
+ /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
+ it into branch if possible. */
+ output_asm_insn ("or\t%%o7, %%g0, %%g1\n\tcall\t%a0, 0\n\t or\t%%g1, %%g0, %%o7",
+ operands);
+ }
+ else
{
-#ifdef HAVE_AS_RELAX_OPTION
- /* If as and ld are relaxing tail call insns into branch always,
- use or %o7,%g0,X; call Y; or X,%g0,%o7 always, so that it can
- be optimized. With sethi/jmpl as nor ld has no easy way how to
- find out if somebody does not branch between the sethi and jmpl. */
- int spare_slot = 0;
-#else
- int spare_slot = ((TARGET_ARCH32 || TARGET_CM_MEDLOW) && ! flag_pic);
-#endif
- HOST_WIDE_INT size = 0;
+ /* This is a regular function so we have to restore the register window.
+ We may have a pending insn for the delay slot, which will be combined
+ with the 'restore' instruction. */
+
+ output_asm_insn ("call\t%a0, 0", operands);
- if ((actual_fsize || ! spare_slot) && delay_slot)
+ if (final_sequence)
{
rtx delay = NEXT_INSN (insn);
+ gcc_assert (delay);
- if (! delay)
- abort ();
+ output_restore (PATTERN (delay));
- final_scan_insn (delay, asm_out_file, 1, 0, 1, NULL);
PATTERN (delay) = gen_blockage ();
INSN_CODE (delay) = -1;
- delay_slot = 0;
- }
- if (actual_fsize)
- {
- if (actual_fsize <= 4096)
- size = actual_fsize;
- else if (actual_fsize <= 8192)
- {
- fputs ("\tsub\t%sp, -4096, %sp\n", asm_out_file);
- size = actual_fsize - 4096;
- }
- else
- {
- build_big_number (asm_out_file, actual_fsize, "%g1");
- fputs ("\tadd\t%%sp, %%g1, %%sp\n", asm_out_file);
- }
- }
- if (spare_slot)
- {
- output_asm_insn ("sethi\t%%hi(%a0), %%g1", operands);
- output_asm_insn ("jmpl\t%%g1 + %%lo(%a0), %%g0", operands);
- if (size)
- fprintf (asm_out_file, "\t sub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n", size);
- else if (! delay_slot)
- fputs ("\t nop\n", asm_out_file);
}
else
- {
- if (size)
- fprintf (asm_out_file, "\tsub\t%%sp, -"HOST_WIDE_INT_PRINT_DEC", %%sp\n", size);
- /* Use or with rs2 %%g0 instead of mov, so that as/ld can optimize
- it into branch if possible. */
- output_asm_insn ("or\t%%o7, %%g0, %%g1", operands);
- output_asm_insn ("call\t%a0, 0", operands);
- output_asm_insn (" or\t%%g1, %%g0, %%o7", operands);
- }
- return "";
+ output_restore (NULL_RTX);
}
- output_asm_insn ("call\t%a0, 0", operands);
- if (delay_slot)
- {
- rtx delay = NEXT_INSN (insn), pat;
-
- if (! delay)
- abort ();
-
- pat = PATTERN (delay);
- if (GET_CODE (pat) != SET)
- abort ();
-
- operands[0] = SET_DEST (pat);
- pat = SET_SRC (pat);
- switch (GET_CODE (pat))
- {
- case PLUS:
- operands[1] = XEXP (pat, 0);
- operands[2] = XEXP (pat, 1);
- output_asm_insn (" restore %r1, %2, %Y0", operands);
- break;
- case LO_SUM:
- operands[1] = XEXP (pat, 0);
- operands[2] = XEXP (pat, 1);
- output_asm_insn (" restore %r1, %%lo(%a2), %Y0", operands);
- break;
- case ASHIFT:
- operands[1] = XEXP (pat, 0);
- output_asm_insn (" restore %r1, %r1, %Y0", operands);
- break;
- default:
- operands[1] = pat;
- output_asm_insn (" restore %%g0, %1, %Y0", operands);
- break;
- }
- PATTERN (delay) = gen_blockage ();
- INSN_CODE (delay) = -1;
- }
- else
- fputs ("\t restore\n", asm_out_file);
return "";
}
/* Functions for handling argument passing.
- For v8 the first six args are normally in registers and the rest are
+ For 32-bit, the first 6 args are normally in registers and the rest are
pushed. Any arg that starts within the first 6 words is at least
partially passed in a register unless its data type forbids.
- For v9, the argument registers are laid out as an array of 16 elements
+ For 64-bit, the argument registers are laid out as an array of 16 elements
and arguments are added sequentially. The first 6 int args and up to the
first 16 fp args (depending on size) are passed in regs.
@@ -4862,7 +4295,7 @@ output_sibcall (rtx insn, rtx call_operand)
Here SP = %sp if -mno-stack-bias or %sp+stack_bias otherwise.
- Integral arguments are always passed as 64 bit quantities appropriately
+ Integral arguments are always passed as 64-bit quantities appropriately
extended.
Passing of floating point values is handled as follows.
@@ -4879,7 +4312,80 @@ output_sibcall (rtx insn, rtx call_operand)
appropriate integer reg and the appropriate fp reg.
If the value is not one of the first 6 arguments the value is passed in
the appropriate fp reg and in memory.
- */
+
+
+ Summary of the calling conventions implemented by GCC on SPARC:
+
+ 32-bit ABI:
+ size argument return value
+
+ small integer <4 int. reg. int. reg.
+ word 4 int. reg. int. reg.
+ double word 8 int. reg. int. reg.
+
+ _Complex small integer <8 int. reg. int. reg.
+ _Complex word 8 int. reg. int. reg.
+ _Complex double word 16 memory int. reg.
+
+ vector integer <=8 int. reg. FP reg.
+ vector integer >8 memory memory
+
+ float 4 int. reg. FP reg.
+ double 8 int. reg. FP reg.
+ long double 16 memory memory
+
+ _Complex float 8 memory FP reg.
+ _Complex double 16 memory FP reg.
+ _Complex long double 32 memory FP reg.
+
+ vector float any memory memory
+
+ aggregate any memory memory
+
+
+
+ 64-bit ABI:
+ size argument return value
+
+ small integer <8 int. reg. int. reg.
+ word 8 int. reg. int. reg.
+ double word 16 int. reg. int. reg.
+
+ _Complex small integer <16 int. reg. int. reg.
+ _Complex word 16 int. reg. int. reg.
+ _Complex double word 32 memory int. reg.
+
+ vector integer <=16 FP reg. FP reg.
+ vector integer 16<s<=32 memory FP reg.
+ vector integer >32 memory memory
+
+ float 4 FP reg. FP reg.
+ double 8 FP reg. FP reg.
+ long double 16 FP reg. FP reg.
+
+ _Complex float 8 FP reg. FP reg.
+ _Complex double 16 FP reg. FP reg.
+ _Complex long double 32 memory FP reg.
+
+ vector float <=16 FP reg. FP reg.
+ vector float 16<s<=32 memory FP reg.
+ vector float >32 memory memory
+
+ aggregate <=16 reg. reg.
+ aggregate 16<s<=32 memory reg.
+ aggregate >32 memory memory
+
+
+
+Note #1: complex floating-point types follow the extended SPARC ABIs as
+implemented by the Sun compiler.
+
+Note #2: integral vector types follow the scalar floating-point types
+conventions to match what is implemented by the Sun VIS SDK.
+
+Note #3: floating-point vector types follow the aggregate types
+conventions. */
+
/* Maximum number of int regs for args. */
#define SPARC_INT_ARG_MAX 6
@@ -4903,6 +4409,23 @@ init_cumulative_args (struct sparc_args *cum, tree fntype,
cum->libcall_p = fntype == 0;
}
+/* Handle the TARGET_PROMOTE_PROTOTYPES target hook.
+ When a prototype says `char' or `short', really pass an `int'. */
+
+static bool
+sparc_promote_prototypes (tree fntype ATTRIBUTE_UNUSED)
+{
+ return TARGET_ARCH32 ? true : false;
+}
+
+/* Handle the TARGET_STRICT_ARGUMENT_NAMING target hook. */
+
+static bool
+sparc_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED)
+{
+ return TARGET_ARCH64 ? true : false;
+}
+
/* Scan the record type TYPE and return the following predicates:
- INTREGS_P: the record contains at least one field or sub-field
that is eligible for promotion in integer registers.
@@ -4923,7 +4446,9 @@ scan_record_type (tree type, int *intregs_p, int *fpregs_p, int *packed_p)
{
if (TREE_CODE (TREE_TYPE (field)) == RECORD_TYPE)
scan_record_type (TREE_TYPE (field), intregs_p, fpregs_p, 0);
- else if (FLOAT_TYPE_P (TREE_TYPE (field)) && TARGET_FPU)
+ else if ((FLOAT_TYPE_P (TREE_TYPE (field))
+ || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
+ && TARGET_FPU)
*fpregs_p = 1;
else
*intregs_p = 1;
@@ -4958,91 +4483,100 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
? SPARC_INCOMING_INT_ARG_FIRST
: SPARC_OUTGOING_INT_ARG_FIRST);
int slotno = cum->words;
+ enum mode_class mclass;
int regno;
*ppadding = 0;
- if (type != 0 && TREE_ADDRESSABLE (type))
+ if (type && TREE_ADDRESSABLE (type))
return -1;
+
if (TARGET_ARCH32
- && type != 0 && mode == BLKmode
+ && mode == BLKmode
+ && type
&& TYPE_ALIGN (type) % PARM_BOUNDARY != 0)
return -1;
- switch (mode)
+ /* For SPARC64, objects requiring 16-byte alignment get it. */
+ if (TARGET_ARCH64
+ && (type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode)) >= 128
+ && (slotno & 1) != 0)
+ slotno++, *ppadding = 1;
+
+ mclass = GET_MODE_CLASS (mode);
+ if (type && TREE_CODE (type) == VECTOR_TYPE)
{
- case VOIDmode :
- /* MODE is VOIDmode when generating the actual call.
- See emit_call_1. */
- return -1;
+ /* Vector types deserve special treatment because they are
+ polymorphic wrt their mode, depending upon whether VIS
+ instructions are enabled. */
+ if (TREE_CODE (TREE_TYPE (type)) == REAL_TYPE)
+ {
+ /* The SPARC port defines no floating-point vector modes. */
+ gcc_assert (mode == BLKmode);
+ }
+ else
+ {
+ /* Integral vector types should either have a vector
+ mode or an integral mode, because we are guaranteed
+ by pass_by_reference that their size is not greater
+ than 16 bytes and TImode is 16-byte wide. */
+ gcc_assert (mode != BLKmode);
- case TImode : case CTImode :
- if (TARGET_ARCH64 && (slotno & 1) != 0)
- slotno++, *ppadding = 1;
+ /* Vector integers are handled like floats according to
+ the Sun VIS SDK. */
+ mclass = MODE_FLOAT;
+ }
+ }
+
+ switch (mclass)
+ {
+ case MODE_FLOAT:
+ case MODE_COMPLEX_FLOAT:
+ if (TARGET_ARCH64 && TARGET_FPU && named)
+ {
+ if (slotno >= SPARC_FP_ARG_MAX)
+ return -1;
+ regno = SPARC_FP_ARG_FIRST + slotno * 2;
+ /* Arguments filling only one single FP register are
+ right-justified in the outer double FP register. */
+ if (GET_MODE_SIZE (mode) <= 4)
+ regno++;
+ break;
+ }
/* fallthrough */
- case QImode : case CQImode :
- case HImode : case CHImode :
- case SImode : case CSImode :
- case DImode : case CDImode :
+ case MODE_INT:
+ case MODE_COMPLEX_INT:
if (slotno >= SPARC_INT_ARG_MAX)
return -1;
regno = regbase + slotno;
break;
- case TFmode : case TCmode :
- if (TARGET_ARCH64 && (slotno & 1) != 0)
- slotno++, *ppadding = 1;
- /* fallthrough */
-
- case SFmode : case SCmode :
- case DFmode : case DCmode :
- if (TARGET_ARCH32)
- {
- if (slotno >= SPARC_INT_ARG_MAX)
- return -1;
- regno = regbase + slotno;
- }
- else
- {
- if (TARGET_FPU && named)
- {
- if (slotno >= SPARC_FP_ARG_MAX)
- return -1;
- regno = SPARC_FP_ARG_FIRST + slotno * 2;
- if (mode == SFmode)
- regno++;
- }
- else
- {
- if (slotno >= SPARC_INT_ARG_MAX)
- return -1;
- regno = regbase + slotno;
- }
- }
- break;
+ case MODE_RANDOM:
+ if (mode == VOIDmode)
+ /* MODE is VOIDmode when generating the actual call. */
+ return -1;
- case BLKmode :
- /* For sparc64, objects requiring 16 byte alignment get it. */
- if (TARGET_ARCH64)
- {
- if (type && TYPE_ALIGN (type) == 128 && (slotno & 1) != 0)
- slotno++, *ppadding = 1;
- }
+ gcc_assert (mode == BLKmode);
if (TARGET_ARCH32
- || (type && TREE_CODE (type) == UNION_TYPE))
+ || !type
+ || (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != RECORD_TYPE))
{
if (slotno >= SPARC_INT_ARG_MAX)
return -1;
regno = regbase + slotno;
}
- else
+ else /* TARGET_ARCH64 && type */
{
int intregs_p = 0, fpregs_p = 0, packed_p = 0;
/* First see what kinds of registers we would need. */
- scan_record_type (type, &intregs_p, &fpregs_p, &packed_p);
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ fpregs_p = 1;
+ else
+ scan_record_type (type, &intregs_p, &fpregs_p, &packed_p);
/* The ABI obviously doesn't specify how packed structures
are passed. These are defined to be passed in int regs
@@ -5053,10 +4587,12 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
/* If all arg slots are filled, then must pass on stack. */
if (fpregs_p && slotno >= SPARC_FP_ARG_MAX)
return -1;
+
/* If there are only int args and all int arg slots are filled,
then must pass on stack. */
if (!fpregs_p && intregs_p && slotno >= SPARC_INT_ARG_MAX)
return -1;
+
/* Note that even if all int arg slots are filled, fp members may
still be passed in regs if such regs are available.
*PREGNO isn't set because there may be more than one, it's up
@@ -5066,7 +4602,7 @@ function_arg_slotno (const struct sparc_args *cum, enum machine_mode mode,
break;
default :
- abort ();
+ gcc_unreachable ();
}
*pregno = regno;
@@ -5129,9 +4665,14 @@ function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
{
HOST_WIDE_INT bitpos = startbitpos;
- if (DECL_SIZE (field) != 0
- && host_integerp (bit_position (field), 1))
- bitpos += int_bit_position (field);
+ if (DECL_SIZE (field) != 0)
+ {
+ if (integer_zerop (DECL_SIZE (field)))
+ continue;
+
+ if (host_integerp (bit_position (field), 1))
+ bitpos += int_bit_position (field);
+ }
/* ??? FIXME: else assume zero offset. */
@@ -5140,7 +4681,8 @@ function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
bitpos,
parms,
packed_p);
- else if (FLOAT_TYPE_P (TREE_TYPE (field))
+ else if ((FLOAT_TYPE_P (TREE_TYPE (field))
+ || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
&& TARGET_FPU
&& parms->named
&& ! packed_p)
@@ -5170,8 +4712,12 @@ function_arg_record_value_1 (tree type, HOST_WIDE_INT startbitpos,
/* There's no need to check this_slotno < SPARC_FP_ARG MAX.
If it wasn't true we wouldn't be here. */
- parms->nregs += 1;
- if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE
+ && DECL_MODE (field) == BLKmode)
+ parms->nregs += TYPE_VECTOR_SUBPARTS (TREE_TYPE (field));
+ else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ parms->nregs += 2;
+ else
parms->nregs += 1;
}
else
@@ -5217,8 +4763,8 @@ function_arg_record_value_3 (HOST_WIDE_INT bitpos,
at the moment but may wish to revisit. */
if (intoffset % BITS_PER_WORD != 0)
- mode = mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
- MODE_INT, 0);
+ mode = smallest_mode_for_size (BITS_PER_WORD - intoffset % BITS_PER_WORD,
+ MODE_INT);
else
mode = word_mode;
@@ -5267,9 +4813,14 @@ function_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos,
{
HOST_WIDE_INT bitpos = startbitpos;
- if (DECL_SIZE (field) != 0
- && host_integerp (bit_position (field), 1))
- bitpos += int_bit_position (field);
+ if (DECL_SIZE (field) != 0)
+ {
+ if (integer_zerop (DECL_SIZE (field)))
+ continue;
+
+ if (host_integerp (bit_position (field), 1))
+ bitpos += int_bit_position (field);
+ }
/* ??? FIXME: else assume zero offset. */
@@ -5278,40 +4829,48 @@ function_arg_record_value_2 (tree type, HOST_WIDE_INT startbitpos,
bitpos,
parms,
packed_p);
- else if (FLOAT_TYPE_P (TREE_TYPE (field))
+ else if ((FLOAT_TYPE_P (TREE_TYPE (field))
+ || TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE)
&& TARGET_FPU
&& parms->named
&& ! packed_p)
{
int this_slotno = parms->slotno + bitpos / BITS_PER_WORD;
- int regno;
+ int regno, nregs, pos;
enum machine_mode mode = DECL_MODE (field);
rtx reg;
function_arg_record_value_3 (bitpos, parms);
- regno = SPARC_FP_ARG_FIRST + this_slotno * 2
- + ((mode == SFmode || mode == SCmode)
- && (bitpos & 32) != 0);
- switch (mode)
- {
- case SCmode: mode = SFmode; break;
- case DCmode: mode = DFmode; break;
- case TCmode: mode = TFmode; break;
- default: break;
+
+ if (TREE_CODE (TREE_TYPE (field)) == VECTOR_TYPE
+ && mode == BLKmode)
+ {
+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
+ nregs = TYPE_VECTOR_SUBPARTS (TREE_TYPE (field));
+ }
+ else if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ {
+ mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (field)));
+ nregs = 2;
}
+ else
+ nregs = 1;
+
+ regno = SPARC_FP_ARG_FIRST + this_slotno * 2;
+ if (GET_MODE_SIZE (mode) <= 4 && (bitpos & 32) != 0)
+ regno++;
reg = gen_rtx_REG (mode, regno);
+ pos = bitpos / BITS_PER_UNIT;
XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
- = gen_rtx_EXPR_LIST (VOIDmode, reg,
- GEN_INT (bitpos / BITS_PER_UNIT));
+ = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos));
parms->nregs += 1;
- if (TREE_CODE (TREE_TYPE (field)) == COMPLEX_TYPE)
+ while (--nregs > 0)
{
regno += GET_MODE_SIZE (mode) / 4;
reg = gen_rtx_REG (mode, regno);
+ pos += GET_MODE_SIZE (mode);
XVECEXP (parms->ret, 0, parms->stack + parms->nregs)
- = gen_rtx_EXPR_LIST (VOIDmode, reg,
- GEN_INT ((bitpos + GET_MODE_BITSIZE (mode))
- / BITS_PER_UNIT));
+ = gen_rtx_EXPR_LIST (VOIDmode, reg, GEN_INT (pos));
parms->nregs += 1;
}
}
@@ -5400,15 +4959,14 @@ function_arg_record_value (tree type, enum machine_mode mode,
if (nregs + slotno > SPARC_INT_ARG_MAX)
nregs = SPARC_INT_ARG_MAX - slotno;
}
- if (nregs == 0)
- abort ();
+ gcc_assert (nregs != 0);
parms.ret = gen_rtx_PARALLEL (mode, rtvec_alloc (parms.stack + nregs));
/* If at least one field must be passed on the stack, generate
(parallel [(expr_list (nil) ...) ...]) so that all fields will
also be passed on the stack. We can't do much better because the
- semantics of FUNCTION_ARG_PARTIAL_NREGS doesn't handle the case
+ semantics of TARGET_ARG_PARTIAL_BYTES doesn't handle the case
of structures for which the fields passed exclusively in registers
are not at the beginning of the structure. */
if (parms.stack)
@@ -5421,8 +4979,7 @@ function_arg_record_value (tree type, enum machine_mode mode,
function_arg_record_value_2 (type, 0, &parms, false);
function_arg_record_value_3 (typesize * BITS_PER_UNIT, &parms);
- if (parms.nregs != nregs)
- abort ();
+ gcc_assert (parms.nregs == nregs);
return parms.ret;
}
@@ -5450,14 +5007,47 @@ function_arg_union_value (int size, enum machine_mode mode, int slotno,
if (slotno == SPARC_INT_ARG_MAX - 1)
nwords = 1;
- /* Unions are passed left-justified. */
regs = gen_rtx_PARALLEL (mode, rtvec_alloc (nwords));
for (i = 0; i < nwords; i++)
- XVECEXP (regs, 0, i)
- = gen_rtx_EXPR_LIST (VOIDmode,
- gen_rtx_REG (word_mode, regno + i),
- GEN_INT (UNITS_PER_WORD * i));
+ {
+ /* Unions are passed left-justified. */
+ XVECEXP (regs, 0, i)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (word_mode, regno),
+ GEN_INT (UNITS_PER_WORD * i));
+ regno++;
+ }
+
+ return regs;
+}
+
+/* Used by function_arg and function_value to implement the conventions
+ for passing and returning large (BLKmode) vectors.
+ Return an expression valid as a return value for the two macros
+ FUNCTION_ARG and FUNCTION_VALUE.
+
+ SIZE is the size in bytes of the vector.
+ BASE_MODE is the argument's base machine mode.
+ REGNO is the FP hard register the vector will be passed in. */
+
+static rtx
+function_arg_vector_value (int size, enum machine_mode base_mode, int regno)
+{
+ unsigned short base_mode_size = GET_MODE_SIZE (base_mode);
+ int nregs = size / base_mode_size, i;
+ rtx regs;
+
+ regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nregs));
+
+ for (i = 0; i < nregs; i++)
+ {
+ XVECEXP (regs, 0, i)
+ = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (base_mode, regno),
+ GEN_INT (base_mode_size * i));
+ regno += base_mode_size / 4;
+ }
return regs;
}
@@ -5485,48 +5075,59 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
? SPARC_INCOMING_INT_ARG_FIRST
: SPARC_OUTGOING_INT_ARG_FIRST);
int slotno, regno, padding;
- rtx reg;
+ enum mode_class mclass = GET_MODE_CLASS (mode);
slotno = function_arg_slotno (cum, mode, type, named, incoming_p,
&regno, &padding);
-
if (slotno == -1)
return 0;
- if (TARGET_ARCH32)
+ /* Vector types deserve special treatment because they are polymorphic wrt
+ their mode, depending upon whether VIS instructions are enabled. */
+ if (type && TREE_CODE (type) == VECTOR_TYPE)
{
- reg = gen_rtx_REG (mode, regno);
- return reg;
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert ((TARGET_ARCH32 && size <= 8)
+ || (TARGET_ARCH64 && size <= 16));
+
+ if (mode == BLKmode)
+ return function_arg_vector_value (size,
+ TYPE_MODE (TREE_TYPE (type)),
+ SPARC_FP_ARG_FIRST + 2*slotno);
+ else
+ mclass = MODE_FLOAT;
}
-
+
+ if (TARGET_ARCH32)
+ return gen_rtx_REG (mode, regno);
+
+ /* Structures up to 16 bytes in size are passed in arg slots on the stack
+ and are promoted to registers if possible. */
if (type && TREE_CODE (type) == RECORD_TYPE)
{
- /* Structures up to 16 bytes in size are passed in arg slots on the
- stack and are promoted to registers where possible. */
-
- if (int_size_in_bytes (type) > 16)
- abort (); /* shouldn't get here */
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert (size <= 16);
return function_arg_record_value (type, mode, slotno, named, regbase);
}
+
+ /* Unions up to 16 bytes in size are passed in integer registers. */
else if (type && TREE_CODE (type) == UNION_TYPE)
{
HOST_WIDE_INT size = int_size_in_bytes (type);
-
- if (size > 16)
- abort (); /* shouldn't get here */
+ gcc_assert (size <= 16);
return function_arg_union_value (size, mode, slotno, regno);
}
+
/* v9 fp args in reg slots beyond the int reg slots get passed in regs
but also have the slot allocated for them.
If no prototype is in scope fp values in register slots get passed
in two places, either fp regs and int regs or fp regs and memory. */
- else if ((GET_MODE_CLASS (mode) == MODE_FLOAT
- || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
- && SPARC_FP_REG_P (regno))
+ else if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
+ && SPARC_FP_REG_P (regno))
{
- reg = gen_rtx_REG (mode, regno);
+ rtx reg = gen_rtx_REG (mode, regno);
if (cum->prototype_p || cum->libcall_p)
{
/* "* 2" because fp reg numbers are recorded in 4 byte
@@ -5587,18 +5188,22 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
}
}
}
- else
+
+ /* All other aggregate types are passed in an integer register in a mode
+ corresponding to the size of the type. */
+ else if (type && AGGREGATE_TYPE_P (type))
{
- /* Scalar or complex int. */
- reg = gen_rtx_REG (mode, regno);
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert (size <= 16);
+
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
}
- return reg;
+ return gen_rtx_REG (mode, regno);
}
-/* Handle the FUNCTION_ARG_PARTIAL_NREGS macro.
- For an arg passed partly in registers and partly in memory,
- this is the number of registers used.
+/* For an arg passed partly in registers and partly in memory,
+ this is the number of bytes of registers used.
For args passed entirely in registers or entirely in memory, zero.
Any arg that starts in the first 6 regs but won't entirely fit in them
@@ -5607,9 +5212,9 @@ function_arg (const struct sparc_args *cum, enum machine_mode mode,
values that begin in the last fp reg [where "last fp reg" varies with the
mode] will be split between that reg and memory. */
-int
-function_arg_partial_nregs (const struct sparc_args *cum,
- enum machine_mode mode, tree type, int named)
+static int
+sparc_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+ tree type, bool named)
{
int slotno, regno, padding;
@@ -5624,84 +5229,92 @@ function_arg_partial_nregs (const struct sparc_args *cum,
if ((slotno + (mode == BLKmode
? ROUND_ADVANCE (int_size_in_bytes (type))
: ROUND_ADVANCE (GET_MODE_SIZE (mode))))
- > NPARM_REGS (SImode))
- return NPARM_REGS (SImode) - slotno;
- return 0;
+ > SPARC_INT_ARG_MAX)
+ return (SPARC_INT_ARG_MAX - slotno) * UNITS_PER_WORD;
}
else
{
+ /* We are guaranteed by pass_by_reference that the size of the
+ argument is not greater than 16 bytes, so we only need to return
+ one word if the argument is partially passed in registers. */
+
if (type && AGGREGATE_TYPE_P (type))
{
int size = int_size_in_bytes (type);
- int align = TYPE_ALIGN (type);
- if (align == 16)
- slotno += slotno & 1;
- if (size > 8 && size <= 16
+ if (size > UNITS_PER_WORD
&& slotno == SPARC_INT_ARG_MAX - 1)
- return 1;
+ return UNITS_PER_WORD;
}
else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_INT
|| (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT
&& ! (TARGET_FPU && named)))
{
/* The complex types are passed as packed types. */
- if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD)
- return 0;
-
- if (GET_MODE_ALIGNMENT (mode) == 128)
- {
- slotno += slotno & 1;
-
- /* ??? The mode needs 3 slots? */
- if (slotno == SPARC_INT_ARG_MAX - 2)
- return 1;
- }
- else
- {
- if (slotno == SPARC_INT_ARG_MAX - 1)
- return 1;
- }
+ if (GET_MODE_SIZE (mode) > UNITS_PER_WORD
+ && slotno == SPARC_INT_ARG_MAX - 1)
+ return UNITS_PER_WORD;
}
else if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT)
{
- if (GET_MODE_ALIGNMENT (mode) == 128)
- slotno += slotno & 1;
if ((slotno + GET_MODE_SIZE (mode) / UNITS_PER_WORD)
> SPARC_FP_ARG_MAX)
- return 1;
+ return UNITS_PER_WORD;
}
- return 0;
}
+
+ return 0;
}
-/* Handle the FUNCTION_ARG_PASS_BY_REFERENCE macro.
- !v9: The SPARC ABI stipulates passing struct arguments (of any size) and
- quad-precision floats by invisible reference.
- v9: Aggregates greater than 16 bytes are passed by reference.
- For Pascal, also pass arrays by reference. */
+/* Handle the TARGET_PASS_BY_REFERENCE target hook.
+ Specify whether to pass the argument by reference. */
-int
-function_arg_pass_by_reference (const struct sparc_args *cum ATTRIBUTE_UNUSED,
- enum machine_mode mode, tree type,
- int named ATTRIBUTE_UNUSED)
+static bool
+sparc_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
+ enum machine_mode mode, tree type,
+ bool named ATTRIBUTE_UNUSED)
{
if (TARGET_ARCH32)
- {
- return ((type && AGGREGATE_TYPE_P (type))
- || mode == SCmode
- || GET_MODE_SIZE (mode) > 8);
- }
+ /* Original SPARC 32-bit ABI says that structures and unions,
+ and quad-precision floats are passed by reference. For Pascal,
+ also pass arrays by reference. All other base types are passed
+ in registers.
+
+ Extended ABI (as implemented by the Sun compiler) says that all
+ complex floats are passed by reference. Pass complex integers
+ in registers up to 8 bytes. More generally, enforce the 2-word
+ cap for passing arguments in registers.
+
+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
+ integers are passed like floats of the same size, that is in
+ registers up to 8 bytes. Pass all vector floats by reference
+ like structure and unions. */
+ return ((type && (AGGREGATE_TYPE_P (type) || VECTOR_FLOAT_TYPE_P (type)))
+ || mode == SCmode
+ /* Catch CDImode, TFmode, DCmode and TCmode. */
+ || GET_MODE_SIZE (mode) > 8
+ || (type
+ && TREE_CODE (type) == VECTOR_TYPE
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
else
- {
- return ((type && TREE_CODE (type) == ARRAY_TYPE)
- /* Consider complex values as aggregates, so care
- for CTImode and TCmode. */
- || GET_MODE_SIZE (mode) > 16
- || (type
- && AGGREGATE_TYPE_P (type)
- && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16));
- }
+ /* Original SPARC 64-bit ABI says that structures and unions
+ smaller than 16 bytes are passed in registers, as well as
+ all other base types.
+
+ Extended ABI (as implemented by the Sun compiler) says that
+ complex floats are passed in registers up to 16 bytes. Pass
+ all complex integers in registers up to 16 bytes. More generally,
+ enforce the 2-word cap for passing arguments in registers.
+
+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
+ integers are passed like floats of the same size, that is in
+ registers (up to 16 bytes). Pass all vector floats like structure
+ and unions. */
+ return ((type
+ && (AGGREGATE_TYPE_P (type) || TREE_CODE (type) == VECTOR_TYPE)
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 16)
+ /* Catch CTImode and TCmode. */
+ || GET_MODE_SIZE (mode) > 16);
}
/* Handle the FUNCTION_ARG_ADVANCE macro.
@@ -5764,50 +5377,177 @@ function_arg_padding (enum machine_mode mode, tree type)
return DEFAULT_FUNCTION_ARG_PADDING (mode, type);
}
+/* Handle the TARGET_RETURN_IN_MEMORY target hook.
+ Specify whether to return the return value in memory. */
+
+static bool
+sparc_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED)
+{
+ if (TARGET_ARCH32)
+ /* Original SPARC 32-bit ABI says that structures and unions,
+ and quad-precision floats are returned in memory. All other
+ base types are returned in registers.
+
+ Extended ABI (as implemented by the Sun compiler) says that
+ all complex floats are returned in registers (8 FP registers
+ at most for '_Complex long double'). Return all complex integers
+ in registers (4 at most for '_Complex long long').
+
+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
+ integers are returned like floats of the same size, that is in
+ registers up to 8 bytes and in memory otherwise. Return all
+ vector floats in memory like structure and unions; note that
+ they always have BLKmode like the latter. */
+ return (TYPE_MODE (type) == BLKmode
+ || TYPE_MODE (type) == TFmode
+ || (TREE_CODE (type) == VECTOR_TYPE
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 8));
+ else
+ /* Original SPARC 64-bit ABI says that structures and unions
+ smaller than 32 bytes are returned in registers, as well as
+ all other base types.
+
+ Extended ABI (as implemented by the Sun compiler) says that all
+ complex floats are returned in registers (8 FP registers at most
+ for '_Complex long double'). Return all complex integers in
+ registers (4 at most for '_Complex TItype').
+
+ Vector ABI (as implemented by the Sun VIS SDK) says that vector
+ integers are returned like floats of the same size, that is in
+ registers. Return all vector floats like structure and unions;
+ note that they always have BLKmode like the latter. */
+ return ((TYPE_MODE (type) == BLKmode
+ && (unsigned HOST_WIDE_INT) int_size_in_bytes (type) > 32));
+}
+
+/* Handle the TARGET_STRUCT_VALUE target hook.
+ Return where to find the structure return value address. */
+
+static rtx
+sparc_struct_value_rtx (tree fndecl, int incoming)
+{
+ if (TARGET_ARCH64)
+ return 0;
+ else
+ {
+ rtx mem;
+
+ if (incoming)
+ mem = gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx,
+ STRUCT_VALUE_OFFSET));
+ else
+ mem = gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx,
+ STRUCT_VALUE_OFFSET));
+
+ /* Only follow the SPARC ABI for fixed-size structure returns.
+ Variable size structure returns are handled per the normal
+ procedures in GCC. This is enabled by -mstd-struct-return */
+ if (incoming == 2
+ && sparc_std_struct_return
+ && TYPE_SIZE_UNIT (TREE_TYPE (fndecl))
+ && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (fndecl))) == INTEGER_CST)
+ {
+ /* We must check and adjust the return address, as it is
+ optional as to whether the return object is really
+ provided. */
+ rtx ret_rtx = gen_rtx_REG (Pmode, 31);
+ rtx scratch = gen_reg_rtx (SImode);
+ rtx endlab = gen_label_rtx ();
+
+ /* Calculate the return object size */
+ tree size = TYPE_SIZE_UNIT (TREE_TYPE (fndecl));
+ rtx size_rtx = GEN_INT (TREE_INT_CST_LOW (size) & 0xfff);
+ /* Construct a temporary return value */
+ rtx temp_val = assign_stack_local (Pmode, TREE_INT_CST_LOW (size), 0);
+
+ /* Implement SPARC 32-bit psABI callee returns struck checking
+ requirements:
+
+ Fetch the instruction where we will return to and see if
+ it's an unimp instruction (the most significant 10 bits
+ will be zero). */
+ emit_move_insn (scratch, gen_rtx_MEM (SImode,
+ plus_constant (ret_rtx, 8)));
+ /* Assume the size is valid and pre-adjust */
+ emit_insn (gen_add3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
+ emit_cmp_and_jump_insns (scratch, size_rtx, EQ, const0_rtx, SImode, 0, endlab);
+ emit_insn (gen_sub3_insn (ret_rtx, ret_rtx, GEN_INT (4)));
+ /* Assign stack temp:
+ Write the address of the memory pointed to by temp_val into
+ the memory pointed to by mem */
+ emit_move_insn (mem, XEXP (temp_val, 0));
+ emit_label (endlab);
+ }
+
+ set_mem_alias_set (mem, struct_value_alias_set);
+ return mem;
+ }
+}
+
/* Handle FUNCTION_VALUE, FUNCTION_OUTGOING_VALUE, and LIBCALL_VALUE macros.
For v9, function return values are subject to the same rules as arguments,
- except that up to 32-bytes may be returned in registers. */
+ except that up to 32 bytes may be returned in registers. */
rtx
function_value (tree type, enum machine_mode mode, int incoming_p)
{
+ /* Beware that the two values are swapped here wrt function_arg. */
+ int regbase = (incoming_p
+ ? SPARC_OUTGOING_INT_ARG_FIRST
+ : SPARC_INCOMING_INT_ARG_FIRST);
+ enum mode_class mclass = GET_MODE_CLASS (mode);
int regno;
- if (TARGET_ARCH64 && type)
+ /* Vector types deserve special treatment because they are polymorphic wrt
+ their mode, depending upon whether VIS instructions are enabled. */
+ if (type && TREE_CODE (type) == VECTOR_TYPE)
{
- int regbase = (incoming_p
- ? SPARC_OUTGOING_INT_ARG_FIRST
- : SPARC_INCOMING_INT_ARG_FIRST);
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert ((TARGET_ARCH32 && size <= 8)
+ || (TARGET_ARCH64 && size <= 32));
+
+ if (mode == BLKmode)
+ return function_arg_vector_value (size,
+ TYPE_MODE (TREE_TYPE (type)),
+ SPARC_FP_ARG_FIRST);
+ else
+ mclass = MODE_FLOAT;
+ }
+ if (TARGET_ARCH64 && type)
+ {
+ /* Structures up to 32 bytes in size are returned in registers. */
if (TREE_CODE (type) == RECORD_TYPE)
{
- /* Structures up to 32 bytes in size are passed in registers,
- promoted to fp registers where possible. */
-
- if (int_size_in_bytes (type) > 32)
- abort (); /* shouldn't get here */
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert (size <= 32);
return function_arg_record_value (type, mode, 0, 1, regbase);
}
+
+ /* Unions up to 32 bytes in size are returned in integer registers. */
else if (TREE_CODE (type) == UNION_TYPE)
{
HOST_WIDE_INT size = int_size_in_bytes (type);
-
- if (size > 32)
- abort (); /* shouldn't get here */
+ gcc_assert (size <= 32);
return function_arg_union_value (size, mode, 0, regbase);
}
+
+ /* Objects that require it are returned in FP registers. */
+ else if (mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT)
+ ;
+
+ /* All other aggregate types are returned in an integer register in a
+ mode corresponding to the size of the type. */
else if (AGGREGATE_TYPE_P (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 ();
+ HOST_WIDE_INT size = int_size_in_bytes (type);
+ gcc_assert (size <= 32);
- mode = mode_for_size (bytes * BITS_PER_UNIT, MODE_INT, 0);
+ mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
/* ??? We probably should have made the same ABI change in
3.4.0 as the one we made for unions. The latter was
@@ -5819,17 +5559,20 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
try to be unduly clever, and simply follow the ABI
for unions in that case. */
if (mode == BLKmode)
- return function_arg_union_value (bytes, mode, 0, regbase);
+ return function_arg_union_value (size, mode, 0, regbase);
+ else
+ mclass = MODE_INT;
}
- else if (GET_MODE_CLASS (mode) == MODE_INT
- && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+
+ /* This must match PROMOTE_FUNCTION_MODE. */
+ else if (mclass == MODE_INT && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
mode = word_mode;
}
- if (incoming_p)
- regno = BASE_RETURN_VALUE_REG (mode);
+ if ((mclass == MODE_FLOAT || mclass == MODE_COMPLEX_FLOAT) && TARGET_FPU)
+ regno = SPARC_FP_ARG_FIRST;
else
- regno = BASE_OUTGOING_VALUE_REG (mode);
+ regno = regbase;
return gen_rtx_REG (mode, regno);
}
@@ -5838,14 +5581,14 @@ function_value (tree type, enum machine_mode mode, int incoming_p)
to determine if stdarg or varargs is used and return the address of
the first unnamed parameter. */
-rtx
+static rtx
sparc_builtin_saveregs (void)
{
int first_reg = current_function_args_info.words;
rtx address;
int regno;
- for (regno = first_reg; regno < NPARM_REGS (word_mode); regno++)
+ for (regno = first_reg; regno < SPARC_INT_ARG_MAX; regno++)
emit_move_insn (gen_rtx_MEM (word_mode,
gen_rtx_PLUS (Pmode,
frame_pointer_rtx,
@@ -5853,7 +5596,7 @@ sparc_builtin_saveregs (void)
+ (UNITS_PER_WORD
* regno)))),
gen_rtx_REG (word_mode,
- BASE_INCOMING_ARG_REG (word_mode) + regno));
+ SPARC_INCOMING_INT_ARG_FIRST + regno));
address = gen_rtx_PLUS (Pmode,
frame_pointer_rtx,
@@ -5863,7 +5606,7 @@ sparc_builtin_saveregs (void)
return address;
}
-/* Implement `va_start' for varargs and stdarg. */
+/* Implement `va_start' for stdarg. */
void
sparc_va_start (tree valist, rtx nextarg)
@@ -5872,119 +5615,105 @@ sparc_va_start (tree valist, rtx nextarg)
std_expand_builtin_va_start (valist, nextarg);
}
-/* Implement `va_arg'. */
+/* Implement `va_arg' for stdarg. */
-rtx
-sparc_va_arg (tree valist, tree type)
+static tree
+sparc_gimplify_va_arg (tree valist, tree type, tree *pre_p, tree *post_p)
{
HOST_WIDE_INT size, rsize, align;
tree addr, incr;
- rtx addr_rtx;
- int indirect = 0;
-
- /* Round up sizeof(type) to a word. */
- size = int_size_in_bytes (type);
- rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
- align = 0;
+ bool indirect;
+ tree ptrtype = build_pointer_type (type);
- if (TARGET_ARCH64)
+ if (pass_by_reference (NULL, TYPE_MODE (type), type, false))
{
- if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
- align = 2 * UNITS_PER_WORD;
-
- /* Consider complex values as aggregates, so care
- for CTImode and TCmode. */
- if ((unsigned HOST_WIDE_INT) size > 16)
- {
- indirect = 1;
- size = rsize = UNITS_PER_WORD;
- align = 0;
- }
- else if (AGGREGATE_TYPE_P (type))
- {
- /* SPARC-V9 ABI states that structures up to 16 bytes in size
- are given whole slots as needed. */
- if (size == 0)
- size = rsize = UNITS_PER_WORD;
- else
- size = rsize;
- }
+ indirect = true;
+ size = rsize = UNITS_PER_WORD;
+ align = 0;
}
else
{
- if (AGGREGATE_TYPE_P (type)
- || TYPE_MODE (type) == SCmode
- || GET_MODE_SIZE (TYPE_MODE (type)) > 8)
+ indirect = false;
+ size = int_size_in_bytes (type);
+ rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
+ align = 0;
+
+ if (TARGET_ARCH64)
{
- indirect = 1;
- size = rsize = UNITS_PER_WORD;
+ /* For SPARC64, objects requiring 16-byte alignment get it. */
+ if (TYPE_ALIGN (type) >= 2 * (unsigned) BITS_PER_WORD)
+ align = 2 * UNITS_PER_WORD;
+
+ /* SPARC-V9 ABI states that structures up to 16 bytes in size
+ are left-justified in their slots. */
+ if (AGGREGATE_TYPE_P (type))
+ {
+ if (size == 0)
+ size = rsize = UNITS_PER_WORD;
+ else
+ size = rsize;
+ }
}
}
incr = valist;
if (align)
{
- incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
- build_int_2 (align - 1, 0)));
- incr = fold (build (BIT_AND_EXPR, ptr_type_node, incr,
- build_int_2 (-align, -1)));
+ incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ ssize_int (align - 1)));
+ incr = fold (build2 (BIT_AND_EXPR, ptr_type_node, incr,
+ ssize_int (-align)));
}
- addr = incr = save_expr (incr);
+ gimplify_expr (&incr, pre_p, post_p, is_gimple_val, fb_rvalue);
+ addr = incr;
+
if (BYTES_BIG_ENDIAN && size < rsize)
+ addr = fold (build2 (PLUS_EXPR, ptr_type_node, incr,
+ ssize_int (rsize - size)));
+
+ if (indirect)
{
- addr = fold (build (PLUS_EXPR, ptr_type_node, incr,
- build_int_2 (rsize - size, 0)));
+ addr = fold_convert (build_pointer_type (ptrtype), addr);
+ addr = build_va_arg_indirect_ref (addr);
}
- incr = fold (build (PLUS_EXPR, ptr_type_node, incr,
- build_int_2 (rsize, 0)));
-
- incr = build (MODIFY_EXPR, ptr_type_node, valist, incr);
- TREE_SIDE_EFFECTS (incr) = 1;
- expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
-
- addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
-
/* If the address isn't aligned properly for the type,
we may need to copy to a temporary.
FIXME: This is inefficient. Usually we can do this
in registers. */
- if (align == 0
- && TYPE_ALIGN (type) > BITS_PER_WORD
- && !indirect)
- {
- /* FIXME: We really need to specify that the temporary is live
- for the whole function because expand_builtin_va_arg wants
- the alias set to be get_varargs_alias_set (), but in this
- case the alias set is that for TYPE and if the memory gets
- reused it will be reused with alias set TYPE. */
- rtx tmp = assign_temp (type, 0, 1, 0);
- rtx dest_addr;
-
- addr_rtx = force_reg (Pmode, addr_rtx);
- addr_rtx = gen_rtx_MEM (BLKmode, addr_rtx);
- set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
- set_mem_align (addr_rtx, BITS_PER_WORD);
- tmp = shallow_copy_rtx (tmp);
- PUT_MODE (tmp, BLKmode);
- set_mem_alias_set (tmp, 0);
-
- dest_addr = emit_block_move (tmp, addr_rtx, GEN_INT (rsize),
- BLOCK_OP_NORMAL);
- if (dest_addr != NULL_RTX)
- addr_rtx = dest_addr;
- else
- addr_rtx = XCEXP (tmp, 0, MEM);
- }
-
- if (indirect)
+ else if (align == 0
+ && TYPE_ALIGN (type) > BITS_PER_WORD)
{
- addr_rtx = force_reg (Pmode, addr_rtx);
- addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
- set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
+ tree tmp = create_tmp_var (type, "va_arg_tmp");
+ tree dest_addr = build_fold_addr_expr (tmp);
+
+ tree copy = build_function_call_expr
+ (implicit_built_in_decls[BUILT_IN_MEMCPY],
+ tree_cons (NULL_TREE, dest_addr,
+ tree_cons (NULL_TREE, addr,
+ tree_cons (NULL_TREE, size_int (rsize),
+ NULL_TREE))));
+
+ gimplify_and_add (copy, pre_p);
+ addr = dest_addr;
}
+ else
+ addr = fold_convert (ptrtype, addr);
+
+ incr = fold (build2 (PLUS_EXPR, ptr_type_node, incr, ssize_int (rsize)));
+ incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
+ gimplify_and_add (incr, post_p);
+
+ return build_va_arg_indirect_ref (addr);
+}
+
+/* Implement the TARGET_VECTOR_MODE_SUPPORTED_P target hook.
+ Specify whether the vector mode is supported by the hardware. */
- return addr_rtx;
+static bool
+sparc_vector_mode_supported_p (enum machine_mode mode)
+{
+ return TARGET_VIS && VECTOR_MODE_P (mode) ? true : false;
}
/* Return the string to output an unconditional branch to LABEL, which is
@@ -5996,51 +5725,29 @@ const char *
output_ubranch (rtx dest, int label, rtx insn)
{
static char string[64];
- bool noop = false;
+ bool v9_form = false;
char *p;
- /* TurboSPARC is reported to have problems with
- with
- foo: b,a foo
- i.e. an empty loop with the annul bit set. The workaround is to use
- foo: b foo; nop
- instead. */
-
- if (! TARGET_V9 && flag_delayed_branch
- && (INSN_ADDRESSES (INSN_UID (dest))
- == INSN_ADDRESSES (INSN_UID (insn))))
+ if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
{
- strcpy (string, "b\t");
- noop = true;
+ int delta = (INSN_ADDRESSES (INSN_UID (dest))
+ - INSN_ADDRESSES (INSN_UID (insn)));
+ /* Leave some instructions for "slop". */
+ if (delta >= -260000 && delta < 260000)
+ v9_form = true;
}
- else
- {
- bool v9_form = false;
- if (TARGET_V9 && INSN_ADDRESSES_SET_P ())
- {
- int delta = (INSN_ADDRESSES (INSN_UID (dest))
- - INSN_ADDRESSES (INSN_UID (insn)));
- /* Leave some instructions for "slop". */
- if (delta >= -260000 && delta < 260000)
- v9_form = true;
- }
-
- if (v9_form)
- strcpy (string, "ba%*,pt\t%%xcc, ");
- else
- strcpy (string, "b%*\t");
- }
+ if (v9_form)
+ strcpy (string, "ba%*,pt\t%%xcc, ");
+ else
+ strcpy (string, "b%*\t");
p = strchr (string, '\0');
*p++ = '%';
*p++ = 'l';
*p++ = '0' + label;
*p++ = '%';
- if (noop)
- *p++ = '#';
- else
- *p++ = '(';
+ *p++ = '(';
*p = '\0';
return string;
@@ -6055,15 +5762,13 @@ output_ubranch (rtx dest, int label, rtx insn)
REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is nonzero if we should generate an annulling branch.
-
- NOOP is nonzero if we have to follow this branch by a noop. */
+ ANNUL is nonzero if we should generate an annulling branch. */
-char *
+const char *
output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
- int noop, rtx insn)
+ rtx insn)
{
- static char string[50];
+ static char string[64];
enum rtx_code code = GET_CODE (op);
rtx cc_reg = XEXP (op, 0);
enum machine_mode mode = GET_MODE (cc_reg);
@@ -6079,7 +5784,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
to
be,pn %xcc, .+12
- nop
+ nop
ba .LC30
and
@@ -6089,7 +5794,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
to
fbe,pt %fcc2, .+16
- nop
+ nop
ba .LC29 */
far = TARGET_V9 && (get_attr_length (insn) >= 3);
@@ -6152,7 +5857,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* ??? !v9: FP branches cannot be preceded by another floating point
@@ -6207,7 +5912,7 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
break;
default:
- abort ();
+ gcc_unreachable ();
}
strcpy (string, branch);
}
@@ -6244,17 +5949,14 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
labelno = v9_fcc_labelno;
if (v8)
{
- if (REGNO (cc_reg) == SPARC_FCC_REG)
- labelno = "";
- else
- abort ();
+ gcc_assert (REGNO (cc_reg) == SPARC_FCC_REG);
+ labelno = "";
}
}
else if (mode == CCXmode || mode == CCX_NOOVmode)
{
labelno = "%%xcc, ";
- if (v8)
- abort ();
+ gcc_assert (! v8);
}
else
{
@@ -6283,19 +5985,19 @@ output_cbranch (rtx op, rtx dest, int label, int reversed, int annul,
p = strchr (p, '\0');
if (far)
{
- strcpy (p, ".+12\n\tnop\n\tb\t");
- if (annul || noop)
+ strcpy (p, ".+12\n\t nop\n\tb\t");
+ /* Skip the next insn if requested or
+ if we know that it will be a nop. */
+ if (annul || ! final_sequence)
p[3] = '6';
- p += 13;
+ p += 14;
}
*p++ = '%';
*p++ = 'l';
- /* Set the char indicating the number of the operand containing the
- label_ref. */
*p++ = label + '0';
+ *p++ = '%';
+ *p++ = '#';
*p = '\0';
- if (noop)
- strcpy (p, "\n\tnop");
return string;
}
@@ -6350,8 +6052,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
break;
default:
- abort();
- break;
+ gcc_unreachable ();
}
if (TARGET_ARCH64)
@@ -6359,7 +6060,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
if (GET_CODE (x) != MEM)
{
slot0 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot0, x));
+ emit_move_insn (slot0, x);
}
else
slot0 = x;
@@ -6367,7 +6068,7 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
if (GET_CODE (y) != MEM)
{
slot1 = assign_stack_temp (TFmode, GET_MODE_SIZE(TFmode), 0);
- emit_insn (gen_rtx_SET (VOIDmode, slot1, y));
+ emit_move_insn (slot1, y);
}
else
slot1 = y;
@@ -6443,14 +6144,12 @@ sparc_emit_float_lib_cmp (rtx x, rtx y, enum rtx_code comparison)
optabs would emit if we didn't have TFmode patterns. */
void
-sparc_emit_floatunsdi (rtx *operands)
+sparc_emit_floatunsdi (rtx *operands, enum machine_mode mode)
{
rtx neglab, donelab, i0, i1, f0, in, out;
- enum machine_mode mode;
out = operands[0];
in = force_reg (DImode, operands[1]);
- mode = GET_MODE (out);
neglab = gen_label_rtx ();
donelab = gen_label_rtx ();
i0 = gen_reg_rtx (DImode);
@@ -6474,6 +6173,47 @@ sparc_emit_floatunsdi (rtx *operands)
emit_label (donelab);
}
+/* Generate an FP to unsigned DImode conversion. This is the same code
+ optabs would emit if we didn't have TFmode patterns. */
+
+void
+sparc_emit_fixunsdi (rtx *operands, enum machine_mode mode)
+{
+ rtx neglab, donelab, i0, i1, f0, in, out, limit;
+
+ out = operands[0];
+ in = force_reg (mode, operands[1]);
+ neglab = gen_label_rtx ();
+ donelab = gen_label_rtx ();
+ i0 = gen_reg_rtx (DImode);
+ i1 = gen_reg_rtx (DImode);
+ limit = gen_reg_rtx (mode);
+ f0 = gen_reg_rtx (mode);
+
+ emit_move_insn (limit,
+ CONST_DOUBLE_FROM_REAL_VALUE (
+ REAL_VALUE_ATOF ("9223372036854775808.0", mode), mode));
+ emit_cmp_and_jump_insns (in, limit, GE, NULL_RTX, mode, 0, neglab);
+
+ emit_insn (gen_rtx_SET (VOIDmode,
+ out,
+ gen_rtx_FIX (DImode, gen_rtx_FIX (mode, in))));
+ emit_jump_insn (gen_jump (donelab));
+ emit_barrier ();
+
+ emit_label (neglab);
+
+ emit_insn (gen_rtx_SET (VOIDmode, f0, gen_rtx_MINUS (mode, in, limit)));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ i0,
+ gen_rtx_FIX (DImode, gen_rtx_FIX (mode, f0))));
+ emit_insn (gen_movdi (i1, const1_rtx));
+ emit_insn (gen_ashldi3 (i1, i1, GEN_INT (63)));
+ emit_insn (gen_xordi3 (out, i0, i1));
+
+ emit_label (donelab);
+}
+
/* Return the string to output a conditional branch to LABEL, testing
register REG. LABEL is the operand number of the label; REG is the
operand number of the reg. OP is the conditional expression. The mode
@@ -6483,15 +6223,13 @@ sparc_emit_floatunsdi (rtx *operands)
REVERSED is nonzero if we should reverse the sense of the comparison.
- ANNUL is nonzero if we should generate an annulling branch.
+ ANNUL is nonzero if we should generate an annulling branch. */
- NOOP is nonzero if we have to follow this branch by a noop. */
-
-char *
+const char *
output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
- int annul, int noop, rtx insn)
+ int annul, rtx insn)
{
- static char string[50];
+ static char string[64];
enum rtx_code code = GET_CODE (op);
enum machine_mode mode = GET_MODE (XEXP (op, 0));
rtx note;
@@ -6506,7 +6244,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
to
brz,pn %g1, .+12
- nop
+ nop
ba,pt %xcc, .LC30
and
@@ -6516,7 +6254,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
to
brlz,pt %o1, .+16
- nop
+ nop
ba,pt %xcc, .LC29 */
far = get_attr_length (insn) >= 3;
@@ -6526,8 +6264,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
code = reverse_condition (code);
/* Only 64 bit versions of these instructions exist. */
- if (mode != DImode)
- abort ();
+ gcc_assert (mode == DImode);
/* Start by writing the branch condition. */
@@ -6558,7 +6295,7 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
break;
default:
- abort ();
+ gcc_unreachable ();
}
p = strchr (string, '\0');
@@ -6597,10 +6334,12 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
veryfar = 0;
}
- strcpy (p, ".+12\n\tnop\n\t");
- if (annul || noop)
+ strcpy (p, ".+12\n\t nop\n\t");
+ /* Skip the next insn if requested or
+ if we know that it will be a nop. */
+ if (annul || ! final_sequence)
p[3] = '6';
- p += 11;
+ p += 12;
if (veryfar)
{
strcpy (p, "b\t");
@@ -6615,11 +6354,10 @@ output_v9branch (rtx op, rtx dest, int reg, int label, int reversed,
*p++ = '%';
*p++ = 'l';
*p++ = '0' + label;
+ *p++ = '%';
+ *p++ = '#';
*p = '\0';
- if (noop)
- strcpy (p, "\n\tnop");
-
return string;
}
@@ -6646,7 +6384,7 @@ epilogue_renumber (register rtx *where, int test)
if (REGNO (*where) >= 8 && REGNO (*where) < 24) /* oX or lX */
return 1;
if (! test && REGNO (*where) >= 24 && REGNO (*where) < 32)
- *where = gen_rtx (REG, GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
+ *where = gen_rtx_REG (GET_MODE (*where), OUTGOING_REGNO (REGNO(*where)));
case SCRATCH:
case CC0:
case PC:
@@ -6733,8 +6471,7 @@ int
sparc_splitdi_legitimate (rtx reg, rtx mem)
{
/* Punt if we are here by mistake. */
- if (! reload_completed)
- abort ();
+ gcc_assert (reload_completed);
/* We must have an offsettable memory reference. */
if (! offsettable_memref_p (mem))
@@ -6916,42 +6653,60 @@ print_operand (FILE *file, rtx x, int code)
switch (code)
{
case '#':
- /* Output a 'nop' if there's nothing for the delay slot. */
- if (dbr_sequence_length () == 0)
+ /* Output an insn in a delay slot. */
+ if (final_sequence)
+ sparc_indent_opcode = 1;
+ else
fputs ("\n\t nop", file);
return;
case '*':
/* Output an annul flag if there's nothing for the delay slot and we
- are optimizing. This is always used with '(' below. */
- /* Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
- this is a dbx bug. So, we only do this when optimizing. */
- /* On UltraSPARC, a branch in a delay slot causes a pipeline flush.
+ are optimizing. This is always used with '(' below.
+ Sun OS 4.1.1 dbx can't handle an annulled unconditional branch;
+ this is a dbx bug. So, we only do this when optimizing.
+ On UltraSPARC, a branch in a delay slot causes a pipeline flush.
Always emit a nop in case the next instruction is a branch. */
- if (dbr_sequence_length () == 0
- && (optimize && (int)sparc_cpu < PROCESSOR_V9))
+ if (! final_sequence && (optimize && (int)sparc_cpu < PROCESSOR_V9))
fputs (",a", file);
return;
case '(':
/* Output a 'nop' if there's nothing for the delay slot and we are
not optimizing. This is always used with '*' above. */
- if (dbr_sequence_length () == 0
- && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
+ if (! final_sequence && ! (optimize && (int)sparc_cpu < PROCESSOR_V9))
fputs ("\n\t nop", file);
+ else if (final_sequence)
+ sparc_indent_opcode = 1;
+ return;
+ case ')':
+ /* Output the right displacement from the saved PC on function return.
+ The caller may have placed an "unimp" insn immediately after the call
+ so we have to account for it. This insn is used in the 32-bit ABI
+ when calling a function that returns a non zero-sized structure. The
+ 64-bit ABI doesn't have it. Be careful to have this test be the same
+ as that used on the call. The exception here is that when
+ sparc_std_struct_return is enabled, the psABI is followed exactly
+ and the adjustment is made by the code in sparc_struct_value_rtx.
+ The call emitted is the same when sparc_std_struct_return is
+ present. */
+ if (! TARGET_ARCH64
+ && current_function_returns_struct
+ && ! sparc_std_struct_return
+ && (TREE_CODE (DECL_SIZE (DECL_RESULT (current_function_decl)))
+ == INTEGER_CST)
+ && ! integer_zerop (DECL_SIZE (DECL_RESULT (current_function_decl))))
+ fputs ("12", file);
+ else
+ fputc ('8', file);
return;
case '_':
/* Output the Embedded Medium/Anywhere code model base register. */
fputs (EMBMEDANY_BASE_REG, file);
return;
- case '@':
- /* Print out what we are using as the frame pointer. This might
- be %fp, or might be %sp+offset. */
- /* ??? What if offset is too big? Perhaps the caller knows it isn't? */
- fprintf (file, "%s+"HOST_WIDE_INT_PRINT_DEC, frame_base_name, frame_base_offset);
- return;
case '&':
/* Print some local dynamic TLS name. */
assemble_name (file, get_some_local_dynamic_name ());
return;
+
case 'Y':
/* Adjust the operand to take into account a RESTORE operation. */
if (GET_CODE (x) == CONST_INT)
@@ -7005,7 +6760,7 @@ print_operand (FILE *file, rtx x, int code)
else if (GET_MODE (x) == CCXmode)
fputs ("%xcc", file);
else
- abort ();
+ gcc_unreachable ();
}
else
/* %fccN register */
@@ -7308,7 +7063,7 @@ sparc_type_code (register tree type)
/* Carefully distinguish all the standard types of C,
without messing up if the language is not C. We do this by
- testing TYPE_PRECISION and TREE_UNSIGNED. The old code used to
+ testing TYPE_PRECISION and TYPE_UNSIGNED. The old code used to
look at both the names and the above fields, but that's redundant.
Any type whose size is between two C types will be considered
to be the wider of the two types. Also, we do not have a
@@ -7318,16 +7073,16 @@ sparc_type_code (register tree type)
size, but that's fine, since neither can the assembler. */
if (TYPE_PRECISION (type) <= CHAR_TYPE_SIZE)
- return (qualifiers | (TREE_UNSIGNED (type) ? 12 : 2));
+ return (qualifiers | (TYPE_UNSIGNED (type) ? 12 : 2));
else if (TYPE_PRECISION (type) <= SHORT_TYPE_SIZE)
- return (qualifiers | (TREE_UNSIGNED (type) ? 13 : 3));
+ return (qualifiers | (TYPE_UNSIGNED (type) ? 13 : 3));
else if (TYPE_PRECISION (type) <= INT_TYPE_SIZE)
- return (qualifiers | (TREE_UNSIGNED (type) ? 14 : 4));
+ return (qualifiers | (TYPE_UNSIGNED (type) ? 14 : 4));
else
- return (qualifiers | (TREE_UNSIGNED (type) ? 15 : 5));
+ return (qualifiers | (TYPE_UNSIGNED (type) ? 15 : 5));
case REAL_TYPE:
/* If this is a range type, consider it to be the underlying
@@ -7350,15 +7105,13 @@ sparc_type_code (register tree type)
existing front-ends. */
return (qualifiers | 7); /* Who knows? */
- case CHAR_TYPE: /* GNU Pascal CHAR type. Not used in C. */
- case BOOLEAN_TYPE: /* GNU Fortran BOOLEAN type. */
- case FILE_TYPE: /* GNU Pascal FILE type. */
- case SET_TYPE: /* GNU Pascal SET type. */
+ case VECTOR_TYPE:
+ case BOOLEAN_TYPE: /* Boolean truth value type. */
case LANG_TYPE: /* ? */
return qualifiers;
default:
- abort (); /* Not a type! */
+ gcc_unreachable (); /* Not a type! */
}
}
@@ -7426,14 +7179,15 @@ sparc_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
aligned on a 16 byte boundary so one flush clears it all. */
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode, tramp))));
if (sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3)
+ && sparc_cpu != PROCESSOR_ULTRASPARC3
+ && sparc_cpu != PROCESSOR_NIAGARA)
emit_insn (gen_flush (validize_mem (gen_rtx_MEM (SImode,
plus_constant (tramp, 8)))));
/* Call __enable_execute_stack after writing onto the stack to make sure
the stack address is accessible. */
#ifdef ENABLE_EXECUTE_STACK
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
#endif
@@ -7468,735 +7222,18 @@ sparc64_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, tramp))));
if (sparc_cpu != PROCESSOR_ULTRASPARC
- && sparc_cpu != PROCESSOR_ULTRASPARC3)
+ && sparc_cpu != PROCESSOR_ULTRASPARC3
+ && sparc_cpu != PROCESSOR_NIAGARA)
emit_insn (gen_flushdi (validize_mem (gen_rtx_MEM (DImode, plus_constant (tramp, 8)))));
/* Call __enable_execute_stack after writing onto the stack to make sure
the stack address is accessible. */
#ifdef ENABLE_EXECUTE_STACK
- emit_library_call (gen_rtx (SYMBOL_REF, Pmode, "__enable_execute_stack"),
+ emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__enable_execute_stack"),
LCT_NORMAL, VOIDmode, 1, tramp, Pmode);
#endif
}
-/* Subroutines to support a flat (single) register window calling
- convention. */
-
-/* Single-register window sparc stack frames look like:
-
- Before call After call
- +-----------------------+ +-----------------------+
- high | | | |
- mem | caller's temps. | | caller's temps. |
- | | | |
- +-----------------------+ +-----------------------+
- | | | |
- | arguments on stack. | | arguments on stack. |
- | | | |
- +-----------------------+FP+92->+-----------------------+
- | 6 words to save | | 6 words to save |
- | arguments passed | | arguments passed |
- | in registers, even | | in registers, even |
- | if not passed. | | if not passed. |
- SP+68->+-----------------------+FP+68->+-----------------------+
- | 1 word struct addr | | 1 word struct addr |
- +-----------------------+FP+64->+-----------------------+
- | | | |
- | 16 word reg save area | | 16 word reg save area |
- | | | |
- SP->+-----------------------+ FP->+-----------------------+
- | 4 word area for |
- | fp/alu reg moves |
- FP-16->+-----------------------+
- | |
- | local variables |
- | |
- +-----------------------+
- | |
- | fp register save |
- | |
- +-----------------------+
- | |
- | gp register save |
- | |
- +-----------------------+
- | |
- | alloca allocations |
- | |
- +-----------------------+
- | |
- | arguments on stack |
- | |
- SP+92->+-----------------------+
- | 6 words to save |
- | arguments passed |
- | in registers, even |
- low | if not passed. |
- memory SP+68->+-----------------------+
- | 1 word struct addr |
- SP+64->+-----------------------+
- | |
- I 16 word reg save area |
- | |
- SP->+-----------------------+ */
-
-/* Structure to be filled in by sparc_flat_compute_frame_size with register
- save masks, and offsets for the current function. */
-
-struct sparc_frame_info
-{
- HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
- HOST_WIDE_INT var_size; /* # bytes that variables take up. */
- int args_size; /* # bytes that outgoing arguments take up. */
- int extra_size; /* # bytes of extra gunk. */
- int gp_reg_size; /* # bytes needed to store gp regs. */
- int fp_reg_size; /* # bytes needed to store fp regs. */
- unsigned long gmask; /* Mask of saved gp registers. */
- unsigned long fmask; /* Mask of saved fp registers. */
- int reg_offset; /* Offset from new sp to store regs. */
- int initialized; /* Nonzero if frame size already calculated. */
-};
-
-/* Current frame information calculated by sparc_flat_compute_frame_size. */
-struct sparc_frame_info current_frame_info;
-
-/* Zero structure to initialize current_frame_info. */
-struct sparc_frame_info zero_frame_info;
-
-#define RETURN_ADDR_REGNUM 15
-#define HARD_FRAME_POINTER_MASK (1 << (HARD_FRAME_POINTER_REGNUM))
-#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
-
-/* Tell prologue and epilogue if register REGNO should be saved / restored. */
-
-static bool
-sparc_flat_must_save_register_p (int regno)
-{
- /* General case: call-saved registers live at some point. */
- if (!call_used_regs[regno] && regs_ever_live[regno])
- return true;
-
- /* Frame pointer register (%i7) if needed. */
- if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed)
- return true;
-
- /* PIC register (%l7) if needed. */
- if (regno == (int) PIC_OFFSET_TABLE_REGNUM
- && flag_pic && current_function_uses_pic_offset_table)
- return true;
-
- /* Return address register (%o7) if needed. */
- if (regno == RETURN_ADDR_REGNUM
- && (regs_ever_live[RETURN_ADDR_REGNUM]
- /* When the PIC offset table is used, the PIC register
- is set by using a bare call that clobbers %o7. */
- || (flag_pic && current_function_uses_pic_offset_table)))
- return true;
-
- return false;
-}
-
-/* Return the bytes needed to compute the frame pointer from the current
- stack pointer. */
-
-HOST_WIDE_INT
-sparc_flat_compute_frame_size (HOST_WIDE_INT size)
- /* # of var. bytes allocated. */
-{
- int regno;
- HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up. */
- HOST_WIDE_INT var_size; /* # bytes that variables take up. */
- int args_size; /* # bytes that outgoing arguments take up. */
- int extra_size; /* # extra bytes. */
- int gp_reg_size; /* # bytes needed to store gp regs. */
- int fp_reg_size; /* # bytes needed to store fp regs. */
- unsigned long gmask; /* Mask of saved gp registers. */
- unsigned long fmask; /* Mask of saved fp registers. */
- int reg_offset; /* Offset to register save area. */
- int need_aligned_p; /* 1 if need the save area 8 byte aligned. */
-
- /* This is the size of the 16 word reg save area, 1 word struct addr
- area, and 4 word fp/alu register copy area. */
- extra_size = -STARTING_FRAME_OFFSET + FIRST_PARM_OFFSET(0);
- var_size = size;
- gp_reg_size = 0;
- fp_reg_size = 0;
- gmask = 0;
- fmask = 0;
- reg_offset = 0;
- need_aligned_p = 0;
-
- args_size = 0;
- if (!leaf_function_p ())
- {
- /* Also include the size needed for the 6 parameter registers. */
- args_size = current_function_outgoing_args_size + 24;
- }
- total_size = var_size + args_size;
-
- /* Calculate space needed for gp registers. */
- for (regno = 1; regno <= 31; regno++)
- {
- if (sparc_flat_must_save_register_p (regno))
- {
- /* If we need to save two regs in a row, ensure there's room to bump
- up the address to align it to a doubleword boundary. */
- if ((regno & 0x1) == 0 && sparc_flat_must_save_register_p (regno+1))
- {
- if (gp_reg_size % 8 != 0)
- gp_reg_size += 4;
- gp_reg_size += 2 * UNITS_PER_WORD;
- gmask |= 3 << regno;
- regno++;
- need_aligned_p = 1;
- }
- else
- {
- gp_reg_size += UNITS_PER_WORD;
- gmask |= 1 << regno;
- }
- }
- }
-
- /* Calculate space needed for fp registers. */
- for (regno = 32; regno <= 63; regno++)
- {
- if (regs_ever_live[regno] && !call_used_regs[regno])
- {
- fp_reg_size += UNITS_PER_WORD;
- fmask |= 1 << (regno - 32);
- }
- }
-
- if (gmask || fmask)
- {
- int n;
- reg_offset = FIRST_PARM_OFFSET(0) + args_size;
- /* Ensure save area is 8 byte aligned if we need it. */
- n = reg_offset % 8;
- if (need_aligned_p && n != 0)
- {
- total_size += 8 - n;
- reg_offset += 8 - n;
- }
- total_size += gp_reg_size + fp_reg_size;
- }
-
- /* If we must allocate a stack frame at all, we must also allocate
- room for register window spillage, so as to be binary compatible
- with libraries and operating systems that do not use -mflat. */
- if (total_size > 0)
- total_size += extra_size;
- else
- extra_size = 0;
-
- total_size = SPARC_STACK_ALIGN (total_size);
-
- /* Save other computed information. */
- current_frame_info.total_size = total_size;
- current_frame_info.var_size = var_size;
- current_frame_info.args_size = args_size;
- current_frame_info.extra_size = extra_size;
- current_frame_info.gp_reg_size = gp_reg_size;
- current_frame_info.fp_reg_size = fp_reg_size;
- current_frame_info.gmask = gmask;
- current_frame_info.fmask = fmask;
- current_frame_info.reg_offset = reg_offset;
- current_frame_info.initialized = reload_completed;
-
- /* Ok, we're done. */
- return total_size;
-}
-
-/* Save/restore registers in GMASK and FMASK at register BASE_REG plus offset
- OFFSET.
-
- BASE_REG must be 8 byte aligned. This allows us to test OFFSET for
- appropriate alignment and use DOUBLEWORD_OP when we can. We assume
- [BASE_REG+OFFSET] will always be a valid address.
-
- WORD_OP is either "st" for save, "ld" for restore.
- DOUBLEWORD_OP is either "std" for save, "ldd" for restore. */
-
-static void
-sparc_flat_save_restore (FILE *file, const char *base_reg, int offset,
- unsigned long gmask, unsigned long fmask,
- const char *word_op, const char *doubleword_op,
- HOST_WIDE_INT base_offset)
-{
- int regno;
-
- if (gmask == 0 && fmask == 0)
- return;
-
- /* Save registers starting from high to low. We've already saved the
- previous frame pointer and previous return address for the debugger's
- sake. The debugger allows us to not need a nop in the epilog if at least
- one register is reloaded in addition to return address. */
-
- if (gmask)
- {
- for (regno = 1; regno <= 31; regno++)
- {
- if ((gmask & (1L << regno)) != 0)
- {
- if ((regno & 0x1) == 0 && ((gmask & (1L << (regno+1))) != 0))
- {
- /* We can save two registers in a row. If we're not at a
- double word boundary, move to one.
- sparc_flat_compute_frame_size ensures there's room to do
- this. */
- if (offset % 8 != 0)
- offset += UNITS_PER_WORD;
-
- if (word_op[0] == 's')
- {
- fprintf (file, "\t%s\t%s, [%s+%d]\n",
- doubleword_op, reg_names[regno],
- base_reg, offset);
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- dwarf2out_reg_save (l, regno, offset + base_offset);
- dwarf2out_reg_save
- (l, regno+1, offset+base_offset + UNITS_PER_WORD);
- }
- }
- else
- fprintf (file, "\t%s\t[%s+%d], %s\n",
- doubleword_op, base_reg, offset,
- reg_names[regno]);
-
- offset += 2 * UNITS_PER_WORD;
- regno++;
- }
- else
- {
- if (word_op[0] == 's')
- {
- fprintf (file, "\t%s\t%s, [%s+%d]\n",
- word_op, reg_names[regno],
- base_reg, offset);
- if (dwarf2out_do_frame ())
- dwarf2out_reg_save ("", regno, offset + base_offset);
- }
- else
- fprintf (file, "\t%s\t[%s+%d], %s\n",
- word_op, base_reg, offset, reg_names[regno]);
-
- offset += UNITS_PER_WORD;
- }
- }
- }
- }
-
- if (fmask)
- {
- for (regno = 32; regno <= 63; regno++)
- {
- if ((fmask & (1L << (regno - 32))) != 0)
- {
- if (word_op[0] == 's')
- {
- fprintf (file, "\t%s\t%s, [%s+%d]\n",
- word_op, reg_names[regno],
- base_reg, offset);
- if (dwarf2out_do_frame ())
- dwarf2out_reg_save ("", regno, offset + base_offset);
- }
- else
- fprintf (file, "\t%s\t[%s+%d], %s\n",
- word_op, base_reg, offset, reg_names[regno]);
-
- offset += UNITS_PER_WORD;
- }
- }
- }
-}
-
-/* Set up the stack and frame (if desired) for the function. */
-
-static void
-sparc_flat_function_prologue (FILE *file, HOST_WIDE_INT size)
-{
- const char *sp_str = reg_names[STACK_POINTER_REGNUM];
- unsigned long gmask = current_frame_info.gmask;
-
- sparc_output_scratch_registers (file);
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s#PROLOGUE# 0\n", ASM_COMMENT_START);
- fprintf (file, "\t%s# vars= "HOST_WIDE_INT_PRINT_DEC", "
- "regs= %d/%d, args= %d, extra= %d\n",
- ASM_COMMENT_START,
- current_frame_info.var_size,
- current_frame_info.gp_reg_size / 4,
- current_frame_info.fp_reg_size / 4,
- current_function_outgoing_args_size,
- current_frame_info.extra_size);
-
- size = SPARC_STACK_ALIGN (size);
- size = (! current_frame_info.initialized
- ? sparc_flat_compute_frame_size (size)
- : current_frame_info.total_size);
-
- /* These cases shouldn't happen. Catch them now. */
- if (size == 0 && (gmask || current_frame_info.fmask))
- abort ();
-
- /* Allocate our stack frame by decrementing %sp.
- At present, the only algorithm gdb can use to determine if this is a
- flat frame is if we always set %i7 if we set %sp. This can be optimized
- in the future by putting in some sort of debugging information that says
- this is a `flat' function. However, there is still the case of debugging
- code without such debugging information (including cases where most fns
- have such info, but there is one that doesn't). So, always do this now
- so we don't get a lot of code out there that gdb can't handle.
- If the frame pointer isn't needn't then that's ok - gdb won't be able to
- distinguish us from a non-flat function but there won't (and shouldn't)
- be any differences anyway. The return pc is saved (if necessary) right
- after %i7 so gdb won't have to look too far to find it. */
- if (size > 0)
- {
- int reg_offset = current_frame_info.reg_offset;
- const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
- static const char *const t1_str = "%g1";
-
- /* Things get a little tricky if local variables take up more than ~4096
- bytes and outgoing arguments take up more than ~4096 bytes. When that
- happens, the register save area can't be accessed from either end of
- the frame. Handle this by decrementing %sp to the start of the gp
- register save area, save the regs, update %i7, and then set %sp to its
- final value. Given that we only have one scratch register to play
- with it is the cheapest solution, and it helps gdb out as it won't
- slow down recognition of flat functions.
- Don't change the order of insns emitted here without checking with
- the gdb folk first. */
-
- /* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
- {
- if (size <= 4096)
- {
- fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
- sp_str, size, sp_str);
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- fp_str, sp_str, reg_offset);
- fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
- "\t%s# set up frame pointer\n",
- sp_str, size, fp_str, ASM_COMMENT_START);
- reg_offset += 4;
- }
- }
- else
- {
- build_big_number (file, size, t1_str);
- fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- fp_str, sp_str, reg_offset);
- fprintf (file, "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
- sp_str, t1_str, fp_str, ASM_COMMENT_START);
- reg_offset += 4;
- }
- }
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
- reg_offset - 4 - size);
- dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
- }
- else
- dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size);
- }
- if (gmask & RETURN_ADDR_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, reg_offset);
- if (dwarf2out_do_frame ())
- dwarf2out_return_save ("", reg_offset - size);
- reg_offset += 4;
- }
- sparc_flat_save_restore (file, sp_str, reg_offset,
- gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- current_frame_info.fmask,
- "st", "std", -size);
- }
- else
- {
- /* Subtract %sp in two steps, but make sure there is always a
- 64-byte register save area, and %sp is properly aligned. */
-
- /* Amount to decrement %sp by, the first time. */
- HOST_WIDE_INT size1 = ((size - reg_offset + 64) + 15) & -16;
-
- /* Amount to decrement %sp by, the second time. */
- HOST_WIDE_INT size2 = size - size1;
-
- /* Offset to register save area from %sp after first decrement. */
- int offset = (int)(size1 - (size - reg_offset));
-
- if (size1 <= 4096)
- {
- fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
- sp_str, size1, sp_str);
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n"
- "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
- "\t%s# set up frame pointer\n",
- fp_str, sp_str, offset, sp_str, size1,
- fp_str, ASM_COMMENT_START);
- offset += 4;
- }
- }
- else
- {
- build_big_number (file, size1, t1_str);
- fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n"
- "\tadd\t%s, %s, %s\t%s# set up frame pointer\n",
- fp_str, sp_str, offset, sp_str, t1_str,
- fp_str, ASM_COMMENT_START);
- offset += 4;
- }
- }
- if (dwarf2out_do_frame ())
- {
- char *l = dwarf2out_cfi_label ();
- if (gmask & HARD_FRAME_POINTER_MASK)
- {
- dwarf2out_reg_save (l, HARD_FRAME_POINTER_REGNUM,
- offset - 4 - size1);
- dwarf2out_def_cfa (l, HARD_FRAME_POINTER_REGNUM, 0);
- }
- else
- dwarf2out_def_cfa (l, STACK_POINTER_REGNUM, size1);
- }
- if (gmask & RETURN_ADDR_MASK)
- {
- fprintf (file, "\tst\t%s, [%s+%d]\n",
- reg_names[RETURN_ADDR_REGNUM], sp_str, offset);
- if (dwarf2out_do_frame ())
- /* offset - size1 == reg_offset - size
- if reg_offset were updated above like offset. */
- dwarf2out_return_save ("", offset - size1);
- offset += 4;
- }
- sparc_flat_save_restore (file, sp_str, offset,
- gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- current_frame_info.fmask,
- "st", "std", -size1);
- if (size2 <= 4096)
- fprintf (file, "\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
- sp_str, size2, sp_str);
- else
- {
- build_big_number (file, size2, t1_str);
- fprintf (file, "\tsub\t%s, %s, %s\n", sp_str, t1_str, sp_str);
- }
- if (dwarf2out_do_frame ())
- if (! (gmask & HARD_FRAME_POINTER_MASK))
- dwarf2out_def_cfa ("", STACK_POINTER_REGNUM, size);
- }
- }
-
- fprintf (file, "\t%s#PROLOGUE# 1\n", ASM_COMMENT_START);
-}
-
-/* Do any necessary cleanup after a function to restore stack, frame,
- and regs. */
-
-static void
-sparc_flat_function_epilogue (FILE *file, HOST_WIDE_INT size)
-{
- rtx epilogue_delay = current_function_epilogue_delay_list;
- int noepilogue = FALSE;
-
- /* This is only for the human reader. */
- fprintf (file, "\t%s#EPILOGUE#\n", ASM_COMMENT_START);
-
- /* The epilogue does not depend on any registers, but the stack
- registers, so we assume that if we have 1 pending nop, it can be
- ignored, and 2 it must be filled (2 nops occur for integer
- multiply and divide). */
-
- size = SPARC_STACK_ALIGN (size);
- size = (!current_frame_info.initialized
- ? sparc_flat_compute_frame_size (size)
- : current_frame_info.total_size);
-
- if (size == 0 && epilogue_delay == 0)
- {
- rtx insn = get_last_insn ();
-
- /* If the last insn was a BARRIER, we don't have to write any code
- because a jump (aka return) was put there. */
- if (GET_CODE (insn) == NOTE)
- insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
- noepilogue = TRUE;
- }
-
- if (!noepilogue)
- {
- int reg_offset = current_frame_info.reg_offset;
- int reg_offset1;
- const char *const sp_str = reg_names[STACK_POINTER_REGNUM];
- const char *const fp_str = reg_names[HARD_FRAME_POINTER_REGNUM];
- static const char *const t1_str = "%g1";
-
- /* In the reload sequence, we don't need to fill the load delay
- slots for most of the loads, also see if we can fill the final
- delay slot if not otherwise filled by the reload sequence. */
-
- if (size > 4096)
- build_big_number (file, size, t1_str);
-
- if (frame_pointer_needed)
- {
- if (size > 4096)
- fprintf (file,"\tsub\t%s, %s, %s\t\t%s# sp not trusted here\n",
- fp_str, t1_str, sp_str, ASM_COMMENT_START);
- else
- fprintf (file,"\tadd\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s"
- "\t\t%s# sp not trusted here\n",
- fp_str, size, sp_str, ASM_COMMENT_START);
- }
-
- /* Is the entire register save area offsettable from %sp? */
- if (reg_offset < 4096 - 64 * UNITS_PER_WORD)
- {
- reg_offset1 = 0;
- }
- else
- {
- /* Restore %sp in two steps, but make sure there is always a
- 64-byte register save area, and %sp is properly aligned. */
-
- /* Amount to increment %sp by, the first time. */
- reg_offset1 = ((reg_offset - 64 - 16) + 15) & -16;
-
- /* Offset to register save area from %sp. */
- reg_offset = reg_offset1 - reg_offset;
-
- if (reg_offset1 > 4096)
- {
- build_big_number (file, reg_offset1, t1_str);
- fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
- }
- else
- fprintf (file, "\tsub\t%s, -%d, %s\n", sp_str, reg_offset1, sp_str);
- }
-
- /* We must restore the frame pointer and return address reg first
- because they are treated specially by the prologue output code. */
- if (current_frame_info.gmask & HARD_FRAME_POINTER_MASK)
- {
- fprintf (file, "\tld\t[%s+%d], %s\n",
- sp_str, reg_offset, fp_str);
- reg_offset += 4;
- }
- if (current_frame_info.gmask & RETURN_ADDR_MASK)
- {
- fprintf (file, "\tld\t[%s+%d], %s\n",
- sp_str, reg_offset, reg_names[RETURN_ADDR_REGNUM]);
- reg_offset += 4;
- }
-
- /* Restore any remaining saved registers. */
- sparc_flat_save_restore (file, sp_str, reg_offset,
- current_frame_info.gmask & ~(HARD_FRAME_POINTER_MASK | RETURN_ADDR_MASK),
- current_frame_info.fmask,
- "ld", "ldd", 0);
-
- /* If we had to increment %sp in two steps, record it so the second
- restoration in the epilogue finishes up. */
- if (reg_offset1 > 0)
- {
- size -= reg_offset1;
- if (size > 4096)
- build_big_number (file, size, t1_str);
- }
-
- if (current_function_returns_struct)
- fprintf (file, "\tjmp\t%%o7+12\n");
- else
- fprintf (file, "\tretl\n");
-
- /* If the only register saved is the return address, we need a
- nop, unless we have an instruction to put into it. Otherwise
- we don't since reloading multiple registers doesn't reference
- the register being loaded. */
-
- if (epilogue_delay)
- {
- if (size)
- abort ();
- final_scan_insn (XEXP (epilogue_delay, 0), file, 1, -2, 1, NULL);
- }
-
- else if (size > 4096)
- fprintf (file, "\tadd\t%s, %s, %s\n", sp_str, t1_str, sp_str);
-
- else if (size > 0)
- fprintf (file, "\tsub\t%s, -"HOST_WIDE_INT_PRINT_DEC", %s\n",
- sp_str, size, sp_str);
-
- else
- fprintf (file, "\tnop\n");
- }
-
- /* Reset state info for each function. */
- current_frame_info = zero_frame_info;
-
- sparc_output_deferred_case_vectors ();
-}
-
-/* Define the number of delay slots needed for the function epilogue.
-
- On the sparc, we need a slot if either no stack has been allocated,
- or the only register saved is the return register. */
-
-int
-sparc_flat_epilogue_delay_slots (void)
-{
- if (!current_frame_info.initialized)
- (void) sparc_flat_compute_frame_size (get_frame_size ());
-
- if (current_frame_info.total_size == 0)
- return 1;
-
- return 0;
-}
-
-/* Return true if TRIAL is a valid insn for the epilogue delay slot.
- Any single length instruction which doesn't reference the stack or frame
- pointer is OK. */
-
-int
-sparc_flat_eligible_for_epilogue_delay (rtx trial, int slot ATTRIBUTE_UNUSED)
-{
- rtx pat = PATTERN (trial);
-
- if (get_attr_length (trial) != 1)
- return 0;
-
- if (! reg_mentioned_p (stack_pointer_rtx, pat)
- && ! reg_mentioned_p (frame_pointer_rtx, pat))
- return 1;
-
- return 0;
-}
-
/* Adjust the cost of a scheduling dependency. Return the new cost of
a dependency LINK or INSN on DEP_INSN. COST is the current cost. */
@@ -8364,20 +7401,10 @@ sparc_sched_init (FILE *dump ATTRIBUTE_UNUSED,
}
static int
-sparc_use_dfa_pipeline_interface (void)
-{
- if ((1 << sparc_cpu) &
- ((1 << PROCESSOR_ULTRASPARC) | (1 << PROCESSOR_CYPRESS) |
- (1 << PROCESSOR_SUPERSPARC) | (1 << PROCESSOR_HYPERSPARC) |
- (1 << PROCESSOR_SPARCLITE86X) | (1 << PROCESSOR_TSC701) |
- (1 << PROCESSOR_ULTRASPARC3)))
- return 1;
- return 0;
-}
-
-static int
sparc_use_sched_lookahead (void)
{
+ if (sparc_cpu == PROCESSOR_NIAGARA)
+ return 0;
if (sparc_cpu == PROCESSOR_ULTRASPARC
|| sparc_cpu == PROCESSOR_ULTRASPARC3)
return 4;
@@ -8393,6 +7420,7 @@ sparc_issue_rate (void)
{
switch (sparc_cpu)
{
+ case PROCESSOR_NIAGARA:
default:
return 1;
case PROCESSOR_V9:
@@ -8558,7 +7586,7 @@ sparc_output_deferred_case_vectors (void)
return;
/* Align to cache line in the function's code section. */
- function_section (current_function_decl);
+ switch_to_section (current_function_section ());
align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
if (align > 0)
@@ -8585,8 +7613,7 @@ sparc_check_64 (rtx x, rtx insn)
int set_once = 0;
rtx y = x;
- if (GET_CODE (x) != REG)
- abort ();
+ gcc_assert (GET_CODE (x) == REG);
if (GET_MODE (x) == DImode)
y = gen_rtx_REG (SImode, REGNO (x) + WORDS_BIG_ENDIAN);
@@ -8635,8 +7662,8 @@ sparc_check_64 (rtx x, rtx insn)
/* Returns assembly code to perform a DImode shift using
a 64-bit global or out register on SPARC-V8+. */
-char *
-sparc_v8plus_shift (rtx *operands, rtx insn, const char *opcode)
+const char *
+output_v8plus_shift (rtx *operands, rtx insn, const char *opcode)
{
static char asm_code[60];
@@ -8687,13 +7714,14 @@ sparc_profile_hook (int labelno)
#ifdef OBJECT_FORMAT_ELF
static void
-sparc_elf_asm_named_section (const char *name, unsigned int flags)
+sparc_elf_asm_named_section (const char *name, unsigned int flags,
+ tree decl)
{
if (flags & SECTION_MERGE)
{
/* entsize cannot be expressed in this section attributes
encoding style. */
- default_elf_asm_named_section (name, flags);
+ default_elf_asm_named_section (name, flags, decl);
return;
}
@@ -8714,10 +7742,12 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags)
}
#endif /* OBJECT_FORMAT_ELF */
-/* We do not allow sibling calls if -mflat, nor
- we do not allow indirect calls to be optimized into sibling calls.
-
- Also, on sparc 32-bit we cannot emit a sibling call when the
+/* We do not allow indirect calls to be optimized into sibling calls.
+
+ We cannot use sibling calls when delayed branches are disabled
+ because they will likely require the call delay slot to be filled.
+
+ Also, on SPARC 32-bit we cannot emit a sibling call when the
current function returns a structure. This is because the "unimp
after call" convention would cause the callee to return to the
wrong place. The generic code already disallows cases where the
@@ -8726,7 +7756,7 @@ sparc_elf_asm_named_section (const char *name, unsigned int flags)
It may seem strange how this last case could occur. Usually there
is code after the call which jumps to epilogue code which dumps the
return value into the struct return area. That ought to invalidate
- the sibling call right? Well, in the c++ case we can end up passing
+ the sibling call right? Well, in the C++ case we can end up passing
the pointer to the struct return area to a constructor (which returns
void) and then nothing else happens. Such a sibling call would look
valid without the added check here. */
@@ -8734,7 +7764,7 @@ static bool
sparc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
{
return (decl
- && ! TARGET_FLAT
+ && flag_delayed_branch
&& (TARGET_ARCH64 || ! current_function_returns_struct));
}
@@ -8749,7 +7779,7 @@ sparc_init_libfuncs (void)
/* Use the subroutines that Sun's library provides for integer
multiply and divide. The `*' prevents an underscore from
being prepended by the compiler. .umul is a little faster
- than .mul. */
+ than .mul. */
set_optab_libfunc (smul_optab, SImode, "*.umul");
set_optab_libfunc (sdiv_optab, SImode, "*.div");
set_optab_libfunc (udiv_optab, SImode, "*.udiv");
@@ -8786,12 +7816,14 @@ sparc_init_libfuncs (void)
set_conv_libfunc (sfix_optab, SImode, TFmode, "_Q_qtoi");
set_conv_libfunc (ufix_optab, SImode, TFmode, "_Q_qtou");
set_conv_libfunc (sfloat_optab, TFmode, SImode, "_Q_itoq");
+ set_conv_libfunc (ufloat_optab, TFmode, SImode, "_Q_utoq");
if (DITF_CONVERSION_LIBFUNCS)
{
set_conv_libfunc (sfix_optab, DImode, TFmode, "_Q_qtoll");
set_conv_libfunc (ufix_optab, DImode, TFmode, "_Q_qtoull");
set_conv_libfunc (sfloat_optab, TFmode, DImode, "_Q_lltoq");
+ set_conv_libfunc (ufloat_optab, TFmode, DImode, "_Q_ulltoq");
}
if (SUN_CONVERSION_LIBFUNCS)
@@ -8835,31 +7867,361 @@ sparc_init_libfuncs (void)
gofast_maybe_init_libfuncs ();
}
-/* ??? Similar to the standard section selection, but force reloc-y-ness
- if SUNOS4_SHARED_LIBRARIES. Unclear why this helps (as opposed to
- pretending PIC always on), but that's what the old code did. */
+#define def_builtin(NAME, CODE, TYPE) \
+ lang_hooks.builtin_function((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, \
+ NULL_TREE)
+
+/* Implement the TARGET_INIT_BUILTINS target hook.
+ Create builtin functions for special SPARC instructions. */
static void
-sparc_aout_select_section (tree t, int reloc, unsigned HOST_WIDE_INT align)
+sparc_init_builtins (void)
{
- default_select_section (t, reloc | SUNOS4_SHARED_LIBRARIES, align);
+ if (TARGET_VIS)
+ sparc_vis_init_builtins ();
}
-/* Use text section for a constant unless we need more alignment than
- that offers. */
+/* Create builtin functions for VIS 1.0 instructions. */
static void
-sparc_aout_select_rtx_section (enum machine_mode mode, rtx x,
- unsigned HOST_WIDE_INT align)
-{
- if (align <= MAX_TEXT_ALIGN
- && ! (flag_pic && (symbolic_operand (x, mode)
- || SUNOS4_SHARED_LIBRARIES)))
- readonly_data_section ();
+sparc_vis_init_builtins (void)
+{
+ tree v4qi = build_vector_type (unsigned_intQI_type_node, 4);
+ tree v8qi = build_vector_type (unsigned_intQI_type_node, 8);
+ tree v4hi = build_vector_type (intHI_type_node, 4);
+ tree v2hi = build_vector_type (intHI_type_node, 2);
+ tree v2si = build_vector_type (intSI_type_node, 2);
+
+ tree v4qi_ftype_v4hi = build_function_type_list (v4qi, v4hi, 0);
+ tree v8qi_ftype_v2si_v8qi = build_function_type_list (v8qi, v2si, v8qi, 0);
+ tree v2hi_ftype_v2si = build_function_type_list (v2hi, v2si, 0);
+ tree v4hi_ftype_v4qi = build_function_type_list (v4hi, v4qi, 0);
+ tree v8qi_ftype_v4qi_v4qi = build_function_type_list (v8qi, v4qi, v4qi, 0);
+ tree v4hi_ftype_v4qi_v4hi = build_function_type_list (v4hi, v4qi, v4hi, 0);
+ tree v4hi_ftype_v4qi_v2hi = build_function_type_list (v4hi, v4qi, v2hi, 0);
+ tree v2si_ftype_v4qi_v2hi = build_function_type_list (v2si, v4qi, v2hi, 0);
+ tree v4hi_ftype_v8qi_v4hi = build_function_type_list (v4hi, v8qi, v4hi, 0);
+ tree v4hi_ftype_v4hi_v4hi = build_function_type_list (v4hi, v4hi, v4hi, 0);
+ tree v2si_ftype_v2si_v2si = build_function_type_list (v2si, v2si, v2si, 0);
+ tree v8qi_ftype_v8qi_v8qi = build_function_type_list (v8qi, v8qi, v8qi, 0);
+ tree di_ftype_v8qi_v8qi_di = build_function_type_list (intDI_type_node,
+ v8qi, v8qi,
+ intDI_type_node, 0);
+ tree di_ftype_di_di = build_function_type_list (intDI_type_node,
+ intDI_type_node,
+ intDI_type_node, 0);
+ tree ptr_ftype_ptr_si = build_function_type_list (ptr_type_node,
+ ptr_type_node,
+ intSI_type_node, 0);
+ tree ptr_ftype_ptr_di = build_function_type_list (ptr_type_node,
+ ptr_type_node,
+ intDI_type_node, 0);
+
+ /* Packing and expanding vectors. */
+ def_builtin ("__builtin_vis_fpack16", CODE_FOR_fpack16_vis, v4qi_ftype_v4hi);
+ def_builtin ("__builtin_vis_fpack32", CODE_FOR_fpack32_vis,
+ v8qi_ftype_v2si_v8qi);
+ def_builtin ("__builtin_vis_fpackfix", CODE_FOR_fpackfix_vis,
+ v2hi_ftype_v2si);
+ def_builtin ("__builtin_vis_fexpand", CODE_FOR_fexpand_vis, v4hi_ftype_v4qi);
+ def_builtin ("__builtin_vis_fpmerge", CODE_FOR_fpmerge_vis,
+ v8qi_ftype_v4qi_v4qi);
+
+ /* Multiplications. */
+ def_builtin ("__builtin_vis_fmul8x16", CODE_FOR_fmul8x16_vis,
+ v4hi_ftype_v4qi_v4hi);
+ def_builtin ("__builtin_vis_fmul8x16au", CODE_FOR_fmul8x16au_vis,
+ v4hi_ftype_v4qi_v2hi);
+ def_builtin ("__builtin_vis_fmul8x16al", CODE_FOR_fmul8x16al_vis,
+ v4hi_ftype_v4qi_v2hi);
+ def_builtin ("__builtin_vis_fmul8sux16", CODE_FOR_fmul8sux16_vis,
+ v4hi_ftype_v8qi_v4hi);
+ def_builtin ("__builtin_vis_fmul8ulx16", CODE_FOR_fmul8ulx16_vis,
+ v4hi_ftype_v8qi_v4hi);
+ def_builtin ("__builtin_vis_fmuld8sux16", CODE_FOR_fmuld8sux16_vis,
+ v2si_ftype_v4qi_v2hi);
+ def_builtin ("__builtin_vis_fmuld8ulx16", CODE_FOR_fmuld8ulx16_vis,
+ v2si_ftype_v4qi_v2hi);
+
+ /* Data aligning. */
+ def_builtin ("__builtin_vis_faligndatav4hi", CODE_FOR_faligndatav4hi_vis,
+ v4hi_ftype_v4hi_v4hi);
+ def_builtin ("__builtin_vis_faligndatav8qi", CODE_FOR_faligndatav8qi_vis,
+ v8qi_ftype_v8qi_v8qi);
+ def_builtin ("__builtin_vis_faligndatav2si", CODE_FOR_faligndatav2si_vis,
+ v2si_ftype_v2si_v2si);
+ def_builtin ("__builtin_vis_faligndatadi", CODE_FOR_faligndatadi_vis,
+ di_ftype_di_di);
+ if (TARGET_ARCH64)
+ def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrdi_vis,
+ ptr_ftype_ptr_di);
else
- data_section ();
+ def_builtin ("__builtin_vis_alignaddr", CODE_FOR_alignaddrsi_vis,
+ ptr_ftype_ptr_si);
+
+ /* Pixel distance. */
+ def_builtin ("__builtin_vis_pdist", CODE_FOR_pdist_vis,
+ di_ftype_v8qi_v8qi_di);
+}
+
+/* Handle TARGET_EXPAND_BUILTIN target hook.
+ Expand builtin functions for sparc intrinsics. */
+
+static rtx
+sparc_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
+ enum machine_mode tmode, int ignore ATTRIBUTE_UNUSED)
+{
+ tree arglist;
+ tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
+ unsigned int icode = DECL_FUNCTION_CODE (fndecl);
+ rtx pat, op[4];
+ enum machine_mode mode[4];
+ int arg_count = 0;
+
+ mode[arg_count] = tmode;
+
+ if (target == 0
+ || GET_MODE (target) != tmode
+ || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
+ op[arg_count] = gen_reg_rtx (tmode);
+ else
+ op[arg_count] = target;
+
+ for (arglist = TREE_OPERAND (exp, 1); arglist;
+ arglist = TREE_CHAIN (arglist))
+ {
+ tree arg = TREE_VALUE (arglist);
+
+ arg_count++;
+ mode[arg_count] = insn_data[icode].operand[arg_count].mode;
+ op[arg_count] = expand_normal (arg);
+
+ if (! (*insn_data[icode].operand[arg_count].predicate) (op[arg_count],
+ mode[arg_count]))
+ op[arg_count] = copy_to_mode_reg (mode[arg_count], op[arg_count]);
+ }
+
+ switch (arg_count)
+ {
+ case 1:
+ pat = GEN_FCN (icode) (op[0], op[1]);
+ break;
+ case 2:
+ pat = GEN_FCN (icode) (op[0], op[1], op[2]);
+ break;
+ case 3:
+ pat = GEN_FCN (icode) (op[0], op[1], op[2], op[3]);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (!pat)
+ return NULL_RTX;
+
+ emit_insn (pat);
+
+ return op[0];
}
+static int
+sparc_vis_mul8x16 (int e8, int e16)
+{
+ return (e8 * e16 + 128) / 256;
+}
+
+/* Multiply the vector elements in ELTS0 to the elements in ELTS1 as specified
+ by FNCODE. All of the elements in ELTS0 and ELTS1 lists must be integer
+ constants. A tree list with the results of the multiplications is returned,
+ and each element in the list is of INNER_TYPE. */
+
+static tree
+sparc_handle_vis_mul8x16 (int fncode, tree inner_type, tree elts0, tree elts1)
+{
+ tree n_elts = NULL_TREE;
+ int scale;
+
+ switch (fncode)
+ {
+ case CODE_FOR_fmul8x16_vis:
+ for (; elts0 && elts1;
+ elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
+ {
+ int val
+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
+ TREE_INT_CST_LOW (TREE_VALUE (elts1)));
+ n_elts = tree_cons (NULL_TREE,
+ build_int_cst (inner_type, val),
+ n_elts);
+ }
+ break;
+
+ case CODE_FOR_fmul8x16au_vis:
+ scale = TREE_INT_CST_LOW (TREE_VALUE (elts1));
+
+ for (; elts0; elts0 = TREE_CHAIN (elts0))
+ {
+ int val
+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
+ scale);
+ n_elts = tree_cons (NULL_TREE,
+ build_int_cst (inner_type, val),
+ n_elts);
+ }
+ break;
+
+ case CODE_FOR_fmul8x16al_vis:
+ scale = TREE_INT_CST_LOW (TREE_VALUE (TREE_CHAIN (elts1)));
+
+ for (; elts0; elts0 = TREE_CHAIN (elts0))
+ {
+ int val
+ = sparc_vis_mul8x16 (TREE_INT_CST_LOW (TREE_VALUE (elts0)),
+ scale);
+ n_elts = tree_cons (NULL_TREE,
+ build_int_cst (inner_type, val),
+ n_elts);
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return nreverse (n_elts);
+
+}
+/* Handle TARGET_FOLD_BUILTIN target hook.
+ Fold builtin functions for SPARC intrinsics. If IGNORE is true the
+ result of the function call is ignored. NULL_TREE is returned if the
+ function could not be folded. */
+
+static tree
+sparc_fold_builtin (tree fndecl, tree arglist, bool ignore)
+{
+ tree arg0, arg1, arg2;
+ tree rtype = TREE_TYPE (TREE_TYPE (fndecl));
+
+
+ if (ignore && DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrsi_vis
+ && DECL_FUNCTION_CODE (fndecl) != CODE_FOR_alignaddrdi_vis)
+ return build_int_cst (rtype, 0);
+
+ switch (DECL_FUNCTION_CODE (fndecl))
+ {
+ case CODE_FOR_fexpand_vis:
+ arg0 = TREE_VALUE (arglist);
+ STRIP_NOPS (arg0);
+
+ if (TREE_CODE (arg0) == VECTOR_CST)
+ {
+ tree inner_type = TREE_TYPE (rtype);
+ tree elts = TREE_VECTOR_CST_ELTS (arg0);
+ tree n_elts = NULL_TREE;
+
+ for (; elts; elts = TREE_CHAIN (elts))
+ {
+ unsigned int val = TREE_INT_CST_LOW (TREE_VALUE (elts)) << 4;
+ n_elts = tree_cons (NULL_TREE,
+ build_int_cst (inner_type, val),
+ n_elts);
+ }
+ return build_vector (rtype, nreverse (n_elts));
+ }
+ break;
+
+ case CODE_FOR_fmul8x16_vis:
+ case CODE_FOR_fmul8x16au_vis:
+ case CODE_FOR_fmul8x16al_vis:
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
+ if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
+ {
+ tree inner_type = TREE_TYPE (rtype);
+ tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
+ tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
+ tree n_elts = sparc_handle_vis_mul8x16 (DECL_FUNCTION_CODE (fndecl),
+ inner_type, elts0, elts1);
+
+ return build_vector (rtype, n_elts);
+ }
+ break;
+
+ case CODE_FOR_fpmerge_vis:
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+
+ if (TREE_CODE (arg0) == VECTOR_CST && TREE_CODE (arg1) == VECTOR_CST)
+ {
+ tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
+ tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
+ tree n_elts = NULL_TREE;
+
+ for (; elts0 && elts1;
+ elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
+ {
+ n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts0), n_elts);
+ n_elts = tree_cons (NULL_TREE, TREE_VALUE (elts1), n_elts);
+ }
+
+ return build_vector (rtype, nreverse (n_elts));
+ }
+ break;
+
+ case CODE_FOR_pdist_vis:
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+ arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
+ STRIP_NOPS (arg0);
+ STRIP_NOPS (arg1);
+ STRIP_NOPS (arg2);
+
+ if (TREE_CODE (arg0) == VECTOR_CST
+ && TREE_CODE (arg1) == VECTOR_CST
+ && TREE_CODE (arg2) == INTEGER_CST)
+ {
+ int overflow = 0;
+ unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (arg2);
+ HOST_WIDE_INT high = TREE_INT_CST_HIGH (arg2);
+ tree elts0 = TREE_VECTOR_CST_ELTS (arg0);
+ tree elts1 = TREE_VECTOR_CST_ELTS (arg1);
+
+ for (; elts0 && elts1;
+ elts0 = TREE_CHAIN (elts0), elts1 = TREE_CHAIN (elts1))
+ {
+ unsigned HOST_WIDE_INT
+ low0 = TREE_INT_CST_LOW (TREE_VALUE (elts0)),
+ low1 = TREE_INT_CST_LOW (TREE_VALUE (elts1));
+ HOST_WIDE_INT high0 = TREE_INT_CST_HIGH (TREE_VALUE (elts0));
+ HOST_WIDE_INT high1 = TREE_INT_CST_HIGH (TREE_VALUE (elts1));
+
+ unsigned HOST_WIDE_INT l;
+ HOST_WIDE_INT h;
+
+ overflow |= neg_double (low1, high1, &l, &h);
+ overflow |= add_double (low0, high0, l, h, &l, &h);
+ if (h < 0)
+ overflow |= neg_double (l, h, &l, &h);
+
+ overflow |= add_double (low, high, l, h, &low, &high);
+ }
+
+ gcc_assert (overflow == 0);
+
+ return build_int_cst_wide (rtype, low, high);
+ }
+
+ default:
+ break;
+ }
+ return NULL_TREE;
+}
+
int
sparc_extra_constraint_check (rtx op, int c, int strict)
{
@@ -8893,6 +8255,9 @@ sparc_extra_constraint_check (rtx op, int c, int strict)
case 'T':
break;
+ case 'Y':
+ return const_zero_operand (op, GET_MODE (op));
+
default:
return 0;
}
@@ -8926,368 +8291,234 @@ sparc_extra_constraint_check (rtx op, int c, int strict)
static bool
sparc_rtx_costs (rtx x, int code, int outer_code, int *total)
{
+ enum machine_mode mode = GET_MODE (x);
+ bool float_mode_p = FLOAT_MODE_P (mode);
+
switch (code)
{
- case PLUS: case MINUS: case ABS: case NEG:
- case FLOAT: case UNSIGNED_FLOAT:
- case FIX: case UNSIGNED_FIX:
- case FLOAT_EXTEND: case FLOAT_TRUNCATE:
- if (FLOAT_MODE_P (GET_MODE (x)))
+ case CONST_INT:
+ if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
{
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- case PROCESSOR_ULTRASPARC3:
- *total = COSTS_N_INSNS (4);
- return true;
-
- case PROCESSOR_SUPERSPARC:
- *total = COSTS_N_INSNS (3);
- return true;
-
- case PROCESSOR_CYPRESS:
- *total = COSTS_N_INSNS (5);
- return true;
-
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- default:
- *total = COSTS_N_INSNS (1);
- return true;
- }
+ *total = 0;
+ return true;
}
+ /* FALLTHRU */
- *total = COSTS_N_INSNS (1);
+ case HIGH:
+ *total = 2;
return true;
- case SQRT:
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (13);
- else
- *total = COSTS_N_INSNS (23);
- return true;
-
- case PROCESSOR_ULTRASPARC3:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (20);
- else
- *total = COSTS_N_INSNS (29);
- return true;
-
- case PROCESSOR_SUPERSPARC:
- *total = COSTS_N_INSNS (12);
- return true;
-
- case PROCESSOR_CYPRESS:
- *total = COSTS_N_INSNS (63);
- return true;
+ case CONST:
+ case LABEL_REF:
+ case SYMBOL_REF:
+ *total = 4;
+ return true;
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- *total = COSTS_N_INSNS (17);
- return true;
+ case CONST_DOUBLE:
+ if (GET_MODE (x) == VOIDmode
+ && ((CONST_DOUBLE_HIGH (x) == 0
+ && CONST_DOUBLE_LOW (x) < 0x1000)
+ || (CONST_DOUBLE_HIGH (x) == -1
+ && CONST_DOUBLE_LOW (x) < 0
+ && CONST_DOUBLE_LOW (x) >= -0x1000)))
+ *total = 0;
+ else
+ *total = 8;
+ return true;
- default:
- *total = COSTS_N_INSNS (30);
- return true;
+ case MEM:
+ /* If outer-code was a sign or zero extension, a cost
+ of COSTS_N_INSNS (1) was already added in. This is
+ why we are subtracting it back out. */
+ if (outer_code == ZERO_EXTEND)
+ {
+ *total = sparc_costs->int_zload - COSTS_N_INSNS (1);
}
-
- case COMPARE:
- if (FLOAT_MODE_P (GET_MODE (x)))
+ else if (outer_code == SIGN_EXTEND)
{
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- case PROCESSOR_ULTRASPARC3:
- *total = COSTS_N_INSNS (1);
- return true;
-
- case PROCESSOR_SUPERSPARC:
- *total = COSTS_N_INSNS (3);
- return true;
-
- case PROCESSOR_CYPRESS:
- *total = COSTS_N_INSNS (5);
- return true;
-
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- default:
- *total = COSTS_N_INSNS (1);
- return true;
- }
+ *total = sparc_costs->int_sload - COSTS_N_INSNS (1);
+ }
+ else if (float_mode_p)
+ {
+ *total = sparc_costs->float_load;
+ }
+ else
+ {
+ *total = sparc_costs->int_load;
}
- /* ??? Maybe mark integer compares as zero cost on
- ??? all UltraSPARC processors because the result
- ??? can be bypassed to a branch in the same group. */
-
- *total = COSTS_N_INSNS (1);
return true;
+ case PLUS:
+ case MINUS:
+ if (float_mode_p)
+ *total = sparc_costs->float_plusminus;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
+
case MULT:
- if (FLOAT_MODE_P (GET_MODE (x)))
+ if (float_mode_p)
+ *total = sparc_costs->float_mul;
+ else if (! TARGET_HARD_MUL)
+ *total = COSTS_N_INSNS (25);
+ else
{
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- case PROCESSOR_ULTRASPARC3:
- *total = COSTS_N_INSNS (4);
- return true;
+ int bit_cost;
- case PROCESSOR_SUPERSPARC:
- *total = COSTS_N_INSNS (3);
- return true;
-
- case PROCESSOR_CYPRESS:
- *total = COSTS_N_INSNS (7);
- return true;
+ bit_cost = 0;
+ if (sparc_costs->int_mul_bit_factor)
+ {
+ int nbits;
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- *total = COSTS_N_INSNS (1);
- return true;
+ if (GET_CODE (XEXP (x, 1)) == CONST_INT)
+ {
+ unsigned HOST_WIDE_INT value = INTVAL (XEXP (x, 1));
+ for (nbits = 0; value != 0; value &= value - 1)
+ nbits++;
+ }
+ else if (GET_CODE (XEXP (x, 1)) == CONST_DOUBLE
+ && GET_MODE (XEXP (x, 1)) == VOIDmode)
+ {
+ rtx x1 = XEXP (x, 1);
+ unsigned HOST_WIDE_INT value1 = CONST_DOUBLE_LOW (x1);
+ unsigned HOST_WIDE_INT value2 = CONST_DOUBLE_HIGH (x1);
+
+ for (nbits = 0; value1 != 0; value1 &= value1 - 1)
+ nbits++;
+ for (; value2 != 0; value2 &= value2 - 1)
+ nbits++;
+ }
+ else
+ nbits = 7;
- default:
- *total = COSTS_N_INSNS (5);
- return true;
+ if (nbits < 3)
+ nbits = 3;
+ bit_cost = (nbits - 3) / sparc_costs->int_mul_bit_factor;
+ bit_cost = COSTS_N_INSNS (bit_cost);
}
- }
-
- /* The latency is actually variable for Ultra-I/II
- And if one of the inputs have a known constant
- value, we could calculate this precisely.
-
- However, for that to be useful we would need to
- add some machine description changes which would
- make sure small constants ended up in rs1 of the
- multiply instruction. This is because the multiply
- latency is determined by the number of clear (or
- set if the value is negative) bits starting from
- the most significant bit of the first input.
-
- The algorithm for computing num_cycles of a multiply
- on Ultra-I/II is:
-
- if (rs1 < 0)
- highest_bit = highest_clear_bit(rs1);
- else
- highest_bit = highest_set_bit(rs1);
- if (num_bits < 3)
- highest_bit = 3;
- num_cycles = 4 + ((highest_bit - 3) / 2);
-
- If we did that we would have to also consider register
- allocation issues that would result from forcing such
- a value into a register.
-
- There are other similar tricks we could play if we
- knew, for example, that one input was an array index.
- Since we do not play any such tricks currently the
- safest thing to do is report the worst case latency. */
- if (sparc_cpu == PROCESSOR_ULTRASPARC)
- {
- *total = (GET_MODE (x) == DImode
- ? COSTS_N_INSNS (34) : COSTS_N_INSNS (19));
- return true;
- }
-
- /* Multiply latency on Ultra-III, fortunately, is constant. */
- if (sparc_cpu == PROCESSOR_ULTRASPARC3)
- {
- *total = COSTS_N_INSNS (6);
- return true;
- }
-
- if (sparc_cpu == PROCESSOR_HYPERSPARC
- || sparc_cpu == PROCESSOR_SPARCLITE86X)
- {
- *total = COSTS_N_INSNS (17);
- return true;
+ if (mode == DImode)
+ *total = sparc_costs->int_mulX + bit_cost;
+ else
+ *total = sparc_costs->int_mul + bit_cost;
}
+ return false;
- *total = (TARGET_HARD_MUL ? COSTS_N_INSNS (5) : COSTS_N_INSNS (25));
- return true;
+ case ASHIFT:
+ case ASHIFTRT:
+ case LSHIFTRT:
+ *total = COSTS_N_INSNS (1) + sparc_costs->shift_penalty;
+ return false;
case DIV:
case UDIV:
case MOD:
case UMOD:
- if (FLOAT_MODE_P (GET_MODE (x)))
+ if (float_mode_p)
{
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (13);
- else
- *total = COSTS_N_INSNS (23);
- return true;
-
- case PROCESSOR_ULTRASPARC3:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (17);
- else
- *total = COSTS_N_INSNS (20);
- return true;
-
- case PROCESSOR_SUPERSPARC:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (6);
- else
- *total = COSTS_N_INSNS (9);
- return true;
-
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- if (GET_MODE (x) == SFmode)
- *total = COSTS_N_INSNS (8);
- else
- *total = COSTS_N_INSNS (12);
- return true;
-
- default:
- *total = COSTS_N_INSNS (7);
- return true;
- }
+ if (mode == DFmode)
+ *total = sparc_costs->float_div_df;
+ else
+ *total = sparc_costs->float_div_sf;
}
-
- if (sparc_cpu == PROCESSOR_ULTRASPARC)
- *total = (GET_MODE (x) == DImode
- ? COSTS_N_INSNS (68) : COSTS_N_INSNS (37));
- else if (sparc_cpu == PROCESSOR_ULTRASPARC3)
- *total = (GET_MODE (x) == DImode
- ? COSTS_N_INSNS (71) : COSTS_N_INSNS (40));
else
- *total = COSTS_N_INSNS (25);
- return true;
-
- case IF_THEN_ELSE:
- /* Conditional moves. */
- switch (sparc_cpu)
{
- case PROCESSOR_ULTRASPARC:
- *total = COSTS_N_INSNS (2);
- return true;
-
- case PROCESSOR_ULTRASPARC3:
- if (FLOAT_MODE_P (GET_MODE (x)))
- *total = COSTS_N_INSNS (3);
+ if (mode == DImode)
+ *total = sparc_costs->int_divX;
else
- *total = COSTS_N_INSNS (2);
- return true;
+ *total = sparc_costs->int_div;
+ }
+ return false;
- default:
+ case NEG:
+ if (! float_mode_p)
+ {
*total = COSTS_N_INSNS (1);
- return true;
+ return false;
}
+ /* FALLTHRU */
- case MEM:
- /* If outer-code is SIGN/ZERO extension we have to subtract
- out COSTS_N_INSNS (1) from whatever we return in determining
- the cost. */
- switch (sparc_cpu)
- {
- case PROCESSOR_ULTRASPARC:
- if (outer_code == ZERO_EXTEND)
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (2);
- return true;
+ case ABS:
+ case FLOAT:
+ case UNSIGNED_FLOAT:
+ case FIX:
+ case UNSIGNED_FIX:
+ case FLOAT_EXTEND:
+ case FLOAT_TRUNCATE:
+ *total = sparc_costs->float_move;
+ return false;
- case PROCESSOR_ULTRASPARC3:
- if (outer_code == ZERO_EXTEND)
- {
- if (GET_MODE (x) == QImode
- || GET_MODE (x) == HImode
- || outer_code == SIGN_EXTEND)
- *total = COSTS_N_INSNS (2);
- else
- *total = COSTS_N_INSNS (1);
- }
- else
- {
- /* This handles sign extension (3 cycles)
- and everything else (2 cycles). */
- *total = COSTS_N_INSNS (2);
- }
- return true;
+ case SQRT:
+ if (mode == DFmode)
+ *total = sparc_costs->float_sqrt_df;
+ else
+ *total = sparc_costs->float_sqrt_sf;
+ return false;
- case PROCESSOR_SUPERSPARC:
- if (FLOAT_MODE_P (GET_MODE (x))
- || outer_code == ZERO_EXTEND
- || outer_code == SIGN_EXTEND)
- *total = COSTS_N_INSNS (0);
- else
- *total = COSTS_N_INSNS (1);
- return true;
+ case COMPARE:
+ if (float_mode_p)
+ *total = sparc_costs->float_cmp;
+ else
+ *total = COSTS_N_INSNS (1);
+ return false;
- case PROCESSOR_TSC701:
- if (outer_code == ZERO_EXTEND
- || outer_code == SIGN_EXTEND)
- *total = COSTS_N_INSNS (2);
- else
- *total = COSTS_N_INSNS (3);
- return true;
-
- case PROCESSOR_CYPRESS:
- if (outer_code == ZERO_EXTEND
- || outer_code == SIGN_EXTEND)
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (2);
- return true;
-
- case PROCESSOR_HYPERSPARC:
- case PROCESSOR_SPARCLITE86X:
- default:
- if (outer_code == ZERO_EXTEND
- || outer_code == SIGN_EXTEND)
- *total = COSTS_N_INSNS (0);
- else
- *total = COSTS_N_INSNS (1);
- return true;
- }
+ case IF_THEN_ELSE:
+ if (float_mode_p)
+ *total = sparc_costs->float_cmove;
+ else
+ *total = sparc_costs->int_cmove;
+ return false;
- case CONST_INT:
- if (INTVAL (x) < 0x1000 && INTVAL (x) >= -0x1000)
+ case IOR:
+ /* Handle the NAND vector patterns. */
+ if (sparc_vector_mode_supported_p (GET_MODE (x))
+ && GET_CODE (XEXP (x, 0)) == NOT
+ && GET_CODE (XEXP (x, 1)) == NOT)
{
- *total = 0;
+ *total = COSTS_N_INSNS (1);
return true;
}
- /* FALLTHRU */
-
- case HIGH:
- *total = 2;
- return true;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = 4;
- return true;
-
- case CONST_DOUBLE:
- if (GET_MODE (x) == DImode
- && ((XINT (x, 3) == 0
- && (unsigned HOST_WIDE_INT) XINT (x, 2) < 0x1000)
- || (XINT (x, 3) == -1
- && XINT (x, 2) < 0
- && XINT (x, 2) >= -0x1000)))
- *total = 0;
else
- *total = 8;
- return true;
+ return false;
default:
return false;
}
}
+/* Emit the sequence of insns SEQ while preserving the registers REG and REG2.
+ This is achieved by means of a manual dynamic stack space allocation in
+ the current frame. We make the assumption that SEQ doesn't contain any
+ function calls, with the possible exception of calls to the PIC helper. */
+
+static void
+emit_and_preserve (rtx seq, rtx reg, rtx reg2)
+{
+ /* We must preserve the lowest 16 words for the register save area. */
+ HOST_WIDE_INT offset = 16*UNITS_PER_WORD;
+ /* We really need only 2 words of fresh stack space. */
+ HOST_WIDE_INT size = SPARC_STACK_ALIGN (offset + 2*UNITS_PER_WORD);
+
+ rtx slot
+ = gen_rtx_MEM (word_mode, plus_constant (stack_pointer_rtx,
+ SPARC_STACK_BIAS + offset));
+
+ emit_insn (gen_stack_pointer_dec (GEN_INT (size)));
+ emit_insn (gen_rtx_SET (VOIDmode, slot, reg));
+ if (reg2)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ adjust_address (slot, word_mode, UNITS_PER_WORD),
+ reg2));
+ emit_insn (seq);
+ if (reg2)
+ emit_insn (gen_rtx_SET (VOIDmode,
+ reg2,
+ adjust_address (slot, word_mode, UNITS_PER_WORD)));
+ emit_insn (gen_rtx_SET (VOIDmode, reg, slot));
+ emit_insn (gen_stack_pointer_inc (GEN_INT (size)));
+}
+
/* Output the assembler code for a thunk function. THUNK_DECL is the
declaration for the thunk function itself, FUNCTION is the decl for
the target function. DELTA is an immediate constant offset to be
@@ -9300,20 +8531,41 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
tree function)
{
rtx this, insn, funexp;
+ unsigned int int_arg_first;
reload_completed = 1;
epilogue_completed = 1;
no_new_pseudos = 1;
- current_function_uses_only_leaf_regs = 1;
+ reset_block_changes ();
emit_note (NOTE_INSN_PROLOGUE_END);
+ if (flag_delayed_branch)
+ {
+ /* We will emit a regular sibcall below, so we need to instruct
+ output_sibcall that we are in a leaf function. */
+ sparc_leaf_function_p = current_function_uses_only_leaf_regs = 1;
+
+ /* This will cause final.c to invoke leaf_renumber_regs so we
+ must behave as if we were in a not-yet-leafified function. */
+ int_arg_first = SPARC_INCOMING_INT_ARG_FIRST;
+ }
+ else
+ {
+ /* We will emit the sibcall manually below, so we will need to
+ manually spill non-leaf registers. */
+ sparc_leaf_function_p = current_function_uses_only_leaf_regs = 0;
+
+ /* We really are in a leaf function. */
+ int_arg_first = SPARC_OUTGOING_INT_ARG_FIRST;
+ }
+
/* Find the "this" pointer. Normally in %o0, but in ARCH64 if the function
returns a structure, the structure return pointer is there instead. */
if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
- this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
+ this = gen_rtx_REG (Pmode, int_arg_first + 1);
else
- this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST);
+ this = gen_rtx_REG (Pmode, int_arg_first);
/* Add DELTA. When possible use a plain add, otherwise load it into
a register first. */
@@ -9338,8 +8590,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
rtx vcall_offset_rtx = GEN_INT (vcall_offset);
rtx scratch = gen_rtx_REG (Pmode, 1);
- if (vcall_offset >= 0)
- abort ();
+ gcc_assert (vcall_offset < 0);
/* SCRATCH = *THIS. */
emit_move_insn (scratch, gen_rtx_MEM (Pmode, this));
@@ -9392,9 +8643,70 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
TREE_USED (function) = 1;
}
funexp = XEXP (DECL_RTL (function), 0);
- funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
- insn = emit_call_insn (gen_sibcall (funexp));
- SIBLING_CALL_P (insn) = 1;
+
+ if (flag_delayed_branch)
+ {
+ funexp = gen_rtx_MEM (FUNCTION_MODE, funexp);
+ insn = emit_call_insn (gen_sibcall (funexp));
+ SIBLING_CALL_P (insn) = 1;
+ }
+ else
+ {
+ /* The hoops we have to jump through in order to generate a sibcall
+ without using delay slots... */
+ rtx spill_reg, spill_reg2, seq, scratch = gen_rtx_REG (Pmode, 1);
+
+ if (flag_pic)
+ {
+ spill_reg = gen_rtx_REG (word_mode, 15); /* %o7 */
+ spill_reg2 = gen_rtx_REG (word_mode, PIC_OFFSET_TABLE_REGNUM);
+ start_sequence ();
+ /* Delay emitting the PIC helper function because it needs to
+ change the section and we are emitting assembly code. */
+ load_pic_register (true); /* clobbers %o7 */
+ scratch = legitimize_pic_address (funexp, Pmode, scratch);
+ seq = get_insns ();
+ end_sequence ();
+ emit_and_preserve (seq, spill_reg, spill_reg2);
+ }
+ else if (TARGET_ARCH32)
+ {
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch,
+ gen_rtx_HIGH (SImode, funexp)));
+ emit_insn (gen_rtx_SET (VOIDmode,
+ scratch,
+ gen_rtx_LO_SUM (SImode, scratch, funexp)));
+ }
+ else /* TARGET_ARCH64 */
+ {
+ switch (sparc_cmodel)
+ {
+ case CM_MEDLOW:
+ case CM_MEDMID:
+ /* The destination can serve as a temporary. */
+ sparc_emit_set_symbolic_const64 (scratch, funexp, scratch);
+ break;
+
+ case CM_MEDANY:
+ case CM_EMBMEDANY:
+ /* The destination cannot serve as a temporary. */
+ spill_reg = gen_rtx_REG (DImode, 15); /* %o7 */
+ start_sequence ();
+ sparc_emit_set_symbolic_const64 (scratch, funexp, spill_reg);
+ seq = get_insns ();
+ end_sequence ();
+ emit_and_preserve (seq, spill_reg, 0);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+
+ emit_jump_insn (gen_indirect_jump (scratch));
+ }
+
emit_barrier ();
/* Run just enough of rest_of_compilation to get the insns emitted.
@@ -9405,7 +8717,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
insn_locators_initialize ();
shorten_branches (insn);
final_start_function (insn, file, 1);
- final (insn, file, 1, 0);
+ final (insn, file, 1);
final_end_function ();
reload_completed = 0;
@@ -9450,7 +8762,7 @@ get_some_local_dynamic_name (void)
&& for_each_rtx (&PATTERN (insn), get_some_local_dynamic_name_1, 0))
return cfun->machine->some_ld_name;
- abort ();
+ gcc_unreachable ();
}
static int
@@ -9469,10 +8781,22 @@ get_some_local_dynamic_name_1 (rtx *px, void *data ATTRIBUTE_UNUSED)
return 0;
}
-/* This is called from dwarf2out.c via ASM_OUTPUT_DWARF_DTPREL.
+/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
+ This is called from dwarf2out.c to emit call frame instructions
+ for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
+static void
+sparc_dwarf_handle_frame_unspec (const char *label,
+ rtx pattern ATTRIBUTE_UNUSED,
+ int index ATTRIBUTE_UNUSED)
+{
+ gcc_assert (index == UNSPECV_SAVEW);
+ dwarf2out_window_save (label);
+}
+
+/* This is called from dwarf2out.c via TARGET_ASM_OUTPUT_DWARF_DTPREL.
We need to emit DTP-relative relocations. */
-void
+static void
sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
{
switch (size)
@@ -9484,10 +8808,142 @@ sparc_output_dwarf_dtprel (FILE *file, int size, rtx x)
fputs ("\t.xword\t%r_tls_dtpoff64(", file);
break;
default:
- abort ();
+ gcc_unreachable ();
}
output_addr_const (file, x);
fputs (")", file);
}
+/* Do whatever processing is required at the end of a file. */
+
+static void
+sparc_file_end (void)
+{
+ /* If we haven't emitted the special PIC helper function, do so now. */
+ if (pic_helper_symbol_name[0] && !pic_helper_emitted_p)
+ emit_pic_helper ();
+
+ if (NEED_INDICATE_EXEC_STACK)
+ file_end_indicate_exec_stack ();
+}
+
+#ifdef TARGET_ALTERNATE_LONG_DOUBLE_MANGLING
+/* Implement TARGET_MANGLE_FUNDAMENTAL_TYPE. */
+
+static const char *
+sparc_mangle_fundamental_type (tree type)
+{
+ if (!TARGET_64BIT
+ && TYPE_MAIN_VARIANT (type) == long_double_type_node
+ && TARGET_LONG_DOUBLE_128)
+ return "g";
+
+ /* For all other types, use normal C++ mangling. */
+ return NULL;
+}
+#endif
+
+/* Expand code to perform a 8 or 16-bit compare and swap by doing 32-bit
+ compare and swap on the word containing the byte or half-word. */
+
+void
+sparc_expand_compare_and_swap_12 (rtx result, rtx mem, rtx oldval, rtx newval)
+{
+ rtx addr1 = force_reg (Pmode, XEXP (mem, 0));
+ rtx addr = gen_reg_rtx (Pmode);
+ rtx off = gen_reg_rtx (SImode);
+ rtx oldv = gen_reg_rtx (SImode);
+ rtx newv = gen_reg_rtx (SImode);
+ rtx oldvalue = gen_reg_rtx (SImode);
+ rtx newvalue = gen_reg_rtx (SImode);
+ rtx res = gen_reg_rtx (SImode);
+ rtx resv = gen_reg_rtx (SImode);
+ rtx memsi, val, mask, end_label, loop_label, cc;
+
+ emit_insn (gen_rtx_SET (VOIDmode, addr,
+ gen_rtx_AND (Pmode, addr1, GEN_INT (-4))));
+
+ if (Pmode != SImode)
+ addr1 = gen_lowpart (SImode, addr1);
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_AND (SImode, addr1, GEN_INT (3))));
+
+ memsi = gen_rtx_MEM (SImode, addr);
+ set_mem_alias_set (memsi, ALIAS_SET_MEMORY_BARRIER);
+ MEM_VOLATILE_P (memsi) = MEM_VOLATILE_P (mem);
+
+ val = force_reg (SImode, memsi);
+
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_XOR (SImode, off,
+ GEN_INT (GET_MODE (mem) == QImode
+ ? 3 : 2))));
+
+ emit_insn (gen_rtx_SET (VOIDmode, off,
+ gen_rtx_ASHIFT (SImode, off, GEN_INT (3))));
+
+ if (GET_MODE (mem) == QImode)
+ mask = force_reg (SImode, GEN_INT (0xff));
+ else
+ mask = force_reg (SImode, GEN_INT (0xffff));
+
+ emit_insn (gen_rtx_SET (VOIDmode, mask,
+ gen_rtx_ASHIFT (SImode, mask, off)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, val,
+ gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
+ val)));
+
+ oldval = gen_lowpart (SImode, oldval);
+ emit_insn (gen_rtx_SET (VOIDmode, oldv,
+ gen_rtx_ASHIFT (SImode, oldval, off)));
+
+ newval = gen_lowpart_common (SImode, newval);
+ emit_insn (gen_rtx_SET (VOIDmode, newv,
+ gen_rtx_ASHIFT (SImode, newval, off)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, oldv,
+ gen_rtx_AND (SImode, oldv, mask)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, newv,
+ gen_rtx_AND (SImode, newv, mask)));
+
+ end_label = gen_label_rtx ();
+ loop_label = gen_label_rtx ();
+ emit_label (loop_label);
+
+ emit_insn (gen_rtx_SET (VOIDmode, oldvalue,
+ gen_rtx_IOR (SImode, oldv, val)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, newvalue,
+ gen_rtx_IOR (SImode, newv, val)));
+
+ emit_insn (gen_sync_compare_and_swapsi (res, memsi, oldvalue, newvalue));
+
+ emit_cmp_and_jump_insns (res, oldvalue, EQ, NULL, SImode, 0, end_label);
+
+ emit_insn (gen_rtx_SET (VOIDmode, resv,
+ gen_rtx_AND (SImode, gen_rtx_NOT (SImode, mask),
+ res)));
+
+ sparc_compare_op0 = resv;
+ sparc_compare_op1 = val;
+ cc = gen_compare_reg (NE);
+
+ emit_insn (gen_rtx_SET (VOIDmode, val, resv));
+
+ sparc_compare_emitted = cc;
+ emit_jump_insn (gen_bne (loop_label));
+
+ emit_label (end_label);
+
+ emit_insn (gen_rtx_SET (VOIDmode, res,
+ gen_rtx_AND (SImode, res, mask)));
+
+ emit_insn (gen_rtx_SET (VOIDmode, res,
+ gen_rtx_LSHIFTRT (SImode, res, off)));
+
+ emit_move_insn (result, gen_lowpart (GET_MODE (result), res));
+}
+
#include "gt-sparc.h"
diff --git a/contrib/gcc/config/sparc/sparc.h b/contrib/gcc/config/sparc/sparc.h
index 9f72bc8..8a2121c 100644
--- a/contrib/gcc/config/sparc/sparc.h
+++ b/contrib/gcc/config/sparc/sparc.h
@@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler, for Sun SPARC.
Copyright (C) 1987, 1988, 1989, 1992, 1994, 1995, 1996, 1997, 1998, 1999
- 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com).
64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
at Cygnus Support.
@@ -19,12 +19,90 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Note that some other tm.h files include this one and then override
whatever definitions are necessary. */
+/* Define the specific costs for a given cpu */
+
+struct processor_costs {
+ /* Integer load */
+ const int int_load;
+
+ /* Integer signed load */
+ const int int_sload;
+
+ /* Integer zeroed load */
+ const int int_zload;
+
+ /* Float load */
+ const int float_load;
+
+ /* fmov, fneg, fabs */
+ const int float_move;
+
+ /* fadd, fsub */
+ const int float_plusminus;
+
+ /* fcmp */
+ const int float_cmp;
+
+ /* fmov, fmovr */
+ const int float_cmove;
+
+ /* fmul */
+ const int float_mul;
+
+ /* fdivs */
+ const int float_div_sf;
+
+ /* fdivd */
+ const int float_div_df;
+
+ /* fsqrts */
+ const int float_sqrt_sf;
+
+ /* fsqrtd */
+ const int float_sqrt_df;
+
+ /* umul/smul */
+ const int int_mul;
+
+ /* mulX */
+ const int int_mulX;
+
+ /* integer multiply cost for each bit set past the most
+ significant 3, so the formula for multiply cost becomes:
+
+ if (rs1 < 0)
+ highest_bit = highest_clear_bit(rs1);
+ else
+ highest_bit = highest_set_bit(rs1);
+ if (highest_bit < 3)
+ highest_bit = 3;
+ cost = int_mul{,X} + ((highest_bit - 3) / int_mul_bit_factor);
+
+ A value of zero indicates that the multiply costs is fixed,
+ and not variable. */
+ const int int_mul_bit_factor;
+
+ /* udiv/sdiv */
+ const int int_div;
+
+ /* divX */
+ const int int_divX;
+
+ /* movcc, movr */
+ const int int_cmove;
+
+ /* penalty for shifts, due to scheduling rules etc. */
+ const int shift_penalty;
+};
+
+extern const struct processor_costs *sparc_costs;
+
/* Target CPU builtins. FIXME: Defining sparc is for the benefit of
Solaris only; otherwise just define __sparc__. Sadly the headers
are such a mess there is no Solaris-specific header. */
@@ -113,8 +191,6 @@ enum cmodel {
CM_EMBMEDANY
};
-/* Value of -mcmodel specified by user. */
-extern const char *sparc_cmodel_string;
/* One of CM_FOO. */
extern enum cmodel sparc_cmodel;
@@ -126,6 +202,19 @@ extern enum cmodel sparc_cmodel;
#define SPARC_DEFAULT_CMODEL CM_32
+/* The SPARC-V9 architecture defines a relaxed memory ordering model (RMO)
+ which requires the following macro to be true if enabled. Prior to V9,
+ there are no instructions to even talk about memory synchronization.
+ Note that the UltraSPARC III processors don't implement RMO, unlike the
+ UltraSPARC II processors. Niagara does not implement RMO either.
+
+ Default to false; for example, Solaris never enables RMO, only ever uses
+ total memory ordering (TMO). */
+#define SPARC_RELAXED_ORDERING false
+
+/* Do not use the .note.GNU-stack convention by default. */
+#define NEED_INDICATE_EXEC_STACK 0
+
/* This is call-clobbered in the normal ABI, but is reserved in the
home grown (aka upward compatible) embedded ABI. */
#define EMBMEDANY_BASE_REG "%g4"
@@ -149,10 +238,12 @@ extern enum cmodel sparc_cmodel;
#define TARGET_CPU_sparc64 7 /* alias */
#define TARGET_CPU_ultrasparc 8
#define TARGET_CPU_ultrasparc3 9
+#define TARGET_CPU_niagara 10
#if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \
|| TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \
- || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3
+ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc3 \
+ || TARGET_CPU_DEFAULT == TARGET_CPU_niagara
#define CPP_CPU32_DEFAULT_SPEC ""
#define ASM_CPU32_DEFAULT_SPEC ""
@@ -173,6 +264,10 @@ extern enum cmodel sparc_cmodel;
#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
#endif
+#if TARGET_CPU_DEFAULT == TARGET_CPU_niagara
+#define CPP_CPU64_DEFAULT_SPEC "-D__sparc_v9__"
+#define ASM_CPU64_DEFAULT_SPEC "-Av9b"
+#endif
#else
@@ -263,6 +358,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=v9:-D__sparc_v9__} \
%{mcpu=ultrasparc:-D__sparc_v9__} \
%{mcpu=ultrasparc3:-D__sparc_v9__} \
+%{mcpu=niagara:-D__sparc_v9__} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(cpp_cpu_default)}}}}}}} \
"
#define CPP_ARCH32_SPEC ""
@@ -312,6 +408,7 @@ extern enum cmodel sparc_cmodel;
%{mcpu=v9:-Av9} \
%{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \
%{mcpu=ultrasparc3:%{!mv8plus:-Av9b}} \
+%{mcpu=niagara:%{!mv8plus:-Av9b}} \
%{!mcpu*:%{!mcypress:%{!msparclite:%{!mf930:%{!mf934:%{!mv8:%{!msupersparc:%(asm_cpu_default)}}}}}}} \
"
@@ -392,131 +489,14 @@ extern enum cmodel sparc_cmodel;
/* Show we can debug even without a frame pointer. */
#define CAN_DEBUG_WITHOUT_FP
-#define OVERRIDE_OPTIONS sparc_override_options ()
-
-/* Generate DBX debugging information. */
+/* Option handling. */
-#define DBX_DEBUGGING_INFO 1
+#define OVERRIDE_OPTIONS sparc_override_options ()
-/* Run-time compilation parameters selecting different hardware subsets. */
-
-extern int target_flags;
-
-/* Nonzero if we should generate code to use the fpu. */
-#define MASK_FPU 1
-#define TARGET_FPU (target_flags & MASK_FPU)
-
-/* Nonzero if we should assume that double pointers might be unaligned.
- This can happen when linking gcc compiled code with other compilers,
- because the ABI only guarantees 4 byte alignment. */
-#define MASK_UNALIGNED_DOUBLES 4
-#define TARGET_UNALIGNED_DOUBLES (target_flags & MASK_UNALIGNED_DOUBLES)
-
-/* Nonzero means that we should generate code for a v8 sparc. */
-#define MASK_V8 0x8
-#define TARGET_V8 (target_flags & MASK_V8)
-
-/* Nonzero means that we should generate code for a sparclite.
- This enables the sparclite specific instructions, but does not affect
- whether FPU instructions are emitted. */
-#define MASK_SPARCLITE 0x10
-#define TARGET_SPARCLITE (target_flags & MASK_SPARCLITE)
-
-/* Nonzero if we're compiling for the sparclet. */
-#define MASK_SPARCLET 0x20
-#define TARGET_SPARCLET (target_flags & MASK_SPARCLET)
-
-/* Nonzero if we're compiling for v9 sparc.
- Note that v9's can run in 32 bit mode so this doesn't necessarily mean
- the word size is 64. */
-#define MASK_V9 0x40
-#define TARGET_V9 (target_flags & MASK_V9)
-
-/* Nonzero to generate code that uses the instructions deprecated in
- the v9 architecture. This option only applies to v9 systems. */
-/* ??? This isn't user selectable yet. It's used to enable such insns
- on 32 bit v9 systems and for the moment they're permanently disabled
- on 64 bit v9 systems. */
-#define MASK_DEPRECATED_V8_INSNS 0x80
-#define TARGET_DEPRECATED_V8_INSNS (target_flags & MASK_DEPRECATED_V8_INSNS)
-
/* Mask of all CPU selection flags. */
#define MASK_ISA \
(MASK_V8 + MASK_SPARCLITE + MASK_SPARCLET + MASK_V9 + MASK_DEPRECATED_V8_INSNS)
-/* Nonzero means don't pass `-assert pure-text' to the linker. */
-#define MASK_IMPURE_TEXT 0x100
-#define TARGET_IMPURE_TEXT (target_flags & MASK_IMPURE_TEXT)
-
-/* Nonzero means that we should generate code using a flat register window
- model, i.e. no save/restore instructions are generated, which is
- compatible with normal sparc code.
- The frame pointer is %i7 instead of %fp. */
-#define MASK_FLAT 0x200
-#define TARGET_FLAT (target_flags & MASK_FLAT)
-
-/* Nonzero means use the registers that the SPARC ABI reserves for
- application software. This must be the default to coincide with the
- setting in FIXED_REGISTERS. */
-#define MASK_APP_REGS 0x400
-#define TARGET_APP_REGS (target_flags & MASK_APP_REGS)
-
-/* Option to select how quad word floating point is implemented.
- When TARGET_HARD_QUAD is true, we use the hardware quad instructions.
- Otherwise, we use the SPARC ABI quad library functions. */
-#define MASK_HARD_QUAD 0x800
-#define TARGET_HARD_QUAD (target_flags & MASK_HARD_QUAD)
-
-/* Nonzero on little-endian machines. */
-/* ??? Little endian support currently only exists for sparclet-aout and
- sparc64-elf configurations. May eventually want to expand the support
- to all targets, but for now it's kept local to only those two. */
-#define MASK_LITTLE_ENDIAN 0x1000
-#define TARGET_LITTLE_ENDIAN (target_flags & MASK_LITTLE_ENDIAN)
-
-/* 0x2000, 0x4000 are unused */
-
-/* Nonzero if pointers are 64 bits. */
-#define MASK_PTR64 0x8000
-#define TARGET_PTR64 (target_flags & MASK_PTR64)
-
-/* Nonzero if generating code to run in a 64 bit environment.
- This is intended to only be used by TARGET_ARCH{32,64} as they are the
- mechanism used to control compile time or run time selection. */
-#define MASK_64BIT 0x10000
-#define TARGET_64BIT (target_flags & MASK_64BIT)
-
-/* 0x20000,0x40000 unused */
-
-/* Nonzero means use a stack bias of 2047. Stack offsets are obtained by
- adding 2047 to %sp. This option is for v9 only and is the default. */
-#define MASK_STACK_BIAS 0x80000
-#define TARGET_STACK_BIAS (target_flags & MASK_STACK_BIAS)
-
-/* 0x100000,0x200000 unused */
-
-/* Nonzero means -m{,no-}fpu was passed on the command line. */
-#define MASK_FPU_SET 0x400000
-#define TARGET_FPU_SET (target_flags & MASK_FPU_SET)
-
-/* Use the UltraSPARC Visual Instruction Set extensions. */
-#define MASK_VIS 0x1000000
-#define TARGET_VIS (target_flags & MASK_VIS)
-
-/* Compile for Solaris V8+. 32 bit Solaris preserves the high bits of
- the current out and global registers and Linux 2.2+ as well. */
-#define MASK_V8PLUS 0x2000000
-#define TARGET_V8PLUS (target_flags & MASK_V8PLUS)
-
-/* Force a the fastest alignment on structures to take advantage of
- faster copies. */
-#define MASK_FASTER_STRUCTS 0x4000000
-#define TARGET_FASTER_STRUCTS (target_flags & MASK_FASTER_STRUCTS)
-
-/* Use IEEE quad long double. */
-#define MASK_LONG_DOUBLE_128 0x8000000
-#define TARGET_LONG_DOUBLE_128 (target_flags & MASK_LONG_DOUBLE_128)
-
/* TARGET_HARD_MUL: Use hardware multiply instructions but not %y.
TARGET_HARD_MUL32: Use hardware multiply instructions with rd %y
to get high 32 bits. False in V8+ or V9 because multiply stores
@@ -531,97 +511,11 @@ extern int target_flags;
(TARGET_V8 || TARGET_SPARCLITE || TARGET_SPARCLET \
|| TARGET_DEPRECATED_V8_INSNS || TARGET_V8PLUS)
-
-/* 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 \
- { {"fpu", MASK_FPU | MASK_FPU_SET, \
- N_("Use hardware fp") }, \
- {"no-fpu", -MASK_FPU, \
- N_("Do not use hardware fp") }, \
- {"no-fpu", MASK_FPU_SET, NULL, }, \
- {"hard-float", MASK_FPU | MASK_FPU_SET, \
- N_("Use hardware fp") }, \
- {"soft-float", -MASK_FPU, \
- N_("Do not use hardware fp") }, \
- {"soft-float", MASK_FPU_SET, NULL }, \
- {"unaligned-doubles", MASK_UNALIGNED_DOUBLES, \
- N_("Assume possible double misalignment") }, \
- {"no-unaligned-doubles", -MASK_UNALIGNED_DOUBLES, \
- N_("Assume all doubles are aligned") }, \
- {"impure-text", MASK_IMPURE_TEXT, \
- N_("Pass -assert pure-text to linker") }, \
- {"no-impure-text", -MASK_IMPURE_TEXT, \
- N_("Do not pass -assert pure-text to linker") }, \
- {"flat", MASK_FLAT, \
- N_("Use flat register window model") }, \
- {"no-flat", -MASK_FLAT, \
- N_("Do not use flat register window model") }, \
- {"app-regs", MASK_APP_REGS, \
- N_("Use ABI reserved registers") }, \
- {"no-app-regs", -MASK_APP_REGS, \
- N_("Do not use ABI reserved registers") }, \
- {"hard-quad-float", MASK_HARD_QUAD, \
- N_("Use hardware quad fp instructions") }, \
- {"soft-quad-float", -MASK_HARD_QUAD, \
- N_("Do not use hardware quad fp instructions") }, \
- {"v8plus", MASK_V8PLUS, \
- N_("Compile for v8plus ABI") }, \
- {"no-v8plus", -MASK_V8PLUS, \
- N_("Do not compile for v8plus ABI") }, \
- {"vis", MASK_VIS, \
- N_("Utilize Visual Instruction Set") }, \
- {"no-vis", -MASK_VIS, \
- N_("Do not utilize Visual Instruction Set") }, \
- /* ??? These are deprecated, coerced to -mcpu=. Delete in 2.9. */ \
- {"cypress", 0, \
- N_("Optimize for Cypress processors") }, \
- {"sparclite", 0, \
- N_("Optimize for SPARCLite processors") }, \
- {"f930", 0, \
- N_("Optimize for F930 processors") }, \
- {"f934", 0, \
- N_("Optimize for F934 processors") }, \
- {"v8", 0, \
- N_("Use V8 SPARC ISA") }, \
- {"supersparc", 0, \
- N_("Optimize for SuperSPARC processors") }, \
- /* End of deprecated options. */ \
- {"ptr64", MASK_PTR64, \
- N_("Pointers are 64-bit") }, \
- {"ptr32", -MASK_PTR64, \
- N_("Pointers are 32-bit") }, \
- {"32", -MASK_64BIT, \
- N_("Use 32-bit ABI") }, \
- {"64", MASK_64BIT, \
- N_("Use 64-bit ABI") }, \
- {"stack-bias", MASK_STACK_BIAS, \
- N_("Use stack bias") }, \
- {"no-stack-bias", -MASK_STACK_BIAS, \
- N_("Do not use stack bias") }, \
- {"faster-structs", MASK_FASTER_STRUCTS, \
- N_("Use structs on stronger alignment for double-word copies") }, \
- {"no-faster-structs", -MASK_FASTER_STRUCTS, \
- N_("Do not use structs on stronger alignment for double-word copies") }, \
- {"relax", 0, \
- N_("Optimize tail call instructions in assembler and linker") }, \
- {"no-relax", 0, \
- N_("Do not optimize tail call instructions in assembler or linker") }, \
- SUBTARGET_SWITCHES \
- { "", TARGET_DEFAULT, ""}}
-
/* MASK_APP_REGS must always be the default because that's what
FIXED_REGISTERS is set to and -ffixed- is processed before
CONDITIONAL_REGISTER_USAGE is called (where we process -mno-app-regs). */
#define TARGET_DEFAULT (MASK_APP_REGS + MASK_FPU)
-/* This is meant to be redefined in target specific files. */
-#define SUBTARGET_SWITCHES
-
/* Processor type.
These must match the values for the cpu attribute in sparc.md. */
enum processor_type {
@@ -638,7 +532,8 @@ enum processor_type {
PROCESSOR_TSC701,
PROCESSOR_V9,
PROCESSOR_ULTRASPARC,
- PROCESSOR_ULTRASPARC3
+ PROCESSOR_ULTRASPARC3,
+ PROCESSOR_NIAGARA
};
/* This is set from -m{cpu,tune}=xxx. */
@@ -648,20 +543,6 @@ extern enum processor_type sparc_cpu;
Every file includes us, but not every file includes insn-attr.h. */
#define sparc_cpu_attr ((enum attr_cpu) sparc_cpu)
-#define TARGET_OPTIONS \
-{ \
- { "cpu=", &sparc_select[1].string, \
- N_("Use features of and schedule code for given CPU"), 0}, \
- { "tune=", &sparc_select[2].string, \
- N_("Schedule code for given CPU"), 0}, \
- { "cmodel=", &sparc_cmodel_string, \
- N_("Use given SPARC code model"), 0}, \
- SUBTARGET_OPTIONS \
-}
-
-/* This is meant to be redefined in target specific files. */
-#define SUBTARGET_OPTIONS
-
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-cpu is ignored if -mcpu is specified.
--with-tune is ignored if -mtune is specified.
@@ -714,6 +595,8 @@ extern struct sparc_cpu_select sparc_select[];
#define MIN_UNITS_PER_WORD 4
#endif
+#define UNITS_PER_SIMD_WORD (TARGET_VIS ? 8 : UNITS_PER_WORD)
+
/* Now define the sizes of the C data types. */
#define SHORT_TYPE_SIZE 16
@@ -722,18 +605,9 @@ extern struct sparc_cpu_select sparc_select[];
#define LONG_LONG_TYPE_SIZE 64
#define FLOAT_TYPE_SIZE 32
#define DOUBLE_TYPE_SIZE 64
-
-#ifdef SPARC_BI_ARCH
-#define MAX_LONG_TYPE_SIZE 64
-#endif
-
-#if 0
-/* ??? This does not work in SunOS 4.x, so it is not enabled here.
- Instead, it is enabled in sol2.h, because it does work under Solaris. */
-/* Define for support of TFmode long double.
- SPARC ABI says that long double is 4 words. */
-#define LONG_DOUBLE_TYPE_SIZE 128
-#endif
+/* LONG_DOUBLE_TYPE_SIZE is defined per OS even though the
+ SPARC ABI says that it is 128-bit wide. */
+/* #define LONG_DOUBLE_TYPE_SIZE 128 */
/* Width in bits of a pointer.
See also the macro `Pmode' defined below. */
@@ -744,54 +618,24 @@ extern struct sparc_cpu_select sparc_select[];
if ptr_mode and Pmode are the same. */
#define POINTERS_EXTEND_UNSIGNED 1
-/* A macro to update MODE and UNSIGNEDP when an object whose type
- is TYPE and which has the specified mode and signedness is to be
- stored in a register. This macro is only called when TYPE is a
- scalar type. */
-#define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE) \
-if (TARGET_ARCH64 \
- && GET_MODE_CLASS (MODE) == MODE_INT \
- && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
- (MODE) = DImode;
-
-/* Define this macro if the promotion described by PROMOTE_MODE
- should also be done for outgoing function arguments. */
-/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
- for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test
- for this value. */
-#define PROMOTE_FUNCTION_ARGS
-
-/* Define this macro if the promotion described by PROMOTE_MODE
- should also be done for the return value of functions.
- If this macro is defined, FUNCTION_VALUE must perform the same
- promotions done by PROMOTE_MODE. */
-/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
- for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test
- for this value. */
-#define PROMOTE_FUNCTION_RETURN
-
-/* Define this macro if the promotion described by PROMOTE_MODE
- should _only_ be performed for outgoing function arguments or
- function return values, as specified by PROMOTE_FUNCTION_ARGS
- and PROMOTE_FUNCTION_RETURN, respectively. */
-/* This is only needed for TARGET_ARCH64, but since PROMOTE_MODE is a no-op
- for TARGET_ARCH32 this is ok. Otherwise we'd need to add a runtime test
- for this value. For TARGET_ARCH64 we need it, as we don't have instructions
+/* For TARGET_ARCH64 we need this, as we don't have instructions
for arithmetic operations which do zero/sign extension at the same time,
so without this we end up with a srl/sra after every assignment to an
user variable, which means very very bad code. */
-#define PROMOTE_FOR_CALL_ONLY
+#define PROMOTE_FUNCTION_MODE(MODE, UNSIGNEDP, TYPE) \
+if (TARGET_ARCH64 \
+ && GET_MODE_CLASS (MODE) == MODE_INT \
+ && GET_MODE_SIZE (MODE) < UNITS_PER_WORD) \
+ (MODE) = word_mode;
/* Allocation boundary (in *bits*) for storing arguments in argument list. */
#define PARM_BOUNDARY (TARGET_ARCH64 ? 64 : 32)
/* Boundary (in *bits*) on which stack pointer should be aligned. */
/* FIXME, this is wrong when TARGET_ARCH64 and TARGET_STACK_BIAS, because
- then sp+2047 is 128-bit aligned so sp is really only byte-aligned. */
+ then %sp+2047 is 128-bit aligned so %sp is really only byte-aligned. */
#define STACK_BOUNDARY (TARGET_ARCH64 ? 128 : 64)
-/* Temporary hack until the FIXME above is fixed. This macro is used
- only in pad_to_arg_alignment in function.c; see the comment there
- for details about what it does. */
+/* Temporary hack until the FIXME above is fixed. */
#define SPARC_STACK_BOUNDARY_HACK (TARGET_ARCH64 && TARGET_STACK_BIAS)
/* ALIGN FRAMES on double word boundaries */
@@ -854,15 +698,6 @@ if (TARGET_ARCH64 \
because the linker fails to align the text section enough!
Put them in the data section. This macro is only used in this file. */
#define MAX_TEXT_ALIGN 32
-
-/* This forces all variables and constants to the data section when PIC.
- This is because the SunOS 4 shared library scheme thinks everything in
- text is a function, and patches the address to point to a loader stub. */
-/* This is defined to zero for every system which doesn't use the a.out object
- file format. */
-#ifndef SUNOS4_SHARED_LIBRARIES
-#define SUNOS4_SHARED_LIBRARIES 0
-#endif
/* Standard register usage. */
@@ -875,7 +710,7 @@ if (TARGET_ARCH64 \
SPARC has 32 integer registers and 32 floating point registers.
64 bit SPARC has 32 additional fp regs, but the odd numbered ones are not
accessible. We still account for them to simplify register computations
- (eg: in CLASS_MAX_NREGS). There are also 4 fp condition code registers, so
+ (e.g.: in CLASS_MAX_NREGS). There are also 4 fp condition code registers, so
32+32+32+4 == 100.
Register 100 is used as the integer condition code register.
Register 101 is used as the soft frame pointer register. */
@@ -900,7 +735,7 @@ if (TARGET_ARCH64 \
/* Argument passing regs. */
#define SPARC_OUTGOING_INT_ARG_FIRST 8
-#define SPARC_INCOMING_INT_ARG_FIRST (TARGET_FLAT ? 8 : 24)
+#define SPARC_INCOMING_INT_ARG_FIRST 24
#define SPARC_FP_ARG_FIRST 32
/* 1 for registers that have pervasive standard uses
@@ -1021,19 +856,6 @@ do \
fixed_regs[4] = 1; \
else if (fixed_regs[4] == 2) \
fixed_regs[4] = 0; \
- if (TARGET_FLAT) \
- { \
- int regno; \
- /* Let the compiler believe the frame pointer is still \
- %fp, but output it as %i7. */ \
- fixed_regs[31] = 1; \
- reg_names[HARD_FRAME_POINTER_REGNUM] = "%i7"; \
- /* Disable leaf functions */ \
- memset (sparc_leaf_regs, 0, FIRST_PSEUDO_REGISTER); \
- /* Make LEAF_REG_REMAP a noop. */ \
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) \
- leaf_reg_remap [regno] = regno; \
- } \
} \
while (0)
@@ -1071,6 +893,11 @@ extern int sparc_mode_class[];
#define HARD_REGNO_MODE_OK(REGNO, MODE) \
((hard_regno_mode_classes[REGNO] & sparc_mode_class[MODE]) != 0)
+/* Value is 1 if it is OK to rename a hard register FROM to another hard
+ register TO. We cannot rename %g1 as it may be used before the save
+ register window instruction in the prologue. */
+#define HARD_REGNO_RENAME_OK(FROM, TO) ((FROM) != 1)
+
/* 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,
@@ -1089,9 +916,6 @@ extern int sparc_mode_class[];
/* Specify the registers used for certain standard purposes.
The values of these macros are register numbers. */
-/* SPARC pc isn't overloaded on a register that the compiler knows about. */
-/* #define PC_REGNUM */
-
/* Register to use for pushing function arguments. */
#define STACK_POINTER_REGNUM 14
@@ -1125,17 +949,9 @@ extern int sparc_mode_class[];
/* 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.
- Used in flow.c, global.c, and reload1.c.
-
- Being a non-leaf function does not mean a frame pointer is needed in the
- flat window model. However, the debugger won't be able to backtrace through
- us with out it. */
-#define FRAME_POINTER_REQUIRED \
- (TARGET_FLAT \
- ? (current_function_calls_alloca \
- || !leaf_function_p ()) \
- : ! (leaf_function_p () && only_leaf_regs_used ()))
+ Used in flow.c, global.c, ra.c and reload1.c. */
+#define FRAME_POINTER_REQUIRED \
+ (! (leaf_function_p () && only_leaf_regs_used ()))
/* Base register for access to arguments of the function. */
#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM
@@ -1155,37 +971,12 @@ extern int sparc_mode_class[];
#define DEFAULT_PCC_STRUCT_RETURN -1
-/* SPARC ABI says that quad-precision floats and all structures are returned
- in memory.
- For v9: unions <= 32 bytes in size are returned in int regs,
- structures up to 32 bytes are returned in int and fp regs. */
-
-#define RETURN_IN_MEMORY(TYPE) \
-(TARGET_ARCH32 \
- ? (TYPE_MODE (TYPE) == BLKmode \
- || TYPE_MODE (TYPE) == TFmode) \
- : (TYPE_MODE (TYPE) == BLKmode \
- && (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) > 32))
-
/* Functions which return large structures get the address
to place the wanted value at offset 64 from the frame.
Must reserve 64 bytes for the in and local registers.
v9: Functions which return large structures get the address to place the
wanted value from an invisible first argument. */
-/* Used only in other #defines in this file. */
#define STRUCT_VALUE_OFFSET 64
-
-#define STRUCT_VALUE \
- (TARGET_ARCH64 \
- ? 0 \
- : gen_rtx_MEM (Pmode, plus_constant (stack_pointer_rtx, \
- STRUCT_VALUE_OFFSET)))
-
-#define STRUCT_VALUE_INCOMING \
- (TARGET_ARCH64 \
- ? 0 \
- : gen_rtx_MEM (Pmode, plus_constant (frame_pointer_rtx, \
- STRUCT_VALUE_OFFSET)))
/* Define the classes of registers for register constraints in the
machine description. Also define ranges of constants.
@@ -1224,11 +1015,12 @@ extern int sparc_mode_class[];
because reg_class_subunion[GENERAL_REGS][FP_REGS] will yield FP_REGS,
because FP_REGS > GENERAL_REGS.
- It is also important that one class contain all the general and all the
- fp regs. Otherwise when spilling a DFmode reg, it may be from EXTRA_FP_REGS
- but find_reloads() may use class GENERAL_OR_FP_REGS. This will cause
- allocate_reload_reg() to bypass it causing an abort because the compiler
- thinks it doesn't have a spill reg when in fact it does.
+ It is also important that one class contain all the general and all
+ the fp regs. Otherwise when spilling a DFmode reg, it may be from
+ EXTRA_FP_REGS but find_reloads() may use class
+ GENERAL_OR_FP_REGS. This will cause allocate_reload_reg() to die
+ because the compiler thinks it doesn't have a spill reg when in
+ fact it does.
v9 also has 4 floating point condition code registers. Since we don't
have a class that is the union of FPCC_REGS with either of the others,
@@ -1405,8 +1197,8 @@ extern char leaf_reg_remap[];
: (C) == 'c' ? FPCC_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.
+/* The letters I, J, K, L, M, N, O, P in a register constraint string
+ can be used to stand for particular ranges of CONST_INTs.
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.
@@ -1417,20 +1209,32 @@ extern char leaf_reg_remap[];
`L' is used for the range of constants supported by the movcc insns.
`M' is used for the range of constants supported by the movrcc insns.
`N' is like K, but for constants wider than 32 bits.
- `O' is used for the range which is just 4096. */
+ `O' is used for the range which is just 4096.
+ `P' is free. */
+/* Predicates for 10-bit, 11-bit and 13-bit signed constants. */
#define SPARC_SIMM10_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x200 < 0x400)
#define SPARC_SIMM11_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x400 < 0x800)
#define SPARC_SIMM13_P(X) ((unsigned HOST_WIDE_INT) (X) + 0x1000 < 0x2000)
-/* 10 and 11 bit immediates are only used for a few specific insns.
+
+/* 10- and 11-bit immediates are only used for a few specific insns.
SMALL_INT is used throughout the port so we continue to use it. */
#define SMALL_INT(X) (SPARC_SIMM13_P (INTVAL (X)))
-/* 13 bit immediate, considering only the low 32 bits */
-#define SMALL_INT32(X) (SPARC_SIMM13_P (trunc_int_for_mode \
- (INTVAL (X), SImode)))
+
+/* Predicate for constants that can be loaded with a sethi instruction.
+ This is the general, 64-bit aware, bitwise version that ensures that
+ only constants whose representation fits in the mask
+
+ 0x00000000fffffc00
+
+ are accepted. It will reject, for example, negative SImode constants
+ on 64-bit hosts, so correct handling is to mask the value beforehand
+ according to the mode of the instruction. */
#define SPARC_SETHI_P(X) \
(((unsigned HOST_WIDE_INT) (X) \
& ((unsigned HOST_WIDE_INT) 0x3ff - GET_MODE_MASK (SImode) - 1)) == 0)
+
+/* Version of the above predicate for SImode constants and below. */
#define SPARC_SETHI32_P(X) \
(SPARC_SETHI_P ((unsigned HOST_WIDE_INT) (X) & GET_MODE_MASK (SImode)))
@@ -1444,13 +1248,12 @@ extern char leaf_reg_remap[];
: (C) == 'O' ? (VALUE) == 4096 \
: 0)
-/* Similar, but for floating constants, and defining letters G and H.
+/* Similar, but for CONST_DOUBLEs, and defining letters G and H.
Here VALUE is the CONST_DOUBLE rtx itself. */
#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) \
- ((C) == 'G' ? fp_zero_operand (VALUE, GET_MODE (VALUE)) \
+ ((C) == 'G' ? const_zero_operand (VALUE, GET_MODE (VALUE)) \
: (C) == 'H' ? arith_double_operand (VALUE, DImode) \
- : (C) == 'O' ? arith_double_4096_operand (VALUE, DImode) \
: 0)
/* Given an rtx X being reloaded into a reg required to be
@@ -1473,7 +1276,7 @@ extern char leaf_reg_remap[];
|| (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \
&& ! TARGET_FPU) \
|| (GET_MODE (X) == TFmode \
- && ! fp_zero_operand (X, TFmode))) \
+ && ! const_zero_operand (X, TFmode))) \
? NO_REGS \
: (!FP_REG_CLASS_P (CLASS) \
&& GET_MODE_CLASS (GET_MODE (X)) == MODE_INT) \
@@ -1565,41 +1368,26 @@ extern char leaf_reg_remap[];
/* Stack layout; function entry, exit and calling. */
-/* Define the number of register that can hold parameters.
- This macro is only used in other macro definitions below and in sparc.c.
- MODE is the mode of the argument.
- !v9: All args are passed in %o0-%o5.
- v9: %o0-%o5 and %f0-%f31 are cumulatively used to pass values.
- See the description in sparc.c. */
-#define NPARM_REGS(MODE) \
-(TARGET_ARCH64 \
- ? (GET_MODE_CLASS (MODE) == MODE_FLOAT ? 32 : 6) \
- : 6)
-
/* 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
+/* Define this to nonzero if the nominal address of the stack frame
is at the high-address end of the local variables;
that is, each additional local variable allocated
goes at a more negative offset in the frame. */
-#define FRAME_GROWS_DOWNWARD
+#define FRAME_GROWS_DOWNWARD 1
/* Offset within stack frame to start allocating local variables at.
If FRAME_GROWS_DOWNWARD, this is the offset to the END of the
first local allocated. Otherwise, it is the offset to the BEGINNING
of the first local allocated. */
-/* This allows space for one TFmode floating point value. */
+/* This allows space for one TFmode floating point value, which is used
+ by SECONDARY_MEMORY_NEEDED_RTX. */
#define STARTING_FRAME_OFFSET \
(TARGET_ARCH64 ? -16 \
: (-SPARC_STACK_ALIGN (LONG_DOUBLE_TYPE_SIZE / BITS_PER_UNIT)))
-/* If we generate an insn to push BYTES bytes,
- this says how many the stack pointer really advances by.
- On SPARC, don't define this because there are no push insns. */
-/* #define PUSH_ROUNDING(BYTES) */
-
/* Offset of first parameter from the argument pointer register value.
!v9: This is 64 for the ins and locals, plus 4 for the struct-return reg
even if this function isn't going to use it.
@@ -1624,7 +1412,6 @@ extern char leaf_reg_remap[];
#define REG_PARM_STACK_SPACE(DECL) (6 * UNITS_PER_WORD)
/* Definitions for register elimination. */
-/* ??? In TARGET_FLAT mode we needn't have a hard frame pointer. */
#define ELIMINABLE_REGS \
{{ FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
@@ -1637,22 +1424,16 @@ extern char leaf_reg_remap[];
#define CAN_ELIMINATE(FROM, TO) \
((TO) == HARD_FRAME_POINTER_REGNUM || !FRAME_POINTER_REQUIRED)
-#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- do { \
- (OFFSET) = 0; \
- if ((TO) == STACK_POINTER_REGNUM) \
- { \
- /* Note, we always pretend that this is a leaf function \
- because if it's not, there's no point in trying to \
- eliminate the frame pointer. If it is a leaf \
- function, we guessed right! */ \
- if (TARGET_FLAT) \
- (OFFSET) = \
- sparc_flat_compute_frame_size (get_frame_size ()); \
- else \
- (OFFSET) = compute_frame_size (get_frame_size (), 1); \
- } \
- (OFFSET) += SPARC_STACK_BIAS; \
+/* We always pretend that this is a leaf function because if it's not,
+ there's no point in trying to eliminate the frame pointer. If it
+ is a leaf function, we guessed right! */
+#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
+ do { \
+ if ((TO) == STACK_POINTER_REGNUM) \
+ (OFFSET) = sparc_compute_frame_size (get_frame_size (), 1); \
+ else \
+ (OFFSET) = 0; \
+ (OFFSET) += SPARC_STACK_BIAS; \
} while (0)
/* Keep the stack pointer constant throughout the function.
@@ -1670,40 +1451,13 @@ extern char leaf_reg_remap[];
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-/* Some subroutine macros specific to this machine.
- When !TARGET_FPU, put float return values in the general registers,
- since we don't have any fp registers. */
-#define BASE_RETURN_VALUE_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
- : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32 : 8))
-
-#define BASE_OUTGOING_VALUE_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
- : TARGET_FLAT ? 8 : 24) \
- : (TARGET_FPU && FLOAT_MODE_P (MODE) && (MODE) != TFmode ? 32\
- : (TARGET_FLAT ? 8 : 24)))
-
-#define BASE_PASSING_ARG_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 : 8) \
- : 8)
-
-/* ??? FIXME -- seems wrong for v9 structure passing... */
-#define BASE_INCOMING_ARG_REG(MODE) \
- (TARGET_ARCH64 \
- ? (TARGET_FPU && FLOAT_MODE_P (MODE) ? 32 \
- : TARGET_FLAT ? 8 : 24) \
- : (TARGET_FLAT ? 8 : 24))
-
/* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the called function
corresponding to register number OUT as seen by the calling function.
Return OUT if register number OUT is not an outbound register. */
#define INCOMING_REGNO(OUT) \
- ((TARGET_FLAT || (OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
+ (((OUT) < 8 || (OUT) > 15) ? (OUT) : (OUT) + 16)
/* Define this macro if the target machine has "register windows". This
C expression returns the register number as seen by the calling function
@@ -1711,14 +1465,14 @@ extern char leaf_reg_remap[];
Return IN if register number IN is not an inbound register. */
#define OUTGOING_REGNO(IN) \
- ((TARGET_FLAT || (IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
+ (((IN) < 24 || (IN) > 31) ? (IN) : (IN) - 16)
/* Define this macro if the target machine has register windows. This
C expression returns true if the register is call-saved but is in the
register window. */
#define LOCAL_REGNO(REGNO) \
- (TARGET_FLAT ? 0 : (REGNO) >= 16 && (REGNO) <= 31)
+ ((REGNO) >= 16 && (REGNO) <= 31)
/* Define how to find the value returned by a function.
VALTYPE is the data type of the value (as a tree).
@@ -1751,7 +1505,7 @@ extern char leaf_reg_remap[];
/* Define the size of space to allocate for the return value of an
untyped_call. */
-#define APPLY_RESULT_SIZE 16
+#define APPLY_RESULT_SIZE (TARGET_ARCH64 ? 24 : 16)
/* 1 if N is a possible register number for function argument passing.
On SPARC, these are the "output" registers. v9 also uses %f0-%f31. */
@@ -1795,13 +1549,6 @@ init_cumulative_args (& (CUM), (FNTYPE), (LIBNAME), (FNDECL));
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
function_arg_advance (& (CUM), (MODE), (TYPE), (NAMED))
-/* Nonzero if we do not know how to pass TYPE solely in registers. */
-
-#define MUST_PASS_IN_STACK(MODE,TYPE) \
- ((TYPE) != 0 \
- && (TREE_CODE (TYPE_SIZE (TYPE)) != INTEGER_CST \
- || TREE_ADDRESSABLE (TYPE)))
-
/* Determine where to put an argument to a function.
Value is zero to push the argument on the stack,
or a hard register in which to store the argument.
@@ -1824,22 +1571,6 @@ function_arg (& (CUM), (MODE), (TYPE), (NAMED), 0)
#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
function_arg (& (CUM), (MODE), (TYPE), (NAMED), 1)
-/* 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) \
-function_arg_partial_nregs (& (CUM), (MODE), (TYPE), (NAMED))
-
-/* A C expression that indicates when an argument must be passed by reference.
- If nonzero for an argument, a copy of that argument is made in memory and a
- pointer to the argument is passed instead of the argument itself.
- The pointer is passed in whatever way is appropriate for passing a pointer
- to that type. */
-
-#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
-function_arg_pass_by_reference (& (CUM), (MODE), (TYPE), (NAMED))
-
/* If defined, a C expression which determines whether, and in which direction,
to pad out an argument with extra space. The value should be of type
`enum direction': either `upward' to pad above the argument,
@@ -1865,6 +1596,7 @@ function_arg_padding ((MODE), (TYPE))
extern GTY(()) rtx sparc_compare_op0;
extern GTY(()) rtx sparc_compare_op1;
+extern GTY(()) rtx sparc_compare_emitted;
/* Generate the special assembly code needed to tell the assembler whatever
@@ -1934,15 +1666,9 @@ do { \
(get_frame_size () != 0 \
|| current_function_calls_alloca || current_function_outgoing_args_size)
-#define DELAY_SLOTS_FOR_EPILOGUE \
- (TARGET_FLAT ? sparc_flat_epilogue_delay_slots () : 1)
-#define ELIGIBLE_FOR_EPILOGUE_DELAY(trial, slots_filled) \
- (TARGET_FLAT ? sparc_flat_eligible_for_epilogue_delay (trial, slots_filled) \
- : eligible_for_epilogue_delay (trial, slots_filled))
-
/* Define registers used by the epilogue and return instruction. */
-#define EPILOGUE_USES(REGNO) \
- (!TARGET_FLAT && REGNO == 31)
+#define EPILOGUE_USES(REGNO) ((REGNO) == 31 \
+ || (current_function_calls_eh_return && (REGNO) == 1))
/* Length in units of the trampoline for entering a nested function. */
@@ -1960,31 +1686,10 @@ do { \
else \
sparc_initialize_trampoline (TRAMP, FNADDR, CXT)
-/* Generate necessary RTL for __builtin_saveregs(). */
-
-#define EXPAND_BUILTIN_SAVEREGS() sparc_builtin_saveregs ()
-
/* Implement `va_start' for varargs and stdarg. */
#define EXPAND_BUILTIN_VA_START(valist, nextarg) \
sparc_va_start (valist, nextarg)
-/* Implement `va_arg'. */
-#define EXPAND_BUILTIN_VA_ARG(valist, type) \
- sparc_va_arg (valist, type)
-
-/* Define this macro if the location where a function argument is passed
- depends on whether or not it is a named argument.
-
- This macro controls how the NAMED argument to FUNCTION_ARG
- is set for varargs and stdarg functions. With this macro defined,
- the NAMED argument is always true for named arguments, and false for
- unnamed arguments. If this is not defined, but SETUP_INCOMING_VARARGS
- is defined, then all arguments are treated as named. Otherwise, all named
- arguments except the last are treated as named.
- For the v9 we want NAMED to mean what it says it means. */
-
-#define STRICT_ARGUMENT_NAMING TARGET_V9
-
/* Generate RTL to flush the register windows so as to make arbitrary frames
available. */
#define SETUP_FRAME_ADDRESSES() \
@@ -1992,11 +1697,14 @@ do { \
/* Given an rtx for the address of a frame,
return an rtx for the address of the word in the frame
- that holds the dynamic chain--the previous frame's address.
- ??? -mflat support? */
+ that holds the dynamic chain--the previous frame's address. */
#define DYNAMIC_CHAIN_ADDRESS(frame) \
plus_constant (frame, 14 * UNITS_PER_WORD + SPARC_STACK_BIAS)
+/* Given an rtx for the frame pointer,
+ return an rtx for the address of the frame. */
+#define FRAME_ADDR_RTX(frame) plus_constant (frame, SPARC_STACK_BIAS)
+
/* The return address isn't on the stack, it is in a register, so we can't
access it from the current frame pointer. We can access it from the
previous frame pointer though by reading a value from the register window
@@ -2168,7 +1876,9 @@ do { \
integer register, needed for ldd/std instructions.
'W' handles the memory operand when moving operands in/out
- of 'e' constraint floating point registers. */
+ of 'e' constraint floating point registers.
+
+ 'Y' handles the zero vector constant. */
#ifndef REG_OK_STRICT
@@ -2353,12 +2063,6 @@ do { \
(! TARGET_PTR64 ? SImode : flag_pic ? DImode : TARGET_CM_MEDLOW ? SImode : DImode)
#endif
-/* Define as C expression which evaluates to nonzero if the tablejump
- instruction expects the table to contain offsets from the address of the
- table.
- Do not define this if the table should contain absolute addresses. */
-/* #define CASE_VECTOR_PC_RELATIVE 1 */
-
/* Define this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 1
@@ -2366,15 +2070,10 @@ do { \
in one reasonably fast instruction. */
#define MOVE_MAX 8
-#if 0 /* Sun 4 has matherr, so this is no good. */
-/* This is the value of the error code EDOM for this machine,
- used by the sqrt instruction. */
-#define TARGET_EDOM 33
+/* If a memory-to-memory move would take MOVE_RATIO or more simple
+ move-instruction pairs, we will do a movmem or libcall instead. */
-/* This is how to refer to the variable errno. */
-#define GEN_ERRNO_RTX \
- gen_rtx_MEM (SImode, gen_rtx_SYMBOL_REF (Pmode, "errno"))
-#endif /* 0 */
+#define MOVE_RATIO (optimize_size ? 3 : 8)
/* Define if operations between registers always perform the operation
on the full register even if a narrower mode is specified. */
@@ -2383,7 +2082,7 @@ do { \
/* Define if loading in MODE, an integral mode narrower than BITS_PER_WORD
will either zero-extend or sign-extend. The value of this macro should
be the code that says which one of the two operations is implicitly
- done, NIL if none. */
+ done, UNKNOWN if none. */
#define LOAD_EXTEND_OP(MODE) ZERO_EXTEND
/* Nonzero if access to memory by bytes is slow and undesirable.
@@ -2392,9 +2091,6 @@ do { \
and maybe make use of that. */
#define SLOW_BYTE_ACCESS 1
-/* When a prototype says `char' or `short', really pass an `int'. */
-#define PROMOTE_PROTOTYPES (TARGET_ARCH32)
-
/* Define this to be nonzero if shift instructions ignore all but the low-order
few bits. */
#define SHIFT_COUNT_TRUNCATED 1
@@ -2406,9 +2102,6 @@ do { \
/* Specify the machine mode used for addresses. */
#define Pmode (TARGET_ARCH64 ? DImode : SImode)
-/* Generate calls to memcpy, memcmp and memset. */
-#define TARGET_MEM_FUNCTIONS
-
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CC_NOOVmode should be used when the first operand
@@ -2457,7 +2150,8 @@ do { \
|| (GENERAL_OR_I64 (CLASS1) && FP_REG_CLASS_P (CLASS2)) \
|| (CLASS1) == FPCC_REGS || (CLASS2) == FPCC_REGS) \
? ((sparc_cpu == PROCESSOR_ULTRASPARC \
- || sparc_cpu == PROCESSOR_ULTRASPARC3) ? 12 : 6) : 2)
+ || sparc_cpu == PROCESSOR_ULTRASPARC3 \
+ || sparc_cpu == PROCESSOR_NIAGARA) ? 12 : 6) : 2)
/* Provide the cost of a branch. For pre-v9 processors we use
a value of 3 to take into account the potential annulling of
@@ -2467,22 +2161,30 @@ do { \
On v9 and later, which have branch prediction facilities, we set
it to the depth of the pipeline as that is the cost of a
- mispredicted branch. */
+ mispredicted branch.
+
+ On Niagara, normal branches insert 3 bubbles into the pipe
+ and annulled branches insert 4 bubbles. */
#define BRANCH_COST \
((sparc_cpu == PROCESSOR_V9 \
|| sparc_cpu == PROCESSOR_ULTRASPARC) \
? 7 \
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
- ? 9 : 3))
+ ? 9 \
+ : (sparc_cpu == PROCESSOR_NIAGARA \
+ ? 4 \
+ : 3)))
#define PREFETCH_BLOCK \
((sparc_cpu == PROCESSOR_ULTRASPARC \
- || sparc_cpu == PROCESSOR_ULTRASPARC3) \
+ || sparc_cpu == PROCESSOR_ULTRASPARC3 \
+ || sparc_cpu == PROCESSOR_NIAGARA) \
? 64 : 32)
#define SIMULTANEOUS_PREFETCHES \
- ((sparc_cpu == PROCESSOR_ULTRASPARC) \
+ ((sparc_cpu == PROCESSOR_ULTRASPARC \
+ || sparc_cpu == PROCESSOR_NIAGARA) \
? 2 \
: (sparc_cpu == PROCESSOR_ULTRASPARC3 \
? 8 : 3))
@@ -2505,12 +2207,6 @@ do { \
#define ASM_APP_OFF ""
-/* ??? Try to make the style consistent here (_OP?). */
-
-#define ASM_FLOAT ".single"
-#define ASM_DOUBLE ".double"
-#define ASM_LONGDOUBLE ".xxx" /* ??? Not known (or used yet). */
-
/* How to refer to registers in assembler output.
This sequence is indexed by compiler's hard-register-number (see above). */
@@ -2666,16 +2362,25 @@ do { \
#define ASM_OUTPUT_IDENT(FILE, NAME) \
fprintf (FILE, "%s\"%s\"\n", IDENT_ASM_OP, NAME);
-/* Emit a dtp-relative reference to a TLS variable. */
+/* Prettify the assembly. */
-#ifdef HAVE_AS_TLS
-#define ASM_OUTPUT_DWARF_DTPREL(FILE, SIZE, X) \
- sparc_output_dwarf_dtprel (FILE, SIZE, X)
-#endif
+extern int sparc_indent_opcode;
+
+#define ASM_OUTPUT_OPCODE(FILE, PTR) \
+ do { \
+ if (sparc_indent_opcode) \
+ { \
+ putc (' ', FILE); \
+ sparc_indent_opcode = 0; \
+ } \
+ } while (0)
+
+#define SPARC_SYMBOL_REF_TLS_P(RTX) \
+ (GET_CODE (RTX) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (RTX) != 0)
#define PRINT_OPERAND_PUNCT_VALID_P(CHAR) \
- ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '^' \
- || (CHAR) == '(' || (CHAR) == '_' || (CHAR) == '&')
+ ((CHAR) == '#' || (CHAR) == '*' || (CHAR) == '(' \
+ || (CHAR) == ')' || (CHAR) == '_' || (CHAR) == '&')
/* Print operand X (an rtx) in assembler syntax to file FILE.
CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
@@ -2701,10 +2406,9 @@ do { \
base = XEXP (addr, 0), index = XEXP (addr, 1); \
if (GET_CODE (base) == LO_SUM) \
{ \
- if (! USE_AS_OFFSETABLE_LO10 \
- || TARGET_ARCH32 \
- || TARGET_CM_MEDMID) \
- abort (); \
+ gcc_assert (USE_AS_OFFSETABLE_LO10 \
+ && TARGET_ARCH64 \
+ && ! TARGET_CM_MEDMID); \
output_operand (XEXP (base, 0), 0); \
fputs ("+%lo(", FILE); \
output_address (XEXP (base, 1)); \
@@ -2720,7 +2424,7 @@ do { \
else if (GET_CODE (index) == SYMBOL_REF \
|| GET_CODE (index) == CONST) \
fputc ('+', FILE), output_addr_const (FILE, index); \
- else abort (); \
+ else gcc_unreachable (); \
} \
} \
else if (GET_CODE (addr) == MINUS \
@@ -2762,69 +2466,16 @@ do { \
} \
}
+/* TLS support defaulting to original Sun flavor. GNU extensions
+ must be activated in separate configuration files. */
#ifdef HAVE_AS_TLS
#define TARGET_TLS 1
#else
#define TARGET_TLS 0
#endif
+
#define TARGET_SUN_TLS TARGET_TLS
#define TARGET_GNU_TLS 0
-/* Define the codes that are matched by predicates in sparc.c. */
-
-#define PREDICATE_CODES \
-{"reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"const1_operand", {CONST_INT}}, \
-{"fp_zero_operand", {CONST_DOUBLE}}, \
-{"fp_register_operand", {SUBREG, REG}}, \
-{"intreg_operand", {SUBREG, REG}}, \
-{"fcc_reg_operand", {REG}}, \
-{"fcc0_reg_operand", {REG}}, \
-{"icc_or_fcc_reg_operand", {REG}}, \
-{"restore_operand", {REG}}, \
-{"call_operand", {MEM}}, \
-{"call_operand_address", {SYMBOL_REF, LABEL_REF, CONST, CONST_DOUBLE, \
- ADDRESSOF, SUBREG, REG, PLUS, LO_SUM, CONST_INT}}, \
-{"symbolic_operand", {SYMBOL_REF, LABEL_REF, CONST}}, \
-{"symbolic_memory_operand", {SUBREG, MEM}}, \
-{"label_ref_operand", {LABEL_REF}}, \
-{"sp64_medium_pic_operand", {CONST}}, \
-{"data_segment_operand", {SYMBOL_REF, PLUS, CONST}}, \
-{"text_segment_operand", {LABEL_REF, SYMBOL_REF, PLUS, CONST}}, \
-{"reg_or_nonsymb_mem_operand", {SUBREG, REG, MEM}}, \
-{"splittable_symbolic_memory_operand", {MEM}}, \
-{"splittable_immediate_memory_operand", {MEM}}, \
-{"eq_or_neq", {EQ, NE}}, \
-{"normal_comp_operator", {GE, GT, LE, LT, GTU, LEU}}, \
-{"noov_compare_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
-{"noov_compare64_op", {NE, EQ, GE, GT, LE, LT, GEU, GTU, LEU, LTU}}, \
-{"v9_regcmp_op", {EQ, NE, GE, LT, LE, GT}}, \
-{"extend_op", {SIGN_EXTEND, ZERO_EXTEND}}, \
-{"cc_arithop", {AND, IOR, XOR}}, \
-{"cc_arithopn", {AND, IOR}}, \
-{"arith_operand", {SUBREG, REG, CONST_INT}}, \
-{"arith_add_operand", {SUBREG, REG, CONST_INT}}, \
-{"arith11_operand", {SUBREG, REG, CONST_INT}}, \
-{"arith10_operand", {SUBREG, REG, CONST_INT}}, \
-{"arith_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"arith_double_add_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"arith11_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"arith10_double_operand", {SUBREG, REG, CONST_INT, CONST_DOUBLE}}, \
-{"small_int", {CONST_INT}}, \
-{"small_int_or_double", {CONST_INT, CONST_DOUBLE}}, \
-{"uns_small_int", {CONST_INT}}, \
-{"uns_arith_operand", {SUBREG, REG, CONST_INT}}, \
-{"clobbered_register", {REG}}, \
-{"input_operand", {SUBREG, REG, CONST_INT, MEM, CONST}}, \
-{"compare_operand", {SUBREG, REG, ZERO_EXTRACT}}, \
-{"const64_operand", {CONST_INT, CONST_DOUBLE}}, \
-{"const64_high_operand", {CONST_INT, CONST_DOUBLE}}, \
-{"tgd_symbolic_operand", {SYMBOL_REF}}, \
-{"tld_symbolic_operand", {SYMBOL_REF}}, \
-{"tie_symbolic_operand", {SYMBOL_REF}}, \
-{"tle_symbolic_operand", {SYMBOL_REF}},
-
/* The number of Pmode words for the setjmp buffer. */
#define JMP_BUF_SIZE 12
-
-#define DONT_ACCESS_GBLS_AFTER_EPILOGUE (flag_pic)
diff --git a/contrib/gcc/config/sparc/sparc.md b/contrib/gcc/config/sparc/sparc.md
index b50d10a..ed68f1e 100644
--- a/contrib/gcc/config/sparc/sparc.md
+++ b/contrib/gcc/config/sparc/sparc.md
@@ -1,6 +1,6 @@
;; Machine description for SPARC chip for GCC
;; Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-;; 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+;; 1999, 2000, 2001, 2002, 2003, 2004, 2005,2006 Free Software Foundation, Inc.
;; Contributed by Michael Tiemann (tiemann@cygnus.com)
;; 64-bit SPARC-V9 support by Michael Tiemann, Jim Wilson, and Doug Evans,
;; at Cygnus Support.
@@ -19,15 +19,15 @@
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
(define_constants
[(UNSPEC_MOVE_PIC 0)
(UNSPEC_UPDATE_RETURN 1)
- (UNSPEC_GET_PC 2)
+ (UNSPEC_LOAD_PCREL_SYM 2)
(UNSPEC_MOVE_PIC_LABEL 5)
(UNSPEC_SETH44 6)
(UNSPEC_SETM44 7)
@@ -45,15 +45,34 @@
(UNSPEC_TLSIE 33)
(UNSPEC_TLSLE 34)
(UNSPEC_TLSLD_BASE 35)
+
+ (UNSPEC_FPACK16 40)
+ (UNSPEC_FPACK32 41)
+ (UNSPEC_FPACKFIX 42)
+ (UNSPEC_FEXPAND 43)
+ (UNSPEC_FPMERGE 44)
+ (UNSPEC_MUL16AL 45)
+ (UNSPEC_MUL8UL 46)
+ (UNSPEC_MULDUL 47)
+ (UNSPEC_ALIGNDATA 48)
+ (UNSPEC_ALIGNADDR 49)
+ (UNSPEC_PDIST 50)
+
+ (UNSPEC_SP_SET 60)
+ (UNSPEC_SP_TEST 61)
])
(define_constants
[(UNSPECV_BLOCKAGE 0)
(UNSPECV_FLUSHW 1)
(UNSPECV_GOTO 2)
- (UNSPECV_GOTO_V9 3)
(UNSPECV_FLUSH 4)
(UNSPECV_SETJMP 5)
+ (UNSPECV_SAVEW 6)
+ (UNSPECV_MEMBAR 7)
+ (UNSPECV_CAS 8)
+ (UNSPECV_SWAP 9)
+ (UNSPECV_LDSTUB 10)
])
;; The upper 32 fp regs on the v9 can't hold SFmode values. To deal with this
@@ -62,6 +81,7 @@
;; constraint letter is 'e'. To avoid any confusion, 'e' is used instead of
;; 'f' for all DF/TFmode values, including those that are specific to the v8.
+
;; Attribute for cpu type.
;; These must match the values for enum processor_type in sparc.h.
(define_attr "cpu"
@@ -74,31 +94,25 @@
sparclet,tsc701,
v9,
ultrasparc,
- ultrasparc3"
+ ultrasparc3,
+ niagara"
(const (symbol_ref "sparc_cpu_attr")))
;; Attribute for the instruction set.
;; At present we only need to distinguish v9/!v9, but for clarity we
;; test TARGET_V8 too.
-(define_attr "isa" "v6,v8,v9,sparclet"
+(define_attr "isa" "v7,v8,v9,sparclet"
(const
(cond [(symbol_ref "TARGET_V9") (const_string "v9")
(symbol_ref "TARGET_V8") (const_string "v8")
(symbol_ref "TARGET_SPARCLET") (const_string "sparclet")]
- (const_string "v6"))))
-
-;; Architecture size.
-(define_attr "arch" "arch32bit,arch64bit"
- (const
- (cond [(symbol_ref "TARGET_ARCH64") (const_string "arch64bit")]
- (const_string "arch32bit"))))
+ (const_string "v7"))))
;; Insn type.
-
(define_attr "type"
"ialu,compare,shift,
load,sload,store,
- uncond_branch,branch,call,sibcall,call_no_delay_slot,
+ uncond_branch,branch,call,sibcall,call_no_delay_slot,return,
imul,idiv,
fpload,fpstore,
fp,fpmove,
@@ -109,34 +123,49 @@
fga,fgm_pack,fgm_mul,fgm_pdist,fgm_cmp,
cmove,
ialuX,
- multi,flushw,iflush,trap"
+ multi,savew,flushw,iflush,trap"
(const_string "ialu"))
-;; true if branch/call has empty delay slot and will emit a nop in it
+;; True if branch/call has empty delay slot and will emit a nop in it
(define_attr "empty_delay_slot" "false,true"
(symbol_ref "empty_delay_slot (insn)"))
-(define_attr "branch_type" "none,icc,fcc,reg" (const_string "none"))
+(define_attr "branch_type" "none,icc,fcc,reg"
+ (const_string "none"))
(define_attr "pic" "false,true"
(symbol_ref "flag_pic != 0"))
-(define_attr "current_function_calls_alloca" "false,true"
+(define_attr "calls_alloca" "false,true"
(symbol_ref "current_function_calls_alloca != 0"))
-(define_attr "flat" "false,true"
- (symbol_ref "TARGET_FLAT != 0"))
+(define_attr "calls_eh_return" "false,true"
+ (symbol_ref "current_function_calls_eh_return !=0 "))
+
+(define_attr "leaf_function" "false,true"
+ (symbol_ref "current_function_uses_only_leaf_regs != 0"))
+
+(define_attr "delayed_branch" "false,true"
+ (symbol_ref "flag_delayed_branch != 0"))
;; Length (in # of insns).
;; Beware that setting a length greater or equal to 3 for conditional branches
;; has a side-effect (see output_cbranch and output_v9branch).
(define_attr "length" ""
- (cond [(eq_attr "type" "uncond_branch,call,sibcall")
+ (cond [(eq_attr "type" "uncond_branch,call")
(if_then_else (eq_attr "empty_delay_slot" "true")
(const_int 2)
(const_int 1))
+ (eq_attr "type" "sibcall")
+ (if_then_else (eq_attr "leaf_function" "true")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 3)
+ (const_int 2))
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1)))
(eq_attr "branch_type" "icc")
- (if_then_else (match_operand 0 "noov_compare64_op" "")
+ (if_then_else (match_operand 0 "noov_compare64_operator" "")
(if_then_else (lt (pc) (match_dup 1))
(if_then_else (lt (minus (match_dup 1) (pc)) (const_int 260000))
(if_then_else (eq_attr "empty_delay_slot" "true")
@@ -156,7 +185,7 @@
(const_int 2)
(const_int 1)))
(eq_attr "branch_type" "fcc")
- (if_then_else (match_operand 0 "fcc0_reg_operand" "")
+ (if_then_else (match_operand 0 "fcc0_register_operand" "")
(if_then_else (eq_attr "empty_delay_slot" "true")
(if_then_else (eq (symbol_ref "TARGET_V9") (const_int 0))
(const_int 3)
@@ -198,17 +227,18 @@
] (const_int 1)))
;; FP precision.
-(define_attr "fptype" "single,double" (const_string "single"))
+(define_attr "fptype" "single,double"
+ (const_string "single"))
;; UltraSPARC-III integer load type.
-(define_attr "us3load_type" "2cycle,3cycle" (const_string "2cycle"))
+(define_attr "us3load_type" "2cycle,3cycle"
+ (const_string "2cycle"))
(define_asm_attributes
[(set_attr "length" "2")
(set_attr "type" "multi")])
;; Attributes for instruction and branch scheduling
-
(define_attr "tls_call_delay" "false,true"
(symbol_ref "tls_call_delay (insn)"))
@@ -224,19 +254,13 @@
(const_string "true")
(const_string "false"))))
-(define_delay (eq_attr "type" "call")
- [(eq_attr "in_call_delay" "true") (nil) (nil)])
-
(define_attr "eligible_for_sibcall_delay" "false,true"
(symbol_ref "eligible_for_sibcall_delay (insn)"))
-(define_delay (eq_attr "type" "sibcall")
- [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
-
-(define_attr "leaf_function" "false,true"
- (const (symbol_ref "current_function_uses_only_leaf_regs")))
+(define_attr "eligible_for_return_delay" "false,true"
+ (symbol_ref "eligible_for_return_delay (insn)"))
-;; ??? Should implement the notion of predelay slots for floating point
+;; ??? !v9: Should implement the notion of predelay slots for floating-point
;; branches. This would allow us to remove the nop always inserted before
;; a floating point branch.
@@ -266,6 +290,12 @@
(const_string "true")
(const_string "false")))
+(define_delay (eq_attr "type" "call")
+ [(eq_attr "in_call_delay" "true") (nil) (nil)])
+
+(define_delay (eq_attr "type" "sibcall")
+ [(eq_attr "eligible_for_sibcall_delay" "true") (nil) (nil)])
+
(define_delay (eq_attr "type" "branch")
[(eq_attr "in_branch_delay" "true")
(nil) (eq_attr "in_annul_branch_delay" "true")])
@@ -273,7 +303,11 @@
(define_delay (eq_attr "type" "uncond_branch")
[(eq_attr "in_uncond_branch_delay" "true")
(nil) (nil)])
-
+
+(define_delay (eq_attr "type" "return")
+ [(eq_attr "eligible_for_return_delay" "true") (nil) (nil)])
+
+
;; Include SPARC DFA schedulers
(include "cypress.md")
@@ -282,10 +316,15 @@
(include "sparclet.md")
(include "ultra1_2.md")
(include "ultra3.md")
+(include "niagara.md")
+
+
+;; Operand and operator predicates.
+
+(include "predicates.md")
+
-
;; Compare instructions.
-;; This controls RTL generation and register allocation.
;; We generate RTL for comparisons and branches by having the cmpxx
;; patterns store away the operands. Then, the scc and bcc patterns
@@ -300,8 +339,6 @@
;; the patterns. Finally, we have the DEFINE_SPLITs for some of the scc
;; insns that actually require more than one machine instruction.
-;; Put cmpsi first among compare insns so it matches two CONST_INT operands.
-
(define_expand "cmpsi"
[(set (reg:CC 100)
(compare:CC (match_operand:SI 0 "compare_operand" "")
@@ -319,7 +356,7 @@
(define_expand "cmpdi"
[(set (reg:CCX 100)
(compare:CCX (match_operand:DI 0 "compare_operand" "")
- (match_operand:DI 1 "arith_double_operand" "")))]
+ (match_operand:DI 1 "arith_operand" "")))]
"TARGET_ARCH64"
{
if (GET_CODE (operands[0]) == ZERO_EXTRACT && operands[1] != const0_rtx)
@@ -379,13 +416,13 @@
(define_insn "*cmpdi_sp64"
[(set (reg:CCX 100)
(compare:CCX (match_operand:DI 0 "register_operand" "r")
- (match_operand:DI 1 "arith_double_operand" "rHI")))]
+ (match_operand:DI 1 "arith_operand" "rI")))]
"TARGET_ARCH64"
"cmp\t%0, %1"
[(set_attr "type" "compare")])
(define_insn "*cmpsf_fpe"
- [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
(compare:CCFPE (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
@@ -397,7 +434,7 @@
[(set_attr "type" "fpcmp")])
(define_insn "*cmpdf_fpe"
- [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
(compare:CCFPE (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
@@ -410,7 +447,7 @@
(set_attr "fptype" "double")])
(define_insn "*cmptf_fpe"
- [(set (match_operand:CCFPE 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFPE 0 "fcc_register_operand" "=c")
(compare:CCFPE (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
@@ -422,7 +459,7 @@
[(set_attr "type" "fpcmp")])
(define_insn "*cmpsf_fp"
- [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
(compare:CCFP (match_operand:SF 1 "register_operand" "f")
(match_operand:SF 2 "register_operand" "f")))]
"TARGET_FPU"
@@ -434,7 +471,7 @@
[(set_attr "type" "fpcmp")])
(define_insn "*cmpdf_fp"
- [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
(compare:CCFP (match_operand:DF 1 "register_operand" "e")
(match_operand:DF 2 "register_operand" "e")))]
"TARGET_FPU"
@@ -447,7 +484,7 @@
(set_attr "fptype" "double")])
(define_insn "*cmptf_fp"
- [(set (match_operand:CCFP 0 "fcc_reg_operand" "=c")
+ [(set (match_operand:CCFP 0 "fcc_register_operand" "=c")
(compare:CCFP (match_operand:TF 1 "register_operand" "e")
(match_operand:TF 2 "register_operand" "e")))]
"TARGET_FPU && TARGET_HARD_QUAD"
@@ -547,7 +584,7 @@
;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
;; However, the code handles both SImode and DImode.
(define_expand "seq"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(eq:SI (match_dup 1) (const_int 0)))]
""
{
@@ -599,7 +636,7 @@
;; ??? v9: Operand 0 needs a mode, so SImode was chosen.
;; However, the code handles both SImode and DImode.
(define_expand "sne"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(ne:SI (match_dup 1) (const_int 0)))]
""
{
@@ -649,7 +686,7 @@
})
(define_expand "sgt"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(gt:SI (match_dup 1) (const_int 0)))]
""
{
@@ -669,7 +706,7 @@
})
(define_expand "slt"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(lt:SI (match_dup 1) (const_int 0)))]
""
{
@@ -689,7 +726,7 @@
})
(define_expand "sge"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(ge:SI (match_dup 1) (const_int 0)))]
""
{
@@ -709,7 +746,7 @@
})
(define_expand "sle"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(le:SI (match_dup 1) (const_int 0)))]
""
{
@@ -729,7 +766,7 @@
})
(define_expand "sgtu"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(gtu:SI (match_dup 1) (const_int 0)))]
""
{
@@ -763,7 +800,7 @@
})
(define_expand "sltu"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(ltu:SI (match_dup 1) (const_int 0)))]
""
{
@@ -772,11 +809,11 @@
if (gen_v9_scc (LTU, operands))
DONE;
}
- operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LTU);
})
(define_expand "sgeu"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(geu:SI (match_dup 1) (const_int 0)))]
""
{
@@ -785,11 +822,11 @@
if (gen_v9_scc (GEU, operands))
DONE;
}
- operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (GEU);
})
(define_expand "sleu"
- [(set (match_operand:SI 0 "intreg_operand" "")
+ [(set (match_operand:SI 0 "int_register_operand" "")
(leu:SI (match_dup 1) (const_int 0)))]
""
{
@@ -826,7 +863,7 @@
;; The SEQ and SNE patterns are special because they can be done
;; without any branching and do not involve a COMPARE. We want
-;; them to always use the splitz below so the results can be
+;; them to always use the splits below so the results can be
;; scheduled.
(define_insn_and_split "*snesi_zero"
@@ -1160,7 +1197,7 @@
;; ??? Combine should canonicalize these next two to the same pattern.
(define_insn "*x_minus_y_minus_sltu"
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC 100) (const_int 0))))]
""
@@ -1169,7 +1206,7 @@
(define_insn "*x_minus_sltu_plus_y"
[(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
(plus:SI (ltu:SI (reg:CC 100) (const_int 0))
(match_operand:SI 2 "arith_operand" "rI"))))]
""
@@ -1194,12 +1231,13 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
- (match_operator:SI 2 "noov_compare_op"
- [(match_operand 1 "icc_or_fcc_reg_operand" "")
+ (match_operator:SI 2 "noov_compare_operator"
+ [(match_operand 1 "icc_or_fcc_register_operand" "")
(const_int 0)]))]
- ;; 32 bit LTU/GEU are better implemented using addx/subx
- "TARGET_V9 && REGNO (operands[1]) == SPARC_ICC_REG
+ "TARGET_V9
+ && REGNO (operands[1]) == SPARC_ICC_REG
&& (GET_MODE (operands[1]) == CCXmode
+ /* 32 bit LTU/GEU are better implemented using addx/subx. */
|| (GET_CODE (operands[2]) != LTU && GET_CODE (operands[2]) != GEU))"
[(set (match_dup 0) (const_int 0))
(set (match_dup 0)
@@ -1235,7 +1273,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (EQ, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (EQ);
})
(define_expand "bne"
@@ -1258,7 +1296,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (NE, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (NE);
})
(define_expand "bgt"
@@ -1281,7 +1319,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (GT, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (GT);
})
(define_expand "bgtu"
@@ -1291,7 +1329,7 @@
(pc)))]
""
{
- operands[1] = gen_compare_reg (GTU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (GTU);
})
(define_expand "blt"
@@ -1314,7 +1352,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (LT, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LT);
})
(define_expand "bltu"
@@ -1324,7 +1362,7 @@
(pc)))]
""
{
- operands[1] = gen_compare_reg (LTU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LTU);
})
(define_expand "bge"
@@ -1347,7 +1385,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (GE, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (GE);
})
(define_expand "bgeu"
@@ -1357,7 +1395,7 @@
(pc)))]
""
{
- operands[1] = gen_compare_reg (GEU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (GEU);
})
(define_expand "ble"
@@ -1380,7 +1418,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (LE, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LE);
})
(define_expand "bleu"
@@ -1390,7 +1428,7 @@
(pc)))]
""
{
- operands[1] = gen_compare_reg (LEU, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LEU);
})
(define_expand "bunordered"
@@ -1407,8 +1445,7 @@
emit_jump_insn (gen_beq (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNORDERED, sparc_compare_op0,
- sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNORDERED);
})
(define_expand "bordered"
@@ -1424,8 +1461,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (ORDERED, sparc_compare_op0,
- sparc_compare_op1);
+ operands[1] = gen_compare_reg (ORDERED);
})
(define_expand "bungt"
@@ -1441,7 +1477,7 @@
emit_jump_insn (gen_bgt (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNGT, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNGT);
})
(define_expand "bunlt"
@@ -1457,7 +1493,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNLT, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNLT);
})
(define_expand "buneq"
@@ -1473,7 +1509,7 @@
emit_jump_insn (gen_beq (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNEQ, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNEQ);
})
(define_expand "bunge"
@@ -1489,7 +1525,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNGE, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNGE);
})
(define_expand "bunle"
@@ -1505,7 +1541,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (UNLE, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (UNLE);
})
(define_expand "bltgt"
@@ -1521,7 +1557,7 @@
emit_jump_insn (gen_bne (operands[0]));
DONE;
}
- operands[1] = gen_compare_reg (LTGT, sparc_compare_op0, sparc_compare_op1);
+ operands[1] = gen_compare_reg (LTGT);
})
;; Now match both normal and inverted jump.
@@ -1529,7 +1565,7 @@
;; XXX fpcmp nop braindamage
(define_insn "*normal_branch"
[(set (pc)
- (if_then_else (match_operator 0 "noov_compare_op"
+ (if_then_else (match_operator 0 "noov_compare_operator"
[(reg 100) (const_int 0)])
(label_ref (match_operand 1 "" ""))
(pc)))]
@@ -1537,7 +1573,7 @@
{
return output_cbranch (operands[0], operands[1], 1, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1545,7 +1581,7 @@
;; XXX fpcmp nop braindamage
(define_insn "*inverted_branch"
[(set (pc)
- (if_then_else (match_operator 0 "noov_compare_op"
+ (if_then_else (match_operator 0 "noov_compare_operator"
[(reg 100) (const_int 0)])
(pc)
(label_ref (match_operand 1 "" ""))))]
@@ -1553,7 +1589,7 @@
{
return output_cbranch (operands[0], operands[1], 1, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "icc")])
@@ -1562,7 +1598,7 @@
(define_insn "*normal_fp_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 0 "fcc_reg_operand" "c")
+ [(match_operand:CCFP 0 "fcc_register_operand" "c")
(const_int 0)])
(label_ref (match_operand 2 "" ""))
(pc)))]
@@ -1570,7 +1606,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1579,7 +1615,7 @@
(define_insn "*inverted_fp_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFP 0 "fcc_reg_operand" "c")
+ [(match_operand:CCFP 0 "fcc_register_operand" "c")
(const_int 0)])
(pc)
(label_ref (match_operand 2 "" ""))))]
@@ -1587,7 +1623,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1596,7 +1632,7 @@
(define_insn "*normal_fpe_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
+ [(match_operand:CCFPE 0 "fcc_register_operand" "c")
(const_int 0)])
(label_ref (match_operand 2 "" ""))
(pc)))]
@@ -1604,7 +1640,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1613,7 +1649,7 @@
(define_insn "*inverted_fpe_branch"
[(set (pc)
(if_then_else (match_operator 1 "comparison_operator"
- [(match_operand:CCFPE 0 "fcc_reg_operand" "c")
+ [(match_operand:CCFPE 0 "fcc_register_operand" "c")
(const_int 0)])
(pc)
(label_ref (match_operand 2 "" ""))))]
@@ -1621,7 +1657,7 @@
{
return output_cbranch (operands[1], operands[2], 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "fcc")])
@@ -1634,7 +1670,7 @@
;; XXX
(define_insn "*normal_int_branch_sp64"
[(set (pc)
- (if_then_else (match_operator 0 "v9_regcmp_op"
+ (if_then_else (match_operator 0 "v9_register_compare_operator"
[(match_operand:DI 1 "register_operand" "r")
(const_int 0)])
(label_ref (match_operand 2 "" ""))
@@ -1643,7 +1679,7 @@
{
return output_v9branch (operands[0], operands[2], 1, 2, 0,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
@@ -1651,7 +1687,7 @@
;; XXX
(define_insn "*inverted_int_branch_sp64"
[(set (pc)
- (if_then_else (match_operator 0 "v9_regcmp_op"
+ (if_then_else (match_operator 0 "v9_register_compare_operator"
[(match_operand:DI 1 "register_operand" "r")
(const_int 0)])
(pc)
@@ -1660,84 +1696,53 @@
{
return output_v9branch (operands[0], operands[2], 1, 2, 1,
final_sequence && INSN_ANNULLED_BRANCH_P (insn),
- ! final_sequence, insn);
+ insn);
}
[(set_attr "type" "branch")
(set_attr "branch_type" "reg")])
-
-;; Load program counter insns.
-
-(define_insn "get_pc"
- [(clobber (reg:SI 15))
- (set (match_operand 0 "register_operand" "=r")
- (unspec [(match_operand 1 "" "") (match_operand 2 "" "")] UNSPEC_GET_PC))]
- "flag_pic && REGNO (operands[0]) == 23"
- "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\tadd\t%0, %%lo(%a1+4), %0"
- [(set_attr "type" "multi")
- (set_attr "length" "3")])
-
-
-;; Move instructions
-
-(define_expand "movqi"
- [(set (match_operand:QI 0 "general_operand" "")
- (match_operand:QI 1 "general_operand" ""))]
- ""
-{
- /* Working with CONST_INTs is easier, so convert
- a double if needed. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- {
- operands[1] = GEN_INT (trunc_int_for_mode
- (CONST_DOUBLE_LOW (operands[1]), QImode));
- }
- /* Handle sets of MEM first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (reg_or_0_operand (operands[1], QImode))
- goto movqi_is_ok;
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (QImode, operands[1]);
- }
- }
+(define_mode_macro P [(SI "Pmode == SImode") (DI "Pmode == DImode")])
- /* Fixup TLS cases. */
- if (tls_symbolic_operand (operands [1]))
- operands[1] = legitimize_tls_address (operands[1]);
+;; Load in operand 0 the (absolute) address of operand 1, which is a symbolic
+;; value subject to a PC-relative relocation. Operand 2 is a helper function
+;; that adds the PC value at the call point to operand 0.
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], QImode, 0);
+(define_insn "load_pcrel_sym<P:mode>"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "symbolic_operand" "")
+ (match_operand:P 2 "call_address_operand" "")] UNSPEC_LOAD_PCREL_SYM))
+ (clobber (reg:P 15))]
+ ""
+{
+ if (flag_delayed_branch)
+ return "sethi\t%%hi(%a1-4), %0\n\tcall\t%a2\n\t add\t%0, %%lo(%a1+4), %0";
+ else
+ return "sethi\t%%hi(%a1-8), %0\n\tadd\t%0, %%lo(%a1-4), %0\n\tcall\t%a2\n\t nop";
+}
+ [(set (attr "type") (const_string "multi"))
+ (set (attr "length")
+ (if_then_else (eq_attr "delayed_branch" "true")
+ (const_int 3)
+ (const_int 4)))])
- if (symbolic_operand (operands[1], QImode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- QImode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- goto movqi_is_ok;
- }
- }
- /* All QI constants require only one insn, so proceed. */
+;; Integer move instructions
- movqi_is_ok:
- ;
+(define_expand "movqi"
+ [(set (match_operand:QI 0 "nonimmediate_operand" "")
+ (match_operand:QI 1 "general_operand" ""))]
+ ""
+{
+ if (sparc_expand_move (QImode, operands))
+ DONE;
})
(define_insn "*movqi_insn"
[(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,m")
(match_operand:QI 1 "input_operand" "rI,m,rJ"))]
"(register_operand (operands[0], QImode)
- || reg_or_0_operand (operands[1], QImode))"
+ || register_or_zero_operand (operands[1], QImode))"
"@
mov\t%1, %0
ldub\t%1, %0
@@ -1746,75 +1751,19 @@
(set_attr "us3load_type" "*,3cycle,*")])
(define_expand "movhi"
- [(set (match_operand:HI 0 "general_operand" "")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "")
(match_operand:HI 1 "general_operand" ""))]
""
{
- /* Working with CONST_INTs is easier, so convert
- a double if needed. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
- /* Handle sets of MEM first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (reg_or_0_operand (operands[1], HImode))
- goto movhi_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (HImode, operands[1]);
- }
- }
-
- /* Fixup TLS cases. */
- if (tls_symbolic_operand (operands [1]))
- operands[1] = legitimize_tls_address (operands[1]);
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], HImode, 0);
-
- if (symbolic_operand (operands[1], HImode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- HImode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- goto movhi_is_ok;
- }
- }
-
- /* This makes sure we will not get rematched due to splittage. */
- if (! CONSTANT_P (operands[1]) || input_operand (operands[1], HImode))
- ;
- else if (CONSTANT_P (operands[1])
- && GET_CODE (operands[1]) != HIGH
- && GET_CODE (operands[1]) != LO_SUM)
- {
- sparc_emit_set_const32 (operands[0], operands[1]);
- DONE;
- }
- movhi_is_ok:
- ;
+ if (sparc_expand_move (HImode, operands))
+ DONE;
})
-(define_insn "*movhi_const64_special"
- [(set (match_operand:HI 0 "register_operand" "=r")
- (match_operand:HI 1 "const64_high_operand" ""))]
- "TARGET_ARCH64"
- "sethi\t%%hi(%a1), %0")
-
(define_insn "*movhi_insn"
[(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m")
(match_operand:HI 1 "input_operand" "rI,K,m,rJ"))]
"(register_operand (operands[0], HImode)
- || reg_or_0_operand (operands[1], HImode))"
+ || register_or_zero_operand (operands[1], HImode))"
"@
mov\t%1, %0
sethi\t%%hi(%a1), %0
@@ -1827,109 +1776,34 @@
(define_insn "*movhi_lo_sum"
[(set (match_operand:HI 0 "register_operand" "=r")
(ior:HI (match_operand:HI 1 "register_operand" "%r")
- (match_operand:HI 2 "small_int" "I")))]
+ (match_operand:HI 2 "small_int_operand" "I")))]
""
"or\t%1, %2, %0")
(define_expand "movsi"
- [(set (match_operand:SI 0 "general_operand" "")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "")
(match_operand:SI 1 "general_operand" ""))]
""
{
- /* Working with CONST_INTs is easier, so convert
- a double if needed. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE)
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
- /* Handle sets of MEM first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (reg_or_0_operand (operands[1], SImode))
- goto movsi_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (SImode, operands[1]);
- }
- }
-
- /* Fixup TLS cases. */
- if (tls_symbolic_operand (operands [1]))
- operands[1] = legitimize_tls_address (operands[1]);
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], SImode, 0);
-
- if (GET_CODE (operands[1]) == LABEL_REF)
- {
- /* shit */
- emit_insn (gen_movsi_pic_label_ref (operands[0], operands[1]));
- DONE;
- }
-
- if (symbolic_operand (operands[1], SImode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- SImode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- goto movsi_is_ok;
- }
- }
-
- /* If we are trying to toss an integer constant into the
- FPU registers, force it into memory. */
- if (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
- && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
- && CONSTANT_P (operands[1]))
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
-
- /* This makes sure we will not get rematched due to splittage. */
- if (! CONSTANT_P (operands[1]) || input_operand (operands[1], SImode))
- ;
- else if (CONSTANT_P (operands[1])
- && GET_CODE (operands[1]) != HIGH
- && GET_CODE (operands[1]) != LO_SUM)
- {
- sparc_emit_set_const32 (operands[0], operands[1]);
- DONE;
- }
- movsi_is_ok:
- ;
+ if (sparc_expand_move (SImode, operands))
+ DONE;
})
-;; This is needed to show CSE exactly which bits are set
-;; in a 64-bit register by sethi instructions.
-(define_insn "*movsi_const64_special"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (match_operand:SI 1 "const64_high_operand" ""))]
- "TARGET_ARCH64"
- "sethi\t%%hi(%a1), %0")
-
(define_insn "*movsi_insn"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,f,r,r,r,f,m,m,d")
- (match_operand:SI 1 "input_operand" "rI,!f,K,J,m,!m,rJ,!f,J"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m,!f,!f,!m,d")
+ (match_operand:SI 1 "input_operand" "rI,K,m,rJ,f,m,f,J"))]
"(register_operand (operands[0], SImode)
- || reg_or_0_operand (operands[1], SImode))"
+ || register_or_zero_operand (operands[1], SImode))"
"@
mov\t%1, %0
- fmovs\t%1, %0
sethi\t%%hi(%a1), %0
- clr\t%0
- ld\t%1, %0
ld\t%1, %0
st\t%r1, %0
+ fmovs\t%1, %0
+ ld\t%1, %0
st\t%1, %0
fzeros\t%0"
- [(set_attr "type" "*,fpmove,*,*,load,fpload,store,fpstore,fga")])
+ [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga")])
(define_insn "*movsi_lo_sum"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -2001,90 +1875,12 @@
"or\t%1, %%lo(%a3-(%a2-.)), %0")
(define_expand "movdi"
- [(set (match_operand:DI 0 "reg_or_nonsymb_mem_operand" "")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "")
(match_operand:DI 1 "general_operand" ""))]
""
{
- /* Where possible, convert CONST_DOUBLE into a CONST_INT. */
- if (GET_CODE (operands[1]) == CONST_DOUBLE
-#if HOST_BITS_PER_WIDE_INT == 32
- && ((CONST_DOUBLE_HIGH (operands[1]) == 0
- && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) == 0)
- || (CONST_DOUBLE_HIGH (operands[1]) == (HOST_WIDE_INT) 0xffffffff
- && (CONST_DOUBLE_LOW (operands[1]) & 0x80000000) != 0))
-#endif
- )
- operands[1] = GEN_INT (CONST_DOUBLE_LOW (operands[1]));
-
- /* Handle MEM cases first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- /* If it's a REG, we can always do it.
- The const zero case is more complex, on v9
- we can always perform it. */
- if (register_operand (operands[1], DImode)
- || (TARGET_V9
- && (operands[1] == const0_rtx)))
- goto movdi_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (DImode, operands[1]);
- }
- }
-
- /* Fixup TLS cases. */
- if (tls_symbolic_operand (operands [1]))
- operands[1] = legitimize_tls_address (operands[1]);
-
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], DImode, 0);
-
- if (GET_CODE (operands[1]) == LABEL_REF)
- {
- if (! TARGET_ARCH64)
- abort ();
- emit_insn (gen_movdi_pic_label_ref (operands[0], operands[1]));
- DONE;
- }
-
- if (symbolic_operand (operands[1], DImode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- DImode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- goto movdi_is_ok;
- }
- }
-
- /* If we are trying to toss an integer constant into the
- FPU registers, force it into memory. */
- if (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) >= SPARC_FIRST_FP_REG
- && REGNO (operands[0]) <= SPARC_LAST_V9_FP_REG
- && CONSTANT_P (operands[1]))
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
-
- /* This makes sure we will not get rematched due to splittage. */
- if (! CONSTANT_P (operands[1]) || input_operand (operands[1], DImode))
- ;
- else if (TARGET_ARCH64
- && GET_CODE (operands[1]) != HIGH
- && GET_CODE (operands[1]) != LO_SUM)
- {
- sparc_emit_set_const64 (operands[0], operands[1]);
- DONE;
- }
-
- movdi_is_ok:
- ;
+ if (sparc_expand_move (DImode, operands))
+ DONE;
})
;; Be careful, fmovd does not exist when !v9.
@@ -2099,15 +1895,15 @@
;; (reg:DI 2 %g2))
;;
-(define_insn "*movdi_insn_sp32_v9"
+(define_insn "*movdi_insn_sp32"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
+ "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
(match_operand:DI 1 "input_operand"
- " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
- "! TARGET_ARCH64 && TARGET_V9
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ "! TARGET_V9
+ && (register_operand (operands[0], DImode)
+ || register_or_zero_operand (operands[1], DImode))"
"@
- stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
@@ -2119,22 +1915,21 @@
ldd\t%1, %0
#
#
- fmovd\\t%1, %0
- ldd\\t%1, %0
- std\\t%1, %0"
- [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
- (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
- (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
+ #"
+ [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
+ (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-(define_insn "*movdi_insn_sp32"
+(define_insn "*movdi_insn_sp32_v9"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=o,T,U,o,r,r,r,?T,?f,?f,?o,?f")
+ "=T,o,T,U,o,r,r,r,?T,?f,?f,?o,?e,?e,?W")
(match_operand:DI 1 "input_operand"
- " J,U,T,r,o,i,r, f, T, o, f, f"))]
+ " J,J,U,T,r,o,i,r, f, T, o, f, e, W, e"))]
"! TARGET_ARCH64
+ && TARGET_V9
&& (register_operand (operands[0], DImode)
- || register_operand (operands[1], DImode))"
+ || register_or_zero_operand (operands[1], DImode))"
"@
+ stx\t%%g0, %0
#
std\t%1, %0
ldd\t%1, %0
@@ -2146,62 +1941,30 @@
ldd\t%1, %0
#
#
- #"
- [(set_attr "type" "store,store,load,*,*,*,*,fpstore,fpload,*,*,*")
- (set_attr "length" "2,*,*,2,2,2,2,*,*,2,2,2")])
-
-;; The following are generated by sparc_emit_set_const64
-(define_insn "*movdi_sp64_dbl"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "const64_operand" ""))]
- "(TARGET_ARCH64
- && HOST_BITS_PER_WIDE_INT != 64)"
- "mov\t%1, %0")
-
-;; This is needed to show CSE exactly which bits are set
-;; in a 64-bit register by sethi instructions.
-(define_insn "*movdi_const64_special"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (match_operand:DI 1 "const64_high_operand" ""))]
- "TARGET_ARCH64"
- "sethi\t%%hi(%a1), %0")
+ fmovd\\t%1, %0
+ ldd\\t%1, %0
+ std\\t%1, %0"
+ [(set_attr "type" "store,store,store,load,*,*,*,*,fpstore,fpload,*,*,fpmove,fpload,fpstore")
+ (set_attr "length" "*,2,*,*,2,2,2,2,*,*,2,2,*,*,*")
+ (set_attr "fptype" "*,*,*,*,*,*,*,*,*,*,*,*,double,*,*")])
-(define_insn "*movdi_insn_sp64_novis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W")
- (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e"))]
- "TARGET_ARCH64 && ! TARGET_VIS
+(define_insn "*movdi_insn_sp64"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,m,?e,?e,?W,b")
+ (match_operand:DI 1 "input_operand" "rI,N,m,rJ,e,W,e,J"))]
+ "TARGET_ARCH64
&& (register_operand (operands[0], DImode)
- || reg_or_0_operand (operands[1], DImode))"
+ || register_or_zero_operand (operands[1], DImode))"
"@
mov\t%1, %0
sethi\t%%hi(%a1), %0
- clr\t%0
- ldx\t%1, %0
- stx\t%r1, %0
- fmovd\t%1, %0
- ldd\t%1, %0
- std\t%1, %0"
- [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore")
- (set_attr "fptype" "*,*,*,*,*,double,*,*")])
-
-(define_insn "*movdi_insn_sp64_vis"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,r,r,m,?e,?e,?W,b")
- (match_operand:DI 1 "input_operand" "rI,N,J,m,rJ,e,W,e,J"))]
- "TARGET_ARCH64 && TARGET_VIS &&
- (register_operand (operands[0], DImode)
- || reg_or_0_operand (operands[1], DImode))"
- "@
- mov\t%1, %0
- sethi\t%%hi(%a1), %0
- clr\t%0
ldx\t%1, %0
stx\t%r1, %0
fmovd\t%1, %0
ldd\t%1, %0
std\t%1, %0
fzero\t%0"
- [(set_attr "type" "*,*,*,load,store,fpmove,fpload,fpstore,fga")
- (set_attr "fptype" "*,*,*,*,*,double,*,*,double")])
+ [(set_attr "type" "*,*,load,store,fpmove,fpload,fpstore,fga")
+ (set_attr "fptype" "*,*,*,*,double,*,*,double")])
(define_expand "movdi_pic_label_ref"
[(set (match_dup 3) (high:DI
@@ -2262,7 +2025,7 @@
(define_insn "*sethi_di_medlow_embmedany_pic"
[(set (match_operand:DI 0 "register_operand" "=r")
- (high:DI (match_operand:DI 1 "sp64_medium_pic_operand" "")))]
+ (high:DI (match_operand:DI 1 "medium_pic_operand" "")))]
"(TARGET_CM_MEDLOW || TARGET_CM_EMBMEDANY) && check_pic (1)"
"sethi\t%%hi(%a1), %0")
@@ -2418,7 +2181,9 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
- if (low == high && (low & 0x3ff) != 0 && low + 0x1000 >= 0x2000)
+ if (low == high
+ && ! SPARC_SETHI32_P (high)
+ && ! SPARC_SIMM13_P (high))
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
gen_highpart (SImode, operands[0])));
else
@@ -2446,8 +2211,8 @@
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (CONST_DOUBLE_LOW (operands[1]) == CONST_DOUBLE_HIGH (operands[1])
- && !(SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
- || SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1]))))
+ && ! SPARC_SETHI32_P (CONST_DOUBLE_HIGH (operands[1]))
+ && ! SPARC_SIMM13_P (CONST_DOUBLE_HIGH (operands[1])))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
gen_highpart (SImode, operands[0])));
@@ -2543,7 +2308,7 @@
(define_split
[(set (match_operand:DI 0 "memory_operand" "")
- (const_int 0))]
+ (match_operand:DI 1 "const_zero_operand" ""))]
"reload_completed
&& (! TARGET_V9
|| (! TARGET_ARCH64
@@ -2555,16 +2320,29 @@
emit_insn (gen_movsi (adjust_address (operands[0], SImode, 4), const0_rtx));
DONE;
})
-
-;; Floating point move insns
-(define_insn "*movsf_insn_novis"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,*r,*r,*r,*r,*r,f,m,m")
- (match_operand:SF 1 "input_operand" "f,G,Q,*rR,S,m,m,f,*rG"))]
- "(TARGET_FPU && ! TARGET_VIS)
- && (register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)
- || fp_zero_operand (operands[1], SFmode))"
+
+;; Floating point and vector move instructions
+
+;; We don't define V1SI because SI should work just fine.
+(define_mode_macro V32 [SF V2HI V4QI])
+
+;; Yes, you guessed it right, the former movsf expander.
+(define_expand "mov<V32:mode>"
+ [(set (match_operand:V32 0 "nonimmediate_operand" "")
+ (match_operand:V32 1 "general_operand" ""))]
+ "<V32:MODE>mode == SFmode || TARGET_VIS"
+{
+ if (sparc_expand_move (<V32:MODE>mode, operands))
+ DONE;
+})
+
+(define_insn "*movsf_insn"
+ [(set (match_operand:V32 0 "nonimmediate_operand" "=d,f,*r,*r,*r,f,*r,m,m")
+ (match_operand:V32 1 "input_operand" "GY,f,*rRY,Q,S,m,m,f,*rGY"))]
+ "TARGET_FPU
+ && (register_operand (operands[0], <V32:MODE>mode)
+ || register_or_zero_operand (operands[1], <V32:MODE>mode))"
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
&& (which_alternative == 2
@@ -2582,90 +2360,42 @@
switch (which_alternative)
{
case 0:
- return "fmovs\t%1, %0";
+ return "fzeros\t%0";
case 1:
- return "clr\t%0";
- case 2:
- return "sethi\t%%hi(%a1), %0";
- case 3:
- return "mov\t%1, %0";
- case 4:
- return "#";
- case 5:
- case 6:
- return "ld\t%1, %0";
- case 7:
- case 8:
- return "st\t%r1, %0";
- default:
- abort();
- }
-}
- [(set_attr "type" "fpmove,*,*,*,*,load,fpload,fpstore,store")])
-
-(define_insn "*movsf_insn_vis"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,*r,*r,*r,*r,*r,f,m,m")
- (match_operand:SF 1 "input_operand" "f,G,G,Q,*rR,S,m,m,f,*rG"))]
- "(TARGET_FPU && TARGET_VIS)
- && (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 == 3
- || which_alternative == 4
- || which_alternative == 5))
- {
- 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 "fmovs\t%1, %0";
- case 1:
- return "fzeros\t%0";
case 2:
- return "clr\t%0";
+ return "mov\t%1, %0";
case 3:
return "sethi\t%%hi(%a1), %0";
case 4:
- return "mov\t%1, %0";
- case 5:
return "#";
+ case 5:
case 6:
- case 7:
return "ld\t%1, %0";
+ case 7:
case 8:
- case 9:
return "st\t%r1, %0";
default:
- abort();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "fpmove,fga,*,*,*,*,load,fpload,fpstore,store")])
+ [(set_attr "type" "fga,fpmove,*,*,*,fpload,load,fpstore,store")])
;; 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"))]
+(define_insn "*movsf_insn_no_fpu"
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,r,r,m")
+ (match_operand:SF 1 "input_operand" "rR,Q,S,m,rG"))]
"! TARGET_FPU
&& (register_operand (operands[0], SFmode)
- || register_operand (operands[1], SFmode)
- || fp_zero_operand (operands[1], SFmode))"
+ || register_or_zero_operand (operands[1], SFmode))"
{
if (GET_CODE (operands[1]) == CONST_DOUBLE
- && (which_alternative == 1
- || which_alternative == 2
- || which_alternative == 3))
+ && (which_alternative == 0
+ || which_alternative == 1
+ || which_alternative == 2))
{
REAL_VALUE_TYPE r;
long i;
@@ -2678,28 +2408,28 @@
switch (which_alternative)
{
case 0:
- return "clr\t%0";
+ return "mov\t%1, %0";
case 1:
return "sethi\t%%hi(%a1), %0";
case 2:
- return "mov\t%1, %0";
- case 3:
return "#";
- case 4:
+ case 3:
return "ld\t%1, %0";
- case 5:
+ case 4:
return "st\t%r1, %0";
default:
- abort();
+ gcc_unreachable ();
}
}
- [(set_attr "type" "*,*,*,*,load,store")])
+ [(set_attr "type" "*,*,*,load,store")])
+
+;; The following 3 patterns build SFmode constants in integer registers.
(define_insn "*movsf_lo_sum"
[(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])"
+ (match_operand:SF 2 "fp_const_high_losum_operand" "S")))]
+ ""
{
REAL_VALUE_TYPE r;
long i;
@@ -2712,8 +2442,8 @@
(define_insn "*movsf_high"
[(set (match_operand:SF 0 "register_operand" "=r")
- (high:SF (match_operand:SF 1 "const_double_operand" "S")))]
- "fp_high_losum_p (operands[1])"
+ (high:SF (match_operand:SF 1 "fp_const_high_losum_operand" "S")))]
+ ""
{
REAL_VALUE_TYPE r;
long i;
@@ -2726,136 +2456,21 @@
(define_split
[(set (match_operand:SF 0 "register_operand" "")
- (match_operand:SF 1 "const_double_operand" ""))]
- "fp_high_losum_p (operands[1])
- && (GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)"
+ (match_operand:SF 1 "fp_const_high_losum_operand" ""))]
+ "REG_P (operands[0]) && 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)))])
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
-{
- /* Force SFmode constants into memory. */
- if (GET_CODE (operands[0]) == REG
- && CONSTANT_P (operands[1]))
- {
- /* emit_group_store will send such bogosity to us when it is
- not storing directly into memory. So fix this up to avoid
- crashes in output_constant_pool. */
- if (operands [1] == const0_rtx)
- operands[1] = CONST0_RTX (SFmode);
-
- if (TARGET_VIS && fp_zero_operand (operands[1], SFmode))
- goto movsf_is_ok;
-
- /* We are able to build any SF constant in integer registers
- with at most 2 instructions. */
- if (REGNO (operands[0]) < 32)
- goto movsf_is_ok;
-
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
- }
-
- /* Handle sets of MEM first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (register_operand (operands[1], SFmode)
- || fp_zero_operand (operands[1], SFmode))
- goto movsf_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (SFmode, operands[1]);
- }
- }
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], SFmode, 0);
-
- if (symbolic_operand (operands[1], SFmode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- SFmode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- }
- }
-
- movsf_is_ok:
- ;
-})
+(define_mode_macro V64 [DF V2SI V4HI V8QI])
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
+;; Yes, you again guessed it right, the former movdf expander.
+(define_expand "mov<V64:mode>"
+ [(set (match_operand:V64 0 "nonimmediate_operand" "")
+ (match_operand:V64 1 "general_operand" ""))]
+ "<V64:MODE>mode == DFmode || TARGET_VIS"
{
- /* Force DFmode constants into memory. */
- if (GET_CODE (operands[0]) == REG
- && CONSTANT_P (operands[1]))
- {
- /* emit_group_store will send such bogosity to us when it is
- not storing directly into memory. So fix this up to avoid
- crashes in output_constant_pool. */
- if (operands [1] == const0_rtx)
- operands[1] = CONST0_RTX (DFmode);
-
- if ((TARGET_VIS || REGNO (operands[0]) < 32)
- && fp_zero_operand (operands[1], DFmode))
- goto movdf_is_ok;
-
- /* We are able to build any DF constant in integer registers. */
- if (REGNO (operands[0]) < 32
- && (reload_completed || reload_in_progress))
- goto movdf_is_ok;
-
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
- }
-
- /* Handle MEM cases first. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))
- goto movdf_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (DFmode, operands[1]);
- }
- }
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], DFmode, 0);
-
- if (symbolic_operand (operands[1], DFmode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- DFmode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- }
- }
-
- movdf_is_ok:
- ;
+ if (sparc_expand_move (<V64:MODE>mode, operands))
+ DONE;
})
;; Be careful, fmovd does not exist when !v9.
@@ -2865,8 +2480,7 @@
"TARGET_FPU
&& ! TARGET_V9
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ || register_or_zero_operand (operands[1], DFmode))"
"@
ldd\t%1, %0
std\t%1, %0
@@ -2881,15 +2495,13 @@
[(set_attr "type" "fpload,fpstore,load,store,*,*,*,*,*,*")
(set_attr "length" "*,*,*,*,2,2,2,2,2,2")])
-(define_insn "*movdf_no_e_insn_sp32"
+(define_insn "*movdf_insn_sp32_no_fpu"
[(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,o,r,o")
(match_operand:DF 1 "input_operand" "T,U,G,ro,r"))]
"! TARGET_FPU
&& ! TARGET_V9
- && ! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ || register_or_zero_operand (operands[1], DFmode))"
"@
ldd\t%1, %0
std\t%1, %0
@@ -2899,61 +2511,15 @@
[(set_attr "type" "load,store,*,*,*")
(set_attr "length" "*,*,2,2,2")])
-(define_insn "*movdf_no_e_insn_v9_sp32"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
- (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
- "! TARGET_FPU
- && TARGET_V9
- && ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
- "@
- ldd\t%1, %0
- std\t%1, %0
- stx\t%r1, %0
- #
- #"
- [(set_attr "type" "load,store,store,*,*")
- (set_attr "length" "*,*,*,2,2")])
-
-;; We have available v9 double floats but not 64-bit
-;; integer registers and no VIS.
-(define_insn "*movdf_insn_v9only_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,T,W,U,T,f,*r,o")
- (match_operand:DF 1 "input_operand" "e,W#F,G,e,T,U,o#F,*roF,*rGf"))]
+;; We have available v9 double floats but not 64-bit integer registers.
+(define_insn "*movdf_insn_sp32_v9"
+ [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,T,W,U,T,f,*r,o")
+ (match_operand:V64 1 "input_operand" "GY,e,W#F,GY,e,T,U,o#F,*roGYF,*rGYf"))]
"TARGET_FPU
&& TARGET_V9
- && ! TARGET_VIS
- && ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
- "@
- fmovd\t%1, %0
- ldd\t%1, %0
- stx\t%r1, %0
- std\t%1, %0
- ldd\t%1, %0
- std\t%1, %0
- #
- #
- #"
- [(set_attr "type" "fpmove,load,store,store,load,store,*,*,*")
- (set_attr "length" "*,*,*,*,*,*,2,2,2")
- (set_attr "fptype" "double,*,*,*,*,*,*,*,*")])
-
-;; We have available v9 double floats but not 64-bit
-;; integer registers but we have VIS.
-(define_insn "*movdf_insn_v9only_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,T,W,U,T,f,*r,o")
- (match_operand:DF 1 "input_operand" "G,e,W#F,G,e,T,U,o#F,*roGF,*rGf"))]
- "TARGET_FPU
- && TARGET_VIS
&& ! TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ && (register_operand (operands[0], <V64:MODE>mode)
+ || register_or_zero_operand (operands[1], <V64:MODE>mode))"
"@
fzero\t%0
fmovd\t%1, %0
@@ -2969,40 +2535,31 @@
(set_attr "length" "*,*,*,*,*,*,*,2,2,2")
(set_attr "fptype" "double,double,*,*,*,*,*,*,*,*")])
-;; We have available both v9 double floats and 64-bit
-;; integer registers. No VIS though.
-(define_insn "*movdf_insn_sp64_novis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,W,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "e,W#F,e,*rG,m,*rG,F"))]
- "TARGET_FPU
- && ! TARGET_VIS
- && TARGET_ARCH64
+(define_insn "*movdf_insn_sp32_v9_no_fpu"
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=U,T,T,r,o")
+ (match_operand:DF 1 "input_operand" "T,U,G,ro,rG"))]
+ "! TARGET_FPU
+ && TARGET_V9
+ && ! TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ || register_or_zero_operand (operands[1], DFmode))"
"@
- fmovd\t%1, %0
ldd\t%1, %0
std\t%1, %0
- mov\t%r1, %0
- ldx\t%1, %0
stx\t%r1, %0
+ #
#"
- [(set_attr "type" "fpmove,load,store,*,load,store,*")
- (set_attr "length" "*,*,*,*,*,*,2")
- (set_attr "fptype" "double,*,*,*,*,*,*")])
-
-;; We have available both v9 double floats and 64-bit
-;; integer registers. And we have VIS.
-(define_insn "*movdf_insn_sp64_vis"
- [(set (match_operand:DF 0 "nonimmediate_operand" "=e,e,e,W,*r,*r,m,*r")
- (match_operand:DF 1 "input_operand" "G,e,W#F,e,*rG,m,*rG,F"))]
+ [(set_attr "type" "load,store,store,*,*")
+ (set_attr "length" "*,*,*,2,2")])
+
+;; We have available both v9 double floats and 64-bit integer registers.
+(define_insn "*movdf_insn_sp64"
+ [(set (match_operand:V64 0 "nonimmediate_operand" "=b,e,e,W,*r,*r,m,*r")
+ (match_operand:V64 1 "input_operand" "GY,e,W#F,e,*rGY,m,*rGY,F"))]
"TARGET_FPU
- && TARGET_VIS
&& TARGET_ARCH64
- && (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ && (register_operand (operands[0], <V64:MODE>mode)
+ || register_or_zero_operand (operands[1], <V64:MODE>mode))"
"@
fzero\t%0
fmovd\t%1, %0
@@ -3016,27 +2573,27 @@
(set_attr "length" "*,*,*,*,*,*,*,2")
(set_attr "fptype" "double,double,*,*,*,*,*,*")])
-(define_insn "*movdf_no_e_insn_sp64"
+(define_insn "*movdf_insn_sp64_no_fpu"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,r,m")
(match_operand:DF 1 "input_operand" "r,m,rG"))]
"! TARGET_FPU
&& TARGET_ARCH64
&& (register_operand (operands[0], DFmode)
- || register_operand (operands[1], DFmode)
- || fp_zero_operand (operands[1], DFmode))"
+ || register_or_zero_operand (operands[1], DFmode))"
"@
mov\t%1, %0
ldx\t%1, %0
stx\t%r1, %0"
[(set_attr "type" "*,load,store")])
+;; This pattern build DFmode constants in integer registers.
(define_split
[(set (match_operand:DF 0 "register_operand" "")
(match_operand:DF 1 "const_double_operand" ""))]
"TARGET_FPU
&& (GET_CODE (operands[0]) == REG
&& REGNO (operands[0]) < 32)
- && ! fp_zero_operand(operands[1], DFmode)
+ && ! const_zero_operand(operands[1], DFmode)
&& reload_completed"
[(clobber (const_int 0))]
{
@@ -3049,27 +2606,26 @@
if (TARGET_ARCH64)
{
-#if HOST_BITS_PER_WIDE_INT == 64
+#if HOST_BITS_PER_WIDE_INT == 32
+ gcc_unreachable ();
+#else
HOST_WIDE_INT val;
val = ((HOST_WIDE_INT)(unsigned long)l[1] |
((HOST_WIDE_INT)(unsigned long)l[0] << 32));
- emit_insn (gen_movdi (operands[0], GEN_INT (val)));
-#else
- emit_insn (gen_movdi (operands[0],
- immed_double_const (l[1], l[0], DImode)));
+ emit_insn (gen_movdi (operands[0], gen_int_mode (val, DImode)));
#endif
}
else
{
emit_insn (gen_movsi (gen_highpart (SImode, operands[0]),
- GEN_INT (l[0])));
+ gen_int_mode (l[0], SImode)));
/* Slick... but this trick loses if this subreg constant part
can be done in one insn. */
if (l[1] == l[0]
- && !(SPARC_SETHI32_P (l[0])
- || SPARC_SIMM13_P (l[0])))
+ && ! SPARC_SETHI32_P (l[0])
+ && ! SPARC_SIMM13_P (l[0]))
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
gen_highpart (SImode, operands[0])));
@@ -3077,7 +2633,7 @@
else
{
emit_insn (gen_movsi (gen_lowpart (SImode, operands[0]),
- GEN_INT (l[1])));
+ gen_int_mode (l[1], SImode)));
}
}
DONE;
@@ -3089,8 +2645,8 @@
;; careful when V9 but not ARCH64 because the integer
;; register DFmode cases must be handled.
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "register_operand" ""))]
+ [(set (match_operand:V64 0 "register_operand" "")
+ (match_operand:V64 1 "register_operand" ""))]
"(! TARGET_V9
|| (! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
@@ -3105,30 +2661,37 @@
rtx set_src = operands[1];
rtx dest1, dest2;
rtx src1, src2;
+ enum machine_mode half_mode;
- dest1 = gen_highpart (SFmode, set_dest);
- dest2 = gen_lowpart (SFmode, set_dest);
- src1 = gen_highpart (SFmode, set_src);
- src2 = gen_lowpart (SFmode, set_src);
+ /* We can be expanded for DFmode or integral vector modes. */
+ if (<V64:MODE>mode == DFmode)
+ half_mode = SFmode;
+ else
+ half_mode = SImode;
+
+ dest1 = gen_highpart (half_mode, set_dest);
+ dest2 = gen_lowpart (half_mode, set_dest);
+ src1 = gen_highpart (half_mode, set_src);
+ src2 = gen_lowpart (half_mode, set_src);
/* Now emit using the real source and destination we found, swapping
the order if we detect overlap. */
if (reg_overlap_mentioned_p (dest1, src2))
{
- emit_insn (gen_movsf (dest2, src2));
- emit_insn (gen_movsf (dest1, src1));
+ emit_move_insn_1 (dest2, src2);
+ emit_move_insn_1 (dest1, src1);
}
else
{
- emit_insn (gen_movsf (dest1, src1));
- emit_insn (gen_movsf (dest2, src2));
+ emit_move_insn_1 (dest1, src1);
+ emit_move_insn_1 (dest2, src2);
}
DONE;
})
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "memory_operand" ""))]
+ [(set (match_operand:V64 0 "register_operand" "")
+ (match_operand:V64 1 "memory_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[0]) % 2) != 0)
@@ -3136,29 +2699,34 @@
&& offsettable_memref_p (operands[1])"
[(clobber (const_int 0))]
{
- rtx word0 = adjust_address (operands[1], SFmode, 0);
- rtx word1 = adjust_address (operands[1], SFmode, 4);
+ enum machine_mode half_mode;
+ rtx word0, word1;
- if (reg_overlap_mentioned_p (gen_highpart (SFmode, operands[0]), word1))
+ /* We can be expanded for DFmode or integral vector modes. */
+ if (<V64:MODE>mode == DFmode)
+ half_mode = SFmode;
+ else
+ half_mode = SImode;
+
+ word0 = adjust_address (operands[1], half_mode, 0);
+ word1 = adjust_address (operands[1], half_mode, 4);
+
+ if (reg_overlap_mentioned_p (gen_highpart (half_mode, operands[0]), word1))
{
- emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
- word1));
- emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
- word0));
+ emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
+ emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
}
else
{
- emit_insn (gen_movsf (gen_highpart (SFmode, operands[0]),
- word0));
- emit_insn (gen_movsf (gen_lowpart (SFmode, operands[0]),
- word1));
+ emit_move_insn_1 (gen_highpart (half_mode, operands[0]), word0);
+ emit_move_insn_1 (gen_lowpart (half_mode, operands[0]), word1);
}
DONE;
})
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (match_operand:DF 1 "register_operand" ""))]
+ [(set (match_operand:V64 0 "memory_operand" "")
+ (match_operand:V64 1 "register_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& (((REGNO (operands[1]) % 2) != 0)
@@ -3166,19 +2734,26 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
- rtx word0 = adjust_address (operands[0], SFmode, 0);
- rtx word1 = adjust_address (operands[0], SFmode, 4);
+ enum machine_mode half_mode;
+ rtx word0, word1;
+
+ /* We can be expanded for DFmode or integral vector modes. */
+ if (<V64:MODE>mode == DFmode)
+ half_mode = SFmode;
+ else
+ half_mode = SImode;
- emit_insn (gen_movsf (word0,
- gen_highpart (SFmode, operands[1])));
- emit_insn (gen_movsf (word1,
- gen_lowpart (SFmode, operands[1])));
+ word0 = adjust_address (operands[0], half_mode, 0);
+ word1 = adjust_address (operands[0], half_mode, 4);
+
+ emit_move_insn_1 (word0, gen_highpart (half_mode, operands[1]));
+ emit_move_insn_1 (word1, gen_lowpart (half_mode, operands[1]));
DONE;
})
(define_split
- [(set (match_operand:DF 0 "memory_operand" "")
- (match_operand:DF 1 "fp_zero_operand" ""))]
+ [(set (match_operand:V64 0 "memory_operand" "")
+ (match_operand:V64 1 "const_zero_operand" ""))]
"reload_completed
&& (! TARGET_V9
|| (! TARGET_ARCH64
@@ -3186,19 +2761,26 @@
&& offsettable_memref_p (operands[0])"
[(clobber (const_int 0))]
{
+ enum machine_mode half_mode;
rtx dest1, dest2;
- dest1 = adjust_address (operands[0], SFmode, 0);
- dest2 = adjust_address (operands[0], SFmode, 4);
+ /* We can be expanded for DFmode or integral vector modes. */
+ if (<V64:MODE>mode == DFmode)
+ half_mode = SFmode;
+ else
+ half_mode = SImode;
+
+ dest1 = adjust_address (operands[0], half_mode, 0);
+ dest2 = adjust_address (operands[0], half_mode, 4);
- emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
- emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+ emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
+ emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
DONE;
})
(define_split
- [(set (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "fp_zero_operand" ""))]
+ [(set (match_operand:V64 0 "register_operand" "")
+ (match_operand:V64 1 "const_zero_operand" ""))]
"reload_completed
&& ! TARGET_ARCH64
&& ((GET_CODE (operands[0]) == REG
@@ -3208,97 +2790,39 @@
&& REGNO (SUBREG_REG (operands[0])) < 32))"
[(clobber (const_int 0))]
{
+ enum machine_mode half_mode;
rtx set_dest = operands[0];
rtx dest1, dest2;
- dest1 = gen_highpart (SFmode, set_dest);
- dest2 = gen_lowpart (SFmode, set_dest);
- emit_insn (gen_movsf (dest1, CONST0_RTX (SFmode)));
- emit_insn (gen_movsf (dest2, CONST0_RTX (SFmode)));
+ /* We can be expanded for DFmode or integral vector modes. */
+ if (<V64:MODE>mode == DFmode)
+ half_mode = SFmode;
+ else
+ half_mode = SImode;
+
+ dest1 = gen_highpart (half_mode, set_dest);
+ dest2 = gen_lowpart (half_mode, set_dest);
+ emit_move_insn_1 (dest1, CONST0_RTX (half_mode));
+ emit_move_insn_1 (dest2, CONST0_RTX (half_mode));
DONE;
})
(define_expand "movtf"
- [(set (match_operand:TF 0 "general_operand" "")
+ [(set (match_operand:TF 0 "nonimmediate_operand" "")
(match_operand:TF 1 "general_operand" ""))]
""
{
- /* Force TFmode constants into memory. */
- if (GET_CODE (operands[0]) == REG
- && CONSTANT_P (operands[1]))
- {
- /* emit_group_store will send such bogosity to us when it is
- not storing directly into memory. So fix this up to avoid
- crashes in output_constant_pool. */
- if (operands [1] == const0_rtx)
- operands[1] = CONST0_RTX (TFmode);
-
- if (TARGET_VIS && fp_zero_operand (operands[1], TFmode))
- goto movtf_is_ok;
-
- operands[1] = validize_mem (force_const_mem (GET_MODE (operands[0]),
- operands[1]));
- }
-
- /* Handle MEM cases first, note that only v9 guarantees
- full 16-byte alignment for quads. */
- if (GET_CODE (operands[0]) == MEM)
- {
- if (register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))
- goto movtf_is_ok;
-
- if (! reload_in_progress)
- {
- operands[0] = validize_mem (operands[0]);
- operands[1] = force_reg (TFmode, operands[1]);
- }
- }
-
- /* Fixup PIC cases. */
- if (flag_pic)
- {
- if (CONSTANT_P (operands[1])
- && pic_address_needs_scratch (operands[1]))
- operands[1] = legitimize_pic_address (operands[1], TFmode, 0);
-
- if (symbolic_operand (operands[1], TFmode))
- {
- operands[1] = legitimize_pic_address (operands[1],
- TFmode,
- (reload_in_progress ?
- operands[0] :
- NULL_RTX));
- }
- }
-
- movtf_is_ok:
- ;
+ if (sparc_expand_move (TFmode, operands))
+ DONE;
})
-;; Be careful, fmovq and {st,ld}{x,q} do not exist when !arch64 so
-;; we must split them all. :-(
(define_insn "*movtf_insn_sp32"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
- (match_operand:TF 1 "input_operand" "oe,GeUr,o,roG"))]
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,U,r")
+ (match_operand:TF 1 "input_operand" "G,oe,GeUr,o,roG"))]
"TARGET_FPU
- && ! TARGET_VIS
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "4")])
-
-(define_insn "*movtf_insn_vis_sp32"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,U,r")
- (match_operand:TF 1 "input_operand" "Goe,GeUr,o,roG"))]
- "TARGET_FPU
- && TARGET_VIS
- && ! TARGET_ARCH64
- && (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
+ || register_or_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "4")])
@@ -3306,94 +2830,52 @@
;; This is necessary to prevent reload from ever trying to use a `e' reg
;; when -mno-fpu.
-(define_insn "*movtf_no_e_insn_sp32"
+(define_insn "*movtf_insn_sp32_no_fpu"
[(set (match_operand:TF 0 "nonimmediate_operand" "=o,U,o,r,o")
(match_operand:TF 1 "input_operand" "G,o,U,roG,r"))]
"! TARGET_FPU
&& ! TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
+ || register_or_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "4")])
-;; Now handle the float reg cases directly when arch64,
-;; hard_quad, and proper reg number alignment are all true.
-(define_insn "*movtf_insn_hq_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,o,r")
- (match_operand:TF 1 "input_operand" "e,m,e,Gr,roG"))]
+(define_insn "*movtf_insn_sp64"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,o,r")
+ (match_operand:TF 1 "input_operand" "G,oe,Ger,roG"))]
"TARGET_FPU
- && ! TARGET_VIS
&& TARGET_ARCH64
- && TARGET_HARD_QUAD
+ && ! TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
- "@
- fmovq\t%1, %0
- ldq\t%1, %0
- stq\t%1, %0
- #
- #"
- [(set_attr "type" "fpmove,fpload,fpstore,*,*")
- (set_attr "length" "*,*,*,2,2")])
+ || register_or_zero_operand (operands[1], TFmode))"
+ "#"
+ [(set_attr "length" "2")])
-(define_insn "*movtf_insn_hq_vis_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,e,m,eo,r,o")
- (match_operand:TF 1 "input_operand" "e,m,e,G,roG,r"))]
+(define_insn "*movtf_insn_sp64_hq"
+ [(set (match_operand:TF 0 "nonimmediate_operand" "=b,e,e,m,o,r")
+ (match_operand:TF 1 "input_operand" "G,e,m,e,rG,roG"))]
"TARGET_FPU
- && TARGET_VIS
&& TARGET_ARCH64
&& TARGET_HARD_QUAD
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
+ || register_or_zero_operand (operands[1], TFmode))"
"@
+ #
fmovq\t%1, %0
ldq\t%1, %0
stq\t%1, %0
#
- #
#"
- [(set_attr "type" "fpmove,fpload,fpstore,*,*,*")
- (set_attr "length" "*,*,*,2,2,2")])
+ [(set_attr "type" "*,fpmove,fpload,fpstore,*,*")
+ (set_attr "length" "2,*,*,*,2,2")])
-;; Now we allow the integer register cases even when
-;; only arch64 is true.
-(define_insn "*movtf_insn_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
- (match_operand:TF 1 "input_operand" "oe,Ger,orG"))]
- "TARGET_FPU
- && ! TARGET_VIS
- && TARGET_ARCH64
- && ! TARGET_HARD_QUAD
- && (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "2")])
-
-(define_insn "*movtf_insn_vis_sp64"
- [(set (match_operand:TF 0 "nonimmediate_operand" "=e,o,r")
- (match_operand:TF 1 "input_operand" "Goe,Ger,orG"))]
- "TARGET_FPU
- && TARGET_VIS
- && TARGET_ARCH64
- && ! TARGET_HARD_QUAD
- && (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
- "#"
- [(set_attr "length" "2")])
-
-(define_insn "*movtf_no_e_insn_sp64"
+(define_insn "*movtf_insn_sp64_no_fpu"
[(set (match_operand:TF 0 "nonimmediate_operand" "=r,o")
(match_operand:TF 1 "input_operand" "orG,rG"))]
"! TARGET_FPU
&& TARGET_ARCH64
&& (register_operand (operands[0], TFmode)
- || register_operand (operands[1], TFmode)
- || fp_zero_operand (operands[1], TFmode))"
+ || register_or_zero_operand (operands[1], TFmode))"
"#"
[(set_attr "length" "2")])
@@ -3435,7 +2917,7 @@
(define_split
[(set (match_operand:TF 0 "nonimmediate_operand" "")
- (match_operand:TF 1 "fp_zero_operand" ""))]
+ (match_operand:TF 1 "const_zero_operand" ""))]
"reload_completed"
[(clobber (const_int 0))]
{
@@ -3453,7 +2935,7 @@
dest2 = adjust_address (set_dest, DFmode, 8);
break;
default:
- abort ();
+ gcc_unreachable ();
}
emit_insn (gen_movdf (dest1, CONST0_RTX (DFmode)));
@@ -3514,8 +2996,9 @@
gen_df_reg (set_src, 1)));
DONE;
})
-
-;; SPARC V9 conditional move instructions.
+
+
+;; SPARC-V9 conditional move instructions.
;; We can handle larger constants here for some flavors, but for now we keep
;; it simple and only allow those constants supported by all flavors.
@@ -3546,8 +3029,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
})
@@ -3575,8 +3057,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
})
@@ -3600,8 +3081,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
cc_reg, const0_rtx);
}
@@ -3610,8 +3090,8 @@
(define_expand "movdicc"
[(set (match_operand:DI 0 "register_operand" "")
(if_then_else:DI (match_operand 1 "comparison_operator" "")
- (match_operand:DI 2 "arith10_double_operand" "")
- (match_operand:DI 3 "arith10_double_operand" "")))]
+ (match_operand:DI 2 "arith10_operand" "")
+ (match_operand:DI 3 "arith10_operand" "")))]
"TARGET_ARCH64"
{
enum rtx_code code = GET_CODE (operands[1]);
@@ -3626,8 +3106,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg),
cc_reg, const0_rtx);
}
@@ -3656,8 +3135,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
})
@@ -3685,8 +3163,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
})
@@ -3714,8 +3191,7 @@
}
else
{
- rtx cc_reg = gen_compare_reg (code,
- sparc_compare_op0, sparc_compare_op1);
+ rtx cc_reg = gen_compare_reg (code);
operands[1] = gen_rtx_fmt_ee (code, GET_MODE (cc_reg), cc_reg, const0_rtx);
}
})
@@ -3725,7 +3201,7 @@
(define_insn "*movqi_cc_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
(if_then_else:QI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:QI 3 "arith11_operand" "rL,0")
(match_operand:QI 4 "arith11_operand" "0,rL")))]
@@ -3738,7 +3214,7 @@
(define_insn "*movhi_cc_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
(if_then_else:HI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:HI 3 "arith11_operand" "rL,0")
(match_operand:HI 4 "arith11_operand" "0,rL")))]
@@ -3751,7 +3227,7 @@
(define_insn "*movsi_cc_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:SI 3 "arith11_operand" "rL,0")
(match_operand:SI 4 "arith11_operand" "0,rL")))]
@@ -3761,14 +3237,13 @@
mov%c1\t%x2, %4, %0"
[(set_attr "type" "cmove")])
-;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(if_then_else:DI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:DI 3 "arith11_double_operand" "rLH,0")
- (match_operand:DI 4 "arith11_double_operand" "0,rLH")))]
+ (match_operand:DI 3 "arith11_operand" "rL,0")
+ (match_operand:DI 4 "arith11_operand" "0,rL")))]
"TARGET_ARCH64"
"@
mov%C1\t%x2, %3, %0
@@ -3778,10 +3253,10 @@
(define_insn "*movdi_cc_sp64_trunc"
[(set (match_operand:SI 0 "register_operand" "=r,r")
(if_then_else:SI (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
- (match_operand:SI 3 "arith11_double_operand" "rLH,0")
- (match_operand:SI 4 "arith11_double_operand" "0,rLH")))]
+ (match_operand:SI 3 "arith11_operand" "rL,0")
+ (match_operand:SI 4 "arith11_operand" "0,rL")))]
"TARGET_ARCH64"
"@
mov%C1\t%x2, %3, %0
@@ -3791,7 +3266,7 @@
(define_insn "*movsf_cc_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
(if_then_else:SF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:SF 3 "register_operand" "f,0")
(match_operand:SF 4 "register_operand" "0,f")))]
@@ -3804,7 +3279,7 @@
(define_insn "movdf_cc_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
(if_then_else:DF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:DF 3 "register_operand" "e,0")
(match_operand:DF 4 "register_operand" "0,e")))]
@@ -3818,7 +3293,7 @@
(define_insn "*movtf_cc_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
(match_operand:TF 4 "register_operand" "0,e")))]
@@ -3831,7 +3306,7 @@
(define_insn_and_split "*movtf_cc_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
(if_then_else:TF (match_operator 1 "comparison_operator"
- [(match_operand 2 "icc_or_fcc_reg_operand" "X,X")
+ [(match_operand 2 "icc_or_fcc_register_operand" "X,X")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
(match_operand:TF 4 "register_operand" "0,e")))]
@@ -3873,7 +3348,7 @@
(define_insn "*movqi_cc_reg_sp64"
[(set (match_operand:QI 0 "register_operand" "=r,r")
- (if_then_else:QI (match_operator 1 "v9_regcmp_op"
+ (if_then_else:QI (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:QI 3 "arith10_operand" "rM,0")
@@ -3886,7 +3361,7 @@
(define_insn "*movhi_cc_reg_sp64"
[(set (match_operand:HI 0 "register_operand" "=r,r")
- (if_then_else:HI (match_operator 1 "v9_regcmp_op"
+ (if_then_else:HI (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:HI 3 "arith10_operand" "rM,0")
@@ -3899,7 +3374,7 @@
(define_insn "*movsi_cc_reg_sp64"
[(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "v9_regcmp_op"
+ (if_then_else:SI (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:SI 3 "arith10_operand" "rM,0")
@@ -3910,27 +3385,13 @@
movr%d1\t%2, %r4, %0"
[(set_attr "type" "cmove")])
-;; ??? The constraints of operands 3,4 need work.
(define_insn "*movdi_cc_reg_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
- (if_then_else:DI (match_operator 1 "v9_regcmp_op"
- [(match_operand:DI 2 "register_operand" "r,r")
- (const_int 0)])
- (match_operand:DI 3 "arith10_double_operand" "rMH,0")
- (match_operand:DI 4 "arith10_double_operand" "0,rMH")))]
- "TARGET_ARCH64"
- "@
- movr%D1\t%2, %r3, %0
- movr%d1\t%2, %r4, %0"
- [(set_attr "type" "cmove")])
-
-(define_insn "*movdi_cc_reg_sp64_trunc"
- [(set (match_operand:SI 0 "register_operand" "=r,r")
- (if_then_else:SI (match_operator 1 "v9_regcmp_op"
+ (if_then_else:DI (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
- (match_operand:SI 3 "arith10_double_operand" "rMH,0")
- (match_operand:SI 4 "arith10_double_operand" "0,rMH")))]
+ (match_operand:DI 3 "arith10_operand" "rM,0")
+ (match_operand:DI 4 "arith10_operand" "0,rM")))]
"TARGET_ARCH64"
"@
movr%D1\t%2, %r3, %0
@@ -3939,7 +3400,7 @@
(define_insn "*movsf_cc_reg_sp64"
[(set (match_operand:SF 0 "register_operand" "=f,f")
- (if_then_else:SF (match_operator 1 "v9_regcmp_op"
+ (if_then_else:SF (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:SF 3 "register_operand" "f,0")
@@ -3952,7 +3413,7 @@
(define_insn "movdf_cc_reg_sp64"
[(set (match_operand:DF 0 "register_operand" "=e,e")
- (if_then_else:DF (match_operator 1 "v9_regcmp_op"
+ (if_then_else:DF (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:DF 3 "register_operand" "e,0")
@@ -3966,7 +3427,7 @@
(define_insn "*movtf_cc_reg_hq_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
- (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
@@ -3979,7 +3440,7 @@
(define_insn_and_split "*movtf_cc_reg_sp64"
[(set (match_operand:TF 0 "register_operand" "=e,e")
- (if_then_else:TF (match_operator 1 "v9_regcmp_op"
+ (if_then_else:TF (match_operator 1 "v9_register_compare_operator"
[(match_operand:DI 2 "register_operand" "r,r")
(const_int 0)])
(match_operand:TF 3 "register_operand" "e,0")
@@ -4021,7 +3482,7 @@
[(set_attr "length" "2")])
-;;- zero extension instructions
+;; Zero-extension instructions
;; These patterns originally accepted general_operands, however, slightly
;; better code is generated by only accepting register_operands, and then
@@ -4137,7 +3598,6 @@
[(set_attr "type" "load")
(set_attr "us3load_type" "3cycle")])
-
;; ??? Write truncdisi pattern using sra?
(define_expand "zero_extendsidi2"
@@ -4301,7 +3761,8 @@
"andcc\t%1, 0xff, %0"
[(set_attr "type" "compare")])
-;;- sign extension instructions
+
+;; Sign-extension instructions
;; These patterns originally accepted general_operands, however, slightly
;; better code is generated by only accepting register_operands, and then
@@ -4486,7 +3947,8 @@
ldsw\t%1, %0"
[(set_attr "type" "shift,sload")
(set_attr "us3load_type" "*,3cycle")])
-
+
+
;; Special pattern for optimizing bit-field compares. This is needed
;; because combine uses this as a canonical form.
@@ -4494,23 +3956,14 @@
[(set (reg:CC 100)
(compare:CC
(zero_extract:SI (match_operand:SI 0 "register_operand" "r")
- (match_operand:SI 1 "small_int_or_double" "n")
- (match_operand:SI 2 "small_int_or_double" "n"))
+ (match_operand:SI 1 "small_int_operand" "I")
+ (match_operand:SI 2 "small_int_operand" "I"))
(const_int 0)))]
- "(GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) > 19)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (operands[2]) > 19)"
-{
- int len = (GET_CODE (operands[1]) == CONST_INT
- ? INTVAL (operands[1])
- : CONST_DOUBLE_LOW (operands[1]));
- int pos = 32 -
- (GET_CODE (operands[2]) == CONST_INT
- ? INTVAL (operands[2])
- : CONST_DOUBLE_LOW (operands[2])) - len;
+ "INTVAL (operands[2]) > 19"
+{
+ int len = INTVAL (operands[1]);
+ int pos = 32 - INTVAL (operands[2]) - len;
HOST_WIDE_INT mask = ((1 << len) - 1) << pos;
-
operands[1] = GEN_INT (mask);
return "andcc\t%0, %1, %%g0";
}
@@ -4520,29 +3973,20 @@
[(set (reg:CCX 100)
(compare:CCX
(zero_extract:DI (match_operand:DI 0 "register_operand" "r")
- (match_operand:SI 1 "small_int_or_double" "n")
- (match_operand:SI 2 "small_int_or_double" "n"))
+ (match_operand:SI 1 "small_int_operand" "I")
+ (match_operand:SI 2 "small_int_operand" "I"))
(const_int 0)))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) > 51)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && CONST_DOUBLE_LOW (operands[2]) > 51))"
-{
- int len = (GET_CODE (operands[1]) == CONST_INT
- ? INTVAL (operands[1])
- : CONST_DOUBLE_LOW (operands[1]));
- int pos = 64 -
- (GET_CODE (operands[2]) == CONST_INT
- ? INTVAL (operands[2])
- : CONST_DOUBLE_LOW (operands[2])) - len;
+ "TARGET_ARCH64 && INTVAL (operands[2]) > 51"
+{
+ int len = INTVAL (operands[1]);
+ int pos = 64 - INTVAL (operands[2]) - len;
HOST_WIDE_INT mask = (((unsigned HOST_WIDE_INT) 1 << len) - 1) << pos;
-
operands[1] = GEN_INT (mask);
return "andcc\t%0, %1, %%g0";
}
[(set_attr "type" "compare")])
-
+
+
;; Conversions between float, double and long double.
(define_insn "extendsfdf2"
@@ -4622,7 +4066,8 @@
"TARGET_FPU && TARGET_HARD_QUAD"
"fqtod\t%1, %0"
[(set_attr "type" "fp")])
-
+
+
;; Conversion between fixed point and floating point.
(define_insn "floatsisf2"
@@ -4672,9 +4117,9 @@
(define_expand "floatunsdisf2"
[(use (match_operand:SF 0 "register_operand" ""))
- (use (match_operand:DI 1 "register_operand" ""))]
+ (use (match_operand:DI 1 "general_operand" ""))]
"TARGET_ARCH64 && TARGET_FPU"
- "sparc_emit_floatunsdi (operands); DONE;")
+ "sparc_emit_floatunsdi (operands, SFmode); DONE;")
(define_insn "floatdidf2"
[(set (match_operand:DF 0 "register_operand" "=e")
@@ -4686,9 +4131,9 @@
(define_expand "floatunsdidf2"
[(use (match_operand:DF 0 "register_operand" ""))
- (use (match_operand:DI 1 "register_operand" ""))]
+ (use (match_operand:DI 1 "general_operand" ""))]
"TARGET_ARCH64 && TARGET_FPU"
- "sparc_emit_floatunsdi (operands); DONE;")
+ "sparc_emit_floatunsdi (operands, DFmode); DONE;")
(define_expand "floatditf2"
[(set (match_operand:TF 0 "nonimmediate_operand" "")
@@ -4757,6 +4202,12 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "fixuns_truncsfdi2"
+ [(use (match_operand:DI 0 "register_operand" ""))
+ (use (match_operand:SF 1 "general_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_fixunsdi (operands, SFmode); DONE;")
+
(define_insn "fix_truncdfdi2"
[(set (match_operand:DI 0 "register_operand" "=e")
(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "e"))))]
@@ -4765,6 +4216,12 @@
[(set_attr "type" "fp")
(set_attr "fptype" "double")])
+(define_expand "fixuns_truncdfdi2"
+ [(use (match_operand:DI 0 "register_operand" ""))
+ (use (match_operand:DF 1 "general_operand" ""))]
+ "TARGET_ARCH64 && TARGET_FPU"
+ "sparc_emit_fixunsdi (operands, DFmode); DONE;")
+
(define_expand "fix_trunctfdi2"
[(set (match_operand:DI 0 "register_operand" "")
(fix:DI (match_operand:TF 1 "general_operand" "")))]
@@ -4783,8 +4240,9 @@
(unsigned_fix:DI (match_operand:TF 1 "general_operand" "")))]
"TARGET_FPU && TARGET_ARCH64 && ! TARGET_HARD_QUAD"
"emit_tfmode_cvt (UNSIGNED_FIX, operands); DONE;")
-
-;;- arithmetic instructions
+
+
+;; Integer addition/subtraction instructions.
(define_expand "adddi3"
[(set (match_operand:DI 0 "register_operand" "")
@@ -4842,41 +4300,6 @@
}
[(set_attr "length" "2")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "arith_double_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64 && reload_completed"
- [(parallel [(set (reg:CC_NOOV 100)
- (compare:CC_NOOV (minus:SI (match_dup 4)
- (match_dup 5))
- (const_int 0)))
- (set (match_dup 3)
- (minus:SI (match_dup 4) (match_dup 5)))])
- (set (match_dup 6)
- (minus:SI (minus:SI (match_dup 7)
- (match_dup 8))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
-{
- operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_lowpart (SImode, operands[1]);
- operands[5] = gen_lowpart (SImode, operands[2]);
- operands[6] = gen_highpart (SImode, operands[0]);
- operands[7] = gen_highpart (SImode, operands[1]);
-#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) < 0)
- operands[8] = constm1_rtx;
- else
- operands[8] = const0_rtx;
- }
- else
-#endif
- operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
-})
-
;; LTU here means "carry set"
(define_insn "addx"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -4890,7 +4313,7 @@
(define_insn_and_split "*addx_extend_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extend:DI (plus:SI (plus:SI
- (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (match_operand:SI 1 "register_or_zero_operand" "%rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"! TARGET_ARCH64"
@@ -4905,46 +4328,13 @@
(define_insn "*addx_extend_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (zero_extend:DI (plus:SI (plus:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
"TARGET_ARCH64"
"addx\t%r1, %2, %0"
[(set_attr "type" "ialuX")])
-(define_insn "subx"
- [(set (match_operand:SI 0 "register_operand" "=r")
- (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
- ""
- "subx\t%r1, %2, %0"
- [(set_attr "type" "ialuX")])
-
-(define_insn "*subx_extend_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
- "TARGET_ARCH64"
- "subx\t%r1, %2, %0"
- [(set_attr "type" "ialuX")])
-
-(define_insn_and_split "*subx_extend"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
- (match_operand:SI 2 "arith_operand" "rI"))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
- "! TARGET_ARCH64"
- "#"
- "&& reload_completed"
- [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
- (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
- (set (match_dup 4) (const_int 0))]
- "operands[3] = gen_lowpart (SImode, operands[0]);
- operands[4] = gen_highpart (SImode, operands[0]);"
- [(set_attr "length" "2")])
-
(define_insn_and_split ""
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
@@ -4969,7 +4359,7 @@
(define_insn "*adddi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(plus:DI (match_operand:DI 1 "register_operand" "%r,r")
- (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
+ (match_operand:DI 2 "arith_add_operand" "rI,O")))]
"TARGET_ARCH64"
"@
add\t%1, %2, %0
@@ -4984,7 +4374,8 @@
add\t%1, %2, %0
sub\t%1, -%2, %0
fpadd32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")])
+ [(set_attr "type" "*,*,fga")
+ (set_attr "fptype" "*,*,single")])
(define_insn "*cmp_cc_plus"
[(set (reg:CC_NOOV 100)
@@ -4997,8 +4388,8 @@
(define_insn "*cmp_ccx_plus"
[(set (reg:CCX_NOOV 100)
- (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_double_operand" "%r")
- (match_operand:DI 1 "arith_double_operand" "rHI"))
+ (compare:CCX_NOOV (plus:DI (match_operand:DI 0 "arith_operand" "%r")
+ (match_operand:DI 1 "arith_operand" "rI"))
(const_int 0)))]
"TARGET_ARCH64"
"addcc\t%0, %1, %%g0"
@@ -5017,8 +4408,8 @@
(define_insn "*cmp_ccx_plus_set"
[(set (reg:CCX_NOOV 100)
- (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI"))
+ (compare:CCX_NOOV (plus:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (match_dup 1) (match_dup 2)))]
@@ -5044,62 +4435,77 @@
}
})
-(define_insn_and_split "*subdi3_sp32"
+(define_insn_and_split "subdi3_insn_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
- (minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
+ (minus:DI (match_operand:DI 1 "register_operand" "r")
+ (match_operand:DI 2 "arith_double_operand" "rHI")))
(clobber (reg:CC 100))]
"! TARGET_ARCH64"
"#"
- "&& reload_completed
- && (GET_CODE (operands[2]) == CONST_INT
- || GET_CODE (operands[2]) == CONST_DOUBLE)"
- [(clobber (const_int 0))]
+ "&& reload_completed"
+ [(parallel [(set (reg:CC_NOOV 100)
+ (compare:CC_NOOV (minus:SI (match_dup 4)
+ (match_dup 5))
+ (const_int 0)))
+ (set (match_dup 3)
+ (minus:SI (match_dup 4) (match_dup 5)))])
+ (set (match_dup 6)
+ (minus:SI (minus:SI (match_dup 7)
+ (match_dup 8))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
{
- rtx highp, lowp;
-
- highp = gen_highpart_mode (SImode, DImode, operands[2]);
- lowp = gen_lowpart (SImode, operands[2]);
- if ((lowp == const0_rtx)
- && (operands[0] == operands[1]))
+ operands[3] = gen_lowpart (SImode, operands[0]);
+ operands[4] = gen_lowpart (SImode, operands[1]);
+ operands[5] = gen_lowpart (SImode, operands[2]);
+ operands[6] = gen_highpart (SImode, operands[0]);
+ operands[7] = gen_highpart (SImode, operands[1]);
+#if HOST_BITS_PER_WIDE_INT == 32
+ if (GET_CODE (operands[2]) == CONST_INT)
{
- emit_insn (gen_rtx_SET (VOIDmode,
- gen_highpart (SImode, operands[0]),
- gen_rtx_MINUS (SImode,
- gen_highpart_mode (SImode, DImode,
- operands[1]),
- highp)));
+ if (INTVAL (operands[2]) < 0)
+ operands[8] = constm1_rtx;
+ else
+ operands[8] = const0_rtx;
}
else
- {
- emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
- gen_lowpart (SImode, operands[1]),
- lowp));
- emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
- gen_highpart_mode (SImode, DImode, operands[1]),
- highp));
- }
- DONE;
+#endif
+ operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
}
[(set_attr "length" "2")])
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (minus:DI (match_operand:DI 1 "register_operand" "")
- (match_operand:DI 2 "register_operand" "")))
- (clobber (reg:CC 100))]
- "! TARGET_ARCH64
- && reload_completed"
- [(clobber (const_int 0))]
-{
- emit_insn (gen_cmp_minus_cc_set (gen_lowpart (SImode, operands[0]),
- gen_lowpart (SImode, operands[1]),
- gen_lowpart (SImode, operands[2])));
- emit_insn (gen_subx (gen_highpart (SImode, operands[0]),
- gen_highpart (SImode, operands[1]),
- gen_highpart (SImode, operands[2])));
- DONE;
-})
+;; LTU here means "carry set"
+(define_insn "subx"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))]
+ ""
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn "*subx_extend_sp64"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "TARGET_ARCH64"
+ "subx\t%r1, %2, %0"
+ [(set_attr "type" "ialuX")])
+
+(define_insn_and_split "*subx_extend"
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (zero_extend:DI (minus:SI (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
+ (match_operand:SI 2 "arith_operand" "rI"))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0)))))]
+ "! TARGET_ARCH64"
+ "#"
+ "&& reload_completed"
+ [(set (match_dup 3) (minus:SI (minus:SI (match_dup 1) (match_dup 2))
+ (ltu:SI (reg:CC_NOOV 100) (const_int 0))))
+ (set (match_dup 4) (const_int 0))]
+ "operands[3] = gen_lowpart (SImode, operands[0]);
+ operands[4] = gen_highpart (SImode, operands[0]);"
+ [(set_attr "length" "2")])
(define_insn_and_split ""
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -5125,7 +4531,7 @@
(define_insn "*subdi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r,r")
(minus:DI (match_operand:DI 1 "register_operand" "r,r")
- (match_operand:DI 2 "arith_double_add_operand" "rHI,O")))]
+ (match_operand:DI 2 "arith_add_operand" "rI,O")))]
"TARGET_ARCH64"
"@
sub\t%1, %2, %0
@@ -5140,11 +4546,12 @@
sub\t%1, %2, %0
add\t%1, -%2, %0
fpsub32s\t%1, %2, %0"
- [(set_attr "type" "*,*,fga")])
+ [(set_attr "type" "*,*,fga")
+ (set_attr "fptype" "*,*,single")])
(define_insn "*cmp_minus_cc"
[(set (reg:CC_NOOV 100)
- (compare:CC_NOOV (minus:SI (match_operand:SI 0 "reg_or_0_operand" "rJ")
+ (compare:CC_NOOV (minus:SI (match_operand:SI 0 "register_or_zero_operand" "rJ")
(match_operand:SI 1 "arith_operand" "rI"))
(const_int 0)))]
""
@@ -5154,7 +4561,7 @@
(define_insn "*cmp_minus_ccx"
[(set (reg:CCX_NOOV 100)
(compare:CCX_NOOV (minus:DI (match_operand:DI 0 "register_operand" "r")
- (match_operand:DI 1 "arith_double_operand" "rHI"))
+ (match_operand:DI 1 "arith_operand" "rI"))
(const_int 0)))]
"TARGET_ARCH64"
"subcc\t%0, %1, %%g0"
@@ -5162,7 +4569,7 @@
(define_insn "cmp_minus_cc_set"
[(set (reg:CC_NOOV 100)
- (compare:CC_NOOV (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rJ")
+ (compare:CC_NOOV (minus:SI (match_operand:SI 1 "register_or_zero_operand" "rJ")
(match_operand:SI 2 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
@@ -5174,15 +4581,16 @@
(define_insn "*cmp_minus_ccx_set"
[(set (reg:CCX_NOOV 100)
(compare:CCX_NOOV (minus:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI"))
+ (match_operand:DI 2 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(minus:DI (match_dup 1) (match_dup 2)))]
"TARGET_ARCH64"
"subcc\t%1, %2, %0"
[(set_attr "type" "compare")])
-
-;; Integer Multiply/Divide.
+
+
+;; Integer multiply/divide instructions.
;; The 32 bit multiply/divide instructions are deprecated on v9, but at
;; least in UltraSPARC I, II and IIi it is a win tick-wise.
@@ -5196,9 +4604,9 @@
[(set_attr "type" "imul")])
(define_expand "muldi3"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mult:DI (match_operand:DI 1 "arith_operand" "")
+ (match_operand:DI 2 "arith_operand" "")))]
"TARGET_ARCH64 || TARGET_V8PLUS"
{
if (TARGET_V8PLUS)
@@ -5210,8 +4618,8 @@
(define_insn "*muldi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
- (mult:DI (match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (mult:DI (match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
"mulx\t%1, %2, %0"
[(set_attr "type" "imul")])
@@ -5220,8 +4628,8 @@
;; XXX
(define_insn "muldi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=r,h")
- (mult:DI (match_operand:DI 1 "arith_double_operand" "%r,0")
- (match_operand:DI 2 "arith_double_operand" "rI,rI")))
+ (mult:DI (match_operand:DI 1 "arith_operand" "%r,0")
+ (match_operand:DI 2 "arith_operand" "rI,rI")))
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_V8PLUS"
@@ -5310,7 +4718,7 @@
(define_insn "const_mulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:DI 2 "small_int" "I,I")))
+ (match_operand:DI 2 "small_int_operand" "I,I")))
(clobber (match_scratch:SI 3 "=X,&h"))]
"TARGET_V8PLUS"
"@
@@ -5351,7 +4759,7 @@
(define_insn "const_mulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "small_int" "I")))]
+ (match_operand:DI 2 "small_int_operand" "I")))]
"TARGET_HARD_MUL32"
{
return TARGET_SPARCLET
@@ -5368,7 +4776,7 @@
(define_insn "const_mulsidi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "small_int" "I")))]
+ (match_operand:DI 2 "small_int_operand" "I")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
"smul\t%1, %2, %0"
[(set_attr "type" "imul")])
@@ -5408,7 +4816,7 @@
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
- (match_operand:SI 3 "const_int_operand" "i,i"))))
+ (match_operand:SI 3 "small_int_operand" "I,I"))))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
@@ -5425,7 +4833,7 @@
(lshiftrt:DI
(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(sign_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
- (match_operand:SI 3 "const_int_operand" "i,i"))
+ (match_operand:SI 3 "small_int_operand" "I,I"))
4))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
@@ -5440,8 +4848,8 @@
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:DI 2 "small_int" "i,i"))
- (match_operand:SI 3 "const_int_operand" "i,i"))))
+ (match_operand:DI 2 "small_int_operand" "I,I"))
+ (match_operand:SI 3 "small_int_operand" "I,I"))))
(clobber (match_scratch:SI 4 "=X,&h"))]
"TARGET_V8PLUS"
"@
@@ -5467,7 +4875,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "small_int" "i"))
+ (match_operand:DI 2 "small_int_operand" "i"))
(const_int 32))))]
"TARGET_HARD_MUL32"
"smul\t%1, %2, %%g0\n\trd\t%%y, %0"
@@ -5545,7 +4953,7 @@
(define_insn "const_umulsidi3_sp32"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "uns_small_int" "")))]
+ (match_operand:DI 2 "uns_small_int_operand" "")))]
"TARGET_HARD_MUL32"
{
return TARGET_SPARCLET
@@ -5562,7 +4970,7 @@
(define_insn "const_umulsidi3_sp64"
[(set (match_operand:DI 0 "register_operand" "=r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "uns_small_int" "")))]
+ (match_operand:DI 2 "uns_small_int_operand" "")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
"umul\t%1, %s2, %0"
[(set_attr "type" "imul")])
@@ -5571,7 +4979,7 @@
(define_insn "const_umulsidi3_v8plus"
[(set (match_operand:DI 0 "register_operand" "=h,r")
(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:DI 2 "uns_small_int" "")))
+ (match_operand:DI 2 "uns_small_int_operand" "")))
(clobber (match_scratch:SI 3 "=X,h"))]
"TARGET_V8PLUS"
"@
@@ -5615,7 +5023,7 @@
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
(zero_extend:DI (match_operand:SI 2 "register_operand" "r,r")))
- (match_operand:SI 3 "const_int_operand" "i,i"))))
+ (match_operand:SI 3 "small_int_operand" "I,I"))))
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
@@ -5629,8 +5037,8 @@
[(set (match_operand:SI 0 "register_operand" "=h,r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
- (match_operand:DI 2 "uns_small_int" ""))
- (match_operand:SI 3 "const_int_operand" "i,i"))))
+ (match_operand:DI 2 "uns_small_int_operand" ""))
+ (match_operand:SI 3 "small_int_operand" "I,I"))))
(clobber (match_scratch:SI 4 "=X,h"))]
"TARGET_V8PLUS"
"@
@@ -5656,15 +5064,15 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(truncate:SI
(lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- (match_operand:DI 2 "uns_small_int" ""))
+ (match_operand:DI 2 "uns_small_int_operand" ""))
(const_int 32))))]
"TARGET_HARD_MUL32"
"umul\t%1, %s2, %%g0\n\trd\t%%y, %0"
[(set_attr "type" "multi")
(set_attr "length" "2")])
-;; The v8 architecture specifies that there must be 3 instructions between
-;; a y register write and a use of it for correct results.
+;; The V8 architecture specifies that there must be 3 instructions between
+;; a Y register write and a use of it for correct results.
(define_expand "divsi3"
[(parallel [(set (match_operand:SI 0 "register_operand" "=r,r")
@@ -5720,7 +5128,7 @@
(define_insn "divdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(div:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
"sdivx\t%1, %2, %0"
[(set_attr "type" "idiv")])
@@ -5748,17 +5156,19 @@
;; XXX
(define_expand "udivsi3"
[(set (match_operand:SI 0 "register_operand" "")
- (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "")
+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "")
(match_operand:SI 2 "input_operand" "")))]
"TARGET_V8 || TARGET_DEPRECATED_V8_INSNS"
"")
+;; The V8 architecture specifies that there must be 3 instructions between
+;; a Y register write and a use of it for correct results.
+
(define_insn "udivsi3_sp32"
[(set (match_operand:SI 0 "register_operand" "=r,&r,&r")
- (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r,r,m")
+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r,r,m")
(match_operand:SI 2 "input_operand" "rI,m,r")))]
- "(TARGET_V8
- || TARGET_DEPRECATED_V8_INSNS)
+ "(TARGET_V8 || TARGET_DEPRECATED_V8_INSNS)
&& TARGET_ARCH32"
{
output_asm_insn ("wr\t%%g0, %%g0, %%y", operands);
@@ -5777,7 +5187,7 @@
(define_insn "udivsi3_sp64"
[(set (match_operand:SI 0 "register_operand" "=r")
- (udiv:SI (match_operand:SI 1 "reg_or_nonsymb_mem_operand" "r")
+ (udiv:SI (match_operand:SI 1 "nonimmediate_operand" "r")
(match_operand:SI 2 "input_operand" "rI")))]
"TARGET_DEPRECATED_V8_INSNS && TARGET_ARCH64"
"wr\t%%g0, 0, %%y\n\tudiv\t%1, %2, %0"
@@ -5787,7 +5197,7 @@
(define_insn "udivdi3"
[(set (match_operand:DI 0 "register_operand" "=r")
(udiv:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))]
+ (match_operand:DI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
"udivx\t%1, %2, %0"
[(set_attr "type" "idiv")])
@@ -5844,103 +5254,73 @@
"TARGET_SPARCLET"
"umacd\t%1, %2, %L0"
[(set_attr "type" "imul")])
-
-;;- Boolean instructions
+
+
+;; Boolean instructions.
+
;; We define DImode `and' so with DImode `not' we can get
;; DImode `andn'. Other combinations are possible.
-(define_expand "anddi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (and:DI (match_operand:DI 1 "arith_double_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))]
+(define_mode_macro V64I [DI V2SI V4HI V8QI])
+(define_mode_macro V32I [SI V2HI V4QI])
+
+(define_expand "and<V64I:mode>3"
+ [(set (match_operand:V64I 0 "register_operand" "")
+ (and:V64I (match_operand:V64I 1 "arith_double_operand" "")
+ (match_operand:V64I 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*anddi3_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*and<V64I:mode>3_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (and:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
+ (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
"@
#
fand\t%1, %2, %0"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*anddi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (and:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*and<V64I:mode>3_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (and:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
+ (match_operand:V64I 2 "arith_operand" "rI,b")))]
"TARGET_ARCH64"
"@
and\t%1, %2, %0
fand\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "andsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (and:SI (match_operand:SI 1 "arith_operand" "%r,d")
- (match_operand:SI 2 "arith_operand" "rI,d")))]
+(define_insn "and<V32I:mode>3"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (and:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
+ (match_operand:V32I 2 "arith_operand" "rI,d")))]
""
"@
and\t%1, %2, %0
fands\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(and:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "" "")))
+ (match_operand:SI 2 "const_compl_high_operand" "")))
(clobber (match_operand:SI 3 "register_operand" ""))]
- "GET_CODE (operands[2]) == CONST_INT
- && !SMALL_INT32 (operands[2])
- && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
+ ""
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (and:SI (not:SI (match_dup 3)) (match_dup 1)))]
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-;; Split DImode logical operations requiring two instructions.
-(define_split
- [(set (match_operand:DI 0 "register_operand" "")
- (match_operator:DI 1 "cc_arithop" ; AND, IOR, XOR
- [(match_operand:DI 2 "register_operand" "")
- (match_operand:DI 3 "arith_double_operand" "")]))]
- "! TARGET_ARCH64
- && reload_completed
- && ((GET_CODE (operands[0]) == REG
- && REGNO (operands[0]) < 32)
- || (GET_CODE (operands[0]) == SUBREG
- && GET_CODE (SUBREG_REG (operands[0])) == REG
- && REGNO (SUBREG_REG (operands[0])) < 32))"
- [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
- (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
-{
- operands[4] = gen_highpart (SImode, operands[0]);
- operands[5] = gen_lowpart (SImode, operands[0]);
- operands[6] = gen_highpart (SImode, operands[2]);
- operands[7] = gen_lowpart (SImode, operands[2]);
-#if HOST_BITS_PER_WIDE_INT == 32
- if (GET_CODE (operands[3]) == CONST_INT)
- {
- if (INTVAL (operands[3]) < 0)
- operands[8] = constm1_rtx;
- else
- operands[8] = const0_rtx;
- }
- else
-#endif
- operands[8] = gen_highpart_mode (SImode, DImode, operands[3]);
- operands[9] = gen_lowpart (SImode, operands[3]);
-})
-
-(define_insn_and_split "*and_not_di_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
- (match_operand:DI 2 "register_operand" "r,b")))]
+(define_insn_and_split "*and_not_<V64I:mode>_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
+ (match_operand:V64I 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
@@ -5961,87 +5341,87 @@
operands[8] = gen_lowpart (SImode, operands[2]);"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*and_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (and:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
- (match_operand:DI 2 "register_operand" "r,b")))]
+(define_insn "*and_not_<V64I:mode>_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (and:V64I (not:V64I (match_operand:V64I 1 "register_operand" "%r,b"))
+ (match_operand:V64I 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
"@
andn\t%2, %1, %0
fandnot1\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*and_not_si"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (and:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
- (match_operand:SI 2 "register_operand" "r,d")))]
+(define_insn "*and_not_<V32I:mode>"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (and:V32I (not:V32I (match_operand:V32I 1 "register_operand" "%r,d"))
+ (match_operand:V32I 2 "register_operand" "r,d")))]
""
"@
andn\t%2, %1, %0
fandnot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
-(define_expand "iordi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (ior:DI (match_operand:DI 1 "arith_double_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))]
+(define_expand "ior<V64I:mode>3"
+ [(set (match_operand:V64I 0 "register_operand" "")
+ (ior:V64I (match_operand:V64I 1 "arith_double_operand" "")
+ (match_operand:V64I 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*iordi3_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*ior<V64I:mode>3_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (ior:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
+ (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
"@
#
for\t%1, %2, %0"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*iordi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (ior:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*ior<V64I:mode>3_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (ior:V64I (match_operand:V64I 1 "arith_operand" "%r,b")
+ (match_operand:V64I 2 "arith_operand" "rI,b")))]
"TARGET_ARCH64"
"@
or\t%1, %2, %0
for\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "iorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (ior:SI (match_operand:SI 1 "arith_operand" "%r,d")
- (match_operand:SI 2 "arith_operand" "rI,d")))]
+(define_insn "ior<V32I:mode>3"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (ior:V32I (match_operand:V32I 1 "arith_operand" "%r,d")
+ (match_operand:V32I 2 "arith_operand" "rI,d")))]
""
"@
or\t%1, %2, %0
fors\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(ior:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "" "")))
+ (match_operand:SI 2 "const_compl_high_operand" "")))
(clobber (match_operand:SI 3 "register_operand" ""))]
- "GET_CODE (operands[2]) == CONST_INT
- && !SMALL_INT32 (operands[2])
- && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
+ ""
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (ior:SI (not:SI (match_dup 3)) (match_dup 1)))]
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
-(define_insn_and_split "*or_not_di_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
- (match_operand:DI 2 "register_operand" "r,b")))]
+(define_insn_and_split "*or_not_<V64I:mode>_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
+ (match_operand:V64I 2 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
@@ -6062,85 +5442,77 @@
operands[8] = gen_lowpart (SImode, operands[2]);"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*or_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (ior:DI (not:DI (match_operand:DI 1 "register_operand" "r,b"))
- (match_operand:DI 2 "register_operand" "r,b")))]
+(define_insn "*or_not_<V64I:mode>_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (ior:V64I (not:V64I (match_operand:V64I 1 "register_operand" "r,b"))
+ (match_operand:V64I 2 "register_operand" "r,b")))]
"TARGET_ARCH64"
"@
orn\t%2, %1, %0
fornot1\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*or_not_si"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (ior:SI (not:SI (match_operand:SI 1 "register_operand" "r,d"))
- (match_operand:SI 2 "register_operand" "r,d")))]
+(define_insn "*or_not_<V32I:mode>"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (ior:V32I (not:V32I (match_operand:V32I 1 "register_operand" "r,d"))
+ (match_operand:V32I 2 "register_operand" "r,d")))]
""
"@
orn\t%2, %1, %0
fornot1s\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
-(define_expand "xordi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (xor:DI (match_operand:DI 1 "arith_double_operand" "")
- (match_operand:DI 2 "arith_double_operand" "")))]
+(define_expand "xor<V64I:mode>3"
+ [(set (match_operand:V64I 0 "register_operand" "")
+ (xor:V64I (match_operand:V64I 1 "arith_double_operand" "")
+ (match_operand:V64I 2 "arith_double_operand" "")))]
""
"")
-(define_insn "*xordi3_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (xor:DI (match_operand:DI 1 "arith_double_operand" "%r,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*xor<V64I:mode>3_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (xor:V64I (match_operand:V64I 1 "arith_double_operand" "%r,b")
+ (match_operand:V64I 2 "arith_double_operand" "rHI,b")))]
"! TARGET_ARCH64"
"@
#
fxor\t%1, %2, %0"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*xordi3_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (xor:DI (match_operand:DI 1 "arith_double_operand" "%rJ,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b")))]
+(define_insn "*xor<V64I:mode>3_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (xor:V64I (match_operand:V64I 1 "arith_operand" "%rJ,b")
+ (match_operand:V64I 2 "arith_operand" "rI,b")))]
"TARGET_ARCH64"
"@
xor\t%r1, %2, %0
fxor\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*xordi3_sp64_dbl"
- [(set (match_operand:DI 0 "register_operand" "=r")
- (xor:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:DI 2 "const64_operand" "")))]
- "(TARGET_ARCH64
- && HOST_BITS_PER_WIDE_INT != 64)"
- "xor\t%1, %2, %0")
-
-(define_insn "xorsi3"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (xor:SI (match_operand:SI 1 "arith_operand" "%rJ,d")
- (match_operand:SI 2 "arith_operand" "rI,d")))]
+(define_insn "xor<V32I:mode>3"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (xor:V32I (match_operand:V32I 1 "arith_operand" "%rJ,d")
+ (match_operand:V32I 2 "arith_operand" "rI,d")))]
""
"@
xor\t%r1, %2, %0
fxors\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(xor:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "" "")))
+ (match_operand:SI 2 "const_compl_high_operand" "")))
(clobber (match_operand:SI 3 "register_operand" ""))]
- "GET_CODE (operands[2]) == CONST_INT
- && !SMALL_INT32 (operands[2])
- && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
+ ""
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (not:SI (xor:SI (match_dup 3) (match_dup 1))))]
{
@@ -6150,23 +5522,55 @@
(define_split
[(set (match_operand:SI 0 "register_operand" "")
(not:SI (xor:SI (match_operand:SI 1 "register_operand" "")
- (match_operand:SI 2 "" ""))))
+ (match_operand:SI 2 "const_compl_high_operand" ""))))
(clobber (match_operand:SI 3 "register_operand" ""))]
- "GET_CODE (operands[2]) == CONST_INT
- && !SMALL_INT32 (operands[2])
- && (INTVAL (operands[2]) & 0x3ff) == 0x3ff"
+ ""
[(set (match_dup 3) (match_dup 4))
(set (match_dup 0) (xor:SI (match_dup 3) (match_dup 1)))]
{
operands[4] = GEN_INT (~INTVAL (operands[2]));
})
+;; Split DImode logical operations requiring two instructions.
+(define_split
+ [(set (match_operand:V64I 0 "register_operand" "")
+ (match_operator:V64I 1 "cc_arith_operator" ; AND, IOR, XOR
+ [(match_operand:V64I 2 "register_operand" "")
+ (match_operand:V64I 3 "arith_double_operand" "")]))]
+ "! TARGET_ARCH64
+ && reload_completed
+ && ((GET_CODE (operands[0]) == REG
+ && REGNO (operands[0]) < 32)
+ || (GET_CODE (operands[0]) == SUBREG
+ && GET_CODE (SUBREG_REG (operands[0])) == REG
+ && REGNO (SUBREG_REG (operands[0])) < 32))"
+ [(set (match_dup 4) (match_op_dup:SI 1 [(match_dup 6) (match_dup 8)]))
+ (set (match_dup 5) (match_op_dup:SI 1 [(match_dup 7) (match_dup 9)]))]
+{
+ operands[4] = gen_highpart (SImode, operands[0]);
+ operands[5] = gen_lowpart (SImode, operands[0]);
+ operands[6] = gen_highpart (SImode, operands[2]);
+ operands[7] = gen_lowpart (SImode, operands[2]);
+#if HOST_BITS_PER_WIDE_INT == 32
+ if (GET_CODE (operands[3]) == CONST_INT && <V64I:MODE>mode == DImode)
+ {
+ if (INTVAL (operands[3]) < 0)
+ operands[8] = constm1_rtx;
+ else
+ operands[8] = const0_rtx;
+ }
+ else
+#endif
+ operands[8] = gen_highpart_mode (SImode, <V64I:MODE>mode, operands[3]);
+ operands[9] = gen_lowpart (SImode, operands[3]);
+})
+
;; xnor patterns. Note that (a ^ ~b) == (~a ^ b) == ~(a ^ b).
;; Combine now canonicalizes to the rightmost expression.
-(define_insn_and_split "*xor_not_di_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (not:DI (xor:DI (match_operand:DI 1 "register_operand" "r,b")
- (match_operand:DI 2 "register_operand" "r,b"))))]
+(define_insn_and_split "*xor_not_<V64I:mode>_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (not:V64I (xor:V64I (match_operand:V64I 1 "register_operand" "r,b")
+ (match_operand:V64I 2 "register_operand" "r,b"))))]
"! TARGET_ARCH64"
"@
#
@@ -6187,28 +5591,29 @@
operands[8] = gen_lowpart (SImode, operands[2]);"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*xor_not_di_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "rJ,b")
- (match_operand:DI 2 "arith_double_operand" "rHI,b"))))]
+(define_insn "*xor_not_<V64I:mode>_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (not:V64I (xor:V64I (match_operand:V64I 1 "register_or_zero_operand" "rJ,b")
+ (match_operand:V64I 2 "arith_operand" "rI,b"))))]
"TARGET_ARCH64"
"@
xnor\t%r1, %2, %0
fxnor\t%1, %2, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*xor_not_si"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "rJ,d")
- (match_operand:SI 2 "arith_operand" "rI,d"))))]
+(define_insn "*xor_not_<V32I:mode>"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (not:V32I (xor:V32I (match_operand:V32I 1 "register_or_zero_operand" "rJ,d")
+ (match_operand:V32I 2 "arith_operand" "rI,d"))))]
""
"@
xnor\t%r1, %2, %0
fxnors\t%1, %2, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
;; These correspond to the above in the case where we also (or only)
;; want to set the condition code.
@@ -6216,7 +5621,7 @@
(define_insn "*cmp_cc_arith_op"
[(set (reg:CC 100)
(compare:CC
- (match_operator:SI 2 "cc_arithop"
+ (match_operator:SI 2 "cc_arith_operator"
[(match_operand:SI 0 "arith_operand" "%r")
(match_operand:SI 1 "arith_operand" "rI")])
(const_int 0)))]
@@ -6227,9 +5632,9 @@
(define_insn "*cmp_ccx_arith_op"
[(set (reg:CCX 100)
(compare:CCX
- (match_operator:DI 2 "cc_arithop"
- [(match_operand:DI 0 "arith_double_operand" "%r")
- (match_operand:DI 1 "arith_double_operand" "rHI")])
+ (match_operator:DI 2 "cc_arith_operator"
+ [(match_operand:DI 0 "arith_operand" "%r")
+ (match_operand:DI 1 "arith_operand" "rI")])
(const_int 0)))]
"TARGET_ARCH64"
"%A2cc\t%0, %1, %%g0"
@@ -6238,12 +5643,12 @@
(define_insn "*cmp_cc_arith_op_set"
[(set (reg:CC 100)
(compare:CC
- (match_operator:SI 3 "cc_arithop"
+ (match_operator:SI 3 "cc_arith_operator"
[(match_operand:SI 1 "arith_operand" "%r")
(match_operand:SI 2 "arith_operand" "rI")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ (match_operator:SI 4 "cc_arith_operator" [(match_dup 1) (match_dup 2)]))]
"GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%A3cc\t%1, %2, %0"
[(set_attr "type" "compare")])
@@ -6251,12 +5656,12 @@
(define_insn "*cmp_ccx_arith_op_set"
[(set (reg:CCX 100)
(compare:CCX
- (match_operator:DI 3 "cc_arithop"
- [(match_operand:DI 1 "arith_double_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")])
+ (match_operator:DI 3 "cc_arith_operator"
+ [(match_operand:DI 1 "arith_operand" "%r")
+ (match_operand:DI 2 "arith_operand" "rI")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_operator:DI 4 "cc_arithop" [(match_dup 1) (match_dup 2)]))]
+ (match_operator:DI 4 "cc_arith_operator" [(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")])
@@ -6264,7 +5669,7 @@
(define_insn "*cmp_cc_xor_not"
[(set (reg:CC 100)
(compare:CC
- (not:SI (xor:SI (match_operand:SI 0 "reg_or_0_operand" "%rJ")
+ (not:SI (xor:SI (match_operand:SI 0 "register_or_zero_operand" "%rJ")
(match_operand:SI 1 "arith_operand" "rI")))
(const_int 0)))]
""
@@ -6274,8 +5679,8 @@
(define_insn "*cmp_ccx_xor_not"
[(set (reg:CCX 100)
(compare:CCX
- (not:DI (xor:DI (match_operand:DI 0 "reg_or_0_operand" "%rJ")
- (match_operand:DI 1 "arith_double_operand" "rHI")))
+ (not:DI (xor:DI (match_operand:DI 0 "register_or_zero_operand" "%rJ")
+ (match_operand:DI 1 "arith_operand" "rI")))
(const_int 0)))]
"TARGET_ARCH64"
"xnorcc\t%r0, %1, %%g0"
@@ -6284,7 +5689,7 @@
(define_insn "*cmp_cc_xor_not_set"
[(set (reg:CC 100)
(compare:CC
- (not:SI (xor:SI (match_operand:SI 1 "reg_or_0_operand" "%rJ")
+ (not:SI (xor:SI (match_operand:SI 1 "register_or_zero_operand" "%rJ")
(match_operand:SI 2 "arith_operand" "rI")))
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
@@ -6296,8 +5701,8 @@
(define_insn "*cmp_ccx_xor_not_set"
[(set (reg:CCX 100)
(compare:CCX
- (not:DI (xor:DI (match_operand:DI 1 "reg_or_0_operand" "%rJ")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
+ (not:DI (xor:DI (match_operand:DI 1 "register_or_zero_operand" "%rJ")
+ (match_operand:DI 2 "arith_operand" "rI")))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (xor:DI (match_dup 1) (match_dup 2))))]
@@ -6308,9 +5713,9 @@
(define_insn "*cmp_cc_arith_op_not"
[(set (reg:CC 100)
(compare:CC
- (match_operator:SI 2 "cc_arithopn"
+ (match_operator:SI 2 "cc_arith_not_operator"
[(not:SI (match_operand:SI 0 "arith_operand" "rI"))
- (match_operand:SI 1 "reg_or_0_operand" "rJ")])
+ (match_operand:SI 1 "register_or_zero_operand" "rJ")])
(const_int 0)))]
""
"%B2cc\t%r1, %0, %%g0"
@@ -6319,9 +5724,9 @@
(define_insn "*cmp_ccx_arith_op_not"
[(set (reg:CCX 100)
(compare:CCX
- (match_operator:DI 2 "cc_arithopn"
- [(not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
- (match_operand:DI 1 "reg_or_0_operand" "rJ")])
+ (match_operator:DI 2 "cc_arith_not_operator"
+ [(not:DI (match_operand:DI 0 "arith_operand" "rI"))
+ (match_operand:DI 1 "register_or_zero_operand" "rJ")])
(const_int 0)))]
"TARGET_ARCH64"
"%B2cc\t%r1, %0, %%g0"
@@ -6330,12 +5735,12 @@
(define_insn "*cmp_cc_arith_op_not_set"
[(set (reg:CC 100)
(compare:CC
- (match_operator:SI 3 "cc_arithopn"
+ (match_operator:SI 3 "cc_arith_not_operator"
[(not:SI (match_operand:SI 1 "arith_operand" "rI"))
- (match_operand:SI 2 "reg_or_0_operand" "rJ")])
+ (match_operand:SI 2 "register_or_zero_operand" "rJ")])
(const_int 0)))
(set (match_operand:SI 0 "register_operand" "=r")
- (match_operator:SI 4 "cc_arithopn"
+ (match_operator:SI 4 "cc_arith_not_operator"
[(not:SI (match_dup 1)) (match_dup 2)]))]
"GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\t%r2, %1, %0"
@@ -6344,12 +5749,12 @@
(define_insn "*cmp_ccx_arith_op_not_set"
[(set (reg:CCX 100)
(compare:CCX
- (match_operator:DI 3 "cc_arithopn"
- [(not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
- (match_operand:DI 2 "reg_or_0_operand" "rJ")])
+ (match_operator:DI 3 "cc_arith_not_operator"
+ [(not:DI (match_operand:DI 1 "arith_operand" "rI"))
+ (match_operand:DI 2 "register_or_zero_operand" "rJ")])
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
- (match_operator:DI 4 "cc_arithopn"
+ (match_operator:DI 4 "cc_arith_not_operator"
[(not:DI (match_dup 1)) (match_dup 2)]))]
"TARGET_ARCH64 && GET_CODE (operands[3]) == GET_CODE (operands[4])"
"%B3cc\t%r2, %1, %0"
@@ -6418,7 +5823,7 @@
(define_insn "*cmp_ccx_neg"
[(set (reg:CCX_NOOV 100)
- (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
+ (compare:CCX_NOOV (neg:DI (match_operand:DI 0 "arith_operand" "rI"))
(const_int 0)))]
"TARGET_ARCH64"
"subcc\t%%g0, %0, %%g0"
@@ -6436,7 +5841,7 @@
(define_insn "*cmp_ccx_set_neg"
[(set (reg:CCX_NOOV 100)
- (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
+ (compare:CCX_NOOV (neg:DI (match_operand:DI 1 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(neg:DI (match_dup 1)))]
@@ -6446,15 +5851,15 @@
;; We cannot use the "not" pseudo insn because the Sun assembler
;; does not know how to make it work for constants.
-(define_expand "one_cmpldi2"
- [(set (match_operand:DI 0 "register_operand" "")
- (not:DI (match_operand:DI 1 "register_operand" "")))]
+(define_expand "one_cmpl<V64I:mode>2"
+ [(set (match_operand:V64I 0 "register_operand" "")
+ (not:V64I (match_operand:V64I 1 "register_operand" "")))]
""
"")
-(define_insn_and_split "*one_cmpldi2_sp32"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (not:DI (match_operand:DI 1 "register_operand" "r,b")))]
+(define_insn_and_split "*one_cmpl<V64I:mode>2_sp32"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (not:V64I (match_operand:V64I 1 "register_operand" "r,b")))]
"! TARGET_ARCH64"
"@
#
@@ -6473,26 +5878,27 @@
operands[5] = gen_lowpart (SImode, operands[1]);"
[(set_attr "type" "*,fga")
(set_attr "length" "2,*")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "*one_cmpldi2_sp64"
- [(set (match_operand:DI 0 "register_operand" "=r,b")
- (not:DI (match_operand:DI 1 "arith_double_operand" "rHI,b")))]
+(define_insn "*one_cmpl<V64I:mode>2_sp64"
+ [(set (match_operand:V64I 0 "register_operand" "=r,b")
+ (not:V64I (match_operand:V64I 1 "arith_operand" "rI,b")))]
"TARGET_ARCH64"
"@
xnor\t%%g0, %1, %0
fnot1\t%1, %0"
[(set_attr "type" "*,fga")
- (set_attr "fptype" "double")])
+ (set_attr "fptype" "*,double")])
-(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "register_operand" "=r,d")
- (not:SI (match_operand:SI 1 "arith_operand" "rI,d")))]
+(define_insn "one_cmpl<V32I:mode>2"
+ [(set (match_operand:V32I 0 "register_operand" "=r,d")
+ (not:V32I (match_operand:V32I 1 "arith_operand" "rI,d")))]
""
"@
xnor\t%%g0, %1, %0
fnot1s\t%1, %0"
- [(set_attr "type" "*,fga")])
+ [(set_attr "type" "*,fga")
+ (set_attr "fptype" "*,single")])
(define_insn "*cmp_cc_not"
[(set (reg:CC 100)
@@ -6504,7 +5910,7 @@
(define_insn "*cmp_ccx_not"
[(set (reg:CCX 100)
- (compare:CCX (not:DI (match_operand:DI 0 "arith_double_operand" "rHI"))
+ (compare:CCX (not:DI (match_operand:DI 0 "arith_operand" "rI"))
(const_int 0)))]
"TARGET_ARCH64"
"xnorcc\t%%g0, %0, %%g0"
@@ -6522,7 +5928,7 @@
(define_insn "*cmp_ccx_set_not"
[(set (reg:CCX 100)
- (compare:CCX (not:DI (match_operand:DI 1 "arith_double_operand" "rHI"))
+ (compare:CCX (not:DI (match_operand:DI 1 "arith_operand" "rI"))
(const_int 0)))
(set (match_operand:DI 0 "register_operand" "=r")
(not:DI (match_dup 1)))]
@@ -6549,7 +5955,8 @@
"TARGET_ARCH64"
"orcc\t%1, 0, %0"
[(set_attr "type" "compare")])
-
+
+
;; Floating point arithmetic instructions.
(define_expand "addtf3"
@@ -6909,8 +6316,9 @@
"TARGET_FPU"
"fsqrts\t%1, %0"
[(set_attr "type" "fpsqrts")])
-
-;;- arithmetic shift instructions
+
+
+;; Arithmetic shift instructions.
(define_insn "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -6918,14 +6326,12 @@
(match_operand:SI 2 "arith_operand" "rI")))]
""
{
- if (operands[2] == const1_rtx)
- return "add\t%1, %1, %0";
if (GET_CODE (operands[2]) == CONST_INT)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);
return "sll\t%1, %2, %0";
}
[(set (attr "type")
- (if_then_else (match_operand 2 "const1_operand" "")
+ (if_then_else (match_operand 2 "const_one_operand" "")
(const_string "ialu") (const_string "shift")))])
(define_expand "ashldi3"
@@ -6949,14 +6355,12 @@
(match_operand:SI 2 "arith_operand" "rI")))]
"TARGET_ARCH64"
{
- if (operands[2] == const1_rtx)
- return "add\t%1, %1, %0";
if (GET_CODE (operands[2]) == CONST_INT)
operands[2] = GEN_INT (INTVAL (operands[2]) & 0x3f);
return "sllx\t%1, %2, %0";
}
[(set (attr "type")
- (if_then_else (match_operand 2 "const1_operand" "")
+ (if_then_else (match_operand 2 "const_one_operand" "")
(const_string "ialu") (const_string "shift")))])
;; XXX UGH!
@@ -6966,7 +6370,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- { return sparc_v8plus_shift (operands, insn, "sllx"); }
+ "* return output_v8plus_shift (operands, insn, \"sllx\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7033,17 +6437,10 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(ashiftrt:DI (ashift:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
(const_int 32))
- (match_operand:SI 2 "small_int_or_double" "n")))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[2]) == CONST_INT
- && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && !CONST_DOUBLE_HIGH (operands[2])
- && CONST_DOUBLE_LOW (operands[2]) >= 32
- && CONST_DOUBLE_LOW (operands[2]) < 64))"
+ (match_operand:SI 2 "small_int_operand" "I")))]
+ "TARGET_ARCH64 && INTVAL (operands[2]) >= 32 && INTVAL (operands[2]) < 64"
{
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
-
return "sra\t%1, %2, %0";
}
[(set_attr "type" "shift")])
@@ -7083,7 +6480,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- { return sparc_v8plus_shift (operands, insn, "srax"); }
+ "* return output_v8plus_shift (operands, insn, \"srax\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7106,14 +6503,8 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(and:DI (subreg:DI (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "arith_operand" "r")) 0)
- (match_operand 3 "" "")))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[3]) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (operands[3]) == 0
- && CONST_DOUBLE_LOW (operands[3]) == 0xffffffff)
- || (HOST_BITS_PER_WIDE_INT >= 64
- && GET_CODE (operands[3]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff))"
+ (match_operand 3 "const_int_operand" "")))]
+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[3]) == 0xffffffff"
"srl\t%1, %2, %0"
[(set_attr "type" "shift")])
@@ -7123,17 +6514,11 @@
(define_insn "*lshrsi3_extend2"
[(set (match_operand:DI 0 "register_operand" "=r")
(zero_extract:DI (subreg:DI (match_operand:SI 1 "register_operand" "r") 0)
- (match_operand 2 "small_int_or_double" "n")
+ (match_operand 2 "small_int_operand" "I")
(const_int 32)))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && CONST_DOUBLE_HIGH (operands[2]) == 0
- && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32"
{
operands[2] = GEN_INT (32 - INTVAL (operands[2]));
-
return "srl\t%1, %2, %0";
}
[(set_attr "type" "shift")])
@@ -7172,7 +6557,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- { return sparc_v8plus_shift (operands, insn, "srlx"); }
+ "* return output_v8plus_shift (operands, insn, \"srlx\");"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -7180,16 +6565,10 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
(const_int 32)) 4)
- (match_operand:SI 2 "small_int_or_double" "n")))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && !CONST_DOUBLE_HIGH (operands[2])
- && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ (match_operand:SI 2 "small_int_operand" "I")))]
+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32"
{
operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
-
return "srax\t%1, %2, %0";
}
[(set_attr "type" "shift")])
@@ -7198,16 +6577,10 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
(const_int 32)) 4)
- (match_operand:SI 2 "small_int_or_double" "n")))]
- "TARGET_ARCH64
- && ((GET_CODE (operands[2]) == CONST_INT
- && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32)
- || (GET_CODE (operands[2]) == CONST_DOUBLE
- && !CONST_DOUBLE_HIGH (operands[2])
- && (unsigned HOST_WIDE_INT) CONST_DOUBLE_LOW (operands[2]) < 32))"
+ (match_operand:SI 2 "small_int_operand" "I")))]
+ "TARGET_ARCH64 && (unsigned HOST_WIDE_INT) INTVAL (operands[2]) < 32"
{
operands[2] = GEN_INT (INTVAL (operands[2]) + 32);
-
return "srlx\t%1, %2, %0";
}
[(set_attr "type" "shift")])
@@ -7215,10 +6588,9 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(ashiftrt:SI (subreg:SI (ashiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:SI 2 "small_int_or_double" "n")) 4)
- (match_operand:SI 3 "small_int_or_double" "n")))]
+ (match_operand:SI 2 "small_int_operand" "I")) 4)
+ (match_operand:SI 3 "small_int_operand" "I")))]
"TARGET_ARCH64
- && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
&& (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
@@ -7232,10 +6604,9 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=r")
(lshiftrt:SI (subreg:SI (lshiftrt:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand:SI 2 "small_int_or_double" "n")) 4)
- (match_operand:SI 3 "small_int_or_double" "n")))]
+ (match_operand:SI 2 "small_int_operand" "I")) 4)
+ (match_operand:SI 3 "small_int_operand" "I")))]
"TARGET_ARCH64
- && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[3]) == CONST_INT
&& (unsigned HOST_WIDE_INT) INTVAL (operands[2]) >= 32
&& (unsigned HOST_WIDE_INT) INTVAL (operands[3]) < 32
&& (unsigned HOST_WIDE_INT) (INTVAL (operands[2]) + INTVAL (operands[3])) < 64"
@@ -7245,8 +6616,10 @@
return "srlx\t%1, %2, %0";
}
[(set_attr "type" "shift")])
-
-;; Unconditional and other jump instructions
+
+
+;; Unconditional and other jump instructions.
+
(define_insn "jump"
[(set (pc) (label_ref (match_operand 0 "" "")))]
""
@@ -7258,8 +6631,7 @@
(use (label_ref (match_operand 1 "" "")))])]
""
{
- if (GET_MODE (operands[0]) != CASE_VECTOR_MODE)
- abort ();
+ gcc_assert (GET_MODE (operands[0]) == CASE_VECTOR_MODE);
/* In pic mode, our address differences are against the base of the
table. Add that base value back in; CSE ought to be able to combine
@@ -7290,16 +6662,9 @@
"jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
-;; This pattern recognizes the "instruction" that appears in
-;; a function call that wants a structure value,
-;; to inform the called function if compiled with Sun CC.
-;(define_insn "*unimp_insn"
-; [(match_operand:SI 0 "immediate_operand" "")]
-; "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) > 0"
-; "unimp\t%0"
-; [(set_attr "type" "marker")])
-;;- jump to subroutine
+;; Jump to subroutine instructions.
+
(define_expand "call"
;; Note that this expression is not used for generating RTL.
;; All the RTL is generated explicitly below.
@@ -7309,10 +6674,11 @@
;; operands[3] is struct_value_size_rtx.
""
{
- rtx fn_rtx, nregs_rtx;
+ rtx fn_rtx;
- if (GET_MODE (operands[0]) != FUNCTION_MODE)
- abort ();
+ gcc_assert (GET_MODE (operands[0]) == FUNCTION_MODE);
+
+ gcc_assert (GET_CODE (operands[3]) == CONST_INT);
if (GET_CODE (XEXP (operands[0], 0)) == LABEL_REF)
{
@@ -7323,6 +6689,7 @@
call-clobbered registers? We lose this if it is a JUMP_INSN.
Why cannot we have delay slots filled if it were a CALL? */
+ /* We accept negative sizes for untyped calls. */
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
emit_jump_insn
(gen_rtx_PARALLEL
@@ -7343,42 +6710,22 @@
fn_rtx = operands[0];
- /* Count the number of parameter registers being used by this call.
- if that argument is NULL, it means we are using them all, which
- means 6 on the sparc. */
-#if 0
- if (operands[2])
- nregs_rtx = GEN_INT (REGNO (operands[2]) - 8);
- else
- nregs_rtx = GEN_INT (6);
-#else
- nregs_rtx = const0_rtx;
-#endif
-
+ /* We accept negative sizes for untyped calls. */
if (! TARGET_ARCH64 && INTVAL (operands[3]) != 0)
emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
- gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
+ gen_rtvec (3, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
operands[3],
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
else
emit_call_insn
(gen_rtx_PARALLEL
(VOIDmode,
- gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx),
+ gen_rtvec (2, gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)))));
finish_call:
-#if 0
- /* If this call wants a structure value,
- emit an unimp insn to let the called function know about this. */
- if (! TARGET_ARCH64 && INTVAL (operands[3]) > 0)
- {
- rtx insn = emit_insn (operands[3]);
- SCHED_GROUP_P (insn) = 1;
- }
-#endif
DONE;
})
@@ -7430,8 +6777,11 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call\t%a0, %1\n\tnop\n\tunimp\t%2"
+ "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xfff);
+ return "call\t%a0, %1\n\t nop\n\tunimp\t%2";
+}
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -7443,8 +6793,11 @@
(match_operand 2 "immediate_operand" "")
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
- "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 0"
- "call\t%a0, %1\n\tnop\n\tunimp\t%2"
+ "! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) > 0"
+{
+ operands[2] = GEN_INT (INTVAL (operands[2]) & 0xfff);
+ return "call\t%a0, %1\n\t nop\n\tunimp\t%2";
+}
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -7457,11 +6810,12 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call\t%a0, %1\n\tnop\n\tnop"
+ "call\t%a0, %1\n\t nop\n\tnop"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
-;; This is a call that wants a structure value.
+;; This is a call that may want a structure value. This is used for
+;; untyped_calls.
(define_insn "*call_symbolic_untyped_struct_value_sp32"
[(call (mem:SI (match_operand:SI 0 "symbolic_operand" "s"))
(match_operand 1 "" ""))
@@ -7469,7 +6823,7 @@
(clobber (reg:SI 15))]
;;- Do not use operand 1 for most machines.
"! TARGET_ARCH64 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0"
- "call\t%a0, %1\n\tnop\n\tnop"
+ "call\t%a0, %1\n\t nop\n\tnop"
[(set_attr "type" "call_no_delay_slot")
(set_attr "length" "3")])
@@ -7483,26 +6837,16 @@
;; operand 3 is next_arg_register
""
{
- rtx fn_rtx, nregs_rtx;
+ rtx fn_rtx;
rtvec vec;
- if (GET_MODE (operands[1]) != FUNCTION_MODE)
- abort ();
+ gcc_assert (GET_MODE (operands[1]) == FUNCTION_MODE);
fn_rtx = operands[1];
-#if 0
- if (operands[3])
- nregs_rtx = GEN_INT (REGNO (operands[3]) - 8);
- else
- nregs_rtx = GEN_INT (6);
-#else
- nregs_rtx = const0_rtx;
-#endif
-
vec = gen_rtvec (2,
gen_rtx_SET (VOIDmode, operands[0],
- gen_rtx_CALL (VOIDmode, fn_rtx, nregs_rtx)),
+ gen_rtx_CALL (VOIDmode, fn_rtx, const0_rtx)),
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (Pmode, 15)));
emit_call_insn (gen_rtx_PARALLEL (VOIDmode, vec));
@@ -7553,21 +6897,22 @@
(define_expand "untyped_call"
[(parallel [(call (match_operand 0 "" "")
(const_int 0))
- (match_operand 1 "" "")
+ (match_operand:BLK 1 "memory_operand" "")
(match_operand 2 "" "")])]
""
{
- int i;
+ rtx valreg1 = gen_rtx_REG (DImode, 8);
+ rtx valreg2 = gen_rtx_REG (TARGET_ARCH64 ? TFmode : DFmode, 32);
+ rtx result = operands[1];
/* Pass constm1 to indicate that it may expect a structure value, but
we don't know what size it is. */
emit_call_insn (GEN_CALL (operands[0], const0_rtx, NULL, constm1_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));
- }
+ /* Save the function value registers. */
+ emit_move_insn (adjust_address (result, DImode, 0), valreg1);
+ emit_move_insn (adjust_address (result, TARGET_ARCH64 ? TFmode : DFmode, 8),
+ valreg2);
/* The optimizer does not know that the call sets the function value
registers we stored in the result block. We avoid problems by
@@ -7578,7 +6923,8 @@
DONE;
})
-;;- tail calls
+;; Tail call instructions.
+
(define_expand "sibcall"
[(parallel [(call (match_operand 0 "call_operand" "") (const_int 0))
(return)])]
@@ -7626,10 +6972,77 @@
"* return output_sibcall(insn, operands[1]);"
[(set_attr "type" "sibcall")])
-(define_expand "sibcall_epilogue"
+
+;; Special instructions.
+
+(define_expand "prologue"
[(const_int 0)]
""
- "DONE;")
+{
+ sparc_expand_prologue ();
+ DONE;
+})
+
+;; The "save register window" insn is modelled as follows so that the DWARF-2
+;; backend automatically emits the required call frame debugging information
+;; while it is parsing it. Therefore, the pattern should not be modified
+;; without first studying the impact of the changes on the debug info.
+;; [(set (%fp) (%sp))
+;; (set (%sp) (unspec_volatile [(%sp) (-frame_size)] UNSPECV_SAVEW))
+;; (set (%i7) (%o7))]
+
+(define_insn "save_register_window<P:mode>"
+ [(set (reg:P 30) (reg:P 14))
+ (set (reg:P 14) (unspec_volatile:P [(reg:P 14)
+ (match_operand:P 0 "arith_operand" "rI")] UNSPECV_SAVEW))
+ (set (reg:P 31) (reg:P 15))]
+ ""
+ "save\t%%sp, %0, %%sp"
+ [(set_attr "type" "savew")])
+
+(define_expand "epilogue"
+ [(return)]
+ ""
+{
+ sparc_expand_epilogue ();
+})
+
+(define_expand "sibcall_epilogue"
+ [(return)]
+ ""
+{
+ sparc_expand_epilogue ();
+ DONE;
+})
+
+(define_expand "return"
+ [(return)]
+ "sparc_can_use_return_insn_p ()"
+ "")
+
+(define_insn "*return_internal"
+ [(return)]
+ ""
+ "* return output_return (insn);"
+ [(set_attr "type" "return")
+ (set (attr "length")
+ (cond [(eq_attr "leaf_function" "true")
+ (if_then_else (eq_attr "empty_delay_slot" "true")
+ (const_int 2)
+ (const_int 1))
+ (eq_attr "calls_eh_return" "true")
+ (if_then_else (eq_attr "delayed_branch" "true")
+ (if_then_else (eq_attr "isa" "v9")
+ (const_int 2)
+ (const_int 3))
+ (if_then_else (eq_attr "isa" "v9")
+ (const_int 3)
+ (const_int 4)))
+ (eq_attr "empty_delay_slot" "true")
+ (if_then_else (eq_attr "delayed_branch" "true")
+ (const_int 2)
+ (const_int 3))
+ ] (const_int 1)))])
;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
;; all of memory. This blocks insns from being moved across this point.
@@ -7681,16 +7094,29 @@
DONE;
})
-;; This is a bit of a hack. We're incrementing a fixed register (%i7),
-;; and parts of the compiler don't want to believe that the add is needed.
+;; Adjust the return address conditionally. If the value of op1 is equal
+;; to all zero then adjust the return address i.e. op0 = op0 + 4.
+;; This is technically *half* the check required by the 32-bit SPARC
+;; psABI. This check only ensures that an "unimp" insn was written by
+;; the caller, but doesn't check to see if the expected size matches
+;; (this is encoded in the 12 lower bits). This check is obsolete and
+;; only used by the above code "untyped_return".
(define_insn "update_return"
[(unspec:SI [(match_operand:SI 0 "register_operand" "r")
(match_operand:SI 1 "register_operand" "r")] UNSPEC_UPDATE_RETURN)]
"! TARGET_ARCH64"
- "cmp\t%1, 0\;be,a\t.+8\;add\t%0, 4, %0"
- [(set_attr "type" "multi")
- (set_attr "length" "3")])
+{
+ if (flag_delayed_branch)
+ return "cmp\t%1, 0\n\tbe,a\t.+8\n\t add\t%0, 4, %0";
+ else
+ return "cmp\t%1, 0\n\tbne\t.+12\n\t nop\n\tadd\t%0, 4, %0";
+}
+ [(set (attr "type") (const_string "multi"))
+ (set (attr "length")
+ (if_then_else (eq_attr "delayed_branch" "true")
+ (const_int 3)
+ (const_int 4)))])
(define_insn "nop"
[(const_int 0)]
@@ -7714,7 +7140,6 @@
"jmp\t%a0%#"
[(set_attr "type" "uncond_branch")])
-;; ??? Doesn't work with -mflat.
(define_expand "nonlocal_goto"
[(match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" "")
@@ -7722,9 +7147,6 @@
(match_operand:SI 3 "" "")]
""
{
-#if 0
- rtx chain = operands[0];
-#endif
rtx lab = operands[1];
rtx stack = operands[2];
rtx fp = operands[3];
@@ -7750,27 +7172,10 @@
and reload the appropriate value into %fp. */
emit_move_insn (hard_frame_pointer_rtx, stack);
- /* USE of frame_pointer_rtx added for consistency; not clear if
- really needed. */
- /*emit_insn (gen_rtx_USE (VOIDmode, frame_pointer_rtx));*/
emit_insn (gen_rtx_USE (VOIDmode, stack_pointer_rtx));
-
-#if 0
- /* Return, restoring reg window and jumping to goto handler. */
- if (TARGET_V9 && GET_CODE (chain) == CONST_INT
- && ! (INTVAL (chain) & ~(HOST_WIDE_INT)0xffffffff))
- {
- emit_jump_insn (gen_goto_handler_and_restore_v9 (labreg,
- static_chain_rtx,
- chain));
- emit_barrier ();
- DONE;
- }
- /* Put in the static chain register the nonlocal label address. */
- emit_move_insn (static_chain_rtx, chain);
-#endif
-
emit_insn (gen_rtx_USE (VOIDmode, static_chain_rtx));
+
+ /* ??? The V9-specific version was disabled in rev 1.65. */
emit_jump_insn (gen_goto_handler_and_restore (labreg));
emit_barrier ();
DONE;
@@ -7786,31 +7191,17 @@
(define_insn "goto_handler_and_restore"
[(unspec_volatile [(match_operand 0 "register_operand" "=r")] UNSPECV_GOTO)]
"GET_MODE (operands[0]) == Pmode"
- "jmp\t%0+0\n\trestore"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-;;(define_insn "goto_handler_and_restore_v9"
-;; [(unspec_volatile [(match_operand:SI 0 "register_operand" "=r,r")
-;; (match_operand:SI 1 "register_operand" "=r,r")
-;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
-;; "TARGET_V9 && ! TARGET_ARCH64"
-;; "@
-;; return\t%0+0\n\tmov\t%2, %Y1
-;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
-;; [(set_attr "type" "multi")
-;; (set_attr "length" "2,3")])
-;;
-;;(define_insn "*goto_handler_and_restore_v9_sp64"
-;; [(unspec_volatile [(match_operand:DI 0 "register_operand" "=r,r")
-;; (match_operand:DI 1 "register_operand" "=r,r")
-;; (match_operand:SI 2 "const_int_operand" "I,n")] UNSPECV_GOTO_V9)]
-;; "TARGET_V9 && TARGET_ARCH64"
-;; "@
-;; return\t%0+0\n\tmov\t%2, %Y1
-;; sethi\t%%hi(%2), %1\n\treturn\t%0+0\n\tor\t%Y1, %%lo(%2), %Y1"
-;; [(set_attr "type" "multi")
-;; (set_attr "length" "2,3")])
+{
+ if (flag_delayed_branch)
+ return "jmp\t%0\n\t restore";
+ else
+ return "mov\t%0,%%g1\n\trestore\n\tjmp\t%%g1\n\t nop";
+}
+ [(set (attr "type") (const_string "multi"))
+ (set (attr "length")
+ (if_then_else (eq_attr "delayed_branch" "true")
+ (const_int 2)
+ (const_int 4)))])
;; For __builtin_setjmp we need to flush register windows iff the function
;; calls alloca as well, because otherwise the register window might be
@@ -7829,7 +7220,7 @@
{
if (! current_function_calls_alloca)
return "";
- if (! TARGET_V9 || TARGET_FLAT)
+ if (! TARGET_V9)
return "\tta\t3\n";
fputs ("\tflushw\n", asm_out_file);
if (flag_pic)
@@ -7846,10 +7237,8 @@
}
[(set_attr "type" "multi")
(set (attr "length")
- (cond [(eq_attr "current_function_calls_alloca" "false")
+ (cond [(eq_attr "calls_alloca" "false")
(const_int 0)
- (eq_attr "flat" "true")
- (const_int 1)
(eq_attr "isa" "!v9")
(const_int 1)
(eq_attr "pic" "true")
@@ -7862,25 +7251,20 @@
[(const_int 0)]
""
{
- if (TARGET_ARCH64)
- emit_insn (gen_setjmp_64 ());
- else
- emit_insn (gen_setjmp_32 ());
+ rtx mem;
+
+ mem = gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
+ SPARC_STACK_BIAS + 14 * UNITS_PER_WORD));
+ emit_insn (gen_rtx_SET (VOIDmode, mem, frame_pointer_rtx));
+
+ mem = gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
+ SPARC_STACK_BIAS + 15 * UNITS_PER_WORD));
+ emit_insn (gen_rtx_SET (VOIDmode, mem, gen_rtx_REG (Pmode, 31)));
DONE;
})
-(define_expand "setjmp_32"
- [(set (mem:SI (plus:SI (reg:SI 14) (const_int 56))) (match_dup 0))
- (set (mem:SI (plus:SI (reg:SI 14) (const_int 60))) (reg:SI 31))]
- ""
- { operands[0] = frame_pointer_rtx; })
-
-(define_expand "setjmp_64"
- [(set (mem:DI (plus:DI (reg:DI 14) (const_int 112))) (match_dup 0))
- (set (mem:DI (plus:DI (reg:DI 14) (const_int 120))) (reg:DI 31))]
- ""
- { operands[0] = frame_pointer_rtx; })
-
;; Special pattern for the FLUSH instruction.
; We do SImode and DImode versions of this to quiet down genrecog's complaints
@@ -7900,8 +7284,8 @@
{ return TARGET_V9 ? "flush\t%f0" : "iflush\t%f0"; }
[(set_attr "type" "iflush")])
-
-;; find first set.
+
+;; Find first set instructions.
;; The scan instruction searches from the most significant bit while ffs
;; searches from the least significant bit. The bit index and treatment of
@@ -8097,165 +7481,8 @@
(compare:CCX (match_dup 1) (const_int 0)))])]
"")
-;; Return peepholes. These are generated by sparc_nonflat_function_epilogue
-;; who then immediately calls final_scan_insn.
-
-(define_insn "*return_qi"
- [(set (match_operand:QI 0 "restore_operand" "")
- (match_operand:QI 1 "arith_operand" "rI"))
- (return)]
- "sparc_emitting_epilogue"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
- else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
- || IN_OR_GLOBAL_P (operands[1])))
- return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
- else
- return "ret\n\trestore %%g0, %1, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_hi"
- [(set (match_operand:HI 0 "restore_operand" "")
- (match_operand:HI 1 "arith_operand" "rI"))
- (return)]
- "sparc_emitting_epilogue"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
- else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
- || IN_OR_GLOBAL_P (operands[1])))
- return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
- else
- return "ret\;restore %%g0, %1, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_si"
- [(set (match_operand:SI 0 "restore_operand" "")
- (match_operand:SI 1 "arith_operand" "rI"))
- (return)]
- "sparc_emitting_epilogue"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
- else if (TARGET_V9 && (GET_CODE (operands[1]) == CONST_INT
- || IN_OR_GLOBAL_P (operands[1])))
- return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
- else
- return "ret\;restore %%g0, %1, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_sf_no_fpu"
- [(set (match_operand:SF 0 "restore_operand" "=r")
- (match_operand:SF 1 "register_operand" "r"))
- (return)]
- "sparc_emitting_epilogue"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %%g0, %1, %Y0";
- else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
- return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
- else
- return "ret\;restore %%g0, %1, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_df_no_fpu"
- [(set (match_operand:DF 0 "restore_operand" "=r")
- (match_operand:DF 1 "register_operand" "r"))
- (return)]
- "sparc_emitting_epilogue && TARGET_ARCH64"
-{
- if (IN_OR_GLOBAL_P (operands[1]))
- return "return\t%%i7+8\n\tmov\t%Y1, %Y0";
- else
- return "ret\;restore %%g0, %1, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_addsi"
- [(set (match_operand:SI 0 "restore_operand" "")
- (plus:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "arith_operand" "rI")))
- (return)]
- "sparc_emitting_epilogue"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %r1, %2, %Y0";
- /* If operands are global or in registers, can use return */
- else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1])
- && (GET_CODE (operands[2]) == CONST_INT
- || IN_OR_GLOBAL_P (operands[2])))
- return "return\t%%i7+8\n\tadd\t%Y1, %Y2, %Y0";
- else
- return "ret\;restore %r1, %2, %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_losum_si"
- [(set (match_operand:SI 0 "restore_operand" "")
- (lo_sum:SI (match_operand:SI 1 "register_operand" "r")
- (match_operand:SI 2 "immediate_operand" "in")))
- (return)]
- "sparc_emitting_epilogue && ! TARGET_CM_MEDMID"
-{
- if (! TARGET_ARCH64 && current_function_returns_struct)
- return "jmp\t%%i7+12\n\trestore %r1, %%lo(%a2), %Y0";
- /* If operands are global or in registers, can use return */
- else if (TARGET_V9 && IN_OR_GLOBAL_P (operands[1]))
- return "return\t%%i7+8\n\tor\t%Y1, %%lo(%a2), %Y0";
- else
- return "ret\;restore %r1, %%lo(%a2), %Y0";
-}
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_di"
- [(set (match_operand:DI 0 "restore_operand" "")
- (match_operand:DI 1 "arith_double_operand" "rHI"))
- (return)]
- "sparc_emitting_epilogue && TARGET_ARCH64"
- "ret\;restore %%g0, %1, %Y0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_adddi"
- [(set (match_operand:DI 0 "restore_operand" "")
- (plus:DI (match_operand:DI 1 "arith_operand" "%r")
- (match_operand:DI 2 "arith_double_operand" "rHI")))
- (return)]
- "sparc_emitting_epilogue && TARGET_ARCH64"
- "ret\;restore %r1, %2, %Y0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-(define_insn "*return_losum_di"
- [(set (match_operand:DI 0 "restore_operand" "")
- (lo_sum:DI (match_operand:DI 1 "arith_operand" "%r")
- (match_operand:DI 2 "immediate_operand" "in")))
- (return)]
- "sparc_emitting_epilogue && TARGET_ARCH64 && ! TARGET_CM_MEDMID"
- "ret\;restore %r1, %%lo(%a2), %Y0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
-
-(define_insn "*return_sf"
- [(set (reg:SF 32)
- (match_operand:SF 0 "register_operand" "f"))
- (return)]
- "sparc_emitting_epilogue"
- "ret\;fmovs\t%0, %%f0"
- [(set_attr "type" "multi")
- (set_attr "length" "2")])
+;; Prefetch instructions.
;; ??? UltraSPARC-III note: A memory operation loading into the floating point register
;; ??? file, if it hits the prefetch cache, has a chance to dual-issue with other memory
@@ -8293,10 +7520,8 @@
int read_or_write = INTVAL (operands[1]);
int locality = INTVAL (operands[2]);
- if (read_or_write != 0 && read_or_write != 1)
- abort ();
- if (locality < 0 || locality > 3)
- abort ();
+ gcc_assert (read_or_write == 0 || read_or_write == 1);
+ gcc_assert (locality >= 0 && locality < 4);
return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
[(set_attr "type" "load")])
@@ -8320,42 +7545,15 @@
int read_or_write = INTVAL (operands[1]);
int locality = INTVAL (operands[2]);
- if (read_or_write != 0 && read_or_write != 1)
- abort ();
- if (locality < 0 || locality > 3)
- abort ();
+ gcc_assert (read_or_write == 0 || read_or_write == 1);
+ gcc_assert (locality >= 0 && locality < 4);
return prefetch_instr [read_or_write][locality == 0 ? 0 : 1];
}
[(set_attr "type" "load")])
-
-(define_expand "prologue"
- [(const_int 1)]
- "flag_pic && current_function_uses_pic_offset_table"
-{
- load_pic_register ();
- DONE;
-})
-;; We need to reload %l7 for -mflat -fpic,
-;; otherwise %l7 should be preserved simply
-;; by loading the function's register window
-(define_expand "exception_receiver"
- [(const_int 0)]
- "TARGET_FLAT && flag_pic"
-{
- load_pic_register ();
- DONE;
-})
-;; Likewise
-(define_expand "builtin_setjmp_receiver"
- [(label_ref (match_operand 0 "" ""))]
- "TARGET_FLAT && flag_pic"
-{
- load_pic_register ();
- DONE;
-})
-
+;; Trap instructions.
+
(define_insn "trap"
[(trap_if (const_int 1) (const_int 5))]
""
@@ -8363,29 +7561,36 @@
[(set_attr "type" "trap")])
(define_expand "conditional_trap"
- [(trap_if (match_operator 0 "noov_compare_op"
- [(match_dup 2) (match_dup 3)])
+ [(trap_if (match_operator 0 "noov_compare_operator" [(match_dup 2) (match_dup 3)])
(match_operand:SI 1 "arith_operand" ""))]
""
- "operands[2] = gen_compare_reg (GET_CODE (operands[0]),
- sparc_compare_op0, sparc_compare_op1);
+ "operands[2] = gen_compare_reg (GET_CODE (operands[0]));
+ if (GET_MODE (operands[2]) != CCmode && GET_MODE (operands[2]) != CCXmode)
+ FAIL;
operands[3] = const0_rtx;")
(define_insn ""
- [(trap_if (match_operator 0 "noov_compare_op" [(reg:CC 100) (const_int 0)])
+ [(trap_if (match_operator 0 "noov_compare_operator" [(reg:CC 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
""
- "t%C0\t%1"
+{
+ if (TARGET_V9)
+ return "t%C0\t%%icc, %1";
+ else
+ return "t%C0\t%1";
+}
[(set_attr "type" "trap")])
(define_insn ""
- [(trap_if (match_operator 0 "noov_compare_op" [(reg:CCX 100) (const_int 0)])
+ [(trap_if (match_operator 0 "noov_compare_operator" [(reg:CCX 100) (const_int 0)])
(match_operand:SI 1 "arith_operand" "rM"))]
"TARGET_V9"
"t%C0\t%%xcc, %1"
[(set_attr "type" "trap")])
-;; TLS support
+
+;; TLS support instructions.
+
(define_insn "tgd_hi22"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (unspec:SI [(match_operand 1 "tgd_symbolic_operand" "")]
@@ -8947,3 +8152,335 @@
"TARGET_TLS && TARGET_ARCH64"
"stx\t%0, [%1 + %2], %%tldo_add(%3)"
[(set_attr "type" "store")])
+
+
+;; Stack protector instructions.
+
+(define_expand "stack_protect_set"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ emit_insn (gen_stack_protect_setdi (operands[0], operands[1]));
+ else
+ emit_insn (gen_stack_protect_setsi (operands[0], operands[1]));
+ DONE;
+})
+
+(define_insn "stack_protect_setsi"
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:SI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH32"
+ "ld\t%1, %2\;st\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_insn "stack_protect_setdi"
+ [(set (match_operand:DI 0 "memory_operand" "=m")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")] UNSPEC_SP_SET))
+ (set (match_scratch:DI 2 "=&r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %2\;stx\t%2, %0\;mov\t0, %2"
+ [(set_attr "type" "multi")
+ (set_attr "length" "3")])
+
+(define_expand "stack_protect_test"
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
+ (match_operand 2 "" "")]
+ ""
+{
+#ifdef TARGET_THREAD_SSP_OFFSET
+ rtx tlsreg = gen_rtx_REG (Pmode, 7);
+ rtx addr = gen_rtx_PLUS (Pmode, tlsreg, GEN_INT (TARGET_THREAD_SSP_OFFSET));
+ operands[1] = gen_rtx_MEM (Pmode, addr);
+#endif
+ if (TARGET_ARCH64)
+ {
+ rtx temp = gen_reg_rtx (Pmode);
+ emit_insn (gen_stack_protect_testdi (temp, operands[0], operands[1]));
+ sparc_compare_op0 = temp;
+ sparc_compare_op1 = const0_rtx;
+ }
+ else
+ {
+ emit_insn (gen_stack_protect_testsi (operands[0], operands[1]));
+ sparc_compare_op0 = operands[0];
+ sparc_compare_op1 = operands[1];
+ sparc_compare_emitted = gen_rtx_REG (CCmode, SPARC_ICC_REG);
+ }
+ emit_jump_insn (gen_beq (operands[2]));
+ DONE;
+})
+
+(define_insn "stack_protect_testsi"
+ [(set (reg:CC 100)
+ (unspec:CC [(match_operand:SI 0 "memory_operand" "m")
+ (match_operand:SI 1 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:SI 3 "=r") (const_int 0))
+ (clobber (match_scratch:SI 2 "=&r"))]
+ "TARGET_ARCH32"
+ "ld\t%0, %2\;ld\t%1, %3\;xorcc\t%2, %3, %2\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+(define_insn "stack_protect_testdi"
+ [(set (match_operand:DI 0 "register_operand" "=&r")
+ (unspec:DI [(match_operand:DI 1 "memory_operand" "m")
+ (match_operand:DI 2 "memory_operand" "m")]
+ UNSPEC_SP_TEST))
+ (set (match_scratch:DI 3 "=r") (const_int 0))]
+ "TARGET_ARCH64"
+ "ldx\t%1, %0\;ldx\t%2, %3\;xor\t%0, %3, %0\;mov\t0, %3"
+ [(set_attr "type" "multi")
+ (set_attr "length" "4")])
+
+
+;; Vector instructions.
+
+(define_insn "addv2si3"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (plus:V2SI (match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V2SI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpadd32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "addv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (plus:V4HI (match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpadd16\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; fpadd32s is emitted by the addsi3 pattern.
+
+(define_insn "addv2hi3"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (plus:V2HI (match_operand:V2HI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fpadd16s\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+(define_insn "subv2si3"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (minus:V2SI (match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V2SI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpsub32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "subv4hi3"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (minus:V4HI (match_operand:V4HI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fpsub16\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; fpsub32s is emitted by the subsi3 pattern.
+
+(define_insn "subv2hi3"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (minus:V2HI (match_operand:V2HI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fpsub16s\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+;; All other logical instructions have integer equivalents so they
+;; are defined together.
+
+;; (ior (not (op1)) (not (op2))) is the canonical form of NAND.
+
+(define_insn "*nand<V64mode>_vis"
+ [(set (match_operand:V64 0 "register_operand" "=e")
+ (ior:V64 (not:V64 (match_operand:V64 1 "register_operand" "e"))
+ (not:V64 (match_operand:V64 2 "register_operand" "e"))))]
+ "TARGET_VIS"
+ "fnand\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "*nand<V32mode>_vis"
+ [(set (match_operand:V32 0 "register_operand" "=f")
+ (ior:V32 (not:V32 (match_operand:V32 1 "register_operand" "f"))
+ (not:V32 (match_operand:V32 2 "register_operand" "f"))))]
+ "TARGET_VIS"
+ "fnands\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "single")])
+
+;; Hard to generate VIS instructions. We have builtins for these.
+
+(define_insn "fpack16_vis"
+ [(set (match_operand:V4QI 0 "register_operand" "=f")
+ (unspec:V4QI [(match_operand:V4HI 1 "register_operand" "e")]
+ UNSPEC_FPACK16))]
+ "TARGET_VIS"
+ "fpack16\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpackfix_vis"
+ [(set (match_operand:V2HI 0 "register_operand" "=f")
+ (unspec:V2HI [(match_operand:V2SI 1 "register_operand" "e")]
+ UNSPEC_FPACKFIX))]
+ "TARGET_VIS"
+ "fpackfix\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fpack32_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (unspec:V8QI [(match_operand:V2SI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")]
+ UNSPEC_FPACK32))]
+ "TARGET_VIS"
+ "fpack32\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "fexpand_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")]
+ UNSPEC_FEXPAND))]
+ "TARGET_VIS"
+ "fexpand\t%1, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; It may be possible to describe this operation as (1 indexed):
+;; (vec_select (vec_duplicate (vec_duplicate (vec_concat 1 2)))
+;; 1,5,10,14,19,23,28,32)
+;; Note that (vec_merge:V8QI [(V4QI) (V4QI)] (10101010 = 170) doesn't work
+;; because vec_merge expects all the operands to be of the same type.
+(define_insn "fpmerge_vis"
+ [(set (match_operand:V8QI 0 "register_operand" "=e")
+ (unspec:V8QI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4QI 2 "register_operand" "f")]
+ UNSPEC_FPMERGE))]
+ "TARGET_VIS"
+ "fpmerge\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+;; Partitioned multiply instructions
+(define_insn "fmul8x16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fmul8x16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmul8x16au_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fmul8x16au\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8x16al_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MUL16AL))]
+ "TARGET_VIS"
+ "fmul8x16al\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmul8sux16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (mult:V4HI (match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")))]
+ "TARGET_VIS"
+ "fmul8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmul8ulx16_vis"
+ [(set (match_operand:V4HI 0 "register_operand" "=e")
+ (unspec:V4HI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V4HI 2 "register_operand" "e")]
+ UNSPEC_MUL8UL))]
+ "TARGET_VIS"
+ "fmul8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Only one of the following two insns can be a multiply.
+(define_insn "fmuld8sux16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (mult:V2SI (match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")))]
+ "TARGET_VIS"
+ "fmuld8sux16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+(define_insn "fmuld8ulx16_vis"
+ [(set (match_operand:V2SI 0 "register_operand" "=e")
+ (unspec:V2SI [(match_operand:V4QI 1 "register_operand" "f")
+ (match_operand:V2HI 2 "register_operand" "f")]
+ UNSPEC_MULDUL))]
+ "TARGET_VIS"
+ "fmuld8ulx16\t%1, %2, %0"
+ [(set_attr "type" "fpmul")
+ (set_attr "fptype" "double")])
+
+;; Using faligndata only makes sense after an alignaddr since the choice of
+;; bytes to take out of each operand is dependent on the results of the last
+;; alignaddr.
+(define_insn "faligndata<V64I:mode>_vis"
+ [(set (match_operand:V64I 0 "register_operand" "=e")
+ (unspec:V64I [(match_operand:V64I 1 "register_operand" "e")
+ (match_operand:V64I 2 "register_operand" "e")]
+ UNSPEC_ALIGNDATA))]
+ "TARGET_VIS"
+ "faligndata\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(define_insn "alignaddr<P:mode>_vis"
+ [(set (match_operand:P 0 "register_operand" "=r")
+ (unspec:P [(match_operand:P 1 "register_or_zero_operand" "rJ")
+ (match_operand:P 2 "register_or_zero_operand" "rJ")]
+ UNSPEC_ALIGNADDR))]
+ "TARGET_VIS"
+ "alignaddr\t%r1, %r2, %0")
+
+(define_insn "pdist_vis"
+ [(set (match_operand:DI 0 "register_operand" "=e")
+ (unspec:DI [(match_operand:V8QI 1 "register_operand" "e")
+ (match_operand:V8QI 2 "register_operand" "e")
+ (match_operand:DI 3 "register_operand" "0")]
+ UNSPEC_PDIST))]
+ "TARGET_VIS"
+ "pdist\t%1, %2, %0"
+ [(set_attr "type" "fga")
+ (set_attr "fptype" "double")])
+
+(include "sync.md")
diff --git a/contrib/gcc/config/sparc/sparc.opt b/contrib/gcc/config/sparc/sparc.opt
new file mode 100644
index 0000000..8cdf11c
--- /dev/null
+++ b/contrib/gcc/config/sparc/sparc.opt
@@ -0,0 +1,126 @@
+; Options for the SPARC port of the compiler
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT
+; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+; License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mfpu
+Target Report Mask(FPU)
+Use hardware FP
+
+mhard-float
+Target RejectNegative Mask(FPU) MaskExists
+Use hardware FP
+
+msoft-float
+Target RejectNegative InverseMask(FPU)
+Do not use hardware FP
+
+munaligned-doubles
+Target Report Mask(UNALIGNED_DOUBLES)
+Assume possible double misalignment
+
+mimpure-text
+Target Report
+Pass -assert pure-text to linker
+
+mapp-regs
+Target Report Mask(APP_REGS)
+Use ABI reserved registers
+
+mhard-quad-float
+Target Report RejectNegative Mask(HARD_QUAD)
+Use hardware quad FP instructions
+
+msoft-quad-float
+Target Report RejectNegative InverseMask(HARD_QUAD)
+Do not use hardware quad fp instructions
+
+mv8plus
+Target Report Mask(V8PLUS)
+Compile for V8+ ABI
+
+mvis
+Target Report Mask(VIS)
+Use UltraSPARC Visual Instruction Set extensions
+
+mptr64
+Target Report RejectNegative Mask(PTR64)
+Pointers are 64-bit
+
+mptr32
+Target Report RejectNegative InverseMask(PTR64)
+Pointers are 32-bit
+
+m64
+Target Report RejectNegative Mask(64BIT)
+Use 64-bit ABI
+
+m32
+Target Report RejectNegative InverseMask(64BIT)
+Use 32-bit ABI
+
+mstack-bias
+Target Report Mask(STACK_BIAS)
+Use stack bias
+
+mfaster-structs
+Target Report Mask(FASTER_STRUCTS)
+Use structs on stronger alignment for double-word copies
+
+mrelax
+Target
+Optimize tail call instructions in assembler and linker
+
+mcpu=
+Target RejectNegative Joined
+Use features of and schedule code for given CPU
+
+mtune=
+Target RejectNegative Joined
+Schedule code for given CPU
+
+mcmodel=
+Target RejectNegative Joined Var(sparc_cmodel_string)
+Use given SPARC-V9 code model
+
+mstd-struct-return
+Target Report RejectNegative Var(sparc_std_struct_return)
+Enable strict 32-bit psABI struct return checking.
+
+Mask(LITTLE_ENDIAN)
+;; Generate code for little-endian
+
+Mask(LONG_DOUBLE_128)
+;; Use 128-bit long double
+
+Mask(SPARCLITE)
+;; Generate code for SPARClite
+
+Mask(SPARCLET)
+;; Generate code for SPARClet
+
+Mask(V8)
+;; Generate code for SPARC-V8
+
+Mask(V9)
+;; Generate code for SPARC-V9
+
+Mask(DEPRECATED_V8_INSNS)
+;; Generate code that uses the V8 instructions deprecated
+;; in the V9 architecture.
diff --git a/contrib/gcc/config/sparc/sparclet.md b/contrib/gcc/config/sparc/sparclet.md
index 15020ba..fdc03ab 100644
--- a/contrib/gcc/config/sparc/sparclet.md
+++ b/contrib/gcc/config/sparc/sparclet.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; The SPARClet is a single-issue processor.
diff --git a/contrib/gcc/config/sparc/supersparc.md b/contrib/gcc/config/sparc/supersparc.md
index 93e4cf7..8aaa75f 100644
--- a/contrib/gcc/config/sparc/supersparc.md
+++ b/contrib/gcc/config/sparc/supersparc.md
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; The SuperSPARC is a tri-issue, which was considered quite parallel
;; at the time it was released. Much like UltraSPARC-I and UltraSPARC-II
diff --git a/contrib/gcc/config/sparc/sync.md b/contrib/gcc/config/sparc/sync.md
new file mode 100644
index 0000000..1337921
--- /dev/null
+++ b/contrib/gcc/config/sparc/sync.md
@@ -0,0 +1,208 @@
+;; GCC machine description for SPARC synchronization instructions.
+;; Copyright (C) 2005
+;; Free Software Foundation, Inc.
+;;
+;; This file is part of GCC.
+;;
+;; GCC is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 2, or (at your option)
+;; any later version.
+;;
+;; GCC is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with GCC; see the file COPYING. If not, write to
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+(define_mode_macro I12MODE [QI HI])
+(define_mode_macro I24MODE [HI SI])
+(define_mode_macro I48MODE [SI (DI "TARGET_ARCH64 || TARGET_V8PLUS")])
+(define_mode_attr modesuffix [(SI "") (DI "x")])
+
+(define_expand "memory_barrier"
+ [(set (mem:BLK (match_dup 0))
+ (unspec_volatile:BLK [(mem:BLK (match_dup 0)) (match_dup 1)]
+ UNSPECV_MEMBAR))]
+ "TARGET_V8 || TARGET_V9"
+{
+ operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (DImode));
+ MEM_VOLATILE_P (operands[0]) = 1;
+ if (TARGET_V9)
+ /* member #StoreStore | #LoadStore | #StoreLoad | #LoadLoad */
+ operands[1] = GEN_INT (15);
+ else
+ /* stbar */
+ operands[1] = GEN_INT (8);
+})
+
+(define_insn "*stbar"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec_volatile:BLK [(match_operand:BLK 1 "" "")
+ (const_int 8)] UNSPECV_MEMBAR))]
+ "TARGET_V8"
+ "stbar"
+ [(set_attr "type" "multi")])
+
+(define_insn "*membar"
+ [(set (match_operand:BLK 0 "" "")
+ (unspec_volatile:BLK [(match_operand:BLK 1 "" "")
+ (match_operand:SI 2 "immediate_operand" "I")]
+ UNSPECV_MEMBAR))]
+ "TARGET_V9"
+ "membar\t%2"
+ [(set_attr "type" "multi")])
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(match_operand:I12MODE 0 "register_operand" "")
+ (match_operand:I12MODE 1 "memory_operand" "")
+ (match_operand:I12MODE 2 "register_operand" "")
+ (match_operand:I12MODE 3 "register_operand" "")]
+ "TARGET_V9"
+{
+ sparc_expand_compare_and_swap_12 (operands[0], operands[1],
+ operands[2], operands[3]);
+ DONE;
+})
+
+(define_expand "sync_compare_and_swap<mode>"
+ [(parallel
+ [(set (match_operand:I48MODE 0 "register_operand" "=r")
+ (match_operand:I48MODE 1 "memory_operand" ""))
+ (set (match_dup 1)
+ (unspec_volatile:I48MODE
+ [(match_operand:I48MODE 2 "register_operand" "")
+ (match_operand:I48MODE 3 "register_operand" "")]
+ UNSPECV_CAS))])]
+ "TARGET_V9"
+{
+ if (! REG_P (XEXP (operands[1], 0)))
+ {
+ rtx addr = force_reg (Pmode, XEXP (operands[1], 0));
+ operands[1] = replace_equiv_address (operands[1], addr);
+ }
+ emit_insn (gen_memory_barrier ());
+})
+
+(define_insn "*sync_compare_and_swap<mode>"
+ [(set (match_operand:I48MODE 0 "register_operand" "=r")
+ (match_operand:I48MODE 1 "memory_reg_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:I48MODE
+ [(match_operand:I48MODE 2 "register_operand" "r")
+ (match_operand:I48MODE 3 "register_operand" "0")]
+ UNSPECV_CAS))]
+ "TARGET_V9 && (<MODE>mode == SImode || TARGET_ARCH64)"
+ "cas<modesuffix>\t%1, %2, %0"
+ [(set_attr "type" "multi")])
+
+(define_insn "*sync_compare_and_swapdi_v8plus"
+ [(set (match_operand:DI 0 "register_operand" "=h")
+ (match_operand:DI 1 "memory_reg_operand" "+m"))
+ (set (match_dup 1)
+ (unspec_volatile:DI
+ [(match_operand:DI 2 "register_operand" "h")
+ (match_operand:DI 3 "register_operand" "0")]
+ UNSPECV_CAS))]
+ "TARGET_V8PLUS"
+{
+ if (sparc_check_64 (operands[3], insn) <= 0)
+ output_asm_insn ("srl\t%L3, 0, %L3", operands);
+ output_asm_insn ("sllx\t%H3, 32, %H3", operands);
+ output_asm_insn ("or\t%L3, %H3, %L3", operands);
+ if (sparc_check_64 (operands[2], insn) <= 0)
+ output_asm_insn ("srl\t%L2, 0, %L2", operands);
+ output_asm_insn ("sllx\t%H2, 32, %H3", operands);
+ output_asm_insn ("or\t%L2, %H3, %H3", operands);
+ output_asm_insn ("casx\t%1, %H3, %L3", operands);
+ return "srlx\t%L3, 32, %H3";
+}
+ [(set_attr "type" "multi")
+ (set_attr "length" "8")])
+
+(define_expand "sync_lock_test_and_set<mode>"
+ [(match_operand:I12MODE 0 "register_operand" "")
+ (match_operand:I12MODE 1 "memory_operand" "")
+ (match_operand:I12MODE 2 "arith_operand" "")]
+ "!TARGET_V9"
+{
+ if (operands[2] != const1_rtx)
+ FAIL;
+ if (TARGET_V8)
+ emit_insn (gen_memory_barrier ());
+ if (<MODE>mode != QImode)
+ operands[1] = adjust_address (operands[1], QImode, 0);
+ emit_insn (gen_ldstub<mode> (operands[0], operands[1]));
+ DONE;
+})
+
+(define_expand "sync_lock_test_and_setsi"
+ [(parallel
+ [(set (match_operand:SI 0 "register_operand" "")
+ (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "")]
+ UNSPECV_SWAP))
+ (set (match_dup 1)
+ (match_operand:SI 2 "arith_operand" ""))])]
+ ""
+{
+ if (! TARGET_V8 && ! TARGET_V9)
+ {
+ if (operands[2] != const1_rtx)
+ FAIL;
+ operands[1] = adjust_address (operands[1], QImode, 0);
+ emit_insn (gen_ldstubsi (operands[0], operands[1]));
+ DONE;
+ }
+ emit_insn (gen_memory_barrier ());
+ operands[2] = force_reg (SImode, operands[2]);
+})
+
+(define_insn "*swapsi"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec_volatile:SI [(match_operand:SI 1 "memory_operand" "+m")]
+ UNSPECV_SWAP))
+ (set (match_dup 1)
+ (match_operand:SI 2 "register_operand" "0"))]
+ "TARGET_V8 || TARGET_V9"
+ "swap\t%1, %0"
+ [(set_attr "type" "multi")])
+
+(define_expand "ldstubqi"
+ [(parallel [(set (match_operand:QI 0 "register_operand" "")
+ (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
+ UNSPECV_LDSTUB))
+ (set (match_dup 1) (const_int -1))])]
+ ""
+ "")
+
+(define_expand "ldstub<mode>"
+ [(parallel [(set (match_operand:I24MODE 0 "register_operand" "")
+ (zero_extend:I24MODE
+ (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "")]
+ UNSPECV_LDSTUB)))
+ (set (match_dup 1) (const_int -1))])]
+ ""
+ "")
+
+(define_insn "*ldstubqi"
+ [(set (match_operand:QI 0 "register_operand" "=r")
+ (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
+ UNSPECV_LDSTUB))
+ (set (match_dup 1) (const_int -1))]
+ ""
+ "ldstub\t%1, %0"
+ [(set_attr "type" "multi")])
+
+(define_insn "*ldstub<mode>"
+ [(set (match_operand:I24MODE 0 "register_operand" "=r")
+ (zero_extend:I24MODE
+ (unspec_volatile:QI [(match_operand:QI 1 "memory_operand" "+m")]
+ UNSPECV_LDSTUB)))
+ (set (match_dup 1) (const_int -1))]
+ ""
+ "ldstub\t%1, %0"
+ [(set_attr "type" "multi")])
diff --git a/contrib/gcc/config/sparc/sysv4-only.h b/contrib/gcc/config/sparc/sysv4-only.h
index da265a0..dca78ba 100644
--- a/contrib/gcc/config/sparc/sysv4-only.h
+++ b/contrib/gcc/config/sparc/sysv4-only.h
@@ -1,5 +1,5 @@
/* Target macros for GCC for SPARC running System V.4
- Copyright (C) 2003
+ Copyright (C) 2003, 2005
Free Software Foundation, Inc.
This file is part of GCC.
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Provide a set of pre-definitions and pre-assertions appropriate for
the SPARC running svr4. __svr4__ is our extension. */
@@ -26,7 +26,6 @@ Boston, MA 02111-1307, USA. */
#define TARGET_OS_CPP_BUILTINS() \
do \
{ \
- builtin_define_std ("sparc"); \
builtin_define_std ("unix"); \
builtin_define ("__svr4__"); \
builtin_assert ("system=unix"); \
diff --git a/contrib/gcc/config/sparc/sysv4.h b/contrib/gcc/config/sparc/sysv4.h
index 776debc..0c0c8e0 100644
--- a/contrib/gcc/config/sparc/sysv4.h
+++ b/contrib/gcc/config/sparc/sysv4.h
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#ifndef TARGET_VERSION
#define TARGET_VERSION fprintf (stderr, " (sparc ELF)");
diff --git a/contrib/gcc/config/sparc/t-linux b/contrib/gcc/config/sparc/t-linux
new file mode 100644
index 0000000..a3e5130
--- /dev/null
+++ b/contrib/gcc/config/sparc/t-linux
@@ -0,0 +1,5 @@
+# Override t-slibgcc-elf-ver to export some libgcc symbols with
+# the symbol versions that glibc used.
+# Avoid the t-linux version file.
+SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \
+ $(srcdir)/config/sparc/libgcc-sparc-glibc.ver
diff --git a/contrib/gcc/config/sparc/t-linux64 b/contrib/gcc/config/sparc/t-linux64
index 3e3fa4c..7a1d5b1 100644
--- a/contrib/gcc/config/sparc/t-linux64
+++ b/contrib/gcc/config/sparc/t-linux64
@@ -8,12 +8,6 @@ INSTALL_LIBGCC = install-multilib
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o crtbeginT.o \
crtfastmath.o
-# Override t-slibgcc-elf-ver to export some libgcc symbols with
-# the symbol versions that glibc used.
-# Avoid the t-linux version file.
-SHLIB_MAPFILES = $(srcdir)/libgcc-std.ver \
- $(srcdir)/config/sparc/libgcc-sparc-glibc.ver
-
CRTSTUFF_T_CFLAGS = `if test x$$($(GCC_FOR_TARGET) $(MULTILIB_CFLAGS) \
-print-multi-os-directory) \
= x../lib64; then echo -mcmodel=medany; fi`
diff --git a/contrib/gcc/config/sparc/ultra1_2.md b/contrib/gcc/config/sparc/ultra1_2.md
index e58c624..b7329fd 100644
--- a/contrib/gcc/config/sparc/ultra1_2.md
+++ b/contrib/gcc/config/sparc/ultra1_2.md
@@ -1,5 +1,5 @@
;; Scheduling description for UltraSPARC-I/II.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; UltraSPARC-I and II are quad-issue processors. Interesting features
;; to note:
@@ -80,7 +80,7 @@
(define_insn_reservation "us1_single" 1
(and (eq_attr "cpu" "ultrasparc")
- (eq_attr "type" "multi,flushw,iflush,trap"))
+ (eq_attr "type" "multi,savew,flushw,iflush,trap"))
"us1_single_issue")
(define_insn_reservation "us1_simple_ieuN" 1
diff --git a/contrib/gcc/config/sparc/ultra3.md b/contrib/gcc/config/sparc/ultra3.md
index 238beab..7f9905f 100644
--- a/contrib/gcc/config/sparc/ultra3.md
+++ b/contrib/gcc/config/sparc/ultra3.md
@@ -1,5 +1,5 @@
;; Scheduling description for UltraSPARC-III.
-;; Copyright (C) 2002 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2004 Free Software Foundation, Inc.
;;
;; This file is part of GCC.
;;
@@ -15,8 +15,8 @@
;;
;; You should have received a copy of the GNU General Public License
;; along with GCC; see the file COPYING. If not, write to
-;; the Free Software Foundation, 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
;; UltraSPARC-III is a quad-issue processor.
;;
@@ -37,7 +37,7 @@
(define_insn_reservation "us3_single" 1
(and (eq_attr "cpu" "ultrasparc3")
- (eq_attr "type" "multi,flushw,iflush,trap"))
+ (eq_attr "type" "multi,savew,flushw,iflush,trap"))
"us3_single_issue")
(define_insn_reservation "us3_integer" 1
diff --git a/contrib/gcc/config/svr3.h b/contrib/gcc/config/svr3.h
index 21595ea..283ebf0 100644
--- a/contrib/gcc/config/svr3.h
+++ b/contrib/gcc/config/svr3.h
@@ -1,6 +1,6 @@
/* Operating system specific defines to be used when targeting GCC for
generic System V Release 3 system.
- Copyright (C) 1991, 1996, 2000, 2002 Free Software Foundation, Inc.
+ Copyright (C) 1991, 1996, 2000, 2002, 2004 Free Software Foundation, Inc.
Contributed by Ron Guilmette (rfg@monkeys.com).
This file is part of GCC.
@@ -17,8 +17,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* Define a symbol indicating that we are using svr3.h. */
#define USING_SVR3_H
@@ -54,7 +54,7 @@ Boston, MA 02111-1307, USA. */
do { \
int align = exact_log2 (ROUNDED); \
if (align > 2) align = 2; \
- data_section (); \
+ switch_to_section (data_section); \
ASM_OUTPUT_ALIGN ((FILE), align == -1 ? 2 : align); \
ASM_OUTPUT_LABEL ((FILE), (NAME)); \
fprintf ((FILE), "\t.set .,.+%u\n", (int)(ROUNDED)); \
@@ -70,10 +70,6 @@ Boston, MA 02111-1307, USA. */
#define NO_DOLLAR_IN_LABEL
-/* Implicit library calls should use memcpy, not bcopy, etc. */
-
-#define TARGET_MEM_FUNCTIONS
-
/* System V Release 3 uses COFF debugging info. */
#define SDB_DEBUGGING_INFO 1
@@ -163,33 +159,3 @@ do { \
} while (0)
#endif /* STACK_GROWS_DOWNWARD */
-
-#undef EXTRA_SECTIONS
-#define EXTRA_SECTIONS in_init, in_fini
-
-#undef EXTRA_SECTION_FUNCTIONS
-#define EXTRA_SECTION_FUNCTIONS \
- INIT_SECTION_FUNCTION \
- FINI_SECTION_FUNCTION
-
-#define INIT_SECTION_FUNCTION \
-void \
-init_section () \
-{ \
- if (in_section != in_init) \
- { \
- fprintf (asm_out_file, "%s\n", INIT_SECTION_ASM_OP); \
- in_section = in_init; \
- } \
-}
-
-#define FINI_SECTION_FUNCTION \
-void \
-fini_section () \
-{ \
- if (in_section != in_fini) \
- { \
- fprintf (asm_out_file, "%s\n", FINI_SECTION_ASM_OP); \
- in_section = in_fini; \
- } \
-}
diff --git a/contrib/gcc/config/svr4.h b/contrib/gcc/config/svr4.h
index ca65cd8..6fa88fc 100644
--- a/contrib/gcc/config/svr4.h
+++ b/contrib/gcc/config/svr4.h
@@ -18,8 +18,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA.
To use this file, make up a line like that in config.gcc:
@@ -203,4 +203,4 @@ Boston, MA 02111-1307, USA.
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#define TARGET_HAS_F_SETLKW
+#define TARGET_POSIX_IO
diff --git a/contrib/gcc/config/t-darwin b/contrib/gcc/config/t-darwin
index a7076ab..8ab072f 100644
--- a/contrib/gcc/config/t-darwin
+++ b/contrib/gcc/config/t-darwin
@@ -1,24 +1,33 @@
darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(REAL_H) insn-config.h \
conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h \
- reload.h function.h $(GGC_H) langhooks.h $(TM_P_H) gt-darwin.h
+ reload.h function.h $(GGC_H) langhooks.h $(TARGET_H) $(TM_P_H) gt-darwin.h \
+ config/darwin-sections.def
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin.c
darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TM_H) $(CPPLIB_H) tree.h c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin-c.c
+ $(TM_H) $(CPPLIB_H) $(TREE_H) c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H) \
+ c-incpath.h flags.h $(C_COMMON_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin-c.c $(PREPROCESSOR_DEFINES)
gt-darwin.h : s-gtype ; @true
-# Explain how to build crt2.o
-$(T)crt2$(objext): $(srcdir)/config/darwin-crt2.c $(GCC_PASSES) \
+# How to build crt3.o
+EXTRA_MULTILIB_PARTS=crt3.o
+# Pass -fno-tree-dominator-opts to work around bug 26840.
+$(T)crt3$(objext): $(srcdir)/config/darwin-crt3.c $(GCC_PASSES) \
$(TCONFIG_H) stmp-int-hdrs tsystem.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) \
- -c $(srcdir)/config/darwin-crt2.c -o $(T)crt2$(objext)
+ -fno-tree-dominator-opts $(DARWIN_EXTRA_CRT_BUILD_CFLAGS) \
+ -c $(srcdir)/config/darwin-crt3.c -o $(T)crt3$(objext)
# Use unwind-dw2-fde-darwin
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-darwin.c \
$(srcdir)/unwind-sjlj.c $(srcdir)/unwind-c.c
LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
-TARGET_LIBGCC2_CFLAGS = -fPIC
+# -pipe because there's an assembler bug, 4077127, which causes
+# it to not properly process the first # directive, causing temporary
+# file names to appear in stabs, causing the bootstrap to fail. Using -pipe
+# works around this by not having any temporary file names.
+TARGET_LIBGCC2_CFLAGS = -fPIC -pipe
diff --git a/contrib/gcc/config/t-dfprules b/contrib/gcc/config/t-dfprules
new file mode 100644
index 0000000..6bf6246
--- /dev/null
+++ b/contrib/gcc/config/t-dfprules
@@ -0,0 +1,10 @@
+# Use DFP_ENABLE to build decimal floating point support routines for
+# all decimal floating point types (32-bit, 64-bit and 128-bit). We
+# use `true' for clarity, but any value will do.
+#
+DFP_ENABLE = true
+
+# DFP_CFLAGS can be used to pass target-specific CFLAGS when compiling
+# dfp-bit.c. This is useful for overriding the definition of macros.
+#
+# DFP_CFLAGS = -DFOO=bar
diff --git a/contrib/gcc/config/t-libunwind-elf b/contrib/gcc/config/t-libunwind-elf
index a9609e7..1fa8aa2 100644
--- a/contrib/gcc/config/t-libunwind-elf
+++ b/contrib/gcc/config/t-libunwind-elf
@@ -5,25 +5,26 @@ LIBUNWIND = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c
LIBUNWINDDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
SHLIBUNWIND_SOVERSION = 7
-SHLIBUNWIND_SONAME = @shlib_so_name@.so.$(SHLIBUNWIND_SOVERSION)
-SHLIBUNWIND_NAME = @shlib_dir@@shlib_so_name@.so.$(SHLIBUNWIND_SOVERSION)
+SHLIBUNWIND_SONAME = @shlib_base_name@.so.$(SHLIBUNWIND_SOVERSION)
SHLIBUNWIND_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared \
-nodefaultlibs -Wl,-h,$(SHLIBUNWIND_SONAME) \
- -Wl,-z,text -Wl,-z,defs -o $(SHLIBUNWIND_NAME).tmp \
+ -Wl,-z,text -Wl,-z,defs -o $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
@multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SOLINK) && \
- if [ -f $(SHLIBUNWIND_NAME) ]; then \
- mv -f $(SHLIBUNWIND_NAME) $(SHLIBUNWIND_NAME).backup; \
+ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+ if [ -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) ]; then \
+ mv -f $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
+ $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).backup; \
else true; fi && \
- mv $(SHLIBUNWIND_NAME).tmp $(SHLIBUNWIND_NAME) && \
- $(LN_S) $(SHLIBUNWIND_NAME) $(SHLIB_SOLINK)
+ mv $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME).tmp \
+ $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) && \
+ $(LN_S) $(SHLIBUNWIND_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
SHLIBUNWIND_INSTALL = \
$$(SHELL) $$(srcdir)/mkinstalldirs $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIBUNWIND_NAME) \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIBUNWIND_SONAME) \
$$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIBUNWIND_SONAME); \
rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
$(LN_S) $(SHLIBUNWIND_SONAME) \
diff --git a/contrib/gcc/config/t-linux b/contrib/gcc/config/t-linux
index f25ab64..f3e792b 100644
--- a/contrib/gcc/config/t-linux
+++ b/contrib/gcc/config/t-linux
@@ -10,4 +10,4 @@ SHLIB_MAPFILES += $(srcdir)/config/libgcc-glibc.ver
# Use unwind-dw2-fde-glibc
LIB2ADDEH = $(srcdir)/unwind-dw2.c $(srcdir)/unwind-dw2-fde-glibc.c \
$(srcdir)/unwind-sjlj.c $(srcdir)/gthr-gnat.c $(srcdir)/unwind-c.c
-LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c gthr-gnat.c
+LIB2ADDEHDEP = unwind.inc unwind-dw2-fde.h unwind-dw2-fde.c
diff --git a/contrib/gcc/config/t-lynx b/contrib/gcc/config/t-lynx
new file mode 100644
index 0000000..a14a53c
--- /dev/null
+++ b/contrib/gcc/config/t-lynx
@@ -0,0 +1,15 @@
+# Compile crtbeginS.o and crtendS.o with pic.
+CRTSTUFF_T_CFLAGS_S = -fPIC
+
+# Compile libgcc2.a with pic.
+TARGET_LIBGCC2_CFLAGS = -fPIC
+
+MULTILIB_OPTIONS = mthreads
+MULTILIB_DIRNAMES = thread
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+Local Variables:
+mode: makefile
+End:
diff --git a/contrib/gcc/config/t-slibgcc-darwin b/contrib/gcc/config/t-slibgcc-darwin
index b820441..0c6eded 100644
--- a/contrib/gcc/config/t-slibgcc-darwin
+++ b/contrib/gcc/config/t-slibgcc-darwin
@@ -1,34 +1,101 @@
# Build a shared libgcc library with the darwin linker.
-SHLIB_MINOR = 1
-SHLIB_REVISION = 0
-SHLIB_VERSTRING = -compatibility_version $(SHLIB_MINOR) -current_version $(SHLIB_MINOR).$(SHLIB_REVISION)
+SHLIB_SOVERSION = 1
+SHLIB_VERSTRING = -compatibility_version $(SHLIB_SOVERSION) -current_version $(SHLIB_SOVERSION).0
SHLIB_EXT = .dylib
-SHLIB_SOLINK = @shlib_base_name@.dylib
-SHLIB_SONAME = @shlib_so_name@.$(SHLIB_MINOR).$(SHLIB_REVISION).dylib
-SHLIB_NAME = @shlib_dir@@shlib_so_name@.$(SHLIB_MINOR).$(SHLIB_REVISION).dylib
+SHLIB_SUFFIX = `if test @multilib_dir@ = ppc64 ; then echo _@multilib_dir@ ; fi`
+SHLIB_INSTALL_NAME = @shlib_base_name@$(SHLIB_SUFFIX).$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_SONAME = @shlib_base_name@.$(SHLIB_SOVERSION)$(SHLIB_EXT)
+SHLIB_SOLINK = @shlib_base_name@.so
SHLIB_MAP = @shlib_map_file@
SHLIB_OBJS = @shlib_objs@
-SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
+SHLIB_DIR = @multilib_dir@
+SHLIB_LC = -lc
+# Darwin only searches in /usr/lib for shared libraries, not in subdirectories,
+# so the libgcc variants have different names not different locations.
+# Note that this version is used for the loader, not the linker; the linker
+# uses the stub versions named by $(LIBGCC).
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -dynamiclib -nodefaultlibs \
- -Wl,-install_name,$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME) \
- -Wl,-flat_namespace -o $(SHLIB_NAME).tmp \
+ -Wl,-install_name,$(slibdir)/$(SHLIB_INSTALL_NAME) \
+ -single_module -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp \
+ -Wl,-exported_symbols_list,$(SHLIB_MAP) \
$(SHLIB_VERSTRING) \
- @multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SOLINK) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
- else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SOLINK)
+ @multilib_flags@ $(SHLIB_OBJS) $(SHLIB_LC)
+
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
SHLIB_INSTALL = \
- $$(SHELL) $$(srcdir)/mkinstalldirs $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIB_NAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
- rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
- $(LN_S) $(SHLIB_SONAME) \
- $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK)
-SHLIB_MKMAP = $(srcdir)/mkmap-symver.awk
-SHLIB_MAPFILES = $(srcdir)/libgcc-darwin.ver
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir); \
+ $(INSTALL_DATA) $(SHLIB_SONAME) \
+ $$(DESTDIR)$$(slibdir)/$(SHLIB_SONAME)
+
+SHLIB_MKMAP = $(srcdir)/mkmap-flat.awk
+SHLIB_MKMAP_OPTS = -v leading_underscore=1
+SHLIB_MAPFILES += $(srcdir)/libgcc-std.ver
+
+# Must use a different directive for hidden visibility in assembly sources.
+ASM_HIDDEN_OP = .private_extern
+
+# In order to support -mmacosx-version-min, you need to have multiple
+# different libgcc_s libraries that actually get linked against, one for
+# each system version supported. They are 'stub' libraries that
+# contain no code, just a list of exported symbols.
+# The actual use of the libraries is controlled by REAL_LIBGCC_SPEC.
+#
+# This assumes each multilib corresponds to a different architecture.
+libgcc_s.%.dylib : $(SHLIB_VERPFX).%.ver stmp-multilib
+ # When building multilibbed target libraries, all the required
+ # libraries are expected to exist in the multilib directory.
+ MLIBS=`$(GCC_FOR_TARGET) --print-multi-lib \
+ | sed -e 's/;.*$$//' -e '/^\.$$/d'` ; \
+ for mlib in $$MLIBS ; do \
+ rm -f $${mlib}/$@ || exit 1 ; \
+ $(LN_S) ../$@ $${mlib}/$@ || exit 1 ; \
+ done
+ MLIBS=`$(GCC_FOR_TARGET) --print-multi-lib \
+ | sed -e 's/;.*$$//' -e '/^\.$$/d'` ; \
+ for mlib in '' $$MLIBS ; do \
+ $(STRIP_FOR_TARGET) -o $(@)_T$${mlib} \
+ -s $(SHLIB_VERPFX).$(*).ver -c -u \
+ ./$${mlib}/libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT).tmp || exit 1 ; \
+ done
+ $(LIPO_FOR_TARGET) -output $@ -create $(@)_T*
+ rm $(@)_T*
+
+libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT): stmp-multilib libgcc_s.10.4.dylib \
+ libgcc_s.10.5.dylib
+ # When building multilibbed target libraries, all the required
+ # libraries are expected to exist in the multilib directory.
+ MLIBS=`$(GCC_FOR_TARGET) --print-multi-lib \
+ | sed -e 's/;.*$$//' -e '/^\.$$/d'` ; \
+ for mlib in '' $$MLIBS ; do \
+ cp ./$${mlib}/libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT).tmp \
+ ./libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT)_T_$${mlib} || exit 1 ; \
+ done
+ $(LIPO_FOR_TARGET) -output libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) \
+ -create libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT)_T*
+ rm libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT)_T*
+
+# From the point-of-view of the Makefiles, libgcc is built by the 'strip'
+# and 'lipo' commands above.
+LIBGCC=libgcc_s.$(SHLIB_SOVERSION)$(SHLIB_EXT) libgcc_s.10.4.dylib \
+ libgcc_s.10.5.dylib stmp-multilib
+
+INSTALL_FILES=libgcc_s.10.4.dylib libgcc_s.10.5.dylib libgcc_s.1.dylib
+
+install-darwin-libgcc-stubs : $(INSTALL_FILES) installdirs
+ for d in $(INSTALL_FILES) ; do \
+ $(INSTALL_DATA) $$d $(DESTDIR)$(slibdir)/$$d || exit 1 ; \
+ done
+ if [ -f $(DESTDIR)$(slibdir)/libgcc_s_ppc64.1.dylib ]; then \
+ rm -f $(DESTDIR)$(slibdir)/libgcc_s_ppc64.1.dylib; \
+ else true; fi
+ $(LN_S) libgcc_s.1.dylib \
+ $(DESTDIR)$(slibdir)/libgcc_s_ppc64.1.dylib
+ if [ -f $(DESTDIR)$(slibdir)/libgcc_s_x86_64.1.dylib ]; then \
+ rm -f $(DESTDIR)$(slibdir)/libgcc_s_x86_64.1.dylib; \
+ else true; fi
+ $(LN_S) libgcc_s.1.dylib \
+ $(DESTDIR)$(slibdir)/libgcc_s_x86_64.1.dylib
+
+INSTALL_LIBGCC = install-darwin-libgcc-stubs install-multilib
diff --git a/contrib/gcc/config/t-slibgcc-elf-ver b/contrib/gcc/config/t-slibgcc-elf-ver
index 5086500..346143c 100644
--- a/contrib/gcc/config/t-slibgcc-elf-ver
+++ b/contrib/gcc/config/t-slibgcc-elf-ver
@@ -4,28 +4,30 @@
SHLIB_EXT = .so
SHLIB_SOLINK = @shlib_base_name@.so
SHLIB_SOVERSION = 1
-SHLIB_SONAME = @shlib_so_name@.so.$(SHLIB_SOVERSION)
-SHLIB_NAME = @shlib_dir@@shlib_so_name@.so.$(SHLIB_SOVERSION)
+SHLIB_SONAME = @shlib_base_name@.so.$(SHLIB_SOVERSION)
SHLIB_MAP = @shlib_map_file@
SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@
SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
SHLIB_LC = -lc
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,--soname=$(SHLIB_SONAME) \
-Wl,--version-script=$(SHLIB_MAP) \
- -o $(SHLIB_NAME).tmp @multilib_flags@ $(SHLIB_OBJS) $(SHLIB_LC) && \
- rm -f $(SHLIB_SOLINK) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
+ -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp @multilib_flags@ \
+ $(SHLIB_OBJS) $(SHLIB_LC) && \
+ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
+ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SOLINK)
+ mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
+ $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
SHLIB_INSTALL = \
- $$(SHELL) $$(srcdir)/mkinstalldirs $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIB_NAME) \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SONAME) \
$$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
$(LN_S) $(SHLIB_SONAME) \
diff --git a/contrib/gcc/config/t-slibgcc-sld b/contrib/gcc/config/t-slibgcc-sld
index 44e7f18..02d21c6 100644
--- a/contrib/gcc/config/t-slibgcc-sld
+++ b/contrib/gcc/config/t-slibgcc-sld
@@ -2,27 +2,28 @@
SHLIB_EXT = .so
SHLIB_SOLINK = @shlib_base_name@.so
-SHLIB_SONAME = @shlib_so_name@.so.1
-SHLIB_NAME = @shlib_dir@@shlib_so_name@.so.1
+SHLIB_SONAME = @shlib_base_name@.so.1
SHLIB_MAP = @shlib_map_file@
SHLIB_OBJS = @shlib_objs@
+SHLIB_DIR = @multilib_dir@
SHLIB_SLIBDIR_QUAL = @shlib_slibdir_qual@
SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,-h,$(SHLIB_SONAME) -Wl,-z,text -Wl,-z,defs \
- -Wl,-M,$(SHLIB_MAP) -o $(SHLIB_NAME).tmp \
+ -Wl,-M,$(SHLIB_MAP) -o $(SHLIB_DIR)/$(SHLIB_SONAME).tmp \
@multilib_flags@ $(SHLIB_OBJS) -lc && \
- rm -f $(SHLIB_SOLINK) && \
- if [ -f $(SHLIB_NAME) ]; then \
- mv -f $(SHLIB_NAME) $(SHLIB_NAME).backup; \
+ rm -f $(SHLIB_DIR)/$(SHLIB_SOLINK) && \
+ if [ -f $(SHLIB_DIR)/$(SHLIB_SONAME) ]; then \
+ mv -f $(SHLIB_DIR)/$(SHLIB_SONAME) \
+ $(SHLIB_DIR)/$(SHLIB_SONAME).backup; \
else true; fi && \
- mv $(SHLIB_NAME).tmp $(SHLIB_NAME) && \
- $(LN_S) $(SHLIB_NAME) $(SHLIB_SOLINK)
+ mv $(SHLIB_DIR)/$(SHLIB_SONAME).tmp $(SHLIB_DIR)/$(SHLIB_SONAME) && \
+ $(LN_S) $(SHLIB_SONAME) $(SHLIB_DIR)/$(SHLIB_SOLINK)
# $(slibdir) double quoted to protect it from expansion while building
# libgcc.mk. We want this delayed until actual install time.
SHLIB_INSTALL = \
- $$(SHELL) $$(srcdir)/mkinstalldirs $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
- $(INSTALL_DATA) $(SHLIB_NAME) \
+ $$(mkinstalldirs) $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL); \
+ $(INSTALL_DATA) $(SHLIB_DIR)/$(SHLIB_SONAME) \
$$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SONAME); \
rm -f $$(DESTDIR)$$(slibdir)$(SHLIB_SLIBDIR_QUAL)/$(SHLIB_SOLINK); \
$(LN_S) $(SHLIB_SONAME) \
diff --git a/contrib/gcc/config/t-sol2 b/contrib/gcc/config/t-sol2
new file mode 100644
index 0000000..2339a0b
--- /dev/null
+++ b/contrib/gcc/config/t-sol2
@@ -0,0 +1,12 @@
+# Solaris-specific format checking and pragmas
+sol2-c.o: $(srcdir)/config/sol2-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ tree.h c-format.h intl.h $(CPPLIB_H) c-pragma.h $(TM_H) $(TM_P_H) \
+ toplev.h $(C_COMMON_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/sol2-c.c
+
+# Solaris-specific attributes
+sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ tree.h $(TM_H) $(TM_P_H) toplev.h $(GGC_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/sol2.c
diff --git a/contrib/gcc/config/t-vxworks b/contrib/gcc/config/t-vxworks
index ebf47e1..677b3b4 100644
--- a/contrib/gcc/config/t-vxworks
+++ b/contrib/gcc/config/t-vxworks
@@ -1,8 +1,7 @@
-# Since we have a functional assert.h, use it.
-INSTALL_ASSERT_H =
+# Don't run fixproto.
+STMP_FIXPROTO =
# Build libgcc using the multilib mechanism
-
LIBGCC = stmp-multilib
INSTALL_LIBGCC = install-multilib
@@ -15,8 +14,14 @@ LIBGCC2_DEBUG_CFLAGS =
# Extra libgcc2 module used by gthr-vxworks.h functions
LIB2FUNCS_EXTRA = $(srcdir)/config/vxlib.c
+# Some runtime modules need these. Can't set extra_headers in config.gcc
+# because the paths are always made absolute to the cpu config dir.
+EXTRA_HEADERS += $(srcdir)/gthr-vxworks.h gthr-default.h
+
# This ensures that the correct target headers are used; some
# VxWorks system headers have names that collide with GCC's
# internal (host) headers, e.g. regs.h.
# FIXME: May not be necessary anymore.
LIBGCC2_INCLUDES="-I$(SYSTEM_HEADER_DIR)"
+
+EXTRA_MULTILIB_PARTS =
diff --git a/contrib/gcc/config/usegas.h b/contrib/gcc/config/usegas.h
index 54fa9bd..8e1b47a 100644
--- a/contrib/gcc/config/usegas.h
+++ b/contrib/gcc/config/usegas.h
@@ -14,8 +14,8 @@
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
/* Just set a single flag we can test for it inside other files. */
#define USE_GAS 1
diff --git a/contrib/gcc/config/vx-common.h b/contrib/gcc/config/vx-common.h
new file mode 100644
index 0000000..cb8d7a0
--- /dev/null
+++ b/contrib/gcc/config/vx-common.h
@@ -0,0 +1,88 @@
+/* Target-independent configuration for VxWorks and VxWorks AE.
+ Copyright (C) 2005 Free Software Foundation, Inc.
+ Contributed by by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* VxWorks headers are C++-aware. */
+#undef NO_IMPLICIT_EXTERN_C
+#define NO_IMPLICIT_EXTERN_C
+
+/* Most of these will probably be overridden by subsequent headers. We
+ undefine them here just in case, and define VXWORKS_ versions of each,
+ to be used in port-specific vxworks.h. */
+#undef LIB_SPEC
+#undef LINK_SPEC
+#undef LIBGCC_SPEC
+#define LIBGCC_SPEC VXWORKS_LIBGCC_SPEC
+#undef STARTFILE_SPEC
+#undef ENDFILE_SPEC
+
+/* Most of these macros are overridden in "config/vxworks.h" or
+ "config/vxworksae.h" and are here merely for documentation
+ purposes. */
+#define VXWORKS_ADDITIONAL_CPP_SPEC ""
+#define VXWORKS_LIB_SPEC ""
+#define VXWORKS_LINK_SPEC ""
+#define VXWORKS_LIBGCC_SPEC ""
+#define VXWORKS_STARTFILE_SPEC ""
+#define VXWORKS_ENDFILE_SPEC ""
+
+/* VxWorks cannot have dots in constructor labels, because it uses a
+ mutant variation of collect2 that generates C code instead of
+ assembly. Thus each constructor label must be a legitimate C
+ symbol. FIXME: Have VxWorks use real collect2 instead. */
+#undef NO_DOLLAR_IN_LABEL
+#define NO_DOT_IN_LABEL
+
+/* VxWorks uses wchar_t == unsigned short (UCS2) on all architectures. */
+#undef WCHAR_TYPE
+#define WCHAR_TYPE "short unsigned int"
+#undef WCHAR_TYPE_SIZE
+#define WCHAR_TYPE_SIZE 16
+
+/* Dwarf2 unwind info is not supported. */
+#define DWARF2_UNWIND_INFO 0
+
+/* VxWorks uses DWARF2. */
+#define DWARF2_DEBUGGING_INFO 1
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+
+/* None of these other formats is supported. */
+#undef DWARF_DEBUGGING_INFO
+#undef DBX_DEBUGGING_INFO
+#undef SDB_DEBUGGING_INFO
+#undef XCOFF_DEBUGGING_INFO
+#undef VMS_DEBUGGING_INFO
+
+/* Kernel mode doesn't have ctors/dtors, but RTP mode does. */
+#define TARGET_HAVE_CTORS_DTORS false
+#define VXWORKS_OVERRIDE_OPTIONS /* empty */
+
+/* No math library needed. */
+#define MATH_LIBRARY ""
+
+/* No profiling. */
+#define VXWORKS_FUNCTION_PROFILER(FILE, LABELNO) do \
+{ \
+ sorry ("profiler support for VxWorks"); \
+} while (0)
+
+/* We occasionally need to distinguish between the VxWorks variants. */
+#define VXWORKS_KIND_NORMAL 1
+#define VXWORKS_KIND_AE 2
diff --git a/contrib/gcc/config/vxlib.c b/contrib/gcc/config/vxlib.c
index 20a257e..8625981 100644
--- a/contrib/gcc/config/vxlib.c
+++ b/contrib/gcc/config/vxlib.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Contributed by Zack Weinberg <zack@codesourcery.com>
This file is part of GCC.
@@ -15,11 +15,8 @@ for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
-
-/* Threads compatibility routines for libgcc2 for VxWorks.
- These are out-of-line routines called from gthr-vxworks.h. */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
/* As a special exception, if you link this library with other files,
some of which are compiled with GCC, to produce an executable,
@@ -28,14 +25,24 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
This exception does not however invalidate any other reasons why
the executable file might be covered by the GNU General Public License. */
+/* Threads compatibility routines for libgcc2 for VxWorks.
+ These are out-of-line routines called from gthr-vxworks.h. */
+
#include "tconfig.h"
#include "tsystem.h"
#include "gthr.h"
+#if defined(__GTHREADS)
#include <vxWorks.h>
+#ifndef __RTP__
#include <vxLib.h>
+#endif
#include <taskLib.h>
+#ifndef __RTP__
#include <taskHookLib.h>
+#else
+# include <errno.h>
+#endif
/* Init-once operation.
@@ -57,8 +64,12 @@ __gthread_once (__gthread_once_t *guard, void (*func)(void))
if (guard->done)
return 0;
+#ifdef __RTP__
+ __gthread_lock_library ();
+#else
while (!vxTas ((void *)&guard->busy))
taskDelay (1);
+#endif
/* Only one thread at a time gets here. Check ->done again, then
go ahead and call func() if no one has done it yet. */
@@ -68,29 +79,37 @@ __gthread_once (__gthread_once_t *guard, void (*func)(void))
guard->done = 1;
}
+#ifdef __RTP__
+ __gthread_unlock_library ();
+#else
guard->busy = 0;
+#endif
return 0;
}
-/* Thread-specific data.
+/* Thread-local storage.
We reserve a field in the TCB to point to a dynamically allocated
- array which is used to store TSD values. A TSD key is simply an
+ array which is used to store TLS values. A TLS key is simply an
offset in this array. The exact location of the TCB field is not
known to this code nor to vxlib.c -- all access to it indirects
- through the routines __gthread_get_tsd_data and
- __gthread_set_tsd_data, which are provided by the VxWorks kernel.
+ through the routines __gthread_get_tls_data and
+ __gthread_set_tls_data, which are provided by the VxWorks kernel.
There is also a global array which records which keys are valid and
which have destructors.
A task delete hook is installed to execute key destructors. The
- routines __gthread_enter_tsd_dtor_context and
- __gthread_leave_tsd_dtor_context, which are also provided by the
+ routines __gthread_enter_tls_dtor_context and
+ __gthread_leave_tls_dtor_context, which are also provided by the
kernel, ensure that it is safe to call free() on memory allocated
by the task being deleted. (This is a no-op on VxWorks 5, but
a major undertaking on AE.)
+ The task delete hook is only installed when at least one thread
+ has TLS data. This is a necessary precaution, to allow this module
+ to be unloaded - a module with a hook can not be removed.
+
Since this interface is used to allocate only a small number of
keys, the table size is small and static, which simplifies the
code quite a bit. Revisit this if and when it becomes necessary. */
@@ -98,23 +117,29 @@ __gthread_once (__gthread_once_t *guard, void (*func)(void))
#define MAX_KEYS 4
/* This is the structure pointed to by the pointer returned
- by __gthread_get_tsd_data. */
-struct tsd_data
+ by __gthread_get_tls_data. */
+struct tls_data
{
+ int *owner;
void *values[MAX_KEYS];
unsigned int generation[MAX_KEYS];
};
+/* To make sure we only delete TLS data associated with this object,
+ include a pointer to a local variable in the TLS data object. */
+static int self_owner;
+
+/* The number of threads for this module which have active TLS data.
+ This is protected by tls_lock. */
+static int active_tls_threads;
/* kernel provided routines */
-extern void *__gthread_get_tsd_data (WIND_TCB *tcb);
-extern void __gthread_set_tsd_data (WIND_TCB *tcb, void *data);
+extern void *__gthread_get_tls_data (void);
+extern void __gthread_set_tls_data (void *data);
-extern void __gthread_enter_tsd_dtor_context (WIND_TCB *tcb);
-extern void __gthread_leave_tsd_dtor_context (WIND_TCB *tcb);
+extern void __gthread_enter_tls_dtor_context (void);
+extern void __gthread_leave_tls_dtor_context (void);
-typedef void (*fet_callback_t) (WIND_TCB *, unsigned int);
-extern void __gthread_for_all_tasks (fet_callback_t fun, unsigned int number);
/* This is a global structure which records all of the active keys.
@@ -128,71 +153,100 @@ extern void __gthread_for_all_tasks (fet_callback_t fun, unsigned int number);
stored in this structure is equal to the generation count stored in
T's specific-value structure. */
-typedef void (*tsd_dtor) (void *);
+typedef void (*tls_dtor) (void *);
-struct tsd_keys
+struct tls_keys
{
- tsd_dtor dtor[MAX_KEYS];
+ tls_dtor dtor[MAX_KEYS];
unsigned int generation[MAX_KEYS];
};
-#define KEY_VALID_P(key) !(tsd_keys.generation[key] & 1)
+#define KEY_VALID_P(key) !(tls_keys.generation[key] & 1)
/* Note: if MAX_KEYS is increased, this initializer must be updated
to match. All the generation counts begin at 1, which means no
key is valid. */
-static struct tsd_keys tsd_keys =
+static struct tls_keys tls_keys =
{
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 }
};
-/* This lock protects the tsd_keys structure. */
-static __gthread_mutex_t tsd_lock;
+/* This lock protects the tls_keys structure. */
+static __gthread_mutex_t tls_lock;
-static __gthread_once_t tsd_init_guard = __GTHREAD_ONCE_INIT;
+static __gthread_once_t tls_init_guard = __GTHREAD_ONCE_INIT;
/* Internal routines. */
/* The task TCB has just been deleted. Call the destructor
- function for each TSD key that has both a destructor and
+ function for each TLS key that has both a destructor and
a non-NULL specific value in this thread.
- This routine does not need to take tsd_lock; the generation
+ This routine does not need to take tls_lock; the generation
count protects us from calling a stale destructor. It does
- need to read tsd_keys.dtor[key] atomically. */
+ need to read tls_keys.dtor[key] atomically. */
static void
-tsd_delete_hook (WIND_TCB *tcb)
+tls_delete_hook (void *tcb ATTRIBUTE_UNUSED)
{
- struct tsd_data *data = __gthread_get_tsd_data (tcb);
+ struct tls_data *data = __gthread_get_tls_data ();
__gthread_key_t key;
- if (data)
+ if (data && data->owner == &self_owner)
{
- __gthread_enter_tsd_dtor_context (tcb);
+ __gthread_enter_tls_dtor_context ();
for (key = 0; key < MAX_KEYS; key++)
{
- if (data->generation[key] == tsd_keys.generation[key])
+ if (data->generation[key] == tls_keys.generation[key])
{
- tsd_dtor dtor = tsd_keys.dtor[key];
+ tls_dtor dtor = tls_keys.dtor[key];
if (dtor)
dtor (data->values[key]);
}
}
free (data);
- __gthread_set_tsd_data (tcb, 0);
- __gthread_leave_tsd_dtor_context (tcb);
+
+ /* We can't handle an error here, so just leave the thread
+ marked as loaded if one occurs. */
+ if (__gthread_mutex_lock (&tls_lock) != ERROR)
+ {
+ active_tls_threads--;
+ if (active_tls_threads == 0)
+ taskDeleteHookDelete ((FUNCPTR)tls_delete_hook);
+ __gthread_mutex_unlock (&tls_lock);
+ }
+
+ __gthread_set_tls_data (0);
+ __gthread_leave_tls_dtor_context ();
}
}
-/* Initialize global data used by the TSD system. */
+/* Initialize global data used by the TLS system. */
static void
-tsd_init (void)
+tls_init (void)
{
- taskDeleteHookAdd ((FUNCPTR)tsd_delete_hook);
- __GTHREAD_MUTEX_INIT_FUNCTION (&tsd_lock);
+ __GTHREAD_MUTEX_INIT_FUNCTION (&tls_lock);
+}
+
+static void tls_destructor (void) __attribute__ ((destructor));
+static void
+tls_destructor (void)
+{
+#ifdef __RTP__
+ /* All threads but this one should have exited by now. */
+ tls_delete_hook (NULL);
+#else
+ /* Unregister the hook forcibly. The counter of active threads may
+ be incorrect, because constructors (like the C++ library's) and
+ destructors (like this one) run in the context of the shell rather
+ than in a task spawned from this module. */
+ taskDeleteHookDelete ((FUNCPTR)tls_delete_hook);
+#endif
+
+ if (tls_init_guard.done && __gthread_mutex_lock (&tls_lock) != ERROR)
+ semDelete (tls_lock);
}
/* External interface */
@@ -204,13 +258,13 @@ tsd_init (void)
this key, with the value as its sole argument. */
int
-__gthread_key_create (__gthread_key_t *keyp, tsd_dtor dtor)
+__gthread_key_create (__gthread_key_t *keyp, tls_dtor dtor)
{
__gthread_key_t key;
- __gthread_once (&tsd_init_guard, tsd_init);
+ __gthread_once (&tls_init_guard, tls_init);
- if (__gthread_mutex_lock (&tsd_lock) == ERROR)
+ if (__gthread_mutex_lock (&tls_lock) == ERROR)
return errno;
for (key = 0; key < MAX_KEYS; key++)
@@ -218,14 +272,14 @@ __gthread_key_create (__gthread_key_t *keyp, tsd_dtor dtor)
goto found_slot;
/* no room */
- __gthread_mutex_unlock (&tsd_lock);
+ __gthread_mutex_unlock (&tls_lock);
return EAGAIN;
found_slot:
- tsd_keys.generation[key]++; /* making it even */
- tsd_keys.dtor[key] = dtor;
+ tls_keys.generation[key]++; /* making it even */
+ tls_keys.dtor[key] = dtor;
*keyp = key;
- __gthread_mutex_unlock (&tsd_lock);
+ __gthread_mutex_unlock (&tls_lock);
return 0;
}
@@ -238,21 +292,21 @@ __gthread_key_delete (__gthread_key_t key)
if (key >= MAX_KEYS)
return EINVAL;
- __gthread_once (&tsd_init_guard, tsd_init);
+ __gthread_once (&tls_init_guard, tls_init);
- if (__gthread_mutex_lock (&tsd_lock) == ERROR)
+ if (__gthread_mutex_lock (&tls_lock) == ERROR)
return errno;
if (!KEY_VALID_P (key))
{
- __gthread_mutex_unlock (&tsd_lock);
+ __gthread_mutex_unlock (&tls_lock);
return EINVAL;
}
- tsd_keys.generation[key]++; /* making it odd */
- tsd_keys.dtor[key] = 0;
+ tls_keys.generation[key]++; /* making it odd */
+ tls_keys.dtor[key] = 0;
- __gthread_mutex_unlock (&tsd_lock);
+ __gthread_mutex_unlock (&tls_lock);
return 0;
}
@@ -266,17 +320,17 @@ __gthread_key_delete (__gthread_key_t key)
void *
__gthread_getspecific (__gthread_key_t key)
{
- struct tsd_data *data;
+ struct tls_data *data;
if (key >= MAX_KEYS)
return 0;
- data = __gthread_get_tsd_data (taskTcb (taskIdSelf ()));
+ data = __gthread_get_tls_data ();
if (!data)
return 0;
- if (data->generation[key] != tsd_keys.generation[key])
+ if (data->generation[key] != tls_keys.generation[key])
return 0;
return data->values[key];
@@ -289,31 +343,37 @@ __gthread_getspecific (__gthread_key_t key)
key_create/key_delete; the worst thing that can happen is that a
value is successfully stored into a dead generation (and then
immediately becomes invalid). However, we do have to make sure
- to read tsd_keys.generation[key] atomically. */
+ to read tls_keys.generation[key] atomically. */
int
__gthread_setspecific (__gthread_key_t key, void *value)
{
- struct tsd_data *data;
- WIND_TCB *tcb;
+ struct tls_data *data;
unsigned int generation;
if (key >= MAX_KEYS)
return EINVAL;
- tcb = taskTcb (taskIdSelf ());
- data = __gthread_get_tsd_data (tcb);
+ data = __gthread_get_tls_data ();
if (!data)
{
- data = malloc (sizeof (struct tsd_data));
+ if (__gthread_mutex_lock (&tls_lock) == ERROR)
+ return ENOMEM;
+ if (active_tls_threads == 0)
+ taskDeleteHookAdd ((FUNCPTR)tls_delete_hook);
+ active_tls_threads++;
+ __gthread_mutex_unlock (&tls_lock);
+
+ data = malloc (sizeof (struct tls_data));
if (!data)
return ENOMEM;
- memset (data, 0, sizeof (struct tsd_data));
- __gthread_set_tsd_data (tcb, data);
+ memset (data, 0, sizeof (struct tls_data));
+ data->owner = &self_owner;
+ __gthread_set_tls_data (data);
}
- generation = tsd_keys.generation[key];
+ generation = tls_keys.generation[key];
if (generation & 1)
return EINVAL;
@@ -323,3 +383,4 @@ __gthread_setspecific (__gthread_key_t key, void *value)
return 0;
}
+#endif /* __GTHREADS */
diff --git a/contrib/gcc/config/vxworks.h b/contrib/gcc/config/vxworks.h
index 085eb8c..70345e2 100644
--- a/contrib/gcc/config/vxworks.h
+++ b/contrib/gcc/config/vxworks.h
@@ -1,64 +1,103 @@
-/* Common VxWorks target definitions for GCC.
- Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+/* Common VxWorks target definitions for GNU compiler.
+ Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Free Software Foundation, Inc.
Contributed by Wind River Systems.
+ Rewritten by CodeSourcery, LLC.
This file is part of GCC.
-GCC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
-GCC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
-/* Specify what to link with. */
-/* VxWorks does all the library stuff itself. */
-#undef LIB_SPEC
-#define LIB_SPEC ""
+/* In kernel mode, VxWorks provides all the libraries itself, as well as
+ the functionality of startup files, etc. In RTP mode, it behaves more
+ like a traditional Unix, with more external files. Most of our specs
+ must be aware of the difference. */
-#undef LINK_SPEC
-#define LINK_SPEC "-r"
+/* The directory containing the VxWorks target headers. */
+#define VXWORKS_TARGET_DIR "/home/tornado/base6/target"
-/* VxWorks provides the functionality of crt0.o and friends itself. */
-#undef STARTFILE_SPEC
-#define STARTFILE_SPEC ""
+/* Since we provide a default -isystem, expand -isystem on the command
+ line early. */
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC " \
+ %{!nostdinc:%{isystem*}} \
+ %{mrtp: -D__RTP__=1 \
+ %{!nostdinc:-isystem " VXWORKS_TARGET_DIR "/usr/h}} \
+ %{!mrtp:-D_WRS_KERNEL=1 \
+ %{!nostdinc:-isystem " VXWORKS_TARGET_DIR "/h}}"
-#undef ENDFILE_SPEC
-#define ENDFILE_SPEC ""
+/* The references to __init and __fini will be satisfied by
+ libc_internal.a. */
+#undef VXWORKS_LIB_SPEC
+#define VXWORKS_LIB_SPEC \
+"%{mrtp:%{shared:-u " USER_LABEL_PREFIX "__init -u " USER_LABEL_PREFIX "__fini} \
+ %{!shared:%{non-static:-u " USER_LABEL_PREFIX "_STI__6__rtld -ldl} \
+ --start-group -lc -lgcc -lc_internal -lnet -ldsi \
+ --end-group}}"
-/* VxWorks cannot have dots in constructor labels, because it uses a
- mutant variation of collect2 that generates C code instead of
- assembly. Thus each constructor label must be a legitimate C
- symbol. FIXME: Have VxWorks use real collect2 instead. */
+/* The no-op spec for "-shared" below is present because otherwise GCC
+ will treat it as an unrecognized option. */
+#undef VXWORKS_LINK_SPEC
+#define VXWORKS_LINK_SPEC \
+"%{!mrtp:-r} \
+ %{!shared: \
+ %{mrtp:-q %{h*} \
+ %{R*} %{!Wl,-T*: %{!T*: %(link_start) }} \
+ %(link_target) %(link_os)}} \
+ %{v:-V} \
+ %{shared:-shared} \
+ %{Bstatic:-Bstatic} \
+ %{Bdynamic:-Bdynamic} \
+ %{!Xbind-lazy:-z now} \
+ %{Xbind-now:%{Xbind-lazy: \
+ %e-Xbind-now and -Xbind-lazy are incompatible}} \
+ %{mrtp:%{!shared:%{!non-static:-static} \
+ %{non-static:--force-dynamic --export-dynamic}}}"
-#undef NO_DOLLAR_IN_LABEL
-#define NO_DOT_IN_LABEL
+/* For VxWorks, the system provides libc_internal.a. This is a superset
+ of libgcc.a; we want to use it. Make sure not to dynamically export
+ any of its symbols, though. Always look for libgcc.a first so that
+ we get the latest versions of the GNU intrinsics during our builds. */
+#undef VXWORKS_LIBGCC_SPEC
+#define VXWORKS_LIBGCC_SPEC \
+ "-lgcc %{mrtp:--exclude-libs=libc_internal,libgcc -lc_internal}"
-/* enable #pragma pack(n) */
-#define HANDLE_SYSV_PRAGMA
+#undef VXWORKS_STARTFILE_SPEC
+#define VXWORKS_STARTFILE_SPEC "%{mrtp:%{!shared:crt0.o%s}}"
+#define VXWORKS_ENDFILE_SPEC ""
-/* No underscore is prepended to any C symbol name. */
-#undef USER_LABEL_PREFIX
-#define USER_LABEL_PREFIX ""
+/* We can use .ctors/.dtors sections only in RTP mode.
+ Unfortunately this must be an integer constant expression;
+ fix up in override_options. */
+#undef VXWORKS_OVERRIDE_OPTIONS
+#define VXWORKS_OVERRIDE_OPTIONS do { \
+ targetm.have_ctors_dtors = TARGET_VXWORKS_RTP; \
+} while (0)
-/* VxWorks uses wchar_t == unsigned short (UCS2) on all architectures. */
-#undef WCHAR_TYPE
-#define WCHAR_TYPE "short unsigned int"
-#undef WCHAR_TYPE_SIZE
-#define WCHAR_TYPE_SIZE 16
+/* The VxWorks runtime uses a clever trick to get the sentinel entry
+ (-1) inserted at the beginning of the .ctors segment. This trick
+ will not work if we ever generate any entries in plain .ctors
+ sections; we must always use .ctors.PRIORITY. */
+#define ALWAYS_NUMBER_CTORS_SECTIONS 1
-/* Dwarf2 unwind info is not supported. */
-#define DWARF2_UNWIND_INFO 0
-/* Weak symbols and link-once sections are not enabled by default. */
-#define DEFAULT_USE_WEAK 0
+/* The name of the symbol for the table of GOTs in a particular
+ RTP. */
+#define VXWORKS_GOTT_BASE "__GOTT_BASE__"
+/* The name of the symbol for the index into the table of GOTs for the
+ GOT associated with the current shared library. */
+#define VXWORKS_GOTT_INDEX "__GOTT_INDEX__"
-/* Only supported debug format is Dwarf2. */
-#undef DBX_DEBUGGING_INFO
+#define VXWORKS_KIND VXWORKS_KIND_NORMAL
diff --git a/contrib/gcc/config/vxworks.opt b/contrib/gcc/config/vxworks.opt
new file mode 100644
index 0000000..98a44f5
--- /dev/null
+++ b/contrib/gcc/config/vxworks.opt
@@ -0,0 +1,32 @@
+; Processor-independent options for VxWorks.
+;
+; Copyright (C) 2005 Free Software Foundation, Inc.
+; Contributed by CodeSourcery, LLC.
+;
+; This file is part of GCC.
+;
+; GCC is free software; you can redistribute it and/or modify it under
+; the terms of the GNU General Public License as published by the Free
+; Software Foundation; either version 2, or (at your option) any later
+; version.
+;
+; GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+; WARRANTY; without even the implied warranty of MERCHANTABILITY or
+; FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+; for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with GCC; see the file COPYING. If not, write to the Free
+; Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+; 02110-1301, USA.
+
+mrtp
+Target Report RejectNegative Mask(VXWORKS_RTP) Condition(VXWORKS_KIND == VXWORKS_KIND_NORMAL)
+Assume the VxWorks RTP environment
+
+; VxWorks AE has two modes: kernel mode and vThreads mode. In
+; general, back ends do not actually need to know which mode they're
+; in, so we do not have to set any flags.
+mvthreads
+Target RejectNegative Condition(VXWORKS_KIND == VXWORKS_KIND_AE)
+Assume the VxWorks vThreads environment
diff --git a/contrib/gcc/config/vxworksae.h b/contrib/gcc/config/vxworksae.h
new file mode 100644
index 0000000..b63192e
--- /dev/null
+++ b/contrib/gcc/config/vxworksae.h
@@ -0,0 +1,58 @@
+/* Common VxWorks AE target definitions for GNU compiler.
+ Copyright (C) 2004, 2005 Free Software Foundation, Inc.
+ Contributed by CodeSourcery, LLC.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING. If not, write to the Free
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA. */
+
+/* This header should be included after including vx-common.h. */
+
+/* Most of the definitions below this point are versions of the
+ vxworks.h definitions, without the -mrtp bits. */
+
+/* The directory containing the VxWorks AE target headers. */
+#define VXWORKSAE_TARGET_DIR \
+ "/home/tornado/vxworks-ae/latest/target"
+
+/* Include target/vThreads/h or target/h (depending on the compilation
+ mode), and then target/val/h (in either mode). The macros defined
+ are in the user's namespace, but the VxWorks headers require
+ them. */
+#undef VXWORKS_ADDITIONAL_CPP_SPEC
+#define VXWORKS_ADDITIONAL_CPP_SPEC " \
+ %{!nostdinc:%{isystem*}} \
+ %{mvthreads:-DVTHREADS=1 \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR "/vThreads/h}} \
+ %{!mvthreads:-DAE653_BUILD=1 \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR "/h}} \
+ %{!nostdinc:-isystem " VXWORKSAE_TARGET_DIR "/val/h}"
+
+#undef VXWORKS_LIB_SPEC
+#define VXWORKS_LIB_SPEC ""
+
+#undef VXWORKS_LINK_SPEC
+#define VXWORKS_LINK_SPEC \
+ "-r %{v:-V}"
+
+#undef VXWORKS_LIBGCC_SPEC
+#define VXWORKS_LIBGCC_SPEC \
+ "-lgcc"
+
+#undef VXWORKS_STARTFILE_SPEC
+#define VXWORKS_STARTFILE_SPEC ""
+
+#define VXWORKS_KIND VXWORKS_KIND_AE
diff --git a/contrib/gcc/config/windiss.h b/contrib/gcc/config/windiss.h
index 7aef9b6..0c1eae1 100644
--- a/contrib/gcc/config/windiss.h
+++ b/contrib/gcc/config/windiss.h
@@ -16,8 +16,8 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING. If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* windiss uses wchar_t == unsigned short (UCS2) on all architectures. */
diff --git a/contrib/gcc/config/x-darwin b/contrib/gcc/config/x-darwin
new file mode 100644
index 0000000..c2ffd7d
--- /dev/null
+++ b/contrib/gcc/config/x-darwin
@@ -0,0 +1,3 @@
+host-darwin.o : $(srcdir)/config/host-darwin.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h toplev.h config/host-darwin.h
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/contrib/gcc/config/x-hpux b/contrib/gcc/config/x-hpux
new file mode 100644
index 0000000..fa0c555
--- /dev/null
+++ b/contrib/gcc/config/x-hpux
@@ -0,0 +1,4 @@
+host-hpux.o : $(srcdir)/config/host-hpux.c $(CONFIG_H) $(SYSTEM_H) \
+ coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
+ $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/host-hpux.c
diff --git a/contrib/gcc/config/x-solaris b/contrib/gcc/config/x-solaris
index 782f4a3..59c7bf6 100644
--- a/contrib/gcc/config/x-solaris
+++ b/contrib/gcc/config/x-solaris
@@ -1,4 +1,4 @@
host-solaris.o : $(srcdir)/config/host-solaris.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h hosthooks.h hosthooks-def.h
+ coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/host-solaris.c
OpenPOWER on IntegriCloud